feat(swagger_v2): added support for the orca staging environment
This commit is contained in:
parent
0f71239db6
commit
1413836b68
9 changed files with 186 additions and 39 deletions
20
cmd/app.go
20
cmd/app.go
|
|
@ -3,6 +3,7 @@ package cmd
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"log"
|
||||||
"net/http"
|
"net/http"
|
||||||
"net/url"
|
"net/url"
|
||||||
"os"
|
"os"
|
||||||
|
|
@ -60,16 +61,23 @@ func newSDKClient() *edgeconnect.Client {
|
||||||
os.Exit(1)
|
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 != "" {
|
if username != "" && password != "" {
|
||||||
return edgeconnect.NewClientWithCredentials(baseURL, username, password,
|
return edgeconnect.NewClientWithCredentials(baseURL, username, password, opts...)
|
||||||
edgeconnect.WithHTTPClient(&http.Client{Timeout: 30 * time.Second}),
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Fallback to no auth for now - in production should require auth
|
// Fallback to no auth for now - in production should require auth
|
||||||
return edgeconnect.NewClient(baseURL,
|
return edgeconnect.NewClient(baseURL, opts...)
|
||||||
edgeconnect.WithHTTPClient(&http.Client{Timeout: 30 * time.Second}),
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
var appCmd = &cobra.Command{
|
var appCmd = &cobra.Command{
|
||||||
|
|
|
||||||
|
|
@ -13,6 +13,7 @@ var (
|
||||||
baseURL string
|
baseURL string
|
||||||
username string
|
username string
|
||||||
password string
|
password string
|
||||||
|
debug bool
|
||||||
)
|
)
|
||||||
|
|
||||||
// rootCmd represents the base command when called without any subcommands
|
// rootCmd represents the base command when called without any subcommands
|
||||||
|
|
@ -39,6 +40,7 @@ func init() {
|
||||||
rootCmd.PersistentFlags().StringVar(&baseURL, "base-url", "", "base URL for the Edge Connect API")
|
rootCmd.PersistentFlags().StringVar(&baseURL, "base-url", "", "base URL for the Edge Connect API")
|
||||||
rootCmd.PersistentFlags().StringVar(&username, "username", "", "username for authentication")
|
rootCmd.PersistentFlags().StringVar(&username, "username", "", "username for authentication")
|
||||||
rootCmd.PersistentFlags().StringVar(&password, "password", "", "password for authentication")
|
rootCmd.PersistentFlags().StringVar(&password, "password", "", "password for authentication")
|
||||||
|
rootCmd.PersistentFlags().BoolVar(&debug, "debug", false, "enable debug logging")
|
||||||
|
|
||||||
viper.BindPFlag("base_url", rootCmd.PersistentFlags().Lookup("base-url"))
|
viper.BindPFlag("base_url", rootCmd.PersistentFlags().Lookup("base-url"))
|
||||||
viper.BindPFlag("username", rootCmd.PersistentFlags().Lookup("username"))
|
viper.BindPFlag("username", rootCmd.PersistentFlags().Lookup("username"))
|
||||||
|
|
|
||||||
|
|
@ -7,6 +7,8 @@ import (
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
|
"gopkg.in/yaml.v3"
|
||||||
)
|
)
|
||||||
|
|
||||||
// EdgeConnectConfig represents the top-level configuration structure
|
// EdgeConnectConfig represents the top-level configuration structure
|
||||||
|
|
@ -98,10 +100,75 @@ func (c *EdgeConnectConfig) GetImagePath() string {
|
||||||
if c.Spec.IsDockerApp() && c.Spec.DockerApp.Image != "" {
|
if c.Spec.IsDockerApp() && c.Spec.DockerApp.Image != "" {
|
||||||
return c.Spec.DockerApp.Image
|
return c.Spec.DockerApp.Image
|
||||||
}
|
}
|
||||||
// Default for kubernetes apps
|
|
||||||
|
// For kubernetes apps, extract image from manifest
|
||||||
|
if c.Spec.IsK8sApp() && c.Spec.K8sApp.ManifestFile != "" {
|
||||||
|
if image, err := extractImageFromK8sManifest(c.Spec.K8sApp.ManifestFile); err == nil && image != "" {
|
||||||
|
return image
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Fallback default for kubernetes apps
|
||||||
return "https://registry-1.docker.io/library/nginx:latest"
|
return "https://registry-1.docker.io/library/nginx:latest"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// extractImageFromK8sManifest extracts the container image from a Kubernetes manifest
|
||||||
|
func extractImageFromK8sManifest(manifestPath string) (string, error) {
|
||||||
|
data, err := os.ReadFile(manifestPath)
|
||||||
|
if err != nil {
|
||||||
|
return "", fmt.Errorf("failed to read manifest: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Parse multi-document YAML
|
||||||
|
decoder := yaml.NewDecoder(strings.NewReader(string(data)))
|
||||||
|
|
||||||
|
for {
|
||||||
|
var doc map[string]interface{}
|
||||||
|
if err := decoder.Decode(&doc); err != nil {
|
||||||
|
break // End of documents or error
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if this is a Deployment
|
||||||
|
kind, ok := doc["kind"].(string)
|
||||||
|
if !ok || kind != "Deployment" {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
// Navigate to spec.template.spec.containers[0].image
|
||||||
|
spec, ok := doc["spec"].(map[string]interface{})
|
||||||
|
if !ok {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
template, ok := spec["template"].(map[string]interface{})
|
||||||
|
if !ok {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
templateSpec, ok := template["spec"].(map[string]interface{})
|
||||||
|
if !ok {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
containers, ok := templateSpec["containers"].([]interface{})
|
||||||
|
if !ok || len(containers) == 0 {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
firstContainer, ok := containers[0].(map[string]interface{})
|
||||||
|
if !ok {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
image, ok := firstContainer["image"].(string)
|
||||||
|
if ok && image != "" {
|
||||||
|
return image, nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return "", fmt.Errorf("no image found in Deployment manifest")
|
||||||
|
}
|
||||||
|
|
||||||
// Validate validates metadata fields
|
// Validate validates metadata fields
|
||||||
func (m *Metadata) Validate() error {
|
func (m *Metadata) Validate() error {
|
||||||
if m.Name == "" {
|
if m.Name == "" {
|
||||||
|
|
|
||||||
|
|
@ -4,9 +4,11 @@
|
||||||
package edgeconnect
|
package edgeconnect
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"bytes"
|
||||||
"context"
|
"context"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"io"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
|
||||||
sdkhttp "edp.buildth.ing/DevFW-CICD/edge-connect-client/sdk/internal/http"
|
sdkhttp "edp.buildth.ing/DevFW-CICD/edge-connect-client/sdk/internal/http"
|
||||||
|
|
@ -164,18 +166,17 @@ func (c *Client) RefreshAppInstance(ctx context.Context, appInstKey AppInstanceK
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// DeleteAppInstance removes an application instance from the specified region
|
// DeleteAppInstance removes an application instance
|
||||||
// Maps to POST /auth/ctrl/DeleteAppInst
|
// Maps to POST /auth/ctrl/DeleteAppInst
|
||||||
func (c *Client) DeleteAppInstance(ctx context.Context, appInstKey AppInstanceKey, region string) error {
|
func (c *Client) DeleteAppInstance(ctx context.Context, appInstKey AppInstanceKey, region string) error {
|
||||||
transport := c.getTransport()
|
transport := c.getTransport()
|
||||||
url := c.BaseURL + "/api/v1/auth/ctrl/DeleteAppInst"
|
url := c.BaseURL + "/api/v1/auth/ctrl/DeleteAppInst"
|
||||||
|
|
||||||
filter := AppInstanceFilter{
|
input := DeleteAppInstanceInput{
|
||||||
AppInstance: AppInstance{Key: appInstKey},
|
Key: appInstKey,
|
||||||
Region: region,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
resp, err := transport.Call(ctx, "POST", url, filter)
|
resp, err := transport.Call(ctx, "POST", url, input)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("DeleteAppInstance failed: %w", err)
|
return fmt.Errorf("DeleteAppInstance failed: %w", err)
|
||||||
}
|
}
|
||||||
|
|
@ -194,13 +195,29 @@ func (c *Client) DeleteAppInstance(ctx context.Context, appInstKey AppInstanceKe
|
||||||
|
|
||||||
// parseStreamingAppInstanceResponse parses the EdgeXR streaming JSON response format for app instances
|
// parseStreamingAppInstanceResponse parses the EdgeXR streaming JSON response format for app instances
|
||||||
func (c *Client) parseStreamingAppInstanceResponse(resp *http.Response, result interface{}) error {
|
func (c *Client) parseStreamingAppInstanceResponse(resp *http.Response, result interface{}) error {
|
||||||
|
bodyBytes, err := io.ReadAll(resp.Body)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("failed to read response body: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Try parsing as a direct JSON array first (v2 API format)
|
||||||
|
switch v := result.(type) {
|
||||||
|
case *[]AppInstance:
|
||||||
|
var appInstances []AppInstance
|
||||||
|
if err := json.Unmarshal(bodyBytes, &appInstances); err == nil {
|
||||||
|
*v = appInstances
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Fall back to streaming format (v1 API format)
|
||||||
var appInstances []AppInstance
|
var appInstances []AppInstance
|
||||||
var messages []string
|
var messages []string
|
||||||
var hasError bool
|
var hasError bool
|
||||||
var errorCode int
|
var errorCode int
|
||||||
var errorMessage string
|
var errorMessage string
|
||||||
|
|
||||||
parseErr := sdkhttp.ParseJSONLines(resp.Body, func(line []byte) error {
|
parseErr := sdkhttp.ParseJSONLines(io.NopCloser(bytes.NewReader(bodyBytes)), func(line []byte) error {
|
||||||
// Try parsing as ResultResponse first (error format)
|
// Try parsing as ResultResponse first (error format)
|
||||||
var resultResp ResultResponse
|
var resultResp ResultResponse
|
||||||
if err := json.Unmarshal(line, &resultResp); err == nil && resultResp.Result.Message != "" {
|
if err := json.Unmarshal(line, &resultResp); err == nil && resultResp.Result.Message != "" {
|
||||||
|
|
|
||||||
|
|
@ -4,6 +4,7 @@
|
||||||
package edgeconnect
|
package edgeconnect
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"bytes"
|
||||||
"context"
|
"context"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
@ -142,12 +143,12 @@ func (c *Client) DeleteApp(ctx context.Context, appKey AppKey, region string) er
|
||||||
transport := c.getTransport()
|
transport := c.getTransport()
|
||||||
url := c.BaseURL + "/api/v1/auth/ctrl/DeleteApp"
|
url := c.BaseURL + "/api/v1/auth/ctrl/DeleteApp"
|
||||||
|
|
||||||
filter := AppFilter{
|
input := DeleteAppInput{
|
||||||
App: App{Key: appKey},
|
Key: appKey,
|
||||||
Region: region,
|
Region: region,
|
||||||
}
|
}
|
||||||
|
|
||||||
resp, err := transport.Call(ctx, "POST", url, filter)
|
resp, err := transport.Call(ctx, "POST", url, input)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("DeleteApp failed: %w", err)
|
return fmt.Errorf("DeleteApp failed: %w", err)
|
||||||
}
|
}
|
||||||
|
|
@ -166,9 +167,27 @@ func (c *Client) DeleteApp(ctx context.Context, appKey AppKey, region string) er
|
||||||
|
|
||||||
// parseStreamingResponse parses the EdgeXR streaming JSON response format
|
// parseStreamingResponse parses the EdgeXR streaming JSON response format
|
||||||
func (c *Client) parseStreamingResponse(resp *http.Response, result interface{}) error {
|
func (c *Client) parseStreamingResponse(resp *http.Response, result interface{}) error {
|
||||||
var responses []Response[App]
|
bodyBytes, err := io.ReadAll(resp.Body)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("failed to read response body: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
parseErr := sdkhttp.ParseJSONLines(resp.Body, func(line []byte) error {
|
// Try parsing as a direct JSON array first (v2 API format)
|
||||||
|
switch v := result.(type) {
|
||||||
|
case *[]App:
|
||||||
|
var apps []App
|
||||||
|
if err := json.Unmarshal(bodyBytes, &apps); err == nil {
|
||||||
|
*v = apps
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Fall back to streaming format (v1 API format)
|
||||||
|
var responses []Response[App]
|
||||||
|
var apps []App
|
||||||
|
var messages []string
|
||||||
|
|
||||||
|
parseErr := sdkhttp.ParseJSONLines(io.NopCloser(bytes.NewReader(bodyBytes)), func(line []byte) error {
|
||||||
var response Response[App]
|
var response Response[App]
|
||||||
if err := json.Unmarshal(line, &response); err != nil {
|
if err := json.Unmarshal(line, &response); err != nil {
|
||||||
return err
|
return err
|
||||||
|
|
@ -182,9 +201,6 @@ func (c *Client) parseStreamingResponse(resp *http.Response, result interface{})
|
||||||
}
|
}
|
||||||
|
|
||||||
// Extract data from responses
|
// Extract data from responses
|
||||||
var apps []App
|
|
||||||
var messages []string
|
|
||||||
|
|
||||||
for _, response := range responses {
|
for _, response := range responses {
|
||||||
if response.HasData() {
|
if response.HasData() {
|
||||||
apps = append(apps, response.Data)
|
apps = append(apps, response.Data)
|
||||||
|
|
|
||||||
|
|
@ -184,24 +184,33 @@ type App struct {
|
||||||
Deployment string `json:"deployment,omitempty"`
|
Deployment string `json:"deployment,omitempty"`
|
||||||
ImageType string `json:"image_type,omitempty"`
|
ImageType string `json:"image_type,omitempty"`
|
||||||
ImagePath string `json:"image_path,omitempty"`
|
ImagePath string `json:"image_path,omitempty"`
|
||||||
|
AccessPorts string `json:"access_ports,omitempty"`
|
||||||
AllowServerless bool `json:"allow_serverless,omitempty"`
|
AllowServerless bool `json:"allow_serverless,omitempty"`
|
||||||
DefaultFlavor Flavor `json:"defaultFlavor,omitempty"`
|
DefaultFlavor Flavor `json:"defaultFlavor,omitempty"`
|
||||||
ServerlessConfig interface{} `json:"serverless_config,omitempty"`
|
ServerlessConfig interface{} `json:"serverless_config,omitempty"`
|
||||||
DeploymentGenerator string `json:"deployment_generator,omitempty"`
|
DeploymentGenerator string `json:"deployment_generator,omitempty"`
|
||||||
DeploymentManifest string `json:"deployment_manifest,omitempty"`
|
DeploymentManifest string `json:"deployment_manifest,omitempty"`
|
||||||
RequiredOutboundConnections []SecurityRule `json:"required_outbound_connections"`
|
RequiredOutboundConnections []SecurityRule `json:"required_outbound_connections"`
|
||||||
|
GlobalID string `json:"global_id,omitempty"`
|
||||||
|
CreatedAt string `json:"created_at,omitempty"`
|
||||||
|
UpdatedAt string `json:"updated_at,omitempty"`
|
||||||
Fields []string `json:"fields,omitempty"`
|
Fields []string `json:"fields,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// AppInstance represents a deployed application instance
|
// AppInstance represents a deployed application instance
|
||||||
type AppInstance struct {
|
type AppInstance struct {
|
||||||
msg `json:",inline"`
|
msg `json:",inline"`
|
||||||
Key AppInstanceKey `json:"key"`
|
Key AppInstanceKey `json:"key"`
|
||||||
AppKey AppKey `json:"app_key,omitempty"`
|
AppKey AppKey `json:"app_key,omitempty"`
|
||||||
Flavor Flavor `json:"flavor,omitempty"`
|
CloudletLoc CloudletLoc `json:"cloudlet_loc,omitempty"`
|
||||||
State string `json:"state,omitempty"`
|
Flavor Flavor `json:"flavor,omitempty"`
|
||||||
PowerState string `json:"power_state,omitempty"`
|
State string `json:"state,omitempty"`
|
||||||
Fields []string `json:"fields,omitempty"`
|
IngressURL string `json:"ingress_url,omitempty"`
|
||||||
|
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
|
// Cloudlet represents edge infrastructure
|
||||||
|
|
@ -224,6 +233,12 @@ type Location struct {
|
||||||
Longitude float64 `json:"longitude"`
|
Longitude float64 `json:"longitude"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// CloudletLoc represents geographical coordinates for cloudlets
|
||||||
|
type CloudletLoc struct {
|
||||||
|
Latitude float64 `json:"latitude"`
|
||||||
|
Longitude float64 `json:"longitude"`
|
||||||
|
}
|
||||||
|
|
||||||
// Input types for API operations
|
// Input types for API operations
|
||||||
|
|
||||||
// NewAppInput represents input for creating an application
|
// NewAppInput represents input for creating an application
|
||||||
|
|
@ -256,6 +271,17 @@ type UpdateAppInstanceInput struct {
|
||||||
AppInst AppInstance `json:"appinst"`
|
AppInst AppInstance `json:"appinst"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// DeleteAppInput represents input for deleting an application
|
||||||
|
type DeleteAppInput struct {
|
||||||
|
Key AppKey `json:"key"`
|
||||||
|
Region string `json:"region"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeleteAppInstanceInput represents input for deleting an app instance
|
||||||
|
type DeleteAppInstanceInput struct {
|
||||||
|
Key AppInstanceKey `json:"key"`
|
||||||
|
}
|
||||||
|
|
||||||
// Response wrapper types
|
// Response wrapper types
|
||||||
|
|
||||||
// Response wraps a single API response
|
// Response wraps a single API response
|
||||||
|
|
|
||||||
|
|
@ -3,8 +3,8 @@
|
||||||
kind: edgeconnect-deployment
|
kind: edgeconnect-deployment
|
||||||
metadata:
|
metadata:
|
||||||
name: "edge-app-demo" # name could be used for appName
|
name: "edge-app-demo" # name could be used for appName
|
||||||
appVersion: "1.0.0"
|
appVersion: "1"
|
||||||
organization: "edp2"
|
organization: "edp2-orca"
|
||||||
spec:
|
spec:
|
||||||
# dockerApp: # Docker is OBSOLETE
|
# dockerApp: # Docker is OBSOLETE
|
||||||
# appVersion: "1.0.0"
|
# appVersion: "1.0.0"
|
||||||
|
|
@ -13,10 +13,10 @@ spec:
|
||||||
k8sApp:
|
k8sApp:
|
||||||
manifestFile: "./k8s-deployment.yaml"
|
manifestFile: "./k8s-deployment.yaml"
|
||||||
infraTemplate:
|
infraTemplate:
|
||||||
- region: "EU"
|
- region: "US"
|
||||||
cloudletOrg: "TelekomOP"
|
cloudletOrg: "TelekomOp"
|
||||||
cloudletName: "Munich"
|
cloudletName: "gardener-shepherd-test"
|
||||||
flavorName: "EU.small"
|
flavorName: "defualt"
|
||||||
network:
|
network:
|
||||||
outboundConnections:
|
outboundConnections:
|
||||||
- protocol: "tcp"
|
- protocol: "tcp"
|
||||||
|
|
|
||||||
|
|
@ -32,7 +32,7 @@ spec:
|
||||||
volumes:
|
volumes:
|
||||||
containers:
|
containers:
|
||||||
- name: edgeconnect-coder
|
- name: edgeconnect-coder
|
||||||
image: nginx:latest
|
image: edp.buildth.ing/devfw-cicd/fibonacci_pipeline:edge_platform_demo
|
||||||
imagePullPolicy: Always
|
imagePullPolicy: Always
|
||||||
ports:
|
ports:
|
||||||
- containerPort: 80
|
- containerPort: 80
|
||||||
|
|
|
||||||
|
|
@ -98,10 +98,12 @@ func NewTransport(opts RetryOptions, auth AuthProvider, logger Logger) *Transpor
|
||||||
// Call executes an HTTP request with retry logic and returns typed response
|
// Call executes an HTTP request with retry logic and returns typed response
|
||||||
func (t *Transport) Call(ctx context.Context, method, url string, body interface{}) (*http.Response, error) {
|
func (t *Transport) Call(ctx context.Context, method, url string, body interface{}) (*http.Response, error) {
|
||||||
var reqBody io.Reader
|
var reqBody io.Reader
|
||||||
|
var jsonData []byte
|
||||||
|
|
||||||
// Marshal request body if provided
|
// Marshal request body if provided
|
||||||
if body != nil {
|
if body != nil {
|
||||||
jsonData, err := json.Marshal(body)
|
var err error
|
||||||
|
jsonData, err = json.Marshal(body)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("failed to marshal request body: %w", err)
|
return nil, fmt.Errorf("failed to marshal request body: %w", err)
|
||||||
}
|
}
|
||||||
|
|
@ -127,8 +129,16 @@ func (t *Transport) Call(ctx context.Context, method, url string, body interface
|
||||||
|
|
||||||
// Log request
|
// Log request
|
||||||
if t.logger != nil {
|
if t.logger != nil {
|
||||||
t.logger.Printf("HTTP %s %s", method, url)
|
t.logger.Printf("=== HTTP REQUEST ===")
|
||||||
t.logger.Printf("BODY %s", reqBody)
|
t.logger.Printf("%s %s", method, url)
|
||||||
|
if len(jsonData) > 0 {
|
||||||
|
var prettyJSON bytes.Buffer
|
||||||
|
if err := json.Indent(&prettyJSON, jsonData, "", " "); err == nil {
|
||||||
|
t.logger.Printf("Request Body:\n%s", prettyJSON.String())
|
||||||
|
} else {
|
||||||
|
t.logger.Printf("Request Body: %s", string(jsonData))
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Execute request
|
// Execute request
|
||||||
|
|
@ -139,7 +149,8 @@ func (t *Transport) Call(ctx context.Context, method, url string, body interface
|
||||||
|
|
||||||
// Log response
|
// Log response
|
||||||
if t.logger != nil {
|
if t.logger != nil {
|
||||||
t.logger.Printf("HTTP %s %s -> %d", method, url, resp.StatusCode)
|
t.logger.Printf("=== HTTP RESPONSE ===")
|
||||||
|
t.logger.Printf("%s %s -> %d", method, url, resp.StatusCode)
|
||||||
}
|
}
|
||||||
|
|
||||||
return resp, nil
|
return resp, nil
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue