feat(sdk): ✨ Implement EdgeXR Master Controller Go SDK foundation
Phase 1 Implementation - Core SDK foundation with typed APIs: ## New Components Added: - **SDK Package Structure**: `/sdk/client`, `/sdk/internal/http`, `/sdk/examples` - **Core Types**: App, AppInstance, Cloudlet with JSON marshaling - **HTTP Transport**: Resilient HTTP client with go-retryablehttp - **Auth System**: Pluggable providers (StaticToken, NoAuth) - **Client**: Configurable SDK client with retry and logging options ## API Implementation: - **App Management**: CreateApp, ShowApp, ShowApps, DeleteApp - **Error Handling**: Structured APIError with status codes and messages - **Response Parsing**: EdgeXR streaming JSON response support - **Context Support**: All APIs accept context.Context for timeouts/cancellation ## Testing & Examples: - **Unit Tests**: Comprehensive test suite with httptest mock servers - **Example App**: Complete app lifecycle demonstration in examples/deploy_app.go - **Test Coverage**: Create, show, list, delete operations with error conditions ## Build Infrastructure: - **Makefile**: Automated code generation, testing, and building - **Dependencies**: Added go-retryablehttp, testify, oapi-codegen - **Configuration**: oapi-codegen.yaml for type generation ## API Mapping: - CreateApp → POST /auth/ctrl/CreateApp - ShowApp → POST /auth/ctrl/ShowApp - DeleteApp → POST /auth/ctrl/DeleteApp Following existing prototype patterns while adding type safety, retry logic, and comprehensive error handling. Ready for Phase 2 AppInstance APIs. 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
parent
a71f35163c
commit
9a06c608b2
32 changed files with 14733 additions and 7 deletions
119
sdk/examples/deploy_app.go
Normal file
119
sdk/examples/deploy_app.go
Normal file
|
|
@ -0,0 +1,119 @@
|
|||
// ABOUTME: Example demonstrating EdgeXR SDK usage for app deployment workflow
|
||||
// ABOUTME: Shows app creation, querying, and cleanup using the typed SDK APIs
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"log"
|
||||
"net/http"
|
||||
"os"
|
||||
"time"
|
||||
|
||||
"edp.buildth.ing/DevFW-CICD/edge-connect-client/sdk/client"
|
||||
)
|
||||
|
||||
func main() {
|
||||
// Configure SDK client
|
||||
baseURL := getEnvOrDefault("EDGEXR_BASE_URL", "https://hub.apps.edge.platform.mg3.mdb.osc.live/api/v1")
|
||||
token := getEnvOrDefault("EDGEXR_TOKEN", "")
|
||||
|
||||
if token == "" {
|
||||
log.Fatal("EDGEXR_TOKEN environment variable is required")
|
||||
}
|
||||
|
||||
// Create SDK client with authentication and logging
|
||||
client := client.NewClient(baseURL,
|
||||
client.WithHTTPClient(&http.Client{Timeout: 30 * time.Second}),
|
||||
client.WithAuthProvider(client.NewStaticTokenProvider(token)),
|
||||
client.WithLogger(log.Default()),
|
||||
)
|
||||
|
||||
ctx := context.Background()
|
||||
|
||||
// Example application to deploy
|
||||
app := &client.NewAppInput{
|
||||
Region: "us-west",
|
||||
App: client.App{
|
||||
Key: client.AppKey{
|
||||
Organization: "myorg",
|
||||
Name: "my-edge-app",
|
||||
Version: "1.0.0",
|
||||
},
|
||||
Deployment: "kubernetes",
|
||||
ImageType: "ImageTypeDocker",
|
||||
ImagePath: "nginx:latest",
|
||||
DefaultFlavor: client.Flavor{Name: "m4.small"},
|
||||
},
|
||||
}
|
||||
|
||||
// Demonstrate app lifecycle
|
||||
if err := demonstrateAppLifecycle(ctx, client, app); err != nil {
|
||||
log.Fatalf("App lifecycle demonstration failed: %v", err)
|
||||
}
|
||||
|
||||
fmt.Println("✅ SDK example completed successfully!")
|
||||
}
|
||||
|
||||
func demonstrateAppLifecycle(ctx context.Context, c *client.Client, input *client.NewAppInput) error {
|
||||
appKey := input.App.Key
|
||||
region := input.Region
|
||||
|
||||
fmt.Printf("🚀 Demonstrating EdgeXR SDK with app: %s/%s v%s\n",
|
||||
appKey.Organization, appKey.Name, appKey.Version)
|
||||
|
||||
// Step 1: Create the application
|
||||
fmt.Println("\n1. Creating application...")
|
||||
if err := c.CreateApp(ctx, input); err != nil {
|
||||
return fmt.Errorf("failed to create app: %w", err)
|
||||
}
|
||||
fmt.Printf("✅ App created: %s/%s v%s\n", appKey.Organization, appKey.Name, appKey.Version)
|
||||
|
||||
// Step 2: Query the application
|
||||
fmt.Println("\n2. Querying application...")
|
||||
app, err := c.ShowApp(ctx, appKey, region)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to show app: %w", err)
|
||||
}
|
||||
fmt.Printf("✅ App found: %s/%s v%s (deployment: %s)\n",
|
||||
app.Key.Organization, app.Key.Name, app.Key.Version, app.Deployment)
|
||||
|
||||
// Step 3: List applications in the organization
|
||||
fmt.Println("\n3. Listing applications...")
|
||||
filter := client.AppKey{Organization: appKey.Organization}
|
||||
apps, err := c.ShowApps(ctx, filter, region)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to list apps: %w", err)
|
||||
}
|
||||
fmt.Printf("✅ Found %d applications in organization '%s'\n", len(apps), appKey.Organization)
|
||||
|
||||
// Step 4: Clean up - delete the application
|
||||
fmt.Println("\n4. Cleaning up...")
|
||||
if err := c.DeleteApp(ctx, appKey, region); err != nil {
|
||||
return fmt.Errorf("failed to delete app: %w", err)
|
||||
}
|
||||
fmt.Printf("✅ App deleted: %s/%s v%s\n", appKey.Organization, appKey.Name, appKey.Version)
|
||||
|
||||
// Step 5: Verify deletion
|
||||
fmt.Println("\n5. Verifying deletion...")
|
||||
_, err = c.ShowApp(ctx, appKey, region)
|
||||
if err != nil {
|
||||
if fmt.Sprintf("%v", err) == client.ErrResourceNotFound.Error() {
|
||||
fmt.Printf("✅ App successfully deleted (not found)\n")
|
||||
} else {
|
||||
return fmt.Errorf("unexpected error verifying deletion: %w", err)
|
||||
}
|
||||
} else {
|
||||
return fmt.Errorf("app still exists after deletion")
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func getEnvOrDefault(key, defaultValue string) string {
|
||||
if value := os.Getenv(key); value != "" {
|
||||
return value
|
||||
}
|
||||
return defaultValue
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue