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>
105 lines
No EOL
2.4 KiB
Go
105 lines
No EOL
2.4 KiB
Go
// ABOUTME: Core EdgeXR Master Controller SDK client with HTTP transport and auth
|
|
// ABOUTME: Provides typed APIs for app, instance, and cloudlet management operations
|
|
|
|
package client
|
|
|
|
import (
|
|
"net/http"
|
|
"strings"
|
|
"time"
|
|
)
|
|
|
|
// Client represents the EdgeXR Master Controller SDK client
|
|
type Client struct {
|
|
BaseURL string
|
|
HTTPClient *http.Client
|
|
AuthProvider AuthProvider
|
|
RetryOpts RetryOptions
|
|
Logger Logger
|
|
}
|
|
|
|
// RetryOptions configures retry behavior for API calls
|
|
type RetryOptions struct {
|
|
MaxRetries int
|
|
InitialDelay time.Duration
|
|
MaxDelay time.Duration
|
|
Multiplier float64
|
|
RetryableHTTPStatusCodes []int
|
|
}
|
|
|
|
// Logger interface for optional logging
|
|
type Logger interface {
|
|
Printf(format string, v ...interface{})
|
|
}
|
|
|
|
// DefaultRetryOptions returns sensible default retry configuration
|
|
func DefaultRetryOptions() RetryOptions {
|
|
return RetryOptions{
|
|
MaxRetries: 3,
|
|
InitialDelay: 1 * time.Second,
|
|
MaxDelay: 30 * time.Second,
|
|
Multiplier: 2.0,
|
|
RetryableHTTPStatusCodes: []int{
|
|
http.StatusRequestTimeout,
|
|
http.StatusTooManyRequests,
|
|
http.StatusInternalServerError,
|
|
http.StatusBadGateway,
|
|
http.StatusServiceUnavailable,
|
|
http.StatusGatewayTimeout,
|
|
},
|
|
}
|
|
}
|
|
|
|
// Option represents a configuration option for the client
|
|
type Option func(*Client)
|
|
|
|
// WithHTTPClient sets a custom HTTP client
|
|
func WithHTTPClient(client *http.Client) Option {
|
|
return func(c *Client) {
|
|
c.HTTPClient = client
|
|
}
|
|
}
|
|
|
|
// WithAuthProvider sets the authentication provider
|
|
func WithAuthProvider(auth AuthProvider) Option {
|
|
return func(c *Client) {
|
|
c.AuthProvider = auth
|
|
}
|
|
}
|
|
|
|
// WithRetryOptions sets retry configuration
|
|
func WithRetryOptions(opts RetryOptions) Option {
|
|
return func(c *Client) {
|
|
c.RetryOpts = opts
|
|
}
|
|
}
|
|
|
|
// WithLogger sets a logger for debugging
|
|
func WithLogger(logger Logger) Option {
|
|
return func(c *Client) {
|
|
c.Logger = logger
|
|
}
|
|
}
|
|
|
|
// NewClient creates a new EdgeXR SDK client
|
|
func NewClient(baseURL string, options ...Option) *Client {
|
|
client := &Client{
|
|
BaseURL: strings.TrimRight(baseURL, "/"),
|
|
HTTPClient: &http.Client{Timeout: 30 * time.Second},
|
|
AuthProvider: NewNoAuthProvider(),
|
|
RetryOpts: DefaultRetryOptions(),
|
|
}
|
|
|
|
for _, opt := range options {
|
|
opt(client)
|
|
}
|
|
|
|
return client
|
|
}
|
|
|
|
// logf logs a message if a logger is configured
|
|
func (c *Client) logf(format string, v ...interface{}) {
|
|
if c.Logger != nil {
|
|
c.Logger.Printf(format, v...)
|
|
}
|
|
} |