feat(config): add API version selector for v1 and v2

Add configurable API version selection with three methods:
- Config file: api_version: "v1" or "v2" in .edge-connect.yaml
- CLI flag: --api-version v1/v2
- Environment variable: EDGE_CONNECT_API_VERSION=v1/v2

Changes:
- Update root.go to add api_version config and env var support
- Update app.go and instance.go to support both v1 and v2 clients
- Add example config file with api_version documentation
- Default to v2 for backward compatibility
- Apply command always uses v2 (advanced feature)

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
Richard Robert Reitz 2025-10-20 13:41:50 +02:00
parent 3486b2228d
commit 2a8e99eb63
5 changed files with 319 additions and 108 deletions

View file

@ -0,0 +1,14 @@
# Example EdgeConnect CLI Configuration File
# Place this file at ~/.edge-connect.yaml or specify with --config flag
# Base URL for the EdgeConnect API
base_url: "https://hub.apps.edge.platform.mg3.mdb.osc.live"
# Authentication credentials
username: "your-username@example.com"
password: "your-password"
# API version to use (v1 or v2)
# Default: v2
# Set via config, --api-version flag, or EDGE_CONNECT_API_VERSION env var
api_version: "v2"

View file

@ -7,8 +7,10 @@ import (
"net/http"
"net/url"
"os"
"strings"
"time"
"edp.buildth.ing/DevFW-CICD/edge-connect-client/sdk/edgeconnect"
v2 "edp.buildth.ing/DevFW-CICD/edge-connect-client/sdk/edgeconnect/v2"
"github.com/spf13/cobra"
"github.com/spf13/viper"
@ -50,7 +52,45 @@ func validateBaseURL(baseURL string) error {
return nil
}
func newSDKClient() *v2.Client {
func getAPIVersion() string {
version := viper.GetString("api_version")
if version == "" {
version = "v2" // default to v2
}
return strings.ToLower(version)
}
func newSDKClientV1() *edgeconnect.Client {
baseURL := viper.GetString("base_url")
username := viper.GetString("username")
password := viper.GetString("password")
err := validateBaseURL(baseURL)
if err != nil {
fmt.Printf("Error parsing baseURL: '%s' with error: %s\n", baseURL, err.Error())
os.Exit(1)
}
// Build options
opts := []edgeconnect.Option{
edgeconnect.WithHTTPClient(&http.Client{Timeout: 30 * time.Second}),
}
// Add logger only if debug flag is set
if debug {
logger := log.New(os.Stderr, "[DEBUG] ", log.LstdFlags)
opts = append(opts, edgeconnect.WithLogger(logger))
}
if username != "" && password != "" {
return edgeconnect.NewClientWithCredentials(baseURL, username, password, opts...)
}
// Fallback to no auth for now - in production should require auth
return edgeconnect.NewClient(baseURL, opts...)
}
func newSDKClientV2() *v2.Client {
baseURL := viper.GetString("base_url")
username := viper.GetString("username")
password := viper.GetString("password")
@ -90,19 +130,37 @@ var createAppCmd = &cobra.Command{
Use: "create",
Short: "Create a new Edge Connect application",
Run: func(cmd *cobra.Command, args []string) {
c := newSDKClient()
input := &v2.NewAppInput{
Region: region,
App: v2.App{
Key: v2.AppKey{
Organization: organization,
Name: appName,
Version: appVersion,
apiVersion := getAPIVersion()
var err error
if apiVersion == "v1" {
c := newSDKClientV1()
input := &edgeconnect.NewAppInput{
Region: region,
App: edgeconnect.App{
Key: edgeconnect.AppKey{
Organization: organization,
Name: appName,
Version: appVersion,
},
},
},
}
err = c.CreateApp(context.Background(), input)
} else {
c := newSDKClientV2()
input := &v2.NewAppInput{
Region: region,
App: v2.App{
Key: v2.AppKey{
Organization: organization,
Name: appName,
Version: appVersion,
},
},
}
err = c.CreateApp(context.Background(), input)
}
err := c.CreateApp(context.Background(), input)
if err != nil {
fmt.Printf("Error creating app: %v\n", err)
os.Exit(1)
@ -115,19 +173,35 @@ var showAppCmd = &cobra.Command{
Use: "show",
Short: "Show details of an Edge Connect application",
Run: func(cmd *cobra.Command, args []string) {
c := newSDKClient()
appKey := v2.AppKey{
Organization: organization,
Name: appName,
Version: appVersion,
}
apiVersion := getAPIVersion()
app, err := c.ShowApp(context.Background(), appKey, region)
if err != nil {
fmt.Printf("Error showing app: %v\n", err)
os.Exit(1)
if apiVersion == "v1" {
c := newSDKClientV1()
appKey := edgeconnect.AppKey{
Organization: organization,
Name: appName,
Version: appVersion,
}
app, err := c.ShowApp(context.Background(), appKey, region)
if err != nil {
fmt.Printf("Error showing app: %v\n", err)
os.Exit(1)
}
fmt.Printf("Application details:\n%+v\n", app)
} else {
c := newSDKClientV2()
appKey := v2.AppKey{
Organization: organization,
Name: appName,
Version: appVersion,
}
app, err := c.ShowApp(context.Background(), appKey, region)
if err != nil {
fmt.Printf("Error showing app: %v\n", err)
os.Exit(1)
}
fmt.Printf("Application details:\n%+v\n", app)
}
fmt.Printf("Application details:\n%+v\n", app)
},
}
@ -135,21 +209,40 @@ var listAppsCmd = &cobra.Command{
Use: "list",
Short: "List Edge Connect applications",
Run: func(cmd *cobra.Command, args []string) {
c := newSDKClient()
appKey := v2.AppKey{
Organization: organization,
Name: appName,
Version: appVersion,
}
apiVersion := getAPIVersion()
apps, err := c.ShowApps(context.Background(), appKey, region)
if err != nil {
fmt.Printf("Error listing apps: %v\n", err)
os.Exit(1)
}
fmt.Println("Applications:")
for _, app := range apps {
fmt.Printf("%+v\n", app)
if apiVersion == "v1" {
c := newSDKClientV1()
appKey := edgeconnect.AppKey{
Organization: organization,
Name: appName,
Version: appVersion,
}
apps, err := c.ShowApps(context.Background(), appKey, region)
if err != nil {
fmt.Printf("Error listing apps: %v\n", err)
os.Exit(1)
}
fmt.Println("Applications:")
for _, app := range apps {
fmt.Printf("%+v\n", app)
}
} else {
c := newSDKClientV2()
appKey := v2.AppKey{
Organization: organization,
Name: appName,
Version: appVersion,
}
apps, err := c.ShowApps(context.Background(), appKey, region)
if err != nil {
fmt.Printf("Error listing apps: %v\n", err)
os.Exit(1)
}
fmt.Println("Applications:")
for _, app := range apps {
fmt.Printf("%+v\n", app)
}
}
},
}
@ -158,14 +251,27 @@ var deleteAppCmd = &cobra.Command{
Use: "delete",
Short: "Delete an Edge Connect application",
Run: func(cmd *cobra.Command, args []string) {
c := newSDKClient()
appKey := v2.AppKey{
Organization: organization,
Name: appName,
Version: appVersion,
apiVersion := getAPIVersion()
var err error
if apiVersion == "v1" {
c := newSDKClientV1()
appKey := edgeconnect.AppKey{
Organization: organization,
Name: appName,
Version: appVersion,
}
err = c.DeleteApp(context.Background(), appKey, region)
} else {
c := newSDKClientV2()
appKey := v2.AppKey{
Organization: organization,
Name: appName,
Version: appVersion,
}
err = c.DeleteApp(context.Background(), appKey, region)
}
err := c.DeleteApp(context.Background(), appKey, region)
if err != nil {
fmt.Printf("Error deleting app: %v\n", err)
os.Exit(1)

View file

@ -67,8 +67,8 @@ func runApply(configPath string, isDryRun bool, autoApprove bool) error {
fmt.Printf("✅ Configuration loaded successfully: %s\n", cfg.Metadata.Name)
// Step 3: Create EdgeConnect client
client := newSDKClient()
// Step 3: Create EdgeConnect client (apply always uses v2)
client := newSDKClientV2()
// Step 4: Create deployment planner
planner := apply.NewPlanner(client)

View file

@ -5,6 +5,7 @@ import (
"fmt"
"os"
"edp.buildth.ing/DevFW-CICD/edge-connect-client/sdk/edgeconnect"
v2 "edp.buildth.ing/DevFW-CICD/edge-connect-client/sdk/edgeconnect/v2"
"github.com/spf13/cobra"
)
@ -26,30 +27,59 @@ var createInstanceCmd = &cobra.Command{
Use: "create",
Short: "Create a new Edge Connect application instance",
Run: func(cmd *cobra.Command, args []string) {
c := newSDKClient()
input := &v2.NewAppInstanceInput{
Region: region,
AppInst: v2.AppInstance{
Key: v2.AppInstanceKey{
Organization: organization,
Name: instanceName,
CloudletKey: v2.CloudletKey{
Organization: cloudletOrg,
Name: cloudletName,
apiVersion := getAPIVersion()
var err error
if apiVersion == "v1" {
c := newSDKClientV1()
input := &edgeconnect.NewAppInstanceInput{
Region: region,
AppInst: edgeconnect.AppInstance{
Key: edgeconnect.AppInstanceKey{
Organization: organization,
Name: instanceName,
CloudletKey: edgeconnect.CloudletKey{
Organization: cloudletOrg,
Name: cloudletName,
},
},
AppKey: edgeconnect.AppKey{
Organization: organization,
Name: appName,
Version: appVersion,
},
Flavor: edgeconnect.Flavor{
Name: flavorName,
},
},
AppKey: v2.AppKey{
Organization: organization,
Name: appName,
Version: appVersion,
}
err = c.CreateAppInstance(context.Background(), input)
} else {
c := newSDKClientV2()
input := &v2.NewAppInstanceInput{
Region: region,
AppInst: v2.AppInstance{
Key: v2.AppInstanceKey{
Organization: organization,
Name: instanceName,
CloudletKey: v2.CloudletKey{
Organization: cloudletOrg,
Name: cloudletName,
},
},
AppKey: v2.AppKey{
Organization: organization,
Name: appName,
Version: appVersion,
},
Flavor: v2.Flavor{
Name: flavorName,
},
},
Flavor: v2.Flavor{
Name: flavorName,
},
},
}
err = c.CreateAppInstance(context.Background(), input)
}
err := c.CreateAppInstance(context.Background(), input)
if err != nil {
fmt.Printf("Error creating app instance: %v\n", err)
os.Exit(1)
@ -62,22 +92,41 @@ var showInstanceCmd = &cobra.Command{
Use: "show",
Short: "Show details of an Edge Connect application instance",
Run: func(cmd *cobra.Command, args []string) {
c := newSDKClient()
instanceKey := v2.AppInstanceKey{
Organization: organization,
Name: instanceName,
CloudletKey: v2.CloudletKey{
Organization: cloudletOrg,
Name: cloudletName,
},
}
apiVersion := getAPIVersion()
instance, err := c.ShowAppInstance(context.Background(), instanceKey, region)
if err != nil {
fmt.Printf("Error showing app instance: %v\n", err)
os.Exit(1)
if apiVersion == "v1" {
c := newSDKClientV1()
instanceKey := edgeconnect.AppInstanceKey{
Organization: organization,
Name: instanceName,
CloudletKey: edgeconnect.CloudletKey{
Organization: cloudletOrg,
Name: cloudletName,
},
}
instance, err := c.ShowAppInstance(context.Background(), instanceKey, region)
if err != nil {
fmt.Printf("Error showing app instance: %v\n", err)
os.Exit(1)
}
fmt.Printf("Application instance details:\n%+v\n", instance)
} else {
c := newSDKClientV2()
instanceKey := v2.AppInstanceKey{
Organization: organization,
Name: instanceName,
CloudletKey: v2.CloudletKey{
Organization: cloudletOrg,
Name: cloudletName,
},
}
instance, err := c.ShowAppInstance(context.Background(), instanceKey, region)
if err != nil {
fmt.Printf("Error showing app instance: %v\n", err)
os.Exit(1)
}
fmt.Printf("Application instance details:\n%+v\n", instance)
}
fmt.Printf("Application instance details:\n%+v\n", instance)
},
}
@ -85,24 +134,46 @@ var listInstancesCmd = &cobra.Command{
Use: "list",
Short: "List Edge Connect application instances",
Run: func(cmd *cobra.Command, args []string) {
c := newSDKClient()
instanceKey := v2.AppInstanceKey{
Organization: organization,
Name: instanceName,
CloudletKey: v2.CloudletKey{
Organization: cloudletOrg,
Name: cloudletName,
},
}
apiVersion := getAPIVersion()
instances, err := c.ShowAppInstances(context.Background(), instanceKey, region)
if err != nil {
fmt.Printf("Error listing app instances: %v\n", err)
os.Exit(1)
}
fmt.Println("Application instances:")
for _, instance := range instances {
fmt.Printf("%+v\n", instance)
if apiVersion == "v1" {
c := newSDKClientV1()
instanceKey := edgeconnect.AppInstanceKey{
Organization: organization,
Name: instanceName,
CloudletKey: edgeconnect.CloudletKey{
Organization: cloudletOrg,
Name: cloudletName,
},
}
instances, err := c.ShowAppInstances(context.Background(), instanceKey, region)
if err != nil {
fmt.Printf("Error listing app instances: %v\n", err)
os.Exit(1)
}
fmt.Println("Application instances:")
for _, instance := range instances {
fmt.Printf("%+v\n", instance)
}
} else {
c := newSDKClientV2()
instanceKey := v2.AppInstanceKey{
Organization: organization,
Name: instanceName,
CloudletKey: v2.CloudletKey{
Organization: cloudletOrg,
Name: cloudletName,
},
}
instances, err := c.ShowAppInstances(context.Background(), instanceKey, region)
if err != nil {
fmt.Printf("Error listing app instances: %v\n", err)
os.Exit(1)
}
fmt.Println("Application instances:")
for _, instance := range instances {
fmt.Printf("%+v\n", instance)
}
}
},
}
@ -111,17 +182,33 @@ var deleteInstanceCmd = &cobra.Command{
Use: "delete",
Short: "Delete an Edge Connect application instance",
Run: func(cmd *cobra.Command, args []string) {
c := newSDKClient()
instanceKey := v2.AppInstanceKey{
Organization: organization,
Name: instanceName,
CloudletKey: v2.CloudletKey{
Organization: cloudletOrg,
Name: cloudletName,
},
apiVersion := getAPIVersion()
var err error
if apiVersion == "v1" {
c := newSDKClientV1()
instanceKey := edgeconnect.AppInstanceKey{
Organization: organization,
Name: instanceName,
CloudletKey: edgeconnect.CloudletKey{
Organization: cloudletOrg,
Name: cloudletName,
},
}
err = c.DeleteAppInstance(context.Background(), instanceKey, region)
} else {
c := newSDKClientV2()
instanceKey := v2.AppInstanceKey{
Organization: organization,
Name: instanceName,
CloudletKey: v2.CloudletKey{
Organization: cloudletOrg,
Name: cloudletName,
},
}
err = c.DeleteAppInstance(context.Background(), instanceKey, region)
}
err := c.DeleteAppInstance(context.Background(), instanceKey, region)
if err != nil {
fmt.Printf("Error deleting app instance: %v\n", err)
os.Exit(1)

View file

@ -9,11 +9,12 @@ import (
)
var (
cfgFile string
baseURL string
username string
password string
debug bool
cfgFile string
baseURL string
username string
password string
debug bool
apiVersion string
)
// rootCmd represents the base command when called without any subcommands
@ -40,11 +41,13 @@ func init() {
rootCmd.PersistentFlags().StringVar(&baseURL, "base-url", "", "base URL for the Edge Connect API")
rootCmd.PersistentFlags().StringVar(&username, "username", "", "username for authentication")
rootCmd.PersistentFlags().StringVar(&password, "password", "", "password for authentication")
rootCmd.PersistentFlags().StringVar(&apiVersion, "api-version", "v2", "API version to use (v1 or v2)")
rootCmd.PersistentFlags().BoolVar(&debug, "debug", false, "enable debug logging")
viper.BindPFlag("base_url", rootCmd.PersistentFlags().Lookup("base-url"))
viper.BindPFlag("username", rootCmd.PersistentFlags().Lookup("username"))
viper.BindPFlag("password", rootCmd.PersistentFlags().Lookup("password"))
viper.BindPFlag("api_version", rootCmd.PersistentFlags().Lookup("api-version"))
}
func initConfig() {
@ -53,6 +56,7 @@ func initConfig() {
viper.BindEnv("base_url", "EDGE_CONNECT_BASE_URL")
viper.BindEnv("username", "EDGE_CONNECT_USERNAME")
viper.BindEnv("password", "EDGE_CONNECT_PASSWORD")
viper.BindEnv("api_version", "EDGE_CONNECT_API_VERSION")
if cfgFile != "" {
viper.SetConfigFile(cfgFile)