diff --git a/comprehensive b/comprehensive deleted file mode 100755 index d780051..0000000 Binary files a/comprehensive and /dev/null differ diff --git a/internal/apply/v2/planner.go b/internal/apply/v2/planner.go index 7253977..797a411 100644 --- a/internal/apply/v2/planner.go +++ b/internal/apply/v2/planner.go @@ -360,6 +360,7 @@ func (p *EdgeConnectPlanner) getCurrentInstanceState(ctx context.Context, desire CloudletName: instance.Key.CloudletKey.Name, FlavorName: instance.Flavor.Name, State: instance.State, + PowerState: instance.PowerState, Exists: true, LastUpdated: time.Now(), // EdgeConnect doesn't provide this } diff --git a/internal/apply/v2/planner_test.go b/internal/apply/v2/planner_test.go index fb390dd..3fbdbc3 100644 --- a/internal/apply/v2/planner_test.go +++ b/internal/apply/v2/planner_test.go @@ -223,7 +223,8 @@ func TestPlanExistingDeploymentNoChanges(t *testing.T) { Flavor: v2.Flavor{ Name: "small", }, - State: "Ready", + State: "Ready", + PowerState: "PowerOn", } mockClient.On("ShowApp", mock.Anything, mock.AnythingOfType("v2.AppKey"), "US"). diff --git a/internal/apply/v2/types.go b/internal/apply/v2/types.go index c7ca07c..26d998e 100644 --- a/internal/apply/v2/types.go +++ b/internal/apply/v2/types.go @@ -170,6 +170,9 @@ type InstanceState struct { // State of the instance (e.g., "Ready", "Pending", "Error") State string + // PowerState of the instance + PowerState string + // LastUpdated timestamp when the instance was last modified LastUpdated time.Time diff --git a/sdk/edgeconnect/appinstance.go b/sdk/edgeconnect/appinstance.go index a4e70f5..34e3486 100644 --- a/sdk/edgeconnect/appinstance.go +++ b/sdk/edgeconnect/appinstance.go @@ -213,20 +213,10 @@ func (c *Client) parseStreamingAppInstanceResponse(resp *http.Response, result i var errorMessage string parseErr := sdkhttp.ParseJSONLines(resp.Body, func(line []byte) error { - if len(line) == 0 { + // On permission denied, Edge API returns just an empty array []! + if len(line) == 0 || line[0] == '[' { return fmt.Errorf("%w", ErrFaultyResponsePerhaps403) } - - // Handle array responses (current API format) - if line[0] == '[' { - var directInstances []AppInstance - if err := json.Unmarshal(line, &directInstances); err != nil { - return err - } - appInstances = append(appInstances, directInstances...) - return nil - } - // Try parsing as ResultResponse first (error format) var resultResp ResultResponse if err := json.Unmarshal(line, &resultResp); err == nil && resultResp.Result.Message != "" { @@ -238,7 +228,7 @@ func (c *Client) parseStreamingAppInstanceResponse(resp *http.Response, result i return nil } - // Try parsing as Response[AppInstance] (legacy streaming format) + // Try parsing as Response[AppInstance] var response Response[AppInstance] if err := json.Unmarshal(line, &response); err != nil { return err diff --git a/sdk/edgeconnect/apps.go b/sdk/edgeconnect/apps.go index e2c4c07..a086475 100644 --- a/sdk/edgeconnect/apps.go +++ b/sdk/edgeconnect/apps.go @@ -180,23 +180,10 @@ func (c *Client) parseStreamingResponse(resp *http.Response, result interface{}) var responses []Response[App] parseErr := sdkhttp.ParseJSONLines(resp.Body, func(line []byte) error { - if len(line) == 0 { + // On permission denied, Edge API returns just an empty array []! + if len(line) == 0 || line[0] == '[' { return fmt.Errorf("%w", ErrFaultyResponsePerhaps403) } - - // Handle array responses (current API format) - if line[0] == '[' { - var directApps []App - if err := json.Unmarshal(line, &directApps); err != nil { - return err - } - for _, app := range directApps { - responses = append(responses, Response[App]{Data: app}) - } - return nil - } - - // Try parsing as Response[App] (legacy streaming format) var response Response[App] if err := json.Unmarshal(line, &response); err != nil { return err diff --git a/sdk/edgeconnect/cloudlet.go b/sdk/edgeconnect/cloudlet.go index 6885539..142b9d6 100644 --- a/sdk/edgeconnect/cloudlet.go +++ b/sdk/edgeconnect/cloudlet.go @@ -229,23 +229,6 @@ func (c *Client) parseStreamingCloudletResponse(resp *http.Response, result inte var responses []Response[Cloudlet] parseErr := sdkhttp.ParseJSONLines(resp.Body, func(line []byte) error { - if len(line) == 0 { - return fmt.Errorf("%w", ErrFaultyResponsePerhaps403) - } - - // Handle array responses (current API format) - if line[0] == '[' { - var directCloudlets []Cloudlet - if err := json.Unmarshal(line, &directCloudlets); err != nil { - return err - } - for _, cl := range directCloudlets { - responses = append(responses, Response[Cloudlet]{Data: cl}) - } - return nil - } - - // Try parsing as Response[Cloudlet] (legacy streaming format) var response Response[Cloudlet] if err := json.Unmarshal(line, &response); err != nil { return err diff --git a/sdk/edgeconnect/v2/appinstance_test.go b/sdk/edgeconnect/v2/appinstance_test.go index ec31c17..04df669 100644 --- a/sdk/edgeconnect/v2/appinstance_test.go +++ b/sdk/edgeconnect/v2/appinstance_test.go @@ -300,7 +300,8 @@ func TestUpdateAppInstance(t *testing.T) { Name: "testapp", Version: "1.0.0", }, - Flavor: Flavor{Name: "m4.medium"}, + Flavor: Flavor{Name: "m4.medium"}, + PowerState: "PowerOn", }, }, mockStatusCode: 200, diff --git a/sdk/edgeconnect/v2/types.go b/sdk/edgeconnect/v2/types.go index ccae8b4..cdaa1ac 100644 --- a/sdk/edgeconnect/v2/types.go +++ b/sdk/edgeconnect/v2/types.go @@ -113,6 +113,7 @@ const ( AppInstFieldConfigsKind = "27.1" AppInstFieldConfigsConfig = "27.2" AppInstFieldHealthCheck = "29" + AppInstFieldPowerState = "31" AppInstFieldExternalVolumeSize = "32" AppInstFieldAvailabilityZone = "33" AppInstFieldVmFlavor = "34" @@ -200,6 +201,7 @@ type App struct { GlobalID string `json:"global_id,omitempty"` CreatedAt string `json:"created_at,omitempty"` UpdatedAt string `json:"updated_at,omitempty"` + Fields []string `json:"fields,omitempty"` } // AppInstance represents a deployed application instance @@ -214,6 +216,8 @@ type AppInstance struct { UniqueID string `json:"unique_id,omitempty"` CreatedAt string `json:"created_at,omitempty"` UpdatedAt string `json:"updated_at,omitempty"` + PowerState string `json:"power_state,omitempty"` + Fields []string `json:"fields,omitempty"` } // Cloudlet represents edge infrastructure diff --git a/sdk/examples/comprehensive/main.go b/sdk/examples/comprehensive/main.go index 02a0730..77c1980 100644 --- a/sdk/examples/comprehensive/main.go +++ b/sdk/examples/comprehensive/main.go @@ -203,6 +203,7 @@ func runComprehensiveWorkflow(ctx context.Context, c *v2.Client, config Workflow fmt.Printf(" • Cloudlet: %s/%s\n", instanceDetails.Key.CloudletKey.Organization, instanceDetails.Key.CloudletKey.Name) fmt.Printf(" • Flavor: %s\n", instanceDetails.Flavor.Name) fmt.Printf(" • State: %s\n", instanceDetails.State) + fmt.Printf(" • Power State: %s\n", instanceDetails.PowerState) // 6. List Application Instances fmt.Println("\n6️⃣ Listing application instances...") @@ -327,7 +328,11 @@ func waitForInstanceReady(ctx context.Context, c *v2.Client, instanceKey v2.AppI continue } - fmt.Printf(" 📊 Instance state: %s\n", instance.State) + fmt.Printf(" 📊 Instance state: %s", instance.State) + if instance.PowerState != "" { + fmt.Printf(" (power: %s)", instance.PowerState) + } + fmt.Printf("\n") // Check if instance is ready (not in creating state) state := strings.ToLower(instance.State)