From 6b8463569f57191f323267c7785edf1da43d5c7c Mon Sep 17 00:00:00 2001 From: Murad Biashimov Date: Thu, 1 Aug 2024 11:48:29 +0200 Subject: [PATCH] feat: add query params support --- .golangci.yaml | 4 - Taskfile.yml | 2 +- client.go | 30 +-- client_generated.go | 3 +- client_test.go | 77 +++++-- generator/main.go | 211 +++++++++++++----- generator/models.go | 5 +- handler/account/account.go | 9 +- .../accountauthentication.go | 9 +- handler/accountteam/accountteam.go | 9 +- .../accountteammember/accountteammember.go | 9 +- handler/applicationuser/applicationuser.go | 9 +- handler/billinggroup/billinggroup.go | 9 +- handler/clickhouse/clickhouse.go | 60 ++++- handler/cloud/cloud.go | 9 +- handler/domain/domain.go | 9 +- handler/flink/flink.go | 9 +- handler/flinkapplication/flinkapplication.go | 9 +- .../flinkapplicationdeployment.go | 9 +- .../flinkapplicationversion.go | 9 +- handler/flinkjob/flinkjob.go | 9 +- handler/kafka/kafka.go | 9 +- handler/kafkaconnect/kafkaconnect.go | 9 +- handler/kafkamirrormaker/kafkamirrormaker.go | 9 +- .../kafkaschemaregistry.go | 9 +- handler/kafkatopic/kafkatopic.go | 9 +- handler/mysql/mysql.go | 9 +- handler/opensearch/opensearch.go | 9 +- handler/organization/organization.go | 9 +- handler/organizationuser/organizationuser.go | 9 +- handler/postgresql/postgresql.go | 9 +- handler/privatelink/privatelink.go | 9 +- handler/project/project.go | 9 +- handler/projectbilling/projectbilling.go | 9 +- handler/service/service.go | 21 +- .../serviceintegration/serviceintegration.go | 9 +- handler/serviceuser/serviceuser.go | 9 +- handler/staticip/staticip.go | 9 +- handler/thanos/thanos.go | 9 +- handler/user/user.go | 9 +- handler/usergroup/usergroup.go | 9 +- handler/vpc/vpc.go | 9 +- 42 files changed, 469 insertions(+), 241 deletions(-) diff --git a/.golangci.yaml b/.golangci.yaml index 0c840a3..f93a600 100644 --- a/.golangci.yaml +++ b/.golangci.yaml @@ -11,7 +11,6 @@ linters: - errorlint - forbidigo - forcetypeassert - - funlen - gocognit - goconst - gocyclo @@ -23,13 +22,11 @@ linters: - govet - importas - ineffassign - - lll - makezero - misspell - nakedret - nestif - nilerr - - nlreturn - prealloc - revive - staticcheck @@ -37,7 +34,6 @@ linters: - unconvert - unused - whitespace - - wsl linters-settings: gocognit: diff --git a/Taskfile.yml b/Taskfile.yml index 5feea90..77889ec 100644 --- a/Taskfile.yml +++ b/Taskfile.yml @@ -15,11 +15,11 @@ tasks: cmds: - rm -rf {{.GEN_OUT_DIR}} - GEN_OUT_DIR={{.GEN_OUT_DIR}} go run -tags=generator ./generator/... + - task: fmt-imports generate: cmds: - task: get-openapi-spec - task: go-generate - - task: fmt-imports test: cmds: - go test -v ./... diff --git a/client.go b/client.go index c615016..f69c929 100644 --- a/client.go +++ b/client.go @@ -77,11 +77,9 @@ type aivenClient struct { // OperationIDKey is the key used to store the operation ID in the context. type OperationIDKey struct{} -func (d *aivenClient) Do(ctx context.Context, operationID, method, path string, v any) ([]byte, error) { +func (d *aivenClient) Do(ctx context.Context, operationID, method, path string, in any, query ...[2]string) ([]byte, error) { ctx = context.WithValue(ctx, OperationIDKey{}, operationID) - var rsp *http.Response - var err error if d.Debug { @@ -105,7 +103,7 @@ func (d *aivenClient) Do(ctx context.Context, operationID, method, path string, }() } - rsp, err = d.do(ctx, method, path, v) + rsp, err = d.do(ctx, method, path, in, query...) if err != nil { return nil, err } @@ -122,11 +120,11 @@ func (d *aivenClient) Do(ctx context.Context, operationID, method, path string, return b, err } -func (d *aivenClient) do(ctx context.Context, method, path string, v any) (*http.Response, error) { +func (d *aivenClient) do(ctx context.Context, method, path string, in any, query ...[2]string) (*http.Response, error) { var body io.Reader - if !(v == nil || isEmpty(v)) { - b, err := json.Marshal(v) + if !(in == nil || isEmpty(in)) { + b, err := json.Marshal(in) if err != nil { return nil, err } @@ -143,13 +141,19 @@ func (d *aivenClient) do(ctx context.Context, method, path string, v any) (*http req.Header.Set("User-Agent", d.UserAgent) req.Header.Set("Authorization", "aivenv1 "+d.Token) - // TODO: BAD hack to get around pagination in most cases - // we should implement this properly at some point but for now - // that should be its own issue - query := req.URL.Query() - query.Add("limit", "999") - req.URL.RawQuery = query.Encode() + q := req.URL.Query() + for _, v := range query { + q.Set(v[0], v[1]) + } + + if !q.Has("limit") { + // TODO: BAD hack to get around pagination in most cases + // we should implement this properly at some point but for now + // that should be its own issue + q.Set("limit", "999") + } + req.URL.RawQuery = q.Encode() return d.doer.Do(req) } diff --git a/client_generated.go b/client_generated.go index 7a3d7bc..e311dc5 100644 --- a/client_generated.go +++ b/client_generated.go @@ -42,8 +42,9 @@ import ( vpc "github.com/aiven/go-client-codegen/handler/vpc" ) +// doer http client type doer interface { - Do(ctx context.Context, operationID, method, path string, v any) ([]byte, error) + Do(ctx context.Context, operationID, method, path string, in any, query ...[2]string) ([]byte, error) } func newClient(doer doer) Client { diff --git a/client_test.go b/client_test.go index 9b6792f..68c02f3 100644 --- a/client_test.go +++ b/client_test.go @@ -8,11 +8,13 @@ import ( "net/http/httptest" "os" "strings" + "sync/atomic" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/aiven/go-client-codegen/handler/clickhouse" "github.com/aiven/go-client-codegen/handler/service" ) @@ -41,24 +43,44 @@ func TestNewClient(t *testing.T) { } func TestServiceCreate(t *testing.T) { + var callCount int64 + // Creates a test server - server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - require.Equal(t, "/v1/project/foo/service", r.URL.Path) - - // Validates request - expectIn := new(service.ServiceCreateIn) - err := json.NewDecoder(r.Body).Decode(expectIn) - assert.NoError(t, err) - assert.Equal(t, "foo", expectIn.ServiceName) - assert.Equal(t, "kafka", expectIn.ServiceType) - assert.Regexp(t, `go-client-codegen/[0-9\.]+ unit-test`, r.Header["User-Agent"]) - - // Creates response - w.Header().Set("Content-Type", "application/json") - w.WriteHeader(http.StatusOK) - _, err = w.Write([]byte(`{"service": {"plan": "wow", "state": "RUNNING"}}`)) - require.NoError(t, err) - })) + mux := http.NewServeMux() + mux.HandleFunc( + "/v1/project/aiven-project/service", + func(w http.ResponseWriter, r *http.Request) { + // Validates request + expectIn := new(service.ServiceCreateIn) + err := json.NewDecoder(r.Body).Decode(expectIn) + assert.NoError(t, err) + assert.Equal(t, "my-clickhouse", expectIn.ServiceName) + assert.Equal(t, "clickhouse", expectIn.ServiceType) + assert.Regexp(t, `go-client-codegen/[0-9\.]+ unit-test`, r.Header["User-Agent"]) + + // Creates response + w.Header().Set("Content-Type", "application/json") + w.WriteHeader(http.StatusOK) + _, err = w.Write([]byte(`{"service": {"plan": "wow", "state": "RUNNING"}}`)) + require.NoError(t, err) + atomic.AddInt64(&callCount, 1) + }, + ) + mux.HandleFunc( + "/v1/project/aiven-project/service/my-clickhouse/clickhouse/query/stats", + func(w http.ResponseWriter, r *http.Request) { + assert.Equal(t, r.URL.RawQuery, "limit=1&order_by=max_time%3Aasc") + + // Creates response + w.Header().Set("Content-Type", "application/json") + w.WriteHeader(http.StatusOK) + _, err := w.Write([]byte(`{"queries": [{"calls": 1}]}`)) + require.NoError(t, err) + atomic.AddInt64(&callCount, 1) + }, + ) + + server := httptest.NewServer(mux) defer server.Close() // Points a new client to the server url @@ -68,12 +90,27 @@ func TestServiceCreate(t *testing.T) { // Makes create request in := &service.ServiceCreateIn{ - ServiceName: "foo", - ServiceType: "kafka", + ServiceName: "my-clickhouse", + ServiceType: "clickhouse", } - out, err := c.ServiceCreate(context.Background(), "foo", in) + + ctx := context.Background() + project := "aiven-project" + out, err := c.ServiceCreate(ctx, project, in) require.NoError(t, err) require.NotNil(t, out) assert.Equal(t, "wow", out.Plan) assert.Equal(t, service.ServiceStateTypeRunning, out.State) + + // Validates query params + stats, err := c.ServiceClickHouseQueryStats( + ctx, project, in.ServiceName, + clickhouse.ServiceClickHouseQueryStatsLimit(1), + clickhouse.ServiceClickHouseQueryStatsOrderByType(clickhouse.OrderByTypeMaxTimeasc), + ) + require.NoError(t, err) + assert.Len(t, stats, 1) + + // All calls are received + assert.EqualValues(t, 2, callCount) } diff --git a/generator/main.go b/generator/main.go index 43e74e4..f5befab 100644 --- a/generator/main.go +++ b/generator/main.go @@ -12,6 +12,7 @@ import ( "regexp" "sort" "strings" + "sync" "time" "github.com/dave/jennifer/jen" @@ -43,15 +44,30 @@ var ( pathVersioning = regexp.MustCompile(`^/v[0-9]/`) ) +var strFormatters = map[SchemaType]string{ + SchemaTypeInteger: "%d", + SchemaTypeNumber: "%f", + SchemaTypeString: "%s", + SchemaTypeBoolean: "%t", +} + func main() { log.Logger = log.Output(zerolog.ConsoleWriter{Out: os.Stderr, TimeFormat: time.RFC3339}) err := exec() if err != nil { - log.Err(err) + log.Err(err).Send() } } +const ( + doerName = "doer" + handlerTypeName = "Handler" + queryParamName = "query" + queryParamTypeName = "queryParam" + queryParamArraySize = 2 +) + // nolint:funlen,gocognit,gocyclo // It's a generator, it's supposed to be long, and we won't expand it. func exec() error { cfg := new(envConfig) @@ -105,7 +121,6 @@ func exec() error { if pkg == "" { log.Error().Msgf("%q id not found in config!", p.ID) - continue } @@ -121,12 +136,6 @@ func exec() error { return fmt.Errorf("param %q not found", ref.Ref) } - if param.In != ParameterInPath { - log.Printf("%q param %s in %q", p.OperationID, param.Name, param.In) - - continue - } - if param.Name == "version_id" { param.Schema.Type = SchemaTypeInteger } @@ -139,27 +148,28 @@ func exec() error { } } - const doerName = "doer" - ctx := jen.Id("ctx").Qual("context", "Context") - doer := jen.Type().Id(doerName).Interface( + doer := jen.Comment(doerName + " http client").Line().Type().Id(doerName).Interface( jen.Id("Do").Params( ctx, jen.List(jen.Id("operationID"), jen.Id("method"), jen.Id("path")).String(), - jen.Id("v").Any(), + jen.Id("in").Any(), + jen.Id(queryParamName).Op("...").Add(fmtQueryParamType()), ).Parens(jen.List(jen.Index().Byte(), jen.Error())), ).Line() + + // A private type to limit query params to the declared keys/values list + queryParamType := jen.Type().Id(queryParamTypeName).Index(jen.Lit(queryParamArraySize)).String() + clientFields := make([]jen.Code, 0, len(pkgs)) clientValues := jen.Dict{} clientTypeValues := make([]jen.Code, 0, len(pkgs)) for _, pkg := range sortedKeys(pkgs) { - const handlerType = "Handler" - paths := pkgs[pkg] fileName := strings.ToLower(pkg) - handlerName := pkg + handlerType - newHandler := "New" + handlerType + handlerName := pkg + handlerTypeName + newHandler := "New" + handlerTypeName scope := make(map[string]*Schema) for _, p := range paths { @@ -172,35 +182,71 @@ func exec() error { file := jen.NewFile(fileName) file.HeaderComment(generatedHeader) - handler := file.Type().Id(handlerType) + + // Adds private types (interfaces) + privateTypes := file.Add(doer) + + // We want to add query params type when there is any + addQueryParams := new(sync.Once) + + // Creates the handler's type (interface) + // Reserves the line in the file + handlerType := file.Type().Id(handlerTypeName) + + // Creates the "new" constructor file.Func().Id(newHandler).Params(jen.Id(doerName).Id(doerName)).Id(handlerName).Block( jen.Return(jen.Id(handlerName).Values(jen.Id(doerName))), ) - file.Add(doer) + + // Creates the handler's implementation file.Type().Id(handlerName).Struct(jen.Id(doerName).Id(doerName)) var typeMethods []jen.Code - for _, path := range paths { // todo: support 204 out := path.Out.OK.Content["application/json"] if out == nil && path.Out.NoContent.Content == nil { log.Printf("%q has no json response. Skipping", path.OperationID) - continue } + // Method's schemas and query params schemas := make([]*Schema, 0) - params := make([]jen.Code, 0, len(path.Parameters)) - params = append(params, ctx) + queryParams := make([]*Schema, 0) + + // Interface and implementation args + funcArgs := []jen.Code{ctx} + // Collects params: in path and in query + // Adds to schemas to render enums for _, p := range path.Parameters { - p.Schema.in = true p.Schema.required = true p.Schema.init(doc, scope, p.Name) - schemas = append(schemas, p.Schema) - param := jen.Id(strcase.ToLowerCamel(p.Schema.CamelName)).Add(getType(p.Schema)) - params = append(params, param) + + if p.In == ParameterInPath { + schemas = append(schemas, p.Schema) + param := jen.Id(p.Schema.lowerCamel()).Add(getType(p.Schema)) + funcArgs = append(funcArgs, param) + continue + } + + // Adds query params type once + addQueryParams.Do(func() { + privateTypes.Add( + jen.Comment(queryParamTypeName+" http query params private type").Line(), + queryParamType.Clone().Line(), + ) + }) + + queryParams = append(queryParams, p.Schema) + + // Adds param function (request modifier) + var code *jen.Statement + code, err = fmtQueryParam(path.FuncName, p) + if err != nil { + return err + } + file.Add(code) } in := path.In.Content["application/json"] @@ -213,14 +259,18 @@ func exec() error { } schemaIn.in = true - schemaIn.init(doc, scope, path.FuncName) schemas = append(schemas, schemaIn) - params = append(params, jen.Id("in").Id("*"+schemaIn.CamelName)) + funcArgs = append(funcArgs, jen.Id("in").Id("*"+schemaIn.CamelName)) + } + + // Adds queryParams options + if len(queryParams) > 0 { + funcArgs = append(funcArgs, jen.Id(queryParamName).Op("...").Id(queryParamTypeName)) } - typeMeth := jen.Id(path.FuncName).Params(params...) - structMeth := jen.Func().Params(jen.Id("h").Id("*" + handlerName)).Id(path.FuncName).Params(params...) + typeMeth := jen.Id(path.FuncName).Params(funcArgs...) + structMeth := jen.Func().Params(jen.Id("h").Id("*" + handlerName)).Id(path.FuncName).Params(funcArgs...) var rsp, schemaOut *Schema if out != nil { @@ -230,7 +280,6 @@ func exec() error { } schemaOut.out = true - schemaOut.init(doc, scope, path.FuncName) rsp = getResponse(schemaOut) } @@ -254,33 +303,36 @@ func exec() error { typeMethods = append(typeMethods, path.Comment(), typeMeth.Line()) + // Crates a go formattable path, i.e.: + // /foo/{foo}/ => /foo/%s/ paramIndex := -1 url := pathClean.ReplaceAllStringFunc(path.Path, func(_ string) string { paramIndex++ - - switch t := path.Parameters[paramIndex].Schema.Type; t { - case SchemaTypeInteger: - return "%d" - case SchemaTypeString: - return "%s" - default: + t, ok := strFormatters[path.Parameters[paramIndex].Schema.Type] + if !ok { panic(fmt.Sprintf("%s unexpected parameter type %s", path.OperationID, t)) } + return t }) - urlParams := make([]jen.Code, 0, len(params)) + + urlParams := make([]jen.Code, 0, len(funcArgs)) urlParams = append(urlParams, jen.Lit(url)) inObj := jen.Nil() - for _, s := range schemas { if s.isObject() { inObj = jen.Id("in") - continue } - v := jen.Id(strcase.ToLowerCamel(s.CamelName)) + v := jen.Id(s.lowerCamel()) + if s.isEnum() { + // Stringifies enums + v = jen.String().Call(v) + } + + // Escapes string values if s.Type == SchemaTypeString { - v = jen.Id("url.PathEscape").Call(v) + v = jen.Qual("net/url", "PathEscape").Call(v) } urlParams = append(urlParams, v) @@ -289,6 +341,7 @@ func exec() error { outObj := jen.Id("_") returnErr := jen.Return(jen.Err()) + // Formats "return" statement if rsp != nil { outObj = jen.Id("b") @@ -308,24 +361,43 @@ func exec() error { } } - block := []jen.Code{ - jen.Id("path").Op(":=").Qual("fmt", "Sprintf").Call(urlParams...), - jen.List(outObj, jen.Err()).Op(":=").Id("h.doer.Do").Call( - jen.Id("ctx"), - jen.Lit(path.OperationID), - jen.Lit(path.Method), - jen.Id("path"), - inObj, - ), + // The Doer call + callOpts := []jen.Code{ + jen.Id("ctx"), + jen.Lit(path.OperationID), + jen.Lit(path.Method), + jen.Id("path"), + inObj, } - ifErr := jen.If(jen.Err().Op("!=").Nil()).Block(returnErr) + var block []jen.Code + + // Adds unpacking for query params + if len(queryParams) > 1 { + q := jen.Id(queryParamName) + p := jen.Id("p") + v := jen.Id("v") + callOpts = append(callOpts, p.Clone().Op("...")) + block = append( + block, + p.Clone().Op(":=").Make(jen.Index().Index(jen.Lit(queryParamArraySize)).String(), jen.Lit(0), jen.Len(q)), + jen.For(jen.List(jen.Id("_"), v.Clone().Op(":=").Range().Add(jen.Id(queryParamName)))). + Block(p.Clone().Op("=").Append(p, v)), + ) + } + // Implementation (method's) body + block = append( + block, + jen.Id("path").Op(":=").Qual("fmt", "Sprintf").Call(urlParams...), + jen.List(outObj, jen.Err()).Op(":=").Id("h.doer.Do").Call(callOpts...), + ) + + ifErr := jen.If(jen.Err().Op("!=").Nil()).Block(returnErr) if rsp == nil { block = append(block, jen.Return(jen.Err())) } else { block = append(block, ifErr) - outReturn := jen.Id("out") if rsp.CamelName != schemaOut.CamelName { @@ -367,7 +439,7 @@ func exec() error { return err } - handler.Interface(typeMethods...) + handlerType.Interface(typeMethods...) err = file.Save(filepath.Join(dirPath, fileName+".go")) if err != nil { @@ -377,7 +449,7 @@ func exec() error { pkgName := filepath.Join(cfg.Module, cfg.HandlerDir, fileName) clientFields = append(clientFields, jen.Qual(pkgName, handlerName)) clientValues[jen.Id(handlerName)] = jen.Qual(pkgName, newHandler).Call(jen.Id(doerName)) - clientTypeValues = append(clientTypeValues, jen.Qual(pkgName, handlerType)) + clientTypeValues = append(clientTypeValues, jen.Qual(pkgName, handlerTypeName)) } client := jen.NewFile(cfg.Package) @@ -543,3 +615,30 @@ var reComment = regexp.MustCompile(`\.?[\r\n]+\s*?`) func fmtComment(c string) string { return reComment.ReplaceAllString(c, ". ") } + +// fmtQueryParam returns a query param +func fmtQueryParam(funcName string, p *Parameter) (*jen.Statement, error) { + keyFuncName := funcName + p.Schema.CamelName + keyVarName := jen.Id(p.Schema.lowerCamel()) + + var value *jen.Statement + format, ok := strFormatters[p.Schema.Type] + if !ok { + return nil, fmt.Errorf("query param with type %q is not supported", p.Schema.Type) + } + value = jen.Qual("fmt", "Sprintf").Call(jen.Lit(format), keyVarName.Clone()) + + param := jen.Comment(fmt.Sprintf("%s %s", keyFuncName, fmtComment(p.Description))) + param.Line() + param.Func().Id(keyFuncName). + Params(keyVarName.Clone().Add(getType(p.Schema))).Params(jen.Id(queryParamTypeName)). + Block( + jen.Return(jen.Id(queryParamTypeName).Values(jen.Lit(p.Schema.name), value)), + ) + return param, nil +} + +// fmtQueryParamType literally returns: [2]string +func fmtQueryParamType() *jen.Statement { + return jen.Index(jen.Lit(queryParamArraySize)).String() +} diff --git a/generator/models.go b/generator/models.go index 50ab71d..c154744 100644 --- a/generator/models.go +++ b/generator/models.go @@ -105,7 +105,6 @@ const ( type Parameter struct { Ref string `json:"$ref"` In ParameterIn `json:"in"` - Required bool `json:"required"` Name string `json:"name"` Description string `json:"description"` Schema *Schema `json:"schema"` @@ -346,6 +345,10 @@ func (s *Schema) isOut() bool { return s.root().out } +func (s *Schema) lowerCamel() string { + return strcase.ToLowerCamel(s.CamelName) +} + func getScalarType(s *Schema) *jen.Statement { switch s.Type { case SchemaTypeString: diff --git a/handler/account/account.go b/handler/account/account.go index 3e55d1b..79782ed 100644 --- a/handler/account/account.go +++ b/handler/account/account.go @@ -10,6 +10,11 @@ import ( "time" ) +// doer http client +type doer interface { + Do(ctx context.Context, operationID, method, path string, in any, query ...[2]string) ([]byte, error) +} + type Handler interface { // AccountAttachPaymentMethod attach payment method for account // POST /v1/account/{account_id}/payment_methods @@ -96,10 +101,6 @@ func NewHandler(doer doer) AccountHandler { return AccountHandler{doer} } -type doer interface { - Do(ctx context.Context, operationID, method, path string, v any) ([]byte, error) -} - type AccountHandler struct { doer doer } diff --git a/handler/accountauthentication/accountauthentication.go b/handler/accountauthentication/accountauthentication.go index 1833bf7..1626cec 100644 --- a/handler/accountauthentication/accountauthentication.go +++ b/handler/accountauthentication/accountauthentication.go @@ -10,6 +10,11 @@ import ( "time" ) +// doer http client +type doer interface { + Do(ctx context.Context, operationID, method, path string, in any, query ...[2]string) ([]byte, error) +} + type Handler interface { // AccountAuthenticationMethodCreate create a new authentication method // POST /v1/account/{account_id}/authentication @@ -41,10 +46,6 @@ func NewHandler(doer doer) AccountAuthenticationHandler { return AccountAuthenticationHandler{doer} } -type doer interface { - Do(ctx context.Context, operationID, method, path string, v any) ([]byte, error) -} - type AccountAuthenticationHandler struct { doer doer } diff --git a/handler/accountteam/accountteam.go b/handler/accountteam/accountteam.go index c68e828..bc6d2a2 100644 --- a/handler/accountteam/accountteam.go +++ b/handler/accountteam/accountteam.go @@ -10,6 +10,11 @@ import ( "time" ) +// doer http client +type doer interface { + Do(ctx context.Context, operationID, method, path string, in any, query ...[2]string) ([]byte, error) +} + type Handler interface { // Deprecated: AccountTeamCreate create a new team // POST /v1/account/{account_id}/teams @@ -66,10 +71,6 @@ func NewHandler(doer doer) AccountTeamHandler { return AccountTeamHandler{doer} } -type doer interface { - Do(ctx context.Context, operationID, method, path string, v any) ([]byte, error) -} - type AccountTeamHandler struct { doer doer } diff --git a/handler/accountteammember/accountteammember.go b/handler/accountteammember/accountteammember.go index 4ea5cd9..b9583a5 100644 --- a/handler/accountteammember/accountteammember.go +++ b/handler/accountteammember/accountteammember.go @@ -10,6 +10,11 @@ import ( "time" ) +// doer http client +type doer interface { + Do(ctx context.Context, operationID, method, path string, in any, query ...[2]string) ([]byte, error) +} + type Handler interface { // Deprecated: AccountTeamMemberCancelInvite cancel pending user invite // DELETE /v1/account/{account_id}/team/{team_id}/invites/{user_email} @@ -41,10 +46,6 @@ func NewHandler(doer doer) AccountTeamMemberHandler { return AccountTeamMemberHandler{doer} } -type doer interface { - Do(ctx context.Context, operationID, method, path string, v any) ([]byte, error) -} - type AccountTeamMemberHandler struct { doer doer } diff --git a/handler/applicationuser/applicationuser.go b/handler/applicationuser/applicationuser.go index 74b8774..9fe9654 100644 --- a/handler/applicationuser/applicationuser.go +++ b/handler/applicationuser/applicationuser.go @@ -10,6 +10,11 @@ import ( "time" ) +// doer http client +type doer interface { + Do(ctx context.Context, operationID, method, path string, in any, query ...[2]string) ([]byte, error) +} + type Handler interface { // ApplicationUserAccessTokenCreate create an application token // POST /v1/organization/{organization_id}/application-users/{user_id}/access-tokens @@ -56,10 +61,6 @@ func NewHandler(doer doer) ApplicationUserHandler { return ApplicationUserHandler{doer} } -type doer interface { - Do(ctx context.Context, operationID, method, path string, v any) ([]byte, error) -} - type ApplicationUserHandler struct { doer doer } diff --git a/handler/billinggroup/billinggroup.go b/handler/billinggroup/billinggroup.go index 68483bc..80e5839 100644 --- a/handler/billinggroup/billinggroup.go +++ b/handler/billinggroup/billinggroup.go @@ -10,6 +10,11 @@ import ( "time" ) +// doer http client +type doer interface { + Do(ctx context.Context, operationID, method, path string, in any, query ...[2]string) ([]byte, error) +} + type Handler interface { // BillingGroupCreate create a billing group // POST /v1/billing-group @@ -81,10 +86,6 @@ func NewHandler(doer doer) BillingGroupHandler { return BillingGroupHandler{doer} } -type doer interface { - Do(ctx context.Context, operationID, method, path string, v any) ([]byte, error) -} - type BillingGroupHandler struct { doer doer } diff --git a/handler/clickhouse/clickhouse.go b/handler/clickhouse/clickhouse.go index f1435de..2cda098 100644 --- a/handler/clickhouse/clickhouse.go +++ b/handler/clickhouse/clickhouse.go @@ -9,6 +9,14 @@ import ( "net/url" ) +// doer http client +type doer interface { + Do(ctx context.Context, operationID, method, path string, in any, query ...[2]string) ([]byte, error) +} + +// queryParam http query params private type +type queryParam [2]string + type Handler interface { // ServiceClickHouseCurrentQueries list active queries // GET /v1/project/{project}/service/{service_name}/clickhouse/query @@ -38,7 +46,7 @@ type Handler interface { // ServiceClickHouseQueryStats return statistics on recent queries // GET /v1/project/{project}/service/{service_name}/clickhouse/query/stats // https://api.aiven.io/doc/#tag/Service:_ClickHouse/operation/ServiceClickHouseQueryStats - ServiceClickHouseQueryStats(ctx context.Context, project string, serviceName string) ([]QueryOutAlt, error) + ServiceClickHouseQueryStats(ctx context.Context, project string, serviceName string, query ...queryParam) ([]QueryOutAlt, error) // ServiceClickHouseTieredStorageSummary get the ClickHouse tiered storage summary // GET /v1/project/{project}/service/{service_name}/clickhouse/tiered-storage/summary @@ -50,10 +58,6 @@ func NewHandler(doer doer) ClickHouseHandler { return ClickHouseHandler{doer} } -type doer interface { - Do(ctx context.Context, operationID, method, path string, v any) ([]byte, error) -} - type ClickHouseHandler struct { doer doer } @@ -107,9 +111,28 @@ func (h *ClickHouseHandler) ServiceClickHouseQuery(ctx context.Context, project } return out, nil } -func (h *ClickHouseHandler) ServiceClickHouseQueryStats(ctx context.Context, project string, serviceName string) ([]QueryOutAlt, error) { + +// ServiceClickHouseQueryStatsLimit Limit for number of results +func ServiceClickHouseQueryStatsLimit(limit int) queryParam { + return queryParam{"limit", fmt.Sprintf("%d", limit)} +} + +// ServiceClickHouseQueryStatsOffset Offset for retrieved results based on sort order +func ServiceClickHouseQueryStatsOffset(offset int) queryParam { + return queryParam{"offset", fmt.Sprintf("%d", offset)} +} + +// ServiceClickHouseQueryStatsOrderByType Order in which to sort retrieved results +func ServiceClickHouseQueryStatsOrderByType(orderByType OrderByType) queryParam { + return queryParam{"order_by", fmt.Sprintf("%s", orderByType)} +} +func (h *ClickHouseHandler) ServiceClickHouseQueryStats(ctx context.Context, project string, serviceName string, query ...queryParam) ([]QueryOutAlt, error) { + p := make([][2]string, 0, len(query)) + for _, v := range query { + p = append(p, v) + } path := fmt.Sprintf("/v1/project/%s/service/%s/clickhouse/query/stats", url.PathEscape(project), url.PathEscape(serviceName)) - b, err := h.doer.Do(ctx, "ServiceClickHouseQueryStats", "GET", path, nil) + b, err := h.doer.Do(ctx, "ServiceClickHouseQueryStats", "GET", path, nil, p...) if err != nil { return nil, err } @@ -161,6 +184,29 @@ type MetaOut struct { Name string `json:"name"` // Column name Type string `json:"type"` // Column type } +type OrderByType string + +const ( + OrderByTypeCallsasc OrderByType = "calls:asc" + OrderByTypeCallsdesc OrderByType = "calls:desc" + OrderByTypeMinTimeasc OrderByType = "min_time:asc" + OrderByTypeMinTimedesc OrderByType = "min_time:desc" + OrderByTypeMaxTimeasc OrderByType = "max_time:asc" + OrderByTypeMaxTimedesc OrderByType = "max_time:desc" + OrderByTypeMeanTimeasc OrderByType = "mean_time:asc" + OrderByTypeMeanTimedesc OrderByType = "mean_time:desc" + OrderByTypeP95Timeasc OrderByType = "p95_time:asc" + OrderByTypeP95Timedesc OrderByType = "p95_time:desc" + OrderByTypeStddevTimeasc OrderByType = "stddev_time:asc" + OrderByTypeStddevTimedesc OrderByType = "stddev_time:desc" + OrderByTypeTotalTimeasc OrderByType = "total_time:asc" + OrderByTypeTotalTimedesc OrderByType = "total_time:desc" +) + +func OrderByTypeChoices() []string { + return []string{"calls:asc", "calls:desc", "min_time:asc", "min_time:desc", "max_time:asc", "max_time:desc", "mean_time:asc", "mean_time:desc", "p95_time:asc", "p95_time:desc", "stddev_time:asc", "stddev_time:desc", "total_time:asc", "total_time:desc"} +} + type QueryOut struct { ClientName *string `json:"client_name,omitempty"` // Client name, if set Database *string `json:"database,omitempty"` diff --git a/handler/cloud/cloud.go b/handler/cloud/cloud.go index aa1a487..2f3a5b8 100644 --- a/handler/cloud/cloud.go +++ b/handler/cloud/cloud.go @@ -9,6 +9,11 @@ import ( "net/url" ) +// doer http client +type doer interface { + Do(ctx context.Context, operationID, method, path string, in any, query ...[2]string) ([]byte, error) +} + type Handler interface { // ListClouds list cloud platforms // GET /v1/clouds @@ -25,10 +30,6 @@ func NewHandler(doer doer) CloudHandler { return CloudHandler{doer} } -type doer interface { - Do(ctx context.Context, operationID, method, path string, v any) ([]byte, error) -} - type CloudHandler struct { doer doer } diff --git a/handler/domain/domain.go b/handler/domain/domain.go index 58571dc..f43511b 100644 --- a/handler/domain/domain.go +++ b/handler/domain/domain.go @@ -10,6 +10,11 @@ import ( "time" ) +// doer http client +type doer interface { + Do(ctx context.Context, operationID, method, path string, in any, query ...[2]string) ([]byte, error) +} + type Handler interface { // OrganizationDomainAdd create a domain // POST /v1/organization/{organization_id}/domains @@ -41,10 +46,6 @@ func NewHandler(doer doer) DomainHandler { return DomainHandler{doer} } -type doer interface { - Do(ctx context.Context, operationID, method, path string, v any) ([]byte, error) -} - type DomainHandler struct { doer doer } diff --git a/handler/flink/flink.go b/handler/flink/flink.go index b7b4cc9..55ef564 100644 --- a/handler/flink/flink.go +++ b/handler/flink/flink.go @@ -9,6 +9,11 @@ import ( "net/url" ) +// doer http client +type doer interface { + Do(ctx context.Context, operationID, method, path string, in any, query ...[2]string) ([]byte, error) +} + type Handler interface { // ServiceFlinkOverview get a cluster overview // GET /v1/project/{project}/service/{service_name}/flink/overview @@ -20,10 +25,6 @@ func NewHandler(doer doer) FlinkHandler { return FlinkHandler{doer} } -type doer interface { - Do(ctx context.Context, operationID, method, path string, v any) ([]byte, error) -} - type FlinkHandler struct { doer doer } diff --git a/handler/flinkapplication/flinkapplication.go b/handler/flinkapplication/flinkapplication.go index 6ceceae..5e77e13 100644 --- a/handler/flinkapplication/flinkapplication.go +++ b/handler/flinkapplication/flinkapplication.go @@ -10,6 +10,11 @@ import ( "time" ) +// doer http client +type doer interface { + Do(ctx context.Context, operationID, method, path string, in any, query ...[2]string) ([]byte, error) +} + type Handler interface { // ServiceFlinkCreateApplication create a Flink Application // POST /v1/project/{project}/service/{service_name}/flink/application @@ -41,10 +46,6 @@ func NewHandler(doer doer) FlinkApplicationHandler { return FlinkApplicationHandler{doer} } -type doer interface { - Do(ctx context.Context, operationID, method, path string, v any) ([]byte, error) -} - type FlinkApplicationHandler struct { doer doer } diff --git a/handler/flinkapplicationdeployment/flinkapplicationdeployment.go b/handler/flinkapplicationdeployment/flinkapplicationdeployment.go index dd34dec..aba09ea 100644 --- a/handler/flinkapplicationdeployment/flinkapplicationdeployment.go +++ b/handler/flinkapplicationdeployment/flinkapplicationdeployment.go @@ -10,6 +10,11 @@ import ( "time" ) +// doer http client +type doer interface { + Do(ctx context.Context, operationID, method, path string, in any, query ...[2]string) ([]byte, error) +} + type Handler interface { // ServiceFlinkCancelApplicationDeployment cancel an ApplicationDeployment // POST /v1/project/{project}/service/{service_name}/flink/application/{application_id}/deployment/{deployment_id}/cancel @@ -46,10 +51,6 @@ func NewHandler(doer doer) FlinkApplicationDeploymentHandler { return FlinkApplicationDeploymentHandler{doer} } -type doer interface { - Do(ctx context.Context, operationID, method, path string, v any) ([]byte, error) -} - type FlinkApplicationDeploymentHandler struct { doer doer } diff --git a/handler/flinkapplicationversion/flinkapplicationversion.go b/handler/flinkapplicationversion/flinkapplicationversion.go index 1b9a972..f776f51 100644 --- a/handler/flinkapplicationversion/flinkapplicationversion.go +++ b/handler/flinkapplicationversion/flinkapplicationversion.go @@ -10,6 +10,11 @@ import ( "time" ) +// doer http client +type doer interface { + Do(ctx context.Context, operationID, method, path string, in any, query ...[2]string) ([]byte, error) +} + type Handler interface { // ServiceFlinkCreateApplicationVersion create a Flink ApplicationVersion // POST /v1/project/{project}/service/{service_name}/flink/application/{application_id}/version @@ -36,10 +41,6 @@ func NewHandler(doer doer) FlinkApplicationVersionHandler { return FlinkApplicationVersionHandler{doer} } -type doer interface { - Do(ctx context.Context, operationID, method, path string, v any) ([]byte, error) -} - type FlinkApplicationVersionHandler struct { doer doer } diff --git a/handler/flinkjob/flinkjob.go b/handler/flinkjob/flinkjob.go index c78eff3..706d0a7 100644 --- a/handler/flinkjob/flinkjob.go +++ b/handler/flinkjob/flinkjob.go @@ -9,6 +9,11 @@ import ( "net/url" ) +// doer http client +type doer interface { + Do(ctx context.Context, operationID, method, path string, in any, query ...[2]string) ([]byte, error) +} + type Handler interface { // ServiceFlinkJobDetails get a Flink job info // GET /v1/project/{project}/service/{service_name}/flink/job/{job_id} @@ -25,10 +30,6 @@ func NewHandler(doer doer) FlinkJobHandler { return FlinkJobHandler{doer} } -type doer interface { - Do(ctx context.Context, operationID, method, path string, v any) ([]byte, error) -} - type FlinkJobHandler struct { doer doer } diff --git a/handler/kafka/kafka.go b/handler/kafka/kafka.go index fc7b874..ca41741 100644 --- a/handler/kafka/kafka.go +++ b/handler/kafka/kafka.go @@ -9,6 +9,11 @@ import ( "net/url" ) +// doer http client +type doer interface { + Do(ctx context.Context, operationID, method, path string, in any, query ...[2]string) ([]byte, error) +} + type Handler interface { // ServiceKafkaAclAdd add a Kafka ACL entry // POST /v1/project/{project}/service/{service_name}/acl @@ -65,10 +70,6 @@ func NewHandler(doer doer) KafkaHandler { return KafkaHandler{doer} } -type doer interface { - Do(ctx context.Context, operationID, method, path string, v any) ([]byte, error) -} - type KafkaHandler struct { doer doer } diff --git a/handler/kafkaconnect/kafkaconnect.go b/handler/kafkaconnect/kafkaconnect.go index 2a1dbb5..0ba1229 100644 --- a/handler/kafkaconnect/kafkaconnect.go +++ b/handler/kafkaconnect/kafkaconnect.go @@ -9,6 +9,11 @@ import ( "net/url" ) +// doer http client +type doer interface { + Do(ctx context.Context, operationID, method, path string, in any, query ...[2]string) ([]byte, error) +} + type Handler interface { // ServiceKafkaConnectCreateConnector create a Kafka Connect connector // POST /v1/project/{project}/service/{service_name}/connectors @@ -70,10 +75,6 @@ func NewHandler(doer doer) KafkaConnectHandler { return KafkaConnectHandler{doer} } -type doer interface { - Do(ctx context.Context, operationID, method, path string, v any) ([]byte, error) -} - type KafkaConnectHandler struct { doer doer } diff --git a/handler/kafkamirrormaker/kafkamirrormaker.go b/handler/kafkamirrormaker/kafkamirrormaker.go index 3cbf2d6..db24fdc 100644 --- a/handler/kafkamirrormaker/kafkamirrormaker.go +++ b/handler/kafkamirrormaker/kafkamirrormaker.go @@ -9,6 +9,11 @@ import ( "net/url" ) +// doer http client +type doer interface { + Do(ctx context.Context, operationID, method, path string, in any, query ...[2]string) ([]byte, error) +} + type Handler interface { // ServiceKafkaMirrorMakerCreateReplicationFlow create a replication flow // POST /v1/project/{project}/service/{service_name}/mirrormaker/replication-flows @@ -40,10 +45,6 @@ func NewHandler(doer doer) KafkaMirrorMakerHandler { return KafkaMirrorMakerHandler{doer} } -type doer interface { - Do(ctx context.Context, operationID, method, path string, v any) ([]byte, error) -} - type KafkaMirrorMakerHandler struct { doer doer } diff --git a/handler/kafkaschemaregistry/kafkaschemaregistry.go b/handler/kafkaschemaregistry/kafkaschemaregistry.go index 6f3b181..207a0a9 100644 --- a/handler/kafkaschemaregistry/kafkaschemaregistry.go +++ b/handler/kafkaschemaregistry/kafkaschemaregistry.go @@ -9,6 +9,11 @@ import ( "net/url" ) +// doer http client +type doer interface { + Do(ctx context.Context, operationID, method, path string, in any, query ...[2]string) ([]byte, error) +} + type Handler interface { // ServiceSchemaRegistryAclAdd add a Schema Registry ACL entry // POST /v1/project/{project}/service/{service_name}/kafka/schema-registry/acl @@ -95,10 +100,6 @@ func NewHandler(doer doer) KafkaSchemaRegistryHandler { return KafkaSchemaRegistryHandler{doer} } -type doer interface { - Do(ctx context.Context, operationID, method, path string, v any) ([]byte, error) -} - type KafkaSchemaRegistryHandler struct { doer doer } diff --git a/handler/kafkatopic/kafkatopic.go b/handler/kafkatopic/kafkatopic.go index fffa115..6f4ac74 100644 --- a/handler/kafkatopic/kafkatopic.go +++ b/handler/kafkatopic/kafkatopic.go @@ -9,6 +9,11 @@ import ( "net/url" ) +// doer http client +type doer interface { + Do(ctx context.Context, operationID, method, path string, in any, query ...[2]string) ([]byte, error) +} + type Handler interface { // ServiceKafkaTopicCreate create a Kafka topic // POST /v1/project/{project}/service/{service_name}/topic @@ -50,10 +55,6 @@ func NewHandler(doer doer) KafkaTopicHandler { return KafkaTopicHandler{doer} } -type doer interface { - Do(ctx context.Context, operationID, method, path string, v any) ([]byte, error) -} - type KafkaTopicHandler struct { doer doer } diff --git a/handler/mysql/mysql.go b/handler/mysql/mysql.go index 073c941..db45d94 100644 --- a/handler/mysql/mysql.go +++ b/handler/mysql/mysql.go @@ -9,6 +9,11 @@ import ( "net/url" ) +// doer http client +type doer interface { + Do(ctx context.Context, operationID, method, path string, in any, query ...[2]string) ([]byte, error) +} + type Handler interface { // MySQLServiceQueryStatistics fetch MySQL service query statistics // POST /v1/project/{project}/service/{service_name}/mysql/query/stats @@ -20,10 +25,6 @@ func NewHandler(doer doer) MySQLHandler { return MySQLHandler{doer} } -type doer interface { - Do(ctx context.Context, operationID, method, path string, v any) ([]byte, error) -} - type MySQLHandler struct { doer doer } diff --git a/handler/opensearch/opensearch.go b/handler/opensearch/opensearch.go index e6fdef0..03057d9 100644 --- a/handler/opensearch/opensearch.go +++ b/handler/opensearch/opensearch.go @@ -10,6 +10,11 @@ import ( "time" ) +// doer http client +type doer interface { + Do(ctx context.Context, operationID, method, path string, in any, query ...[2]string) ([]byte, error) +} + type Handler interface { // ServiceOpenSearchAclGet show OpenSearch ACL configuration // GET /v1/project/{project}/service/{service_name}/opensearch/acl @@ -56,10 +61,6 @@ func NewHandler(doer doer) OpenSearchHandler { return OpenSearchHandler{doer} } -type doer interface { - Do(ctx context.Context, operationID, method, path string, v any) ([]byte, error) -} - type OpenSearchHandler struct { doer doer } diff --git a/handler/organization/organization.go b/handler/organization/organization.go index 4711d70..df97801 100644 --- a/handler/organization/organization.go +++ b/handler/organization/organization.go @@ -10,6 +10,11 @@ import ( "time" ) +// doer http client +type doer interface { + Do(ctx context.Context, operationID, method, path string, in any, query ...[2]string) ([]byte, error) +} + type Handler interface { // OrganizationAuthDomainLink link a domain to an organization's identity provider // PUT /v1/organization/{organization_id}/authentication-methods/{authentication_method_id}/domains @@ -61,10 +66,6 @@ func NewHandler(doer doer) OrganizationHandler { return OrganizationHandler{doer} } -type doer interface { - Do(ctx context.Context, operationID, method, path string, v any) ([]byte, error) -} - type OrganizationHandler struct { doer doer } diff --git a/handler/organizationuser/organizationuser.go b/handler/organizationuser/organizationuser.go index 7a6a7fc..1a264ba 100644 --- a/handler/organizationuser/organizationuser.go +++ b/handler/organizationuser/organizationuser.go @@ -10,6 +10,11 @@ import ( "time" ) +// doer http client +type doer interface { + Do(ctx context.Context, operationID, method, path string, in any, query ...[2]string) ([]byte, error) +} + type Handler interface { // OrganizationUserAuthenticationMethodsList list authentication methods for a user in the organization // GET /v1/organization/{organization_id}/user/{member_user_id}/authentication_methods @@ -76,10 +81,6 @@ func NewHandler(doer doer) OrganizationUserHandler { return OrganizationUserHandler{doer} } -type doer interface { - Do(ctx context.Context, operationID, method, path string, v any) ([]byte, error) -} - type OrganizationUserHandler struct { doer doer } diff --git a/handler/postgresql/postgresql.go b/handler/postgresql/postgresql.go index a1cca12..5472a8f 100644 --- a/handler/postgresql/postgresql.go +++ b/handler/postgresql/postgresql.go @@ -9,6 +9,11 @@ import ( "net/url" ) +// doer http client +type doer interface { + Do(ctx context.Context, operationID, method, path string, in any, query ...[2]string) ([]byte, error) +} + type Handler interface { // PGServiceAvailableExtensions list PostgreSQL extensions that can be loaded with CREATE EXTENSION in this service // GET /v1/project/{project}/service/{service_name}/pg/available-extensions @@ -45,10 +50,6 @@ func NewHandler(doer doer) PostgreSQLHandler { return PostgreSQLHandler{doer} } -type doer interface { - Do(ctx context.Context, operationID, method, path string, v any) ([]byte, error) -} - type PostgreSQLHandler struct { doer doer } diff --git a/handler/privatelink/privatelink.go b/handler/privatelink/privatelink.go index 25a9552..c05b297 100644 --- a/handler/privatelink/privatelink.go +++ b/handler/privatelink/privatelink.go @@ -9,6 +9,11 @@ import ( "net/url" ) +// doer http client +type doer interface { + Do(ctx context.Context, operationID, method, path string, in any, query ...[2]string) ([]byte, error) +} + type Handler interface { // PublicPrivatelinkAvailabilityList list privatelink clouds and prices // GET /v1/tenants/{tenant}/privatelink-availability @@ -80,10 +85,6 @@ func NewHandler(doer doer) PrivatelinkHandler { return PrivatelinkHandler{doer} } -type doer interface { - Do(ctx context.Context, operationID, method, path string, v any) ([]byte, error) -} - type PrivatelinkHandler struct { doer doer } diff --git a/handler/project/project.go b/handler/project/project.go index 580a052..31bcadd 100644 --- a/handler/project/project.go +++ b/handler/project/project.go @@ -10,6 +10,11 @@ import ( "time" ) +// doer http client +type doer interface { + Do(ctx context.Context, operationID, method, path string, in any, query ...[2]string) ([]byte, error) +} + type Handler interface { // ListProjectVpcPeeringConnectionTypes list VPC peering connection types for a project // GET /v1/project/{project}/vpc-peering-connection-types @@ -116,10 +121,6 @@ func NewHandler(doer doer) ProjectHandler { return ProjectHandler{doer} } -type doer interface { - Do(ctx context.Context, operationID, method, path string, v any) ([]byte, error) -} - type ProjectHandler struct { doer doer } diff --git a/handler/projectbilling/projectbilling.go b/handler/projectbilling/projectbilling.go index 248cb5f..1bf840b 100644 --- a/handler/projectbilling/projectbilling.go +++ b/handler/projectbilling/projectbilling.go @@ -10,6 +10,11 @@ import ( "time" ) +// doer http client +type doer interface { + Do(ctx context.Context, operationID, method, path string, in any, query ...[2]string) ([]byte, error) +} + type Handler interface { // InvoiceGet get a single invoice // GET /v1/invoices/{invoice_number} @@ -36,10 +41,6 @@ func NewHandler(doer doer) ProjectBillingHandler { return ProjectBillingHandler{doer} } -type doer interface { - Do(ctx context.Context, operationID, method, path string, v any) ([]byte, error) -} - type ProjectBillingHandler struct { doer doer } diff --git a/handler/service/service.go b/handler/service/service.go index e0fc9cc..076da7f 100644 --- a/handler/service/service.go +++ b/handler/service/service.go @@ -10,6 +10,14 @@ import ( "time" ) +// doer http client +type doer interface { + Do(ctx context.Context, operationID, method, path string, in any, query ...[2]string) ([]byte, error) +} + +// queryParam http query params private type +type queryParam [2]string + type Handler interface { // ListProjectServiceTypes list service types for a project // GET /v1/project/{project}/service_types @@ -159,17 +167,13 @@ type Handler interface { // ServiceUpdate update service configuration // PUT /v1/project/{project}/service/{service_name} // https://api.aiven.io/doc/#tag/Service/operation/ServiceUpdate - ServiceUpdate(ctx context.Context, project string, serviceName string, in *ServiceUpdateIn) (*ServiceUpdateOut, error) + ServiceUpdate(ctx context.Context, project string, serviceName string, in *ServiceUpdateIn, query ...queryParam) (*ServiceUpdateOut, error) } func NewHandler(doer doer) ServiceHandler { return ServiceHandler{doer} } -type doer interface { - Do(ctx context.Context, operationID, method, path string, v any) ([]byte, error) -} - type ServiceHandler struct { doer doer } @@ -503,7 +507,12 @@ func (h *ServiceHandler) ServiceTaskGet(ctx context.Context, project string, ser } return &out.Task, nil } -func (h *ServiceHandler) ServiceUpdate(ctx context.Context, project string, serviceName string, in *ServiceUpdateIn) (*ServiceUpdateOut, error) { + +// ServiceUpdateAllowUncleanPoweroff Allows or disallows powering off a service if some WAL segments are not available for a future restoration of the service, which might result in data loss when powering the service back on +func ServiceUpdateAllowUncleanPoweroff(allowUncleanPoweroff bool) queryParam { + return queryParam{"allow_unclean_poweroff", fmt.Sprintf("%t", allowUncleanPoweroff)} +} +func (h *ServiceHandler) ServiceUpdate(ctx context.Context, project string, serviceName string, in *ServiceUpdateIn, query ...queryParam) (*ServiceUpdateOut, error) { path := fmt.Sprintf("/v1/project/%s/service/%s", url.PathEscape(project), url.PathEscape(serviceName)) b, err := h.doer.Do(ctx, "ServiceUpdate", "PUT", path, in) if err != nil { diff --git a/handler/serviceintegration/serviceintegration.go b/handler/serviceintegration/serviceintegration.go index aab501a..b51aa00 100644 --- a/handler/serviceintegration/serviceintegration.go +++ b/handler/serviceintegration/serviceintegration.go @@ -9,6 +9,11 @@ import ( "net/url" ) +// doer http client +type doer interface { + Do(ctx context.Context, operationID, method, path string, in any, query ...[2]string) ([]byte, error) +} + type Handler interface { // ServiceIntegrationCreate create a new service integration // POST /v1/project/{project}/integration @@ -75,10 +80,6 @@ func NewHandler(doer doer) ServiceIntegrationHandler { return ServiceIntegrationHandler{doer} } -type doer interface { - Do(ctx context.Context, operationID, method, path string, v any) ([]byte, error) -} - type ServiceIntegrationHandler struct { doer doer } diff --git a/handler/serviceuser/serviceuser.go b/handler/serviceuser/serviceuser.go index 7b34bd4..7a50dfa 100644 --- a/handler/serviceuser/serviceuser.go +++ b/handler/serviceuser/serviceuser.go @@ -10,6 +10,11 @@ import ( "time" ) +// doer http client +type doer interface { + Do(ctx context.Context, operationID, method, path string, in any, query ...[2]string) ([]byte, error) +} + type Handler interface { // ServiceUserCreate create a new (sub) user for service // POST /v1/project/{project}/service/{service_name}/user @@ -41,10 +46,6 @@ func NewHandler(doer doer) ServiceUserHandler { return ServiceUserHandler{doer} } -type doer interface { - Do(ctx context.Context, operationID, method, path string, v any) ([]byte, error) -} - type ServiceUserHandler struct { doer doer } diff --git a/handler/staticip/staticip.go b/handler/staticip/staticip.go index 7a210fd..920a30b 100644 --- a/handler/staticip/staticip.go +++ b/handler/staticip/staticip.go @@ -9,6 +9,11 @@ import ( "net/url" ) +// doer http client +type doer interface { + Do(ctx context.Context, operationID, method, path string, in any, query ...[2]string) ([]byte, error) +} + type Handler interface { // ProjectStaticIPAssociate associate a static IP address with a service // POST /v1/project/{project}/static-ips/{static_ip_address_id}/association @@ -50,10 +55,6 @@ func NewHandler(doer doer) StaticIPHandler { return StaticIPHandler{doer} } -type doer interface { - Do(ctx context.Context, operationID, method, path string, v any) ([]byte, error) -} - type StaticIPHandler struct { doer doer } diff --git a/handler/thanos/thanos.go b/handler/thanos/thanos.go index 0bf1448..cd41ceb 100644 --- a/handler/thanos/thanos.go +++ b/handler/thanos/thanos.go @@ -9,6 +9,11 @@ import ( "net/url" ) +// doer http client +type doer interface { + Do(ctx context.Context, operationID, method, path string, in any, query ...[2]string) ([]byte, error) +} + type Handler interface { // ServiceThanosStorageSummary get Thanos object storage summary // GET /v1/project/{project}/service/{service_name}/thanos/storage/summary @@ -20,10 +25,6 @@ func NewHandler(doer doer) ThanosHandler { return ThanosHandler{doer} } -type doer interface { - Do(ctx context.Context, operationID, method, path string, v any) ([]byte, error) -} - type ThanosHandler struct { doer doer } diff --git a/handler/user/user.go b/handler/user/user.go index a1ca2a5..0b2efd3 100644 --- a/handler/user/user.go +++ b/handler/user/user.go @@ -10,6 +10,11 @@ import ( "time" ) +// doer http client +type doer interface { + Do(ctx context.Context, operationID, method, path string, in any, query ...[2]string) ([]byte, error) +} + type Handler interface { // AccessTokenCreate create new access token // POST /v1/access_token @@ -151,10 +156,6 @@ func NewHandler(doer doer) UserHandler { return UserHandler{doer} } -type doer interface { - Do(ctx context.Context, operationID, method, path string, v any) ([]byte, error) -} - type UserHandler struct { doer doer } diff --git a/handler/usergroup/usergroup.go b/handler/usergroup/usergroup.go index 5610643..d6d68d3 100644 --- a/handler/usergroup/usergroup.go +++ b/handler/usergroup/usergroup.go @@ -10,6 +10,11 @@ import ( "time" ) +// doer http client +type doer interface { + Do(ctx context.Context, operationID, method, path string, in any, query ...[2]string) ([]byte, error) +} + type Handler interface { // UserGroupCreate create a group // POST /v1/organization/{organization_id}/user-groups @@ -51,10 +56,6 @@ func NewHandler(doer doer) UserGroupHandler { return UserGroupHandler{doer} } -type doer interface { - Do(ctx context.Context, operationID, method, path string, v any) ([]byte, error) -} - type UserGroupHandler struct { doer doer } diff --git a/handler/vpc/vpc.go b/handler/vpc/vpc.go index c630d61..a171d8e 100644 --- a/handler/vpc/vpc.go +++ b/handler/vpc/vpc.go @@ -10,6 +10,11 @@ import ( "time" ) +// doer http client +type doer interface { + Do(ctx context.Context, operationID, method, path string, in any, query ...[2]string) ([]byte, error) +} + type Handler interface { // VpcCreate create a VPC in a cloud for the project // POST /v1/project/{project}/vpcs @@ -61,10 +66,6 @@ func NewHandler(doer doer) VpcHandler { return VpcHandler{doer} } -type doer interface { - Do(ctx context.Context, operationID, method, path string, v any) ([]byte, error) -} - type VpcHandler struct { doer doer }