From 20e3afdf0d88aef30fd82443cb8042b9217c2275 Mon Sep 17 00:00:00 2001 From: Patrick Sy Date: Tue, 7 Oct 2025 14:37:54 +0200 Subject: [PATCH 01/10] chore: Added flake --- .envrc.example | 1 + .gitignore | 4 ++++ flake.lock | 25 +++++++++++++++++++++++++ flake.nix | 38 ++++++++++++++++++++++++++++++++++++++ 4 files changed, 68 insertions(+) create mode 100644 .envrc.example create mode 100644 flake.lock create mode 100644 flake.nix diff --git a/.envrc.example b/.envrc.example new file mode 100644 index 0000000..3550a30 --- /dev/null +++ b/.envrc.example @@ -0,0 +1 @@ +use flake diff --git a/.gitignore b/.gitignore index 7cf5941..c08c1df 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,7 @@ edge-connect # Added by goreleaser init: dist/ + +### direnv ### +.direnv +.envrc diff --git a/flake.lock b/flake.lock new file mode 100644 index 0000000..eb9d74d --- /dev/null +++ b/flake.lock @@ -0,0 +1,25 @@ +{ + "nodes": { + "nixpkgs": { + "locked": { + "lastModified": 1759733170, + "narHash": "sha256-TXnlsVb5Z8HXZ6mZoeOAIwxmvGHp1g4Dw89eLvIwKVI=", + "rev": "8913c168d1c56dc49a7718685968f38752171c3b", + "revCount": 873256, + "type": "tarball", + "url": "https://api.flakehub.com/f/pinned/NixOS/nixpkgs/0.1.873256%2Brev-8913c168d1c56dc49a7718685968f38752171c3b/0199bd36-8ae7-7817-b019-8688eb4f61ff/source.tar.gz" + }, + "original": { + "type": "tarball", + "url": "https://flakehub.com/f/NixOS/nixpkgs/0.1" + } + }, + "root": { + "inputs": { + "nixpkgs": "nixpkgs" + } + } + }, + "root": "root", + "version": 7 +} diff --git a/flake.nix b/flake.nix new file mode 100644 index 0000000..2536eb7 --- /dev/null +++ b/flake.nix @@ -0,0 +1,38 @@ +{ + description = "A Nix-flake-based Go development environment"; + + inputs.nixpkgs.url = "https://flakehub.com/f/NixOS/nixpkgs/0.1"; + + outputs = inputs: + let + goVersion = 25; # Change this to update the whole stack + + supportedSystems = [ "x86_64-linux" "aarch64-linux" "x86_64-darwin" "aarch64-darwin" ]; + forEachSupportedSystem = f: inputs.nixpkgs.lib.genAttrs supportedSystems (system: f { + pkgs = import inputs.nixpkgs { + inherit system; + overlays = [ inputs.self.overlays.default ]; + }; + }); + in + { + overlays.default = final: prev: { + go = final."go_1_${toString goVersion}"; + }; + + devShells = forEachSupportedSystem ({ pkgs }: { + default = pkgs.mkShell { + packages = with pkgs; [ + # go (version is specified by overlay) + go + + # goimports, godoc, etc. + gotools + + # https://github.com/golangci/golangci-lint + golangci-lint + ]; + }; + }); + }; +} From b712ae0869e4f8a2f159fec516d2fdba67c04cbd Mon Sep 17 00:00:00 2001 From: Patrick Sy Date: Tue, 7 Oct 2025 15:40:27 +0200 Subject: [PATCH 02/10] fix(cli): Fixed tests after outputting plan diff --- internal/apply/planner.go | 9 +++++++-- internal/apply/planner_test.go | 2 ++ 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/internal/apply/planner.go b/internal/apply/planner.go index a9219ea..4e2a3e0 100644 --- a/internal/apply/planner.go +++ b/internal/apply/planner.go @@ -391,8 +391,13 @@ func (p *EdgeConnectPlanner) compareAppStates(current, desired *AppState) ([]str // Compare outbound connections outboundChanges := p.compareOutboundConnections(current.OutboundConnections, desired.OutboundConnections) if len(outboundChanges) > 0 { - changes = append(changes, "Outbound connections changed:") - changes = append(changes, outboundChanges...) + sb:= strings.Builder{} + sb.WriteString("Outbound connections changed:\n") + for _, change := range outboundChanges { + sb.WriteString(change) + sb.WriteString("\n") + } + changes = append(changes, sb.String()) } return changes, manifestChanged diff --git a/internal/apply/planner_test.go b/internal/apply/planner_test.go index cd9ef31..358ae41 100644 --- a/internal/apply/planner_test.go +++ b/internal/apply/planner_test.go @@ -185,6 +185,7 @@ func TestPlanExistingDeploymentNoChanges(t *testing.T) { // Note: We would calculate expected manifest hash here when API supports it // Mock existing app with same manifest hash and outbound connections + manifestContent := "apiVersion: v1\nkind: Pod\nmetadata:\n name: test\n" existingApp := &edgeconnect.App{ Key: edgeconnect.AppKey{ Organization: "testorg", @@ -192,6 +193,7 @@ func TestPlanExistingDeploymentNoChanges(t *testing.T) { Version: "1.0.0", }, Deployment: "kubernetes", + DeploymentManifest: manifestContent, RequiredOutboundConnections: []edgeconnect.SecurityRule{ { Protocol: "tcp", From 97517caceae90a30934bc22ec11fd23ac8cf606f Mon Sep 17 00:00:00 2001 From: Patrick Sy Date: Tue, 7 Oct 2025 16:01:38 +0200 Subject: [PATCH 03/10] refactor(yaml): moved AppVersion into metadata --- internal/apply/manager_test.go | 4 +- internal/apply/planner.go | 7 +-- internal/apply/planner_test.go | 4 +- internal/apply/strategy_recreate.go | 2 +- internal/config/example_test.go | 5 +- internal/config/parser_test.go | 54 ++++++++++++------- internal/config/types.go | 43 ++++----------- .../comprehensive/EdgeConnectConfig.yaml | 2 +- 8 files changed, 57 insertions(+), 64 deletions(-) diff --git a/internal/apply/manager_test.go b/internal/apply/manager_test.go index 17fd027..539e7e0 100644 --- a/internal/apply/manager_test.go +++ b/internal/apply/manager_test.go @@ -137,11 +137,11 @@ func createTestManagerConfig(t *testing.T) *config.EdgeConnectConfig { return &config.EdgeConnectConfig{ Kind: "edgeconnect-deployment", Metadata: config.Metadata{ - Name: "test-app", + Name: "test-app", + AppVersion: "1.0.0", }, Spec: config.Spec{ K8sApp: &config.K8sApp{ - AppVersion: "1.0.0", ManifestFile: manifestFile, }, InfraTemplate: []config.InfraTemplate{ diff --git a/internal/apply/planner.go b/internal/apply/planner.go index 4e2a3e0..c0a9f70 100644 --- a/internal/apply/planner.go +++ b/internal/apply/planner.go @@ -134,7 +134,7 @@ func (p *EdgeConnectPlanner) planAppAction(ctx context.Context, config *config.E // Build desired app state desired := &AppState{ Name: config.Metadata.Name, - Version: config.Spec.GetAppVersion(), + Version: config.Metadata.AppVersion, Organization: config.Spec.InfraTemplate[0].Organization, // Use first infra template for org Region: config.Spec.InfraTemplate[0].Region, // Use first infra template for region Exists: false, // Will be set based on current state @@ -204,6 +204,7 @@ func (p *EdgeConnectPlanner) planAppAction(ctx context.Context, config *config.E action.Type = ActionUpdate action.Changes = changes action.Reason = "Application configuration has changed" + fmt.Printf("Changes: %v\n", changes) if manifestChanged { warnings = append(warnings, "Manifest file has changed - instances may need to be recreated") @@ -219,11 +220,11 @@ func (p *EdgeConnectPlanner) planInstanceActions(ctx context.Context, config *co var warnings []string for _, infra := range config.Spec.InfraTemplate { - instanceName := getInstanceName(config.Metadata.Name, config.Spec.GetAppVersion()) + instanceName := getInstanceName(config.Metadata.Name, config.Metadata.AppVersion) desired := &InstanceState{ Name: instanceName, - AppVersion: config.Spec.GetAppVersion(), + AppVersion: config.Metadata.AppVersion, Organization: infra.Organization, Region: infra.Region, CloudletOrg: infra.CloudletOrg, diff --git a/internal/apply/planner_test.go b/internal/apply/planner_test.go index 358ae41..5568dea 100644 --- a/internal/apply/planner_test.go +++ b/internal/apply/planner_test.go @@ -112,11 +112,11 @@ func createTestConfig(t *testing.T) *config.EdgeConnectConfig { return &config.EdgeConnectConfig{ Kind: "edgeconnect-deployment", Metadata: config.Metadata{ - Name: "test-app", + Name: "test-app", + AppVersion: "1.0.0", }, Spec: config.Spec{ K8sApp: &config.K8sApp{ - AppVersion: "1.0.0", ManifestFile: manifestFile, }, InfraTemplate: []config.InfraTemplate{ diff --git a/internal/apply/strategy_recreate.go b/internal/apply/strategy_recreate.go index da88664..3ac1502 100644 --- a/internal/apply/strategy_recreate.go +++ b/internal/apply/strategy_recreate.go @@ -440,7 +440,7 @@ func (r *RecreateStrategy) createInstance(ctx context.Context, action InstanceAc AppKey: edgeconnect.AppKey{ Organization: action.Target.Organization, Name: config.Metadata.Name, - Version: config.Spec.GetAppVersion(), + Version: config.Metadata.AppVersion, }, Flavor: edgeconnect.Flavor{ Name: action.Target.FlavorName, diff --git a/internal/config/example_test.go b/internal/config/example_test.go index 7219412..7316430 100644 --- a/internal/config/example_test.go +++ b/internal/config/example_test.go @@ -28,7 +28,7 @@ func TestParseExampleConfig(t *testing.T) { // Check k8s app configuration require.NotNil(t, config.Spec.K8sApp) - assert.Equal(t, "1.0.0", config.Spec.K8sApp.AppVersion) + assert.Equal(t, "1.0.0", config.Metadata.AppVersion) // Note: ManifestFile path should be resolved to absolute path assert.Contains(t, config.Spec.K8sApp.ManifestFile, "k8s-deployment.yaml") @@ -59,7 +59,6 @@ func TestParseExampleConfig(t *testing.T) { // Test utility methods assert.Equal(t, "edge-app-demo", config.Metadata.Name) - assert.Equal(t, "1.0.0", config.Spec.GetAppVersion()) assert.Contains(t, config.Spec.GetManifestFile(), "k8s-deployment.yaml") assert.True(t, config.Spec.IsK8sApp()) assert.False(t, config.Spec.IsDockerApp()) @@ -73,10 +72,10 @@ func TestValidateExampleStructure(t *testing.T) { Kind: "edgeconnect-deployment", Metadata: Metadata{ Name: "edge-app-demo", + AppVersion: "1.0.0", }, Spec: Spec{ DockerApp: &DockerApp{ // Use DockerApp to avoid manifest file validation - AppVersion: "1.0.0", Image: "nginx:latest", }, InfraTemplate: []InfraTemplate{ diff --git a/internal/config/parser_test.go b/internal/config/parser_test.go index d5e0865..c713ff5 100644 --- a/internal/config/parser_test.go +++ b/internal/config/parser_test.go @@ -32,9 +32,9 @@ func TestConfigParser_ParseBytes(t *testing.T) { kind: edgeconnect-deployment metadata: name: "test-app" + appVersion: "1.0.0" spec: k8sApp: - appVersion: "1.0.0" manifestFile: "./test-manifest.yaml" infraTemplate: - organization: "testorg" @@ -52,9 +52,9 @@ spec: kind: edgeconnect-deployment metadata: name: "test-app" + appVersion: "1.0.0" spec: dockerApp: - appVersion: "1.0.0" image: "nginx:latest" infraTemplate: - organization: "testorg" @@ -70,9 +70,9 @@ spec: yaml: ` metadata: name: "test-app" + appVersion: "1.0.0" spec: k8sApp: - appVersion: "1.0.0" manifestFile: "./test-manifest.yaml" infraTemplate: - organization: "testorg" @@ -90,9 +90,9 @@ spec: kind: invalid-kind metadata: name: "test-app" + appVersion: "1.0.0" spec: dockerApp: - appVersion: "1.0.0" image: "nginx:latest" infraTemplate: - organization: "testorg" @@ -110,6 +110,7 @@ spec: kind: edgeconnect-deployment metadata: name: "test-app" + appVersion: "1.0.0" spec: infraTemplate: - organization: "testorg" @@ -127,13 +128,12 @@ spec: kind: edgeconnect-deployment metadata: name: "test-app" + appVersion: "1.0.0" spec: k8sApp: - appVersion: "1.0.0" manifestFile: "./test-manifest.yaml" dockerApp: appName: "test-app" - appVersion: "1.0.0" image: "nginx:latest" infraTemplate: - organization: "testorg" @@ -151,9 +151,9 @@ spec: kind: edgeconnect-deployment metadata: name: "test-app" + appVersion: "1.0.0" spec: dockerApp: - appVersion: "1.0.0" image: "nginx:latest" infraTemplate: [] `, @@ -166,9 +166,9 @@ spec: kind: edgeconnect-deployment metadata: name: "test-app" + appVersion: "1.0.0" spec: dockerApp: - appVersion: "1.0.0" image: "nginx:latest" infraTemplate: - organization: "testorg" @@ -222,9 +222,9 @@ func TestConfigParser_ParseFile(t *testing.T) { kind: edgeconnect-deployment metadata: name: "test-app" + appVersion: "1.0.0" spec: dockerApp: - appVersion: "1.0.0" image: "nginx:latest" infraTemplate: - organization: "testorg" @@ -284,9 +284,9 @@ func TestConfigParser_RelativePathResolution(t *testing.T) { kind: edgeconnect-deployment metadata: name: "test-app" + appVersion: "1.0.0" spec: k8sApp: - appVersion: "1.0.0" manifestFile: "./manifest.yaml" infraTemplate: - organization: "testorg" @@ -322,10 +322,10 @@ func TestEdgeConnectConfig_Validate(t *testing.T) { Kind: "edgeconnect-deployment", Metadata: Metadata{ Name: "test-app", + AppVersion: "1.0.0", }, Spec: Spec{ DockerApp: &DockerApp{ - AppVersion: "1.0.0", Image: "nginx:latest", }, InfraTemplate: []InfraTemplate{ @@ -385,24 +385,42 @@ func TestMetadata_Validate(t *testing.T) { }{ { name: "valid metadata", - metadata: Metadata{Name: "test-app"}, + metadata: Metadata{Name: "test-app", AppVersion: "1.0.0"}, wantErr: false, }, { name: "empty name", - metadata: Metadata{Name: ""}, + metadata: Metadata{Name: "", AppVersion: "1.0.0"}, wantErr: true, errMsg: "metadata.name is required", }, { name: "name with leading whitespace", - metadata: Metadata{Name: " test-app"}, + metadata: Metadata{Name: " test-app", AppVersion: "1.0.0"}, wantErr: true, errMsg: "cannot have leading/trailing whitespace", }, { name: "name with trailing whitespace", - metadata: Metadata{Name: "test-app "}, + metadata: Metadata{Name: "test-app ", AppVersion: "1.0.0"}, + wantErr: true, + errMsg: "cannot have leading/trailing whitespace", + }, + { + name: "empty app version", + metadata: Metadata{Name: "test-app", AppVersion: ""}, + wantErr: true, + errMsg: "metadata.appVersion is required", + }, + { + name: "app version with leading whitespace", + metadata: Metadata{Name: "test-app", AppVersion: " 1.0.0"}, + wantErr: true, + errMsg: "cannot have leading/trailing whitespace", + }, + { + name: "app version with trailing whitespace", + metadata: Metadata{Name: "test-app", AppVersion: "1.0.0 "}, wantErr: true, errMsg: "cannot have leading/trailing whitespace", }, @@ -526,24 +544,20 @@ func TestOutboundConnection_Validate(t *testing.T) { func TestSpec_GetMethods(t *testing.T) { k8sSpec := &Spec{ K8sApp: &K8sApp{ - AppVersion: "1.0.0", ManifestFile: "k8s.yaml", }, } dockerSpec := &Spec{ DockerApp: &DockerApp{ - AppVersion: "2.0.0", ManifestFile: "docker.yaml", }, } - assert.Equal(t, "1.0.0", k8sSpec.GetAppVersion()) assert.Equal(t, "k8s.yaml", k8sSpec.GetManifestFile()) assert.True(t, k8sSpec.IsK8sApp()) assert.False(t, k8sSpec.IsDockerApp()) - assert.Equal(t, "2.0.0", dockerSpec.GetAppVersion()) assert.Equal(t, "docker.yaml", dockerSpec.GetManifestFile()) assert.False(t, dockerSpec.IsK8sApp()) assert.True(t, dockerSpec.IsDockerApp()) @@ -564,9 +578,9 @@ func TestReadManifestFile(t *testing.T) { kind: edgeconnect-deployment metadata: name: "test-app" + appVersion: "1.0.0" spec: k8sApp: - appVersion: "1.0.0" manifestFile: "./manifest.yaml" infraTemplate: - organization: "testorg" diff --git a/internal/config/types.go b/internal/config/types.go index 71388d0..88b52b7 100644 --- a/internal/config/types.go +++ b/internal/config/types.go @@ -18,7 +18,8 @@ type EdgeConnectConfig struct { // Metadata contains configuration metadata type Metadata struct { - Name string `yaml:"name"` + Name string `yaml:"name"` + AppVersion string `yaml:"appVersion"` } // Spec defines the application and infrastructure specification @@ -32,13 +33,11 @@ type Spec struct { // K8sApp defines Kubernetes application configuration type K8sApp struct { - AppVersion string `yaml:"appVersion"` ManifestFile string `yaml:"manifestFile"` } // DockerApp defines Docker application configuration type DockerApp struct { - AppVersion string `yaml:"appVersion"` ManifestFile string `yaml:"manifestFile"` Image string `yaml:"image"` } @@ -113,6 +112,15 @@ func (m *Metadata) Validate() error { return fmt.Errorf("metadata.name cannot have leading/trailing whitespace") } + if m.AppVersion == "" { + return fmt.Errorf("metadata.appVersion is required") + } + + // Validate version format + if strings.TrimSpace(m.AppVersion) != m.AppVersion { + return fmt.Errorf("metadata.appVersion cannot have leading/trailing whitespace") + } + return nil } @@ -171,10 +179,6 @@ func (s *Spec) Validate() error { // Validate validates k8s app configuration func (k *K8sApp) Validate() error { - if k.AppVersion == "" { - return fmt.Errorf("appVersion is required") - } - if k.ManifestFile == "" { return fmt.Errorf("manifestFile is required") } @@ -184,29 +188,15 @@ func (k *K8sApp) Validate() error { return fmt.Errorf("manifestFile does not exist: %s", k.ManifestFile) } - // Validate version format - if strings.TrimSpace(k.AppVersion) != k.AppVersion { - return fmt.Errorf("appVersion cannot have leading/trailing whitespace") - } - return nil } // Validate validates docker app configuration func (d *DockerApp) Validate() error { - if d.AppVersion == "" { - return fmt.Errorf("appVersion is required") - } - if d.Image == "" { return fmt.Errorf("image is required") } - // Validate version format - if strings.TrimSpace(d.AppVersion) != d.AppVersion { - return fmt.Errorf("appVersion cannot have leading/trailing whitespace") - } - // Check if manifest file exists if specified if d.ManifestFile != "" { if _, err := os.Stat(d.ManifestFile); os.IsNotExist(err) { @@ -326,17 +316,6 @@ func (d *DockerApp) GetManifestPath(configDir string) string { return filepath.Join(configDir, d.ManifestFile) } -// GetAppVersion returns the application version from the active app type -func (s *Spec) GetAppVersion() string { - if s.K8sApp != nil { - return s.K8sApp.AppVersion - } - if s.DockerApp != nil { - return s.DockerApp.AppVersion - } - return "" -} - // GetManifestFile returns the manifest file path from the active app type func (s *Spec) GetManifestFile() string { if s.K8sApp != nil { diff --git a/sdk/examples/comprehensive/EdgeConnectConfig.yaml b/sdk/examples/comprehensive/EdgeConnectConfig.yaml index 842494a..1430b33 100644 --- a/sdk/examples/comprehensive/EdgeConnectConfig.yaml +++ b/sdk/examples/comprehensive/EdgeConnectConfig.yaml @@ -3,13 +3,13 @@ kind: edgeconnect-deployment metadata: name: "edge-app-demo" # name could be used for appName + appVersion: "1.0.0" spec: # dockerApp: # Docker is OBSOLETE # appVersion: "1.0.0" # manifestFile: "./docker-compose.yaml" # image: "https://registry-1.docker.io/library/nginx:latest" k8sApp: - appVersion: "1.0.0" manifestFile: "./k8s-deployment.yaml" infraTemplate: - organization: "edp2" From fdb931acc2f44e4baf0982ca8d6b50d5b8e77fa4 Mon Sep 17 00:00:00 2001 From: Patrick Sy Date: Tue, 7 Oct 2025 16:08:48 +0200 Subject: [PATCH 04/10] ci: Added test workflow running on each push except tags --- .github/workflows/test.yaml | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) create mode 100644 .github/workflows/test.yaml diff --git a/.github/workflows/test.yaml b/.github/workflows/test.yaml new file mode 100644 index 0000000..5c1cefa --- /dev/null +++ b/.github/workflows/test.yaml @@ -0,0 +1,23 @@ +name: test + +on: + push: + branches: + - '*' + tags-ignore: + - '*' + +jobs: + test: + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v4 + with: + fetch-depth: 0 + - name: Set up Go + uses: actions/setup-go@v6 + with: + go-version: ">=1.25.1" + - name: Test code + run: make test From b958acd94e64c039e0bfda4989539ea53aecc53a Mon Sep 17 00:00:00 2001 From: Patrick Sy Date: Tue, 7 Oct 2025 16:30:57 +0200 Subject: [PATCH 05/10] refactor(yaml): Moved organisation to metadata --- internal/apply/manager.go | 2 +- internal/apply/planner.go | 4 ++-- internal/apply/strategy_recreate.go | 6 +++--- internal/config/types.go | 16 ++++++++-------- .../comprehensive/EdgeConnectConfig.yaml | 4 ++-- 5 files changed, 16 insertions(+), 16 deletions(-) diff --git a/internal/apply/manager.go b/internal/apply/manager.go index 9951ada..45477ab 100644 --- a/internal/apply/manager.go +++ b/internal/apply/manager.go @@ -265,7 +265,7 @@ func (rm *EdgeConnectResourceManager) rollbackInstance(ctx context.Context, acti for _, instanceAction := range plan.InstanceActions { if instanceAction.InstanceName == action.Target { instanceKey := edgeconnect.AppInstanceKey{ - Organization: instanceAction.Target.Organization, + Organization: plan.AppAction.Desired.Organization, Name: instanceAction.InstanceName, CloudletKey: edgeconnect.CloudletKey{ Organization: instanceAction.Target.CloudletOrg, diff --git a/internal/apply/planner.go b/internal/apply/planner.go index c0a9f70..1cbc58d 100644 --- a/internal/apply/planner.go +++ b/internal/apply/planner.go @@ -135,7 +135,7 @@ func (p *EdgeConnectPlanner) planAppAction(ctx context.Context, config *config.E desired := &AppState{ Name: config.Metadata.Name, Version: config.Metadata.AppVersion, - Organization: config.Spec.InfraTemplate[0].Organization, // Use first infra template for org + Organization: config.Metadata.Organization, // Use first infra template for org Region: config.Spec.InfraTemplate[0].Region, // Use first infra template for region Exists: false, // Will be set based on current state } @@ -225,7 +225,7 @@ func (p *EdgeConnectPlanner) planInstanceActions(ctx context.Context, config *co desired := &InstanceState{ Name: instanceName, AppVersion: config.Metadata.AppVersion, - Organization: infra.Organization, + Organization: config.Metadata.Organization, Region: infra.Region, CloudletOrg: infra.CloudletOrg, CloudletName: infra.CloudletName, diff --git a/internal/apply/strategy_recreate.go b/internal/apply/strategy_recreate.go index 3ac1502..b2302ca 100644 --- a/internal/apply/strategy_recreate.go +++ b/internal/apply/strategy_recreate.go @@ -408,7 +408,7 @@ func (r *RecreateStrategy) executeAppActionWithRetry(ctx context.Context, action // deleteInstance deletes an instance (reuse existing logic from manager.go) func (r *RecreateStrategy) deleteInstance(ctx context.Context, action InstanceAction) (bool, error) { instanceKey := edgeconnect.AppInstanceKey{ - Organization: action.Target.Organization, + Organization: action.Desired.Organization, Name: action.InstanceName, CloudletKey: edgeconnect.CloudletKey{ Organization: action.Target.CloudletOrg, @@ -430,7 +430,7 @@ func (r *RecreateStrategy) createInstance(ctx context.Context, action InstanceAc Region: action.Target.Region, AppInst: edgeconnect.AppInstance{ Key: edgeconnect.AppInstanceKey{ - Organization: action.Target.Organization, + Organization: action.Desired.Organization, Name: action.InstanceName, CloudletKey: edgeconnect.CloudletKey{ Organization: action.Target.CloudletOrg, @@ -438,7 +438,7 @@ func (r *RecreateStrategy) createInstance(ctx context.Context, action InstanceAc }, }, AppKey: edgeconnect.AppKey{ - Organization: action.Target.Organization, + Organization: action.Desired.Organization, Name: config.Metadata.Name, Version: config.Metadata.AppVersion, }, diff --git a/internal/config/types.go b/internal/config/types.go index 88b52b7..05d84b7 100644 --- a/internal/config/types.go +++ b/internal/config/types.go @@ -18,8 +18,9 @@ type EdgeConnectConfig struct { // Metadata contains configuration metadata type Metadata struct { - Name string `yaml:"name"` - AppVersion string `yaml:"appVersion"` + Name string `yaml:"name"` + AppVersion string `yaml:"appVersion"` + Organization string `yaml:"organization"` } // Spec defines the application and infrastructure specification @@ -44,7 +45,6 @@ type DockerApp struct { // InfraTemplate defines infrastructure deployment targets type InfraTemplate struct { - Organization string `yaml:"organization"` Region string `yaml:"region"` CloudletOrg string `yaml:"cloudletOrg"` CloudletName string `yaml:"cloudletName"` @@ -121,6 +121,11 @@ func (m *Metadata) Validate() error { return fmt.Errorf("metadata.appVersion cannot have leading/trailing whitespace") } + if m.Organization == "" { + return fmt.Errorf("organization is required") + } + + return nil } @@ -209,10 +214,6 @@ func (d *DockerApp) Validate() error { // Validate validates infrastructure template configuration func (i *InfraTemplate) Validate() error { - if i.Organization == "" { - return fmt.Errorf("organization is required") - } - if i.Region == "" { return fmt.Errorf("region is required") } @@ -231,7 +232,6 @@ func (i *InfraTemplate) Validate() error { // Validate no leading/trailing whitespace fields := map[string]string{ - "organization": i.Organization, "region": i.Region, "cloudletOrg": i.CloudletOrg, "cloudletName": i.CloudletName, diff --git a/sdk/examples/comprehensive/EdgeConnectConfig.yaml b/sdk/examples/comprehensive/EdgeConnectConfig.yaml index 1430b33..b45abc4 100644 --- a/sdk/examples/comprehensive/EdgeConnectConfig.yaml +++ b/sdk/examples/comprehensive/EdgeConnectConfig.yaml @@ -4,6 +4,7 @@ kind: edgeconnect-deployment metadata: name: "edge-app-demo" # name could be used for appName appVersion: "1.0.0" + organization: "edp2" spec: # dockerApp: # Docker is OBSOLETE # appVersion: "1.0.0" @@ -12,8 +13,7 @@ spec: k8sApp: manifestFile: "./k8s-deployment.yaml" infraTemplate: - - organization: "edp2" - region: "EU" + - region: "EU" cloudletOrg: "TelekomOP" cloudletName: "Munich" flavorName: "EU.small" From e04370a3763c511aaab18285953c586c2620a092 Mon Sep 17 00:00:00 2001 From: Richard Robert Reitz Date: Tue, 7 Oct 2025 17:05:35 +0200 Subject: [PATCH 06/10] fix(test): started fixing tests --- internal/config/example_test.go | 3 +-- internal/config/parser_test.go | 48 ++++++++++++++++----------------- 2 files changed, 25 insertions(+), 26 deletions(-) diff --git a/internal/config/example_test.go b/internal/config/example_test.go index 7316430..dfa3840 100644 --- a/internal/config/example_test.go +++ b/internal/config/example_test.go @@ -35,7 +35,6 @@ func TestParseExampleConfig(t *testing.T) { // Check infrastructure template require.Len(t, config.Spec.InfraTemplate, 1) infra := config.Spec.InfraTemplate[0] - assert.Equal(t, "edp2", infra.Organization) assert.Equal(t, "EU", infra.Region) assert.Equal(t, "TelekomOP", infra.CloudletOrg) assert.Equal(t, "Munich", infra.CloudletName) @@ -73,6 +72,7 @@ func TestValidateExampleStructure(t *testing.T) { Metadata: Metadata{ Name: "edge-app-demo", AppVersion: "1.0.0", + Organization: "edp2", }, Spec: Spec{ DockerApp: &DockerApp{ // Use DockerApp to avoid manifest file validation @@ -80,7 +80,6 @@ func TestValidateExampleStructure(t *testing.T) { }, InfraTemplate: []InfraTemplate{ { - Organization: "edp2", Region: "EU", CloudletOrg: "TelekomOP", CloudletName: "Munich", diff --git a/internal/config/parser_test.go b/internal/config/parser_test.go index c713ff5..cb672ae 100644 --- a/internal/config/parser_test.go +++ b/internal/config/parser_test.go @@ -33,12 +33,12 @@ kind: edgeconnect-deployment metadata: name: "test-app" appVersion: "1.0.0" + organization: "testorg" spec: k8sApp: manifestFile: "./test-manifest.yaml" infraTemplate: - - organization: "testorg" - region: "US" + - region: "US" cloudletOrg: "TestOP" cloudletName: "TestCloudlet" flavorName: "small" @@ -53,12 +53,12 @@ kind: edgeconnect-deployment metadata: name: "test-app" appVersion: "1.0.0" + organization: "testorg" spec: dockerApp: image: "nginx:latest" infraTemplate: - - organization: "testorg" - region: "US" + - region: "US" cloudletOrg: "TestOP" cloudletName: "TestCloudlet" flavorName: "small" @@ -71,12 +71,12 @@ spec: metadata: name: "test-app" appVersion: "1.0.0" + organization: "testorg" spec: k8sApp: manifestFile: "./test-manifest.yaml" infraTemplate: - - organization: "testorg" - region: "US" + - region: "US" cloudletOrg: "TestOP" cloudletName: "TestCloudlet" flavorName: "small" @@ -91,12 +91,12 @@ kind: invalid-kind metadata: name: "test-app" appVersion: "1.0.0" + organization: "testorg" spec: dockerApp: image: "nginx:latest" infraTemplate: - - organization: "testorg" - region: "US" + - region: "US" cloudletOrg: "TestOP" cloudletName: "TestCloudlet" flavorName: "small" @@ -111,10 +111,10 @@ kind: edgeconnect-deployment metadata: name: "test-app" appVersion: "1.0.0" + organization: "testorg" spec: infraTemplate: - - organization: "testorg" - region: "US" + - region: "US" cloudletOrg: "TestOP" cloudletName: "TestCloudlet" flavorName: "small" @@ -129,6 +129,7 @@ kind: edgeconnect-deployment metadata: name: "test-app" appVersion: "1.0.0" + organization: "testorg" spec: k8sApp: manifestFile: "./test-manifest.yaml" @@ -136,8 +137,7 @@ spec: appName: "test-app" image: "nginx:latest" infraTemplate: - - organization: "testorg" - region: "US" + - region: "US" cloudletOrg: "TestOP" cloudletName: "TestCloudlet" flavorName: "small" @@ -167,12 +167,12 @@ kind: edgeconnect-deployment metadata: name: "test-app" appVersion: "1.0.0" + organization: "testorg" spec: dockerApp: image: "nginx:latest" infraTemplate: - - organization: "testorg" - region: "US" + - region: "US" cloudletOrg: "TestOP" cloudletName: "TestCloudlet" flavorName: "small" @@ -223,12 +223,12 @@ kind: edgeconnect-deployment metadata: name: "test-app" appVersion: "1.0.0" + organization: "testorg" spec: dockerApp: image: "nginx:latest" infraTemplate: - - organization: "testorg" - region: "US" + - region: "US" cloudletOrg: "TestOP" cloudletName: "TestCloudlet" flavorName: "small" @@ -285,12 +285,12 @@ kind: edgeconnect-deployment metadata: name: "test-app" appVersion: "1.0.0" + organization: "testorg" spec: k8sApp: manifestFile: "./manifest.yaml" infraTemplate: - - organization: "testorg" - region: "US" + - region: "US" cloudletOrg: "TestOP" cloudletName: "TestCloudlet" flavorName: "small" @@ -321,16 +321,16 @@ func TestEdgeConnectConfig_Validate(t *testing.T) { config: EdgeConnectConfig{ Kind: "edgeconnect-deployment", Metadata: Metadata{ - Name: "test-app", - AppVersion: "1.0.0", + Name: "test-app", + AppVersion: "1.0.0", + Organization: "testorg", }, Spec: Spec{ DockerApp: &DockerApp{ - Image: "nginx:latest", + Image: "nginx:latest", }, InfraTemplate: []InfraTemplate{ { - Organization: "testorg", Region: "US", CloudletOrg: "TestOP", CloudletName: "TestCloudlet", @@ -579,12 +579,12 @@ kind: edgeconnect-deployment metadata: name: "test-app" appVersion: "1.0.0" + organization: "testorg" spec: k8sApp: manifestFile: "./manifest.yaml" infraTemplate: - - organization: "testorg" - region: "US" + - region: "US" cloudletOrg: "TestOP" cloudletName: "TestCloudlet" flavorName: "small" From 6a91b556a58d91f0e9901d85170ccd1dbf856b5e Mon Sep 17 00:00:00 2001 From: Richard Robert Reitz Date: Tue, 7 Oct 2025 17:09:36 +0200 Subject: [PATCH 07/10] fix(test): fixed compile errors --- internal/apply/manager_test.go | 9 +++------ internal/apply/planner_test.go | 9 ++++----- 2 files changed, 7 insertions(+), 11 deletions(-) diff --git a/internal/apply/manager_test.go b/internal/apply/manager_test.go index 539e7e0..6060a37 100644 --- a/internal/apply/manager_test.go +++ b/internal/apply/manager_test.go @@ -110,7 +110,6 @@ func createTestDeploymentPlan() *DeploymentPlan { { Type: ActionCreate, Target: config.InfraTemplate{ - Organization: "testorg", Region: "US", CloudletOrg: "cloudletorg", CloudletName: "cloudlet1", @@ -137,8 +136,9 @@ func createTestManagerConfig(t *testing.T) *config.EdgeConnectConfig { return &config.EdgeConnectConfig{ Kind: "edgeconnect-deployment", Metadata: config.Metadata{ - Name: "test-app", - AppVersion: "1.0.0", + Name: "test-app", + AppVersion: "1.0.0", + Organization: "testorg", }, Spec: config.Spec{ K8sApp: &config.K8sApp{ @@ -146,7 +146,6 @@ func createTestManagerConfig(t *testing.T) *config.EdgeConnectConfig { }, InfraTemplate: []config.InfraTemplate{ { - Organization: "testorg", Region: "US", CloudletOrg: "cloudletorg", CloudletName: "cloudlet1", @@ -309,7 +308,6 @@ func TestApplyDeploymentMultipleInstances(t *testing.T) { { Type: ActionCreate, Target: config.InfraTemplate{ - Organization: "testorg", Region: "US", CloudletOrg: "cloudletorg1", CloudletName: "cloudlet1", @@ -321,7 +319,6 @@ func TestApplyDeploymentMultipleInstances(t *testing.T) { { Type: ActionCreate, Target: config.InfraTemplate{ - Organization: "testorg", Region: "EU", CloudletOrg: "cloudletorg2", CloudletName: "cloudlet2", diff --git a/internal/apply/planner_test.go b/internal/apply/planner_test.go index 5568dea..d946a14 100644 --- a/internal/apply/planner_test.go +++ b/internal/apply/planner_test.go @@ -112,8 +112,9 @@ func createTestConfig(t *testing.T) *config.EdgeConnectConfig { return &config.EdgeConnectConfig{ Kind: "edgeconnect-deployment", Metadata: config.Metadata{ - Name: "test-app", - AppVersion: "1.0.0", + Name: "test-app", + AppVersion: "1.0.0", + Organization: "testorg", }, Spec: config.Spec{ K8sApp: &config.K8sApp{ @@ -121,7 +122,6 @@ func createTestConfig(t *testing.T) *config.EdgeConnectConfig { }, InfraTemplate: []config.InfraTemplate{ { - Organization: "testorg", Region: "US", CloudletOrg: "TestCloudletOrg", CloudletName: "TestCloudlet", @@ -192,7 +192,7 @@ func TestPlanExistingDeploymentNoChanges(t *testing.T) { Name: "test-app", Version: "1.0.0", }, - Deployment: "kubernetes", + Deployment: "kubernetes", DeploymentManifest: manifestContent, RequiredOutboundConnections: []edgeconnect.SecurityRule{ { @@ -286,7 +286,6 @@ func TestPlanMultipleInfrastructures(t *testing.T) { // Add a second infrastructure target testConfig.Spec.InfraTemplate = append(testConfig.Spec.InfraTemplate, config.InfraTemplate{ - Organization: "testorg", Region: "EU", CloudletOrg: "EUCloudletOrg", CloudletName: "EUCloudlet", From ce2fb4208dafd8fb6a0ac9a30e80b9a18eca589f Mon Sep 17 00:00:00 2001 From: Richard Robert Reitz Date: Tue, 7 Oct 2025 17:19:52 +0200 Subject: [PATCH 08/10] fix(test): finish fixing organisation refactoring tests failures --- internal/config/parser_test.go | 33 ++++++++++++++++++++++++++------- internal/config/types.go | 5 ++++- 2 files changed, 30 insertions(+), 8 deletions(-) diff --git a/internal/config/parser_test.go b/internal/config/parser_test.go index cb672ae..7e9cd61 100644 --- a/internal/config/parser_test.go +++ b/internal/config/parser_test.go @@ -152,6 +152,7 @@ kind: edgeconnect-deployment metadata: name: "test-app" appVersion: "1.0.0" + organization: "testorg" spec: dockerApp: image: "nginx:latest" @@ -385,42 +386,60 @@ func TestMetadata_Validate(t *testing.T) { }{ { name: "valid metadata", - metadata: Metadata{Name: "test-app", AppVersion: "1.0.0"}, + metadata: Metadata{Name: "test-app", AppVersion: "1.0.0", Organization: "testorg"}, wantErr: false, }, { name: "empty name", - metadata: Metadata{Name: "", AppVersion: "1.0.0"}, + metadata: Metadata{Name: "", AppVersion: "1.0.0", Organization: "testorg"}, wantErr: true, errMsg: "metadata.name is required", }, { name: "name with leading whitespace", - metadata: Metadata{Name: " test-app", AppVersion: "1.0.0"}, + metadata: Metadata{Name: " test-app", AppVersion: "1.0.0", Organization: "testorg"}, wantErr: true, errMsg: "cannot have leading/trailing whitespace", }, { name: "name with trailing whitespace", - metadata: Metadata{Name: "test-app ", AppVersion: "1.0.0"}, + metadata: Metadata{Name: "test-app ", AppVersion: "1.0.0", Organization: "testorg"}, wantErr: true, errMsg: "cannot have leading/trailing whitespace", }, { name: "empty app version", - metadata: Metadata{Name: "test-app", AppVersion: ""}, + metadata: Metadata{Name: "test-app", AppVersion: "", Organization: "testorg"}, wantErr: true, errMsg: "metadata.appVersion is required", }, { name: "app version with leading whitespace", - metadata: Metadata{Name: "test-app", AppVersion: " 1.0.0"}, + metadata: Metadata{Name: "test-app", AppVersion: " 1.0.0", Organization: "testorg"}, wantErr: true, errMsg: "cannot have leading/trailing whitespace", }, { name: "app version with trailing whitespace", - metadata: Metadata{Name: "test-app", AppVersion: "1.0.0 "}, + metadata: Metadata{Name: "test-app", AppVersion: "1.0.0 ", Organization: "testorg"}, + wantErr: true, + errMsg: "cannot have leading/trailing whitespace", + }, + { + name: "empty organization", + metadata: Metadata{Name: "test-app", AppVersion: "1.0.0", Organization: ""}, + wantErr: true, + errMsg: "metadata.organization is required", + }, + { + name: "organization with leading whitespace", + metadata: Metadata{Name: "test-app", AppVersion: "1.0.0", Organization: " testorg"}, + wantErr: true, + errMsg: "cannot have leading/trailing whitespace", + }, + { + name: "organization with trailing whitespace", + metadata: Metadata{Name: "test-app", AppVersion: "1.0.0", Organization: "testorg "}, wantErr: true, errMsg: "cannot have leading/trailing whitespace", }, diff --git a/internal/config/types.go b/internal/config/types.go index 05d84b7..665d873 100644 --- a/internal/config/types.go +++ b/internal/config/types.go @@ -122,9 +122,12 @@ func (m *Metadata) Validate() error { } if m.Organization == "" { - return fmt.Errorf("organization is required") + return fmt.Errorf("metadata.organization is required") } + if strings.TrimSpace(m.Organization) != m.Organization { + return fmt.Errorf("metadata.Organization cannot have leading/trailing whitespace") + } return nil } From ce801f30d0c598292850ecc6c5244e4e72caf5b6 Mon Sep 17 00:00:00 2001 From: Richard Robert Reitz Date: Tue, 7 Oct 2025 17:21:38 +0200 Subject: [PATCH 09/10] fix(test): finish fixing organisation refactoring tests failures --- internal/config/types.go | 1 - 1 file changed, 1 deletion(-) diff --git a/internal/config/types.go b/internal/config/types.go index 665d873..9b365dd 100644 --- a/internal/config/types.go +++ b/internal/config/types.go @@ -116,7 +116,6 @@ func (m *Metadata) Validate() error { return fmt.Errorf("metadata.appVersion is required") } - // Validate version format if strings.TrimSpace(m.AppVersion) != m.AppVersion { return fmt.Errorf("metadata.appVersion cannot have leading/trailing whitespace") } From da3c4a3e4c5c5879a2b20eb5b97199007a07f135 Mon Sep 17 00:00:00 2001 From: Patrick Sy Date: Thu, 13 Nov 2025 15:40:36 +0100 Subject: [PATCH 10/10] feat(api): Added AppKey property to ShowAppInstances --- cmd/instance.go | 5 ++++- internal/apply/planner.go | 15 +++++++++------ internal/apply/planner_test.go | 10 +--------- sdk/edgeconnect/appinstance.go | 4 ++-- sdk/edgeconnect/appinstance_test.go | 5 ++++- sdk/examples/comprehensive/main.go | 6 +++--- 6 files changed, 23 insertions(+), 22 deletions(-) diff --git a/cmd/instance.go b/cmd/instance.go index de22062..15a17d9 100644 --- a/cmd/instance.go +++ b/cmd/instance.go @@ -14,6 +14,7 @@ var ( cloudletOrg string instanceName string flavorName string + appId string ) var appInstanceCmd = &cobra.Command{ @@ -71,8 +72,9 @@ var showInstanceCmd = &cobra.Command{ Name: cloudletName, }, } + appkey := edgeconnect.AppKey{Name: appId} - instance, err := c.ShowAppInstance(context.Background(), instanceKey, region) + instance, err := c.ShowAppInstance(context.Background(), instanceKey, appkey, region) if err != nil { fmt.Printf("Error showing app instance: %v\n", err) os.Exit(1) @@ -142,6 +144,7 @@ func init() { cmd.Flags().StringVarP(&cloudletName, "cloudlet", "c", "", "cloudlet name (required)") cmd.Flags().StringVarP(&cloudletOrg, "cloudlet-org", "", "", "cloudlet organization (required)") cmd.Flags().StringVarP(®ion, "region", "r", "", "region (required)") + cmd.Flags().StringVarP(&appId, "app-id", "i", "", "application id") cmd.MarkFlagRequired("org") cmd.MarkFlagRequired("name") diff --git a/internal/apply/planner.go b/internal/apply/planner.go index 1cbc58d..5ae35ef 100644 --- a/internal/apply/planner.go +++ b/internal/apply/planner.go @@ -21,7 +21,7 @@ type EdgeConnectClientInterface interface { CreateApp(ctx context.Context, input *edgeconnect.NewAppInput) error UpdateApp(ctx context.Context, input *edgeconnect.UpdateAppInput) error DeleteApp(ctx context.Context, appKey edgeconnect.AppKey, region string) error - ShowAppInstance(ctx context.Context, instanceKey edgeconnect.AppInstanceKey, region string) (edgeconnect.AppInstance, error) + ShowAppInstance(ctx context.Context, instanceKey edgeconnect.AppInstanceKey, appKey edgeconnect.AppKey, region string) (edgeconnect.AppInstance, error) CreateAppInstance(ctx context.Context, input *edgeconnect.NewAppInstanceInput) error UpdateAppInstance(ctx context.Context, input *edgeconnect.UpdateAppInstanceInput) error DeleteAppInstance(ctx context.Context, instanceKey edgeconnect.AppInstanceKey, region string) error @@ -135,9 +135,9 @@ func (p *EdgeConnectPlanner) planAppAction(ctx context.Context, config *config.E desired := &AppState{ Name: config.Metadata.Name, Version: config.Metadata.AppVersion, - Organization: config.Metadata.Organization, // Use first infra template for org - Region: config.Spec.InfraTemplate[0].Region, // Use first infra template for region - Exists: false, // Will be set based on current state + Organization: config.Metadata.Organization, // Use first infra template for org + Region: config.Spec.InfraTemplate[0].Region, // Use first infra template for region + Exists: false, // Will be set based on current state } if config.Spec.IsK8sApp() { @@ -347,8 +347,11 @@ func (p *EdgeConnectPlanner) getCurrentInstanceState(ctx context.Context, desire Name: desired.CloudletName, }, } + appKey := edgeconnect.AppKey{ + Name: desired.AppName, + } - instance, err := p.client.ShowAppInstance(timeoutCtx, instanceKey, desired.Region) + instance, err := p.client.ShowAppInstance(timeoutCtx, instanceKey, appKey, desired.Region) if err != nil { return nil, err } @@ -392,7 +395,7 @@ func (p *EdgeConnectPlanner) compareAppStates(current, desired *AppState) ([]str // Compare outbound connections outboundChanges := p.compareOutboundConnections(current.OutboundConnections, desired.OutboundConnections) if len(outboundChanges) > 0 { - sb:= strings.Builder{} + sb := strings.Builder{} sb.WriteString("Outbound connections changed:\n") for _, change := range outboundChanges { sb.WriteString(change) diff --git a/internal/apply/planner_test.go b/internal/apply/planner_test.go index d946a14..88de968 100644 --- a/internal/apply/planner_test.go +++ b/internal/apply/planner_test.go @@ -29,7 +29,7 @@ func (m *MockEdgeConnectClient) ShowApp(ctx context.Context, appKey edgeconnect. return args.Get(0).(edgeconnect.App), args.Error(1) } -func (m *MockEdgeConnectClient) ShowAppInstance(ctx context.Context, instanceKey edgeconnect.AppInstanceKey, region string) (edgeconnect.AppInstance, error) { +func (m *MockEdgeConnectClient) ShowAppInstance(ctx context.Context, instanceKey edgeconnect.AppInstanceKey, appKey edgeconnect.AppKey, region string) (edgeconnect.AppInstance, error) { args := m.Called(ctx, instanceKey, region) if args.Get(0) == nil { return edgeconnect.AppInstance{}, args.Error(1) @@ -75,14 +75,6 @@ func (m *MockEdgeConnectClient) ShowApps(ctx context.Context, appKey edgeconnect return args.Get(0).([]edgeconnect.App), args.Error(1) } -func (m *MockEdgeConnectClient) ShowAppInstances(ctx context.Context, instanceKey edgeconnect.AppInstanceKey, region string) ([]edgeconnect.AppInstance, error) { - args := m.Called(ctx, instanceKey, region) - if args.Get(0) == nil { - return nil, args.Error(1) - } - return args.Get(0).([]edgeconnect.AppInstance), args.Error(1) -} - func TestNewPlanner(t *testing.T) { mockClient := &MockEdgeConnectClient{} planner := NewPlanner(mockClient) diff --git a/sdk/edgeconnect/appinstance.go b/sdk/edgeconnect/appinstance.go index 8d568a8..713a9b0 100644 --- a/sdk/edgeconnect/appinstance.go +++ b/sdk/edgeconnect/appinstance.go @@ -36,12 +36,12 @@ func (c *Client) CreateAppInstance(ctx context.Context, input *NewAppInstanceInp // ShowAppInstance retrieves a single application instance by key and region // Maps to POST /auth/ctrl/ShowAppInst -func (c *Client) ShowAppInstance(ctx context.Context, appInstKey AppInstanceKey, region string) (AppInstance, error) { +func (c *Client) ShowAppInstance(ctx context.Context, appInstKey AppInstanceKey, appKey AppKey, region string) (AppInstance, error) { transport := c.getTransport() url := c.BaseURL + "/api/v1/auth/ctrl/ShowAppInst" filter := AppInstanceFilter{ - AppInstance: AppInstance{Key: appInstKey}, + AppInstance: AppInstance{AppKey: appKey, Key: appInstKey}, Region: region, } diff --git a/sdk/edgeconnect/appinstance_test.go b/sdk/edgeconnect/appinstance_test.go index fc8bfc4..df79803 100644 --- a/sdk/edgeconnect/appinstance_test.go +++ b/sdk/edgeconnect/appinstance_test.go @@ -101,6 +101,7 @@ func TestCreateAppInstance(t *testing.T) { func TestShowAppInstance(t *testing.T) { tests := []struct { name string + appKey AppKey appInstKey AppInstanceKey region string mockStatusCode int @@ -118,6 +119,7 @@ func TestShowAppInstance(t *testing.T) { Name: "testcloudlet", }, }, + appKey: AppKey{Name: "test-app-id"}, region: "us-west", mockStatusCode: 200, mockResponse: `{"data": {"key": {"organization": "testorg", "name": "testinst", "cloudlet_key": {"organization": "cloudletorg", "name": "testcloudlet"}}, "state": "Ready"}} @@ -135,6 +137,7 @@ func TestShowAppInstance(t *testing.T) { Name: "testcloudlet", }, }, + appKey: AppKey{Name: "test-app-id"}, region: "us-west", mockStatusCode: 404, mockResponse: "", @@ -164,7 +167,7 @@ func TestShowAppInstance(t *testing.T) { // Execute test ctx := context.Background() - appInst, err := client.ShowAppInstance(ctx, tt.appInstKey, tt.region) + appInst, err := client.ShowAppInstance(ctx, tt.appInstKey, tt.appKey, tt.region) // Verify results if tt.expectError { diff --git a/sdk/examples/comprehensive/main.go b/sdk/examples/comprehensive/main.go index 616279f..e85845c 100644 --- a/sdk/examples/comprehensive/main.go +++ b/sdk/examples/comprehensive/main.go @@ -193,7 +193,7 @@ func runComprehensiveWorkflow(ctx context.Context, c *edgeconnect.Client, config }, } - instanceDetails, err := waitForInstanceReady(ctx, c, instanceKey, config.Region, 5*time.Minute) + instanceDetails, err := waitForInstanceReady(ctx, c, instanceKey, edgeconnect.AppKey{}, config.Region, 5*time.Minute) if err != nil { return fmt.Errorf("failed to wait for instance ready: %w", err) } @@ -306,7 +306,7 @@ func getEnvOrDefault(key, defaultValue string) string { } // waitForInstanceReady polls the instance status until it's no longer "Creating" or timeout -func waitForInstanceReady(ctx context.Context, c *edgeconnect.Client, instanceKey edgeconnect.AppInstanceKey, region string, timeout time.Duration) (edgeconnect.AppInstance, error) { +func waitForInstanceReady(ctx context.Context, c *edgeconnect.Client, instanceKey edgeconnect.AppInstanceKey, appKey edgeconnect.AppKey, region string, timeout time.Duration) (edgeconnect.AppInstance, error) { timeoutCtx, cancel := context.WithTimeout(ctx, timeout) defer cancel() @@ -321,7 +321,7 @@ func waitForInstanceReady(ctx context.Context, c *edgeconnect.Client, instanceKe return edgeconnect.AppInstance{}, fmt.Errorf("timeout waiting for instance to be ready after %v", timeout) case <-ticker.C: - instance, err := c.ShowAppInstance(timeoutCtx, instanceKey, region) + instance, err := c.ShowAppInstance(timeoutCtx, instanceKey, appKey, region) if err != nil { // Log error but continue polling fmt.Printf(" ⚠️ Error checking instance state: %v\n", err)