diff --git a/.generator/schemas/adminapi.yaml b/.generator/schemas/adminapi.yaml index 718a6e88..5c8da724 100644 --- a/.generator/schemas/adminapi.yaml +++ b/.generator/schemas/adminapi.yaml @@ -7,6 +7,10 @@ info: altText: ApeCloud logo description: | The Admin API is used to manage the ApeCloud platform. + contact: + email: support@apecloud.com + name: ApeCloud Support + url: https://www.apecloud.com servers: - url: http://127.0.0.1:8080 description: local diff --git a/.generator/schemas/openapi.yaml b/.generator/schemas/openapi.yaml index 77fff399..0b64f7cc 100644 --- a/.generator/schemas/openapi.yaml +++ b/.generator/schemas/openapi.yaml @@ -15,6 +15,10 @@ info: We use standard HTTP authentication and provide API keys to identify who you are. Your API keys carry many privileges, so be sure to keep them secret! Do not share your secret API keys in publicly accessible areas such as GitHub, client-side code, and so forth. All API requests must be made over HTTPS. Calls made over plain HTTP will fail. API requests without authentication will also fail. + contact: + email: support@apecloud.com + name: ApeCloud Support + url: https://www.apecloud.com servers: - url: http://127.0.0.1:8080 description: local diff --git a/.generator/src/generator/templates/client.j2 b/.generator/src/generator/templates/client.j2 index 658b3122..49d48add 100644 --- a/.generator/src/generator/templates/client.j2 +++ b/.generator/src/generator/templates/client.j2 @@ -25,6 +25,7 @@ import ( "time" "unicode/utf8" + "github.com/icholy/digest" "golang.org/x/oauth2" ) @@ -389,6 +390,14 @@ func (c *APIClient) PrepareRequest( if auth, ok := ctx.Value(ContextAccessToken).(string); ok { localVarRequest.Header.Add("Authorization", "Bearer "+auth) } + + // Digest Authentication + if auth, ok := ctx.Value(ContextDigestAuth).(DigestAuth); ok { + c.Cfg.HTTPClient.Transport = &digest.Transport{ + Username: auth.UserName, + Password: auth.Password, + } + } } for header, value := range c.Cfg.DefaultHeader { diff --git a/.generator/src/generator/templates/configuration.j2 b/.generator/src/generator/templates/configuration.j2 index ead5f04a..8197e273 100644 --- a/.generator/src/generator/templates/configuration.j2 +++ b/.generator/src/generator/templates/configuration.j2 @@ -51,8 +51,17 @@ var ( // ContextOperationServerVariables overrides a server configuration variables using operation specific values. ContextOperationServerVariables = contextKey("serverOperationVariables") + + // ContextDigestAuth takes DigestAuth as authentication for the request. + ContextDigestAuth = contextKey("digest") ) +// DigestAuth provides digest http authentication to a request passed via context using ContextDigestAuth. +type DigestAuth struct { + UserName string `json:"username,omitempty"` + Password string `json:"password,omitempty"` +} + // BasicAuth provides basic http authentication to a request passed via context using ContextBasicAuth. type BasicAuth struct { UserName string `json:"userName,omitempty"` @@ -364,14 +373,17 @@ func NewDefaultContext(ctx context.Context) context.Context { ) } - keys := make(map[string]APIKey) - if apiKey, ok := os.LookupEnv("KB_CLOUD_API_KEY"); ok { - keys["apiKeyAuth"] = APIKey{Key: apiKey} + auth := DigestAuth{} + if keyName, ok := os.LookupEnv("KB_CLOUD_API_KEY_NAME"); ok { + auth.UserName = keyName + } + if keySecret, ok := os.LookupEnv("KB_CLOUD_API_KEY_SECRET"); ok { + auth.Password = keySecret } ctx = context.WithValue( ctx, - ContextAPIKeys, - keys, + ContextDigestAuth, + auth, ) return ctx diff --git a/.vscode/launch.json b/.vscode/launch.json new file mode 100644 index 00000000..80d08e49 --- /dev/null +++ b/.vscode/launch.json @@ -0,0 +1,21 @@ +{ + // Use IntelliSense to learn about possible attributes. + // Hover to view descriptions of existing attributes. + // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 + "version": "0.2.0", + "configurations": [ + { + "name": "Launch test function", + "type": "go", + "request": "launch", + "mode": "test", + "program": "${workspaceFolder}/tests/api/api_organization_test.go", + "args": [ + "-test.run", + "TestListOrgs" + ], + "envFile": "${workspaceFolder}/.env", + "showLog": false, + } + ] +} \ No newline at end of file diff --git a/api/common/client.go b/api/common/client.go index 9e7a7c19..0bdfd46d 100644 --- a/api/common/client.go +++ b/api/common/client.go @@ -27,6 +27,7 @@ import ( "strings" "time" + "github.com/icholy/digest" "golang.org/x/oauth2" ) @@ -389,6 +390,14 @@ func (c *APIClient) PrepareRequest( if auth, ok := ctx.Value(ContextAccessToken).(string); ok { localVarRequest.Header.Add("Authorization", "Bearer "+auth) } + + // Digest Authentication + if auth, ok := ctx.Value(ContextDigestAuth).(DigestAuth); ok { + c.Cfg.HTTPClient.Transport = &digest.Transport{ + Username: auth.UserName, + Password: auth.Password, + } + } } for header, value := range c.Cfg.DefaultHeader { diff --git a/api/common/configuration.go b/api/common/configuration.go index 4a8afdeb..ea91bd14 100644 --- a/api/common/configuration.go +++ b/api/common/configuration.go @@ -54,8 +54,17 @@ var ( // ContextOperationServerVariables overrides a server configuration variables using operation specific values. ContextOperationServerVariables = contextKey("serverOperationVariables") + + // ContextDigestAuth takes DigestAuth as authentication for the request. + ContextDigestAuth = contextKey("digest") ) +// DigestAuth provides digest http authentication to a request passed via context using ContextDigestAuth. +type DigestAuth struct { + UserName string `json:"username,omitempty"` + Password string `json:"password,omitempty"` +} + // BasicAuth provides basic http authentication to a request passed via context using ContextBasicAuth. type BasicAuth struct { UserName string `json:"userName,omitempty"` @@ -323,14 +332,17 @@ func NewDefaultContext(ctx context.Context) context.Context { ) } - keys := make(map[string]APIKey) - if apiKey, ok := os.LookupEnv("KB_CLOUD_API_KEY"); ok { - keys["apiKeyAuth"] = APIKey{Key: apiKey} + auth := DigestAuth{} + if keyName, ok := os.LookupEnv("KB_CLOUD_API_KEY_NAME"); ok { + auth.UserName = keyName + } + if keySecret, ok := os.LookupEnv("KB_CLOUD_API_KEY_SECRET"); ok { + auth.Password = keySecret } ctx = context.WithValue( ctx, - ContextAPIKeys, - keys, + ContextDigestAuth, + auth, ) return ctx diff --git a/api/kbcloud/model_load_balancer_available_type.go b/api/kbcloud/model_load_balancer_available_type.go new file mode 100644 index 00000000..8f0f5232 --- /dev/null +++ b/api/kbcloud/model_load_balancer_available_type.go @@ -0,0 +1,70 @@ +// Unless explicitly stated otherwise all files in this repository are licensed under the Apache-2.0 License. +// This product includes software developed at ApeCloud (https://www.apecloud.com/). +// Copyright 2022-Present ApeCloud Co., Ltd + +package kbcloud + +import ( + "fmt" + + "github.com/apecloud/kb-cloud-client-go/api/common" +) + +// LoadBalancerAvailableType Whether the loadbalancer is available in the environment. +type LoadBalancerAvailableType string + +// List of LoadBalancerAvailableType. +const ( + LoadBalancerAvailableTypeAvailable LoadBalancerAvailableType = "Available" + LoadBalancerAvailableTypeUnavailable LoadBalancerAvailableType = "Unavailable" + LoadBalancerAvailableTypeChecking LoadBalancerAvailableType = "Checking" + LoadBalancerAvailableTypeUnknown LoadBalancerAvailableType = "Unknown" +) + +var allowedLoadBalancerAvailableTypeEnumValues = []LoadBalancerAvailableType{ + LoadBalancerAvailableTypeAvailable, + LoadBalancerAvailableTypeUnavailable, + LoadBalancerAvailableTypeChecking, + LoadBalancerAvailableTypeUnknown, +} + +// GetAllowedValues returns the list of possible values. +func (v *LoadBalancerAvailableType) GetAllowedValues() []LoadBalancerAvailableType { + return allowedLoadBalancerAvailableTypeEnumValues +} + +// UnmarshalJSON deserializes the given payload. +func (v *LoadBalancerAvailableType) UnmarshalJSON(src []byte) error { + var value string + err := common.Unmarshal(src, &value) + if err != nil { + return err + } + *v = LoadBalancerAvailableType(value) + return nil +} + +// NewLoadBalancerAvailableTypeFromValue returns a pointer to a valid LoadBalancerAvailableType +// for the value passed as argument, or an error if the value passed is not allowed by the enum. +func NewLoadBalancerAvailableTypeFromValue(v string) (*LoadBalancerAvailableType, error) { + ev := LoadBalancerAvailableType(v) + if ev.IsValid() { + return &ev, nil + } + return nil, fmt.Errorf("invalid value '%v' for LoadBalancerAvailableType: valid values are %v", v, allowedLoadBalancerAvailableTypeEnumValues) +} + +// IsValid return true if the value is valid for the enum, false otherwise. +func (v LoadBalancerAvailableType) IsValid() bool { + for _, existing := range allowedLoadBalancerAvailableTypeEnumValues { + if existing == v { + return true + } + } + return false +} + +// Ptr returns reference to LoadBalancerAvailableType value. +func (v LoadBalancerAvailableType) Ptr() *LoadBalancerAvailableType { + return &v +} diff --git a/generate.sh b/generate.sh new file mode 100644 index 00000000..871faee3 --- /dev/null +++ b/generate.sh @@ -0,0 +1,11 @@ +#!/bin/bash + +set -e +set -x + +cd .generator +poetry install +poetry run python -m generator ./schemas/* -o ../api + +cd ../api +goimports -w . \ No newline at end of file diff --git a/go.mod b/go.mod index 40bc2bd6..62db63c8 100644 --- a/go.mod +++ b/go.mod @@ -6,6 +6,7 @@ require ( github.com/goccy/go-json v0.10.2 github.com/google/uuid v1.5.0 golang.org/x/oauth2 v0.10.0 + github.com/icholy/digest v0.1.23 ) require ( diff --git a/go.sum b/go.sum index 729950df..463413a7 100644 --- a/go.sum +++ b/go.sum @@ -9,6 +9,8 @@ github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38= github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/uuid v1.5.0 h1:1p67kYwdtXjb0gL0BPiP1Av9wiZPo5A8z2cWkTZ+eyU= github.com/google/uuid v1.5.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/icholy/digest v0.1.23 h1:4hX2pIloP0aDx7RJW0JewhPPy3R8kU+vWKdxPsCCGtY= +github.com/icholy/digest v0.1.23/go.mod h1:QNrsSGQ5v7v9cReDI0+eyjsXGUoRSUZQHeQ5C4XLa0Y= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks= golang.org/x/net v0.12.0 h1:cfawfvKITfUsFCeJIHJrbSxpeu/E81khclypR0GVT50= diff --git a/tests/api/api_cluster_test.go b/tests/api/api_cluster_test.go index 53bd943f..7eddf94b 100644 --- a/tests/api/api_cluster_test.go +++ b/tests/api/api_cluster_test.go @@ -24,7 +24,7 @@ func TestCreateCluster(t *testing.T) { Version: common.PtrString("8.4.2"), Namespace: common.PtrString("kubeblocks-cloud-ns"), SingleZone: common.PtrBool(true), - TerminationPolicy: common.Ptr(kbcloud.CLUSTERTERMINATIONPOLICY_DELETE), + TerminationPolicy: common.Ptr(kbcloud.ClusterTerminationPolicyDelete), ProxyEnabled: common.PtrBool(true), EnvironmentName: "test", Components: []kbcloud.ComponentsItem{ diff --git a/tests/api/api_organization_test.go b/tests/api/api_organization_test.go new file mode 100644 index 00000000..fa9aa852 --- /dev/null +++ b/tests/api/api_organization_test.go @@ -0,0 +1,22 @@ +package test + +import ( + "context" + "net/http" + "testing" + + "github.com/apecloud/kb-cloud-client-go/api/kbcloud" + "github.com/apecloud/kb-cloud-client-go/tests" +) + +func TestListOrgs(t *testing.T) { + ctx := WithClient(WithTestAuth(NewDefaultContext(context.Background()))) + assert := tests.Assert(ctx, t) + client := Client(ctx) + api := kbcloud.NewOrganizationApi(client) + + orgs, resp, err := api.ListOrg(ctx) + assert.NoError(err) + assert.Equal(http.StatusOK, resp.StatusCode) + assert.NotNil(orgs) +} diff --git a/tests/api/utils.go b/tests/api/utils.go index 01e06d47..ce680b49 100644 --- a/tests/api/utils.go +++ b/tests/api/utils.go @@ -44,17 +44,10 @@ func WithFakeAuth(ctx context.Context) context.Context { func WithTestAuth(ctx context.Context) context.Context { return context.WithValue( ctx, - common.ContextAPIKeys, - map[string]common.APIKey{ - "BearerToken": { - Key: os.Getenv("KB_CLOUD_TEST_CLIENT_BEARER_TOKEN"), - }, - "apiKeyAuth": { - Key: os.Getenv("KB_CLOUD_TEST_CLIENT_API_KEY"), - }, - "appKeyAuth": { - Key: os.Getenv("KB_CLOUD_TEST_CLIENT_APP_KEY"), - }, + common.ContextDigestAuth, + common.DigestAuth{ + UserName: os.Getenv("KB_CLOUD_TEST_API_KEY_NAME"), + Password: os.Getenv("KB_CLOUD_TEST_API_KEY_SECRET"), }, ) } diff --git a/tests/go.mod b/tests/go.mod index 0d3ff1bb..9944b8cb 100644 --- a/tests/go.mod +++ b/tests/go.mod @@ -33,6 +33,7 @@ require ( github.com/hashicorp/go-secure-stdlib/parseutil v0.1.7 // indirect github.com/hashicorp/go-secure-stdlib/strutil v0.1.2 // indirect github.com/hashicorp/go-sockaddr v1.0.2 // indirect + github.com/icholy/digest v0.1.23 // indirect github.com/mitchellh/go-homedir v1.1.0 // indirect github.com/mitchellh/mapstructure v1.5.0 // indirect github.com/outcaste-io/ristretto v0.2.3 // indirect @@ -56,4 +57,4 @@ require ( gopkg.in/yaml.v3 v3.0.1 // indirect ) -replace github.com/apecloud/kb-cloud-client-go => ../ \ No newline at end of file +replace github.com/apecloud/kb-cloud-client-go => ../ diff --git a/tests/go.sum b/tests/go.sum index 9482bbfe..0b8107fe 100644 --- a/tests/go.sum +++ b/tests/go.sum @@ -94,6 +94,8 @@ github.com/hashicorp/go-secure-stdlib/strutil v0.1.2/go.mod h1:Gou2R9+il93BqX25L github.com/hashicorp/go-sockaddr v1.0.2 h1:ztczhD1jLxIRjVejw8gFomI1BQZOe2WoVOu0SyteCQc= github.com/hashicorp/go-sockaddr v1.0.2/go.mod h1:rB4wwRAUzs07qva3c5SdrY/NEtAUjGlgmH/UkBUC97A= github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= +github.com/icholy/digest v0.1.23 h1:4hX2pIloP0aDx7RJW0JewhPPy3R8kU+vWKdxPsCCGtY= +github.com/icholy/digest v0.1.23/go.mod h1:QNrsSGQ5v7v9cReDI0+eyjsXGUoRSUZQHeQ5C4XLa0Y= github.com/jonboulle/clockwork v0.4.0 h1:p4Cf1aMWXnXAUh8lVfewRBx1zaTSYKrKMF2g3ST4RZ4= github.com/jonboulle/clockwork v0.4.0/go.mod h1:xgRqUGwRcjKCO1vbZUEtSLrqKoPSsUpK7fnezOII0kc= github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51 h1:Z9n2FFNUXsshfwJMBgNA0RU6/i7WVaAegv3PtuIHPMs=