diff --git a/cmd/influx/bucket.go b/cmd/influx/bucket.go new file mode 100644 index 0000000..77f69f3 --- /dev/null +++ b/cmd/influx/bucket.go @@ -0,0 +1,216 @@ +package main + +import ( + "github.com/influxdata/influx-cli/v2/internal" + "github.com/urfave/cli/v2" +) + +var bucketCmd = cli.Command{ + Name: "bucket", + Usage: "Bucket management commands", + Subcommands: []*cli.Command{ + { + Name: "create", + Usage: "Create bucket", + Flags: append( + commonFlags, + &cli.StringFlag{ + Name: "name", + Usage: "New bucket name", + Aliases: []string{"n"}, + EnvVars: []string{"INFLUX_BUCKET_NAME"}, + Required: true, + }, + &cli.StringFlag{ + Name: "description", + Usage: "Description of the bucket that will be created", + Aliases: []string{"d"}, + }, + &cli.StringFlag{ + Name: "retention", + Usage: "Duration bucket will retain data, or 0 for infinite", + Aliases: []string{"r"}, + DefaultText: "infinite", + }, + &cli.StringFlag{ + Name: "shard-group-duration", + Usage: "Shard group duration used internally by the storage engine", + DefaultText: "calculated from retention", + }, + &cli.StringFlag{ + Name: "org-id", + Usage: "The ID of the organization", + EnvVars: []string{"INFLUX_ORG_ID"}, + }, + &cli.StringFlag{ + Name: "org", + Usage: "The name of the organization", + Aliases: []string{"o"}, + EnvVars: []string{"INFLUX_ORG"}, + }, + ), + Action: func(ctx *cli.Context) error { + cli, err := newCli(ctx) + if err != nil { + return err + } + client, err := newApiClient(ctx, cli, true) + if err != nil { + return err + } + clients := internal.BucketsClients{ + BucketApi: client.BucketsApi, + OrgApi: client.OrganizationsApi, + } + return cli.BucketsCreate(standardCtx(ctx), &clients, &internal.BucketsCreateParams{ + OrgID: ctx.String("org-id"), + OrgName: ctx.String("org"), + Name: ctx.String("name"), + Description: ctx.String("description"), + Retention: ctx.String("retention"), + ShardGroupDuration: ctx.String("shard-group-duration"), + }) + }, + }, + { + Name: "delete", + Usage: "Delete bucket", + Flags: append( + commonFlags, + &cli.StringFlag{ + Name: "id", + Usage: "The bucket ID, required if name isn't provided", + Aliases: []string{"i"}, + }, + &cli.StringFlag{ + Name: "name", + Usage: "The bucket name, org or org-id will be required by choosing this", + Aliases: []string{"n"}, + }, + &cli.StringFlag{ + Name: "org-id", + Usage: "The ID of the organization", + EnvVars: []string{"INFLUX_ORG_ID"}, + }, + &cli.StringFlag{ + Name: "org", + Usage: "The name of the organization", + Aliases: []string{"o"}, + EnvVars: []string{"INFLUX_ORG"}, + }, + ), + Action: func(ctx *cli.Context) error { + cli, err := newCli(ctx) + if err != nil { + return err + } + client, err := newApiClient(ctx, cli, true) + if err != nil { + return err + } + return cli.BucketsDelete(standardCtx(ctx), client.BucketsApi, &internal.BucketsDeleteParams{ + ID: ctx.String("id"), + Name: ctx.String("name"), + OrgID: ctx.String("org-id"), + OrgName: ctx.String("org"), + }) + }, + }, + { + Name: "list", + Usage: "List buckets", + Aliases: []string{"find", "ls"}, + Flags: append( + commonFlags, + &cli.StringFlag{ + Name: "name", + Usage: "The bucket name", + Aliases: []string{"n"}, + EnvVars: []string{"INFLUX_BUCKET_NAME"}, + }, + &cli.StringFlag{ + Name: "org-id", + Usage: "The ID of the organization", + EnvVars: []string{"INFLUX_ORG_ID"}, + }, + &cli.StringFlag{ + Name: "org", + Usage: "The name of the organization", + Aliases: []string{"o"}, + EnvVars: []string{"INFLUX_ORG"}, + }, + &cli.StringFlag{ + Name: "id", + Usage: "The bucket ID", + Aliases: []string{"i"}, + }, + ), + Action: func(ctx *cli.Context) error { + cli, err := newCli(ctx) + if err != nil { + return err + } + client, err := newApiClient(ctx, cli, true) + if err != nil { + return err + } + return cli.BucketsList(standardCtx(ctx), client.BucketsApi, &internal.BucketsListParams{ + ID: ctx.String("id"), + Name: ctx.String("name"), + OrgID: ctx.String("org-id"), + OrgName: ctx.String("org"), + }) + }, + }, + { + Name: "update", + Usage: "Update bucket", + Flags: append( + commonFlags, + &cli.StringFlag{ + Name: "name", + Usage: "New name to set on the bucket", + Aliases: []string{"n"}, + EnvVars: []string{"INFLUX_BUCKET_NAME"}, + }, + &cli.StringFlag{ + Name: "id", + Usage: "The bucket ID", + Aliases: []string{"i"}, + Required: true, + }, + &cli.StringFlag{ + Name: "description", + Usage: "New description to set on the bucket", + Aliases: []string{"d"}, + }, + &cli.StringFlag{ + Name: "retention", + Usage: "New retention duration to set on the bucket, or 0 for infinite", + Aliases: []string{"r"}, + }, + &cli.StringFlag{ + Name: "shard-group-duration", + Usage: "New shard group duration to set on the bucket, or 0 to have the server calculate a value", + }, + ), + Action: func(ctx *cli.Context) error { + cli, err := newCli(ctx) + if err != nil { + return err + } + client, err := newApiClient(ctx, cli, true) + if err != nil { + return err + } + return cli.BucketsUpdate(standardCtx(ctx), client.BucketsApi, &internal.BucketsUpdateParams{ + ID: ctx.String("id"), + Name: ctx.String("name"), + Description: ctx.String("description"), + Retention: ctx.String("retention"), + ShardGroupDuration: ctx.String("shard-group-duration"), + }) + }, + }, + }, +} diff --git a/cmd/influx/main.go b/cmd/influx/main.go index dc0ddb5..39aabff 100644 --- a/cmd/influx/main.go +++ b/cmd/influx/main.go @@ -52,8 +52,8 @@ var ( // // We replicate the pattern from the old CLI so existing scripts and docs stay valid. -// Some commands (i.e. `setup` use custom help-text for the token flag). -var commonFlagsNoToken = []cli.Flag{ +// Flags used by all CLI commands. +var coreFlags = []cli.Flag{ &cli.StringFlag{ Name: hostFlag, Usage: "HTTP address of InfluxDB", @@ -85,13 +85,31 @@ var commonFlagsNoToken = []cli.Flag{ }, } -// Most commands use this form of the token flag. -var commonFlags = append(commonFlagsNoToken, &cli.StringFlag{ +// Flags used by commands that display API resources to the user. +var printFlags = []cli.Flag{ + &cli.BoolFlag{ + Name: printJsonFlag, + Usage: "Output data as JSON", + EnvVars: []string{"INFLUX_OUTPUT_JSON"}, + }, + &cli.BoolFlag{ + Name: hideHeadersFlag, + Usage: "Hide the table headers in output data", + EnvVars: []string{"INFLUX_HIDE_HEADERS"}, + }, +} + +// Flag used by commands that hit an authenticated API. +var commonTokenFlag = cli.StringFlag{ Name: tokenFlag, Usage: "Authentication token", Aliases: []string{"t"}, EnvVars: []string{"INFLUX_TOKEN"}, -}) +} + +var commonFlagsNoToken = append(coreFlags, printFlags...) +var commonFlagsNoPrint = append(coreFlags, &commonTokenFlag) +var commonFlags = append(commonFlagsNoToken, &commonTokenFlag) // newCli builds a CLI core that reads from stdin, writes to stdout/stderr, manages a local config store, // and optionally tracks a trace ID specified over the CLI. @@ -181,6 +199,7 @@ var app = cli.App{ &pingCmd, &setupCmd, &writeCmd, + &bucketCmd, }, } diff --git a/cmd/influx/ping.go b/cmd/influx/ping.go index b9652db..588bbb6 100644 --- a/cmd/influx/ping.go +++ b/cmd/influx/ping.go @@ -5,7 +5,7 @@ import "github.com/urfave/cli/v2" var pingCmd = cli.Command{ Name: "ping", Usage: "Check the InfluxDB /health endpoint", - Flags: commonFlagsNoToken, + Flags: coreFlags, Action: func(ctx *cli.Context) error { cli, err := newCli(ctx) if err != nil { diff --git a/cmd/influx/setup.go b/cmd/influx/setup.go index daf763c..887defd 100644 --- a/cmd/influx/setup.go +++ b/cmd/influx/setup.go @@ -53,16 +53,6 @@ var setupCmd = cli.Command{ Usage: "Name to set on CLI config generated for the InfluxDB instance, required if other configs exist", Aliases: []string{"n"}, }, - &cli.BoolFlag{ - Name: printJsonFlag, - Usage: "Output data as JSON", - EnvVars: []string{"INFLUX_OUTPUT_JSON"}, - }, - &cli.BoolFlag{ - Name: hideHeadersFlag, - Usage: "Hide the table headers in output data", - EnvVars: []string{"INFLUX_HIDE_HEADERS"}, - }, ), Action: func(ctx *cli.Context) error { cli, err := newCli(ctx) diff --git a/cmd/influx/write.go b/cmd/influx/write.go index 1a21e32..f3fb19d 100644 --- a/cmd/influx/write.go +++ b/cmd/influx/write.go @@ -15,7 +15,7 @@ import ( ) var writeFlags = append( - commonFlags, + commonFlagsNoPrint, &cli.StringFlag{ Name: "bucket-id", Usage: "The ID of destination bucket", diff --git a/etc/generate-openapi.sh b/etc/generate-openapi.sh index 46e491e..e369267 100755 --- a/etc/generate-openapi.sh +++ b/etc/generate-openapi.sh @@ -4,7 +4,7 @@ declare -r ETC_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" &> /dev/null && pwd)" declare -r ROOT_DIR="$(dirname ${ETC_DIR})" declare -r GENERATOR_DOCKER_IMG=openapitools/openapi-generator-cli:v5.1.0 -declare -r OPENAPI_COMMIT=4b75803e472eadb7be101fbe84f1f120f0a008b0 +declare -r OPENAPI_COMMIT=e41d5e327a67e472a46cd6edfe673496e1b066dd # Download our target API spec. # NOTE: openapi-generator supports HTTP references to API docs, but using that feature diff --git a/internal/api/api_buckets.go b/internal/api/api_buckets.go new file mode 100644 index 0000000..fffd535 --- /dev/null +++ b/internal/api/api_buckets.go @@ -0,0 +1,850 @@ +/* + * Subset of Influx API covered by Influx CLI + * + * No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator) + * + * API version: 2.0.0 + */ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package api + +import ( + "bytes" + _context "context" + _ioutil "io/ioutil" + _nethttp "net/http" + _neturl "net/url" + "strings" +) + +// Linger please +var ( + _ _context.Context +) + +type BucketsApi interface { + + /* + * DeleteBucketsID Delete a bucket + * @param ctx _context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + * @param bucketID The ID of the bucket to delete. + * @return ApiDeleteBucketsIDRequest + */ + DeleteBucketsID(ctx _context.Context, bucketID string) ApiDeleteBucketsIDRequest + + /* + * DeleteBucketsIDExecute executes the request + */ + DeleteBucketsIDExecute(r ApiDeleteBucketsIDRequest) (*_nethttp.Response, error) + + /* + * GetBuckets List all buckets + * @param ctx _context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + * @return ApiGetBucketsRequest + */ + GetBuckets(ctx _context.Context) ApiGetBucketsRequest + + /* + * GetBucketsExecute executes the request + * @return Buckets + */ + GetBucketsExecute(r ApiGetBucketsRequest) (Buckets, *_nethttp.Response, error) + + /* + * GetBucketsID Retrieve a bucket + * @param ctx _context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + * @param bucketID The bucket ID. + * @return ApiGetBucketsIDRequest + */ + GetBucketsID(ctx _context.Context, bucketID string) ApiGetBucketsIDRequest + + /* + * GetBucketsIDExecute executes the request + * @return Bucket + */ + GetBucketsIDExecute(r ApiGetBucketsIDRequest) (Bucket, *_nethttp.Response, error) + + /* + * PatchBucketsID Update a bucket + * @param ctx _context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + * @param bucketID The bucket ID. + * @return ApiPatchBucketsIDRequest + */ + PatchBucketsID(ctx _context.Context, bucketID string) ApiPatchBucketsIDRequest + + /* + * PatchBucketsIDExecute executes the request + * @return Bucket + */ + PatchBucketsIDExecute(r ApiPatchBucketsIDRequest) (Bucket, *_nethttp.Response, error) + + /* + * PostBuckets Create a bucket + * @param ctx _context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + * @return ApiPostBucketsRequest + */ + PostBuckets(ctx _context.Context) ApiPostBucketsRequest + + /* + * PostBucketsExecute executes the request + * @return Bucket + */ + PostBucketsExecute(r ApiPostBucketsRequest) (Bucket, *_nethttp.Response, error) +} + +// BucketsApiService BucketsApi service +type BucketsApiService service + +type ApiDeleteBucketsIDRequest struct { + ctx _context.Context + ApiService BucketsApi + bucketID string + zapTraceSpan *string +} + +func (r ApiDeleteBucketsIDRequest) BucketID(bucketID string) ApiDeleteBucketsIDRequest { + r.bucketID = bucketID + return r +} +func (r ApiDeleteBucketsIDRequest) GetBucketID() string { + return r.bucketID +} + +func (r ApiDeleteBucketsIDRequest) ZapTraceSpan(zapTraceSpan string) ApiDeleteBucketsIDRequest { + r.zapTraceSpan = &zapTraceSpan + return r +} +func (r ApiDeleteBucketsIDRequest) GetZapTraceSpan() *string { + return r.zapTraceSpan +} + +func (r ApiDeleteBucketsIDRequest) Execute() (*_nethttp.Response, error) { + return r.ApiService.DeleteBucketsIDExecute(r) +} + +/* + * DeleteBucketsID Delete a bucket + * @param ctx _context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + * @param bucketID The ID of the bucket to delete. + * @return ApiDeleteBucketsIDRequest + */ +func (a *BucketsApiService) DeleteBucketsID(ctx _context.Context, bucketID string) ApiDeleteBucketsIDRequest { + return ApiDeleteBucketsIDRequest{ + ApiService: a, + ctx: ctx, + bucketID: bucketID, + } +} + +/* + * Execute executes the request + */ +func (a *BucketsApiService) DeleteBucketsIDExecute(r ApiDeleteBucketsIDRequest) (*_nethttp.Response, error) { + var ( + localVarHTTPMethod = _nethttp.MethodDelete + localVarPostBody interface{} + localVarFormFileName string + localVarFileName string + localVarFileBytes []byte + ) + + localBasePath, err := a.client.cfg.ServerURLWithContext(r.ctx, "BucketsApiService.DeleteBucketsID") + if err != nil { + return nil, GenericOpenAPIError{error: err.Error()} + } + + localVarPath := localBasePath + "/buckets/{bucketID}" + localVarPath = strings.Replace(localVarPath, "{"+"bucketID"+"}", _neturl.PathEscape(parameterToString(r.bucketID, "")), -1) + + localVarHeaderParams := make(map[string]string) + localVarQueryParams := _neturl.Values{} + localVarFormParams := _neturl.Values{} + + // to determine the Content-Type header + localVarHTTPContentTypes := []string{} + + // set Content-Type header + localVarHTTPContentType := selectHeaderContentType(localVarHTTPContentTypes) + if localVarHTTPContentType != "" { + localVarHeaderParams["Content-Type"] = localVarHTTPContentType + } + + // to determine the Accept header + localVarHTTPHeaderAccepts := []string{"application/json"} + + // set Accept header + localVarHTTPHeaderAccept := selectHeaderAccept(localVarHTTPHeaderAccepts) + if localVarHTTPHeaderAccept != "" { + localVarHeaderParams["Accept"] = localVarHTTPHeaderAccept + } + if r.zapTraceSpan != nil { + localVarHeaderParams["Zap-Trace-Span"] = parameterToString(*r.zapTraceSpan, "") + } + req, err := a.client.prepareRequest(r.ctx, localVarPath, localVarHTTPMethod, localVarPostBody, localVarHeaderParams, localVarQueryParams, localVarFormParams, localVarFormFileName, localVarFileName, localVarFileBytes) + if err != nil { + return nil, err + } + + localVarHTTPResponse, err := a.client.callAPI(req) + if err != nil || localVarHTTPResponse == nil { + return localVarHTTPResponse, err + } + + localVarBody, err := _ioutil.ReadAll(localVarHTTPResponse.Body) + localVarHTTPResponse.Body.Close() + localVarHTTPResponse.Body = _ioutil.NopCloser(bytes.NewBuffer(localVarBody)) + if err != nil { + return localVarHTTPResponse, err + } + + if localVarHTTPResponse.StatusCode >= 300 { + newErr := GenericOpenAPIError{ + body: localVarBody, + error: localVarHTTPResponse.Status, + } + if localVarHTTPResponse.StatusCode == 404 { + var v Error + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarHTTPResponse, newErr + } + newErr.model = &v + return localVarHTTPResponse, newErr + } + var v Error + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarHTTPResponse, newErr + } + newErr.model = &v + return localVarHTTPResponse, newErr + } + + return localVarHTTPResponse, nil +} + +type ApiGetBucketsRequest struct { + ctx _context.Context + ApiService BucketsApi + zapTraceSpan *string + offset *int32 + limit *int32 + after *string + org *string + orgID *string + name *string + id *string +} + +func (r ApiGetBucketsRequest) ZapTraceSpan(zapTraceSpan string) ApiGetBucketsRequest { + r.zapTraceSpan = &zapTraceSpan + return r +} +func (r ApiGetBucketsRequest) GetZapTraceSpan() *string { + return r.zapTraceSpan +} + +func (r ApiGetBucketsRequest) Offset(offset int32) ApiGetBucketsRequest { + r.offset = &offset + return r +} +func (r ApiGetBucketsRequest) GetOffset() *int32 { + return r.offset +} + +func (r ApiGetBucketsRequest) Limit(limit int32) ApiGetBucketsRequest { + r.limit = &limit + return r +} +func (r ApiGetBucketsRequest) GetLimit() *int32 { + return r.limit +} + +func (r ApiGetBucketsRequest) After(after string) ApiGetBucketsRequest { + r.after = &after + return r +} +func (r ApiGetBucketsRequest) GetAfter() *string { + return r.after +} + +func (r ApiGetBucketsRequest) Org(org string) ApiGetBucketsRequest { + r.org = &org + return r +} +func (r ApiGetBucketsRequest) GetOrg() *string { + return r.org +} + +func (r ApiGetBucketsRequest) OrgID(orgID string) ApiGetBucketsRequest { + r.orgID = &orgID + return r +} +func (r ApiGetBucketsRequest) GetOrgID() *string { + return r.orgID +} + +func (r ApiGetBucketsRequest) Name(name string) ApiGetBucketsRequest { + r.name = &name + return r +} +func (r ApiGetBucketsRequest) GetName() *string { + return r.name +} + +func (r ApiGetBucketsRequest) Id(id string) ApiGetBucketsRequest { + r.id = &id + return r +} +func (r ApiGetBucketsRequest) GetId() *string { + return r.id +} + +func (r ApiGetBucketsRequest) Execute() (Buckets, *_nethttp.Response, error) { + return r.ApiService.GetBucketsExecute(r) +} + +/* + * GetBuckets List all buckets + * @param ctx _context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + * @return ApiGetBucketsRequest + */ +func (a *BucketsApiService) GetBuckets(ctx _context.Context) ApiGetBucketsRequest { + return ApiGetBucketsRequest{ + ApiService: a, + ctx: ctx, + } +} + +/* + * Execute executes the request + * @return Buckets + */ +func (a *BucketsApiService) GetBucketsExecute(r ApiGetBucketsRequest) (Buckets, *_nethttp.Response, error) { + var ( + localVarHTTPMethod = _nethttp.MethodGet + localVarPostBody interface{} + localVarFormFileName string + localVarFileName string + localVarFileBytes []byte + localVarReturnValue Buckets + ) + + localBasePath, err := a.client.cfg.ServerURLWithContext(r.ctx, "BucketsApiService.GetBuckets") + if err != nil { + return localVarReturnValue, nil, GenericOpenAPIError{error: err.Error()} + } + + localVarPath := localBasePath + "/buckets" + + localVarHeaderParams := make(map[string]string) + localVarQueryParams := _neturl.Values{} + localVarFormParams := _neturl.Values{} + + if r.offset != nil { + localVarQueryParams.Add("offset", parameterToString(*r.offset, "")) + } + if r.limit != nil { + localVarQueryParams.Add("limit", parameterToString(*r.limit, "")) + } + if r.after != nil { + localVarQueryParams.Add("after", parameterToString(*r.after, "")) + } + if r.org != nil { + localVarQueryParams.Add("org", parameterToString(*r.org, "")) + } + if r.orgID != nil { + localVarQueryParams.Add("orgID", parameterToString(*r.orgID, "")) + } + if r.name != nil { + localVarQueryParams.Add("name", parameterToString(*r.name, "")) + } + if r.id != nil { + localVarQueryParams.Add("id", parameterToString(*r.id, "")) + } + // to determine the Content-Type header + localVarHTTPContentTypes := []string{} + + // set Content-Type header + localVarHTTPContentType := selectHeaderContentType(localVarHTTPContentTypes) + if localVarHTTPContentType != "" { + localVarHeaderParams["Content-Type"] = localVarHTTPContentType + } + + // to determine the Accept header + localVarHTTPHeaderAccepts := []string{"application/json"} + + // set Accept header + localVarHTTPHeaderAccept := selectHeaderAccept(localVarHTTPHeaderAccepts) + if localVarHTTPHeaderAccept != "" { + localVarHeaderParams["Accept"] = localVarHTTPHeaderAccept + } + if r.zapTraceSpan != nil { + localVarHeaderParams["Zap-Trace-Span"] = parameterToString(*r.zapTraceSpan, "") + } + req, err := a.client.prepareRequest(r.ctx, localVarPath, localVarHTTPMethod, localVarPostBody, localVarHeaderParams, localVarQueryParams, localVarFormParams, localVarFormFileName, localVarFileName, localVarFileBytes) + if err != nil { + return localVarReturnValue, nil, err + } + + localVarHTTPResponse, err := a.client.callAPI(req) + if err != nil || localVarHTTPResponse == nil { + return localVarReturnValue, localVarHTTPResponse, err + } + + localVarBody, err := _ioutil.ReadAll(localVarHTTPResponse.Body) + localVarHTTPResponse.Body.Close() + localVarHTTPResponse.Body = _ioutil.NopCloser(bytes.NewBuffer(localVarBody)) + if err != nil { + return localVarReturnValue, localVarHTTPResponse, err + } + + if localVarHTTPResponse.StatusCode >= 300 { + newErr := GenericOpenAPIError{ + body: localVarBody, + error: localVarHTTPResponse.Status, + } + var v Error + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = &v + return localVarReturnValue, localVarHTTPResponse, newErr + } + + err = a.client.decode(&localVarReturnValue, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr := GenericOpenAPIError{ + body: localVarBody, + error: err.Error(), + } + return localVarReturnValue, localVarHTTPResponse, newErr + } + + return localVarReturnValue, localVarHTTPResponse, nil +} + +type ApiGetBucketsIDRequest struct { + ctx _context.Context + ApiService BucketsApi + bucketID string + zapTraceSpan *string +} + +func (r ApiGetBucketsIDRequest) BucketID(bucketID string) ApiGetBucketsIDRequest { + r.bucketID = bucketID + return r +} +func (r ApiGetBucketsIDRequest) GetBucketID() string { + return r.bucketID +} + +func (r ApiGetBucketsIDRequest) ZapTraceSpan(zapTraceSpan string) ApiGetBucketsIDRequest { + r.zapTraceSpan = &zapTraceSpan + return r +} +func (r ApiGetBucketsIDRequest) GetZapTraceSpan() *string { + return r.zapTraceSpan +} + +func (r ApiGetBucketsIDRequest) Execute() (Bucket, *_nethttp.Response, error) { + return r.ApiService.GetBucketsIDExecute(r) +} + +/* + * GetBucketsID Retrieve a bucket + * @param ctx _context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + * @param bucketID The bucket ID. + * @return ApiGetBucketsIDRequest + */ +func (a *BucketsApiService) GetBucketsID(ctx _context.Context, bucketID string) ApiGetBucketsIDRequest { + return ApiGetBucketsIDRequest{ + ApiService: a, + ctx: ctx, + bucketID: bucketID, + } +} + +/* + * Execute executes the request + * @return Bucket + */ +func (a *BucketsApiService) GetBucketsIDExecute(r ApiGetBucketsIDRequest) (Bucket, *_nethttp.Response, error) { + var ( + localVarHTTPMethod = _nethttp.MethodGet + localVarPostBody interface{} + localVarFormFileName string + localVarFileName string + localVarFileBytes []byte + localVarReturnValue Bucket + ) + + localBasePath, err := a.client.cfg.ServerURLWithContext(r.ctx, "BucketsApiService.GetBucketsID") + if err != nil { + return localVarReturnValue, nil, GenericOpenAPIError{error: err.Error()} + } + + localVarPath := localBasePath + "/buckets/{bucketID}" + localVarPath = strings.Replace(localVarPath, "{"+"bucketID"+"}", _neturl.PathEscape(parameterToString(r.bucketID, "")), -1) + + localVarHeaderParams := make(map[string]string) + localVarQueryParams := _neturl.Values{} + localVarFormParams := _neturl.Values{} + + // to determine the Content-Type header + localVarHTTPContentTypes := []string{} + + // set Content-Type header + localVarHTTPContentType := selectHeaderContentType(localVarHTTPContentTypes) + if localVarHTTPContentType != "" { + localVarHeaderParams["Content-Type"] = localVarHTTPContentType + } + + // to determine the Accept header + localVarHTTPHeaderAccepts := []string{"application/json"} + + // set Accept header + localVarHTTPHeaderAccept := selectHeaderAccept(localVarHTTPHeaderAccepts) + if localVarHTTPHeaderAccept != "" { + localVarHeaderParams["Accept"] = localVarHTTPHeaderAccept + } + if r.zapTraceSpan != nil { + localVarHeaderParams["Zap-Trace-Span"] = parameterToString(*r.zapTraceSpan, "") + } + req, err := a.client.prepareRequest(r.ctx, localVarPath, localVarHTTPMethod, localVarPostBody, localVarHeaderParams, localVarQueryParams, localVarFormParams, localVarFormFileName, localVarFileName, localVarFileBytes) + if err != nil { + return localVarReturnValue, nil, err + } + + localVarHTTPResponse, err := a.client.callAPI(req) + if err != nil || localVarHTTPResponse == nil { + return localVarReturnValue, localVarHTTPResponse, err + } + + localVarBody, err := _ioutil.ReadAll(localVarHTTPResponse.Body) + localVarHTTPResponse.Body.Close() + localVarHTTPResponse.Body = _ioutil.NopCloser(bytes.NewBuffer(localVarBody)) + if err != nil { + return localVarReturnValue, localVarHTTPResponse, err + } + + if localVarHTTPResponse.StatusCode >= 300 { + newErr := GenericOpenAPIError{ + body: localVarBody, + error: localVarHTTPResponse.Status, + } + var v Error + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = &v + return localVarReturnValue, localVarHTTPResponse, newErr + } + + err = a.client.decode(&localVarReturnValue, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr := GenericOpenAPIError{ + body: localVarBody, + error: err.Error(), + } + return localVarReturnValue, localVarHTTPResponse, newErr + } + + return localVarReturnValue, localVarHTTPResponse, nil +} + +type ApiPatchBucketsIDRequest struct { + ctx _context.Context + ApiService BucketsApi + bucketID string + patchBucketRequest *PatchBucketRequest + zapTraceSpan *string +} + +func (r ApiPatchBucketsIDRequest) BucketID(bucketID string) ApiPatchBucketsIDRequest { + r.bucketID = bucketID + return r +} +func (r ApiPatchBucketsIDRequest) GetBucketID() string { + return r.bucketID +} + +func (r ApiPatchBucketsIDRequest) PatchBucketRequest(patchBucketRequest PatchBucketRequest) ApiPatchBucketsIDRequest { + r.patchBucketRequest = &patchBucketRequest + return r +} +func (r ApiPatchBucketsIDRequest) GetPatchBucketRequest() *PatchBucketRequest { + return r.patchBucketRequest +} + +func (r ApiPatchBucketsIDRequest) ZapTraceSpan(zapTraceSpan string) ApiPatchBucketsIDRequest { + r.zapTraceSpan = &zapTraceSpan + return r +} +func (r ApiPatchBucketsIDRequest) GetZapTraceSpan() *string { + return r.zapTraceSpan +} + +func (r ApiPatchBucketsIDRequest) Execute() (Bucket, *_nethttp.Response, error) { + return r.ApiService.PatchBucketsIDExecute(r) +} + +/* + * PatchBucketsID Update a bucket + * @param ctx _context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + * @param bucketID The bucket ID. + * @return ApiPatchBucketsIDRequest + */ +func (a *BucketsApiService) PatchBucketsID(ctx _context.Context, bucketID string) ApiPatchBucketsIDRequest { + return ApiPatchBucketsIDRequest{ + ApiService: a, + ctx: ctx, + bucketID: bucketID, + } +} + +/* + * Execute executes the request + * @return Bucket + */ +func (a *BucketsApiService) PatchBucketsIDExecute(r ApiPatchBucketsIDRequest) (Bucket, *_nethttp.Response, error) { + var ( + localVarHTTPMethod = _nethttp.MethodPatch + localVarPostBody interface{} + localVarFormFileName string + localVarFileName string + localVarFileBytes []byte + localVarReturnValue Bucket + ) + + localBasePath, err := a.client.cfg.ServerURLWithContext(r.ctx, "BucketsApiService.PatchBucketsID") + if err != nil { + return localVarReturnValue, nil, GenericOpenAPIError{error: err.Error()} + } + + localVarPath := localBasePath + "/buckets/{bucketID}" + localVarPath = strings.Replace(localVarPath, "{"+"bucketID"+"}", _neturl.PathEscape(parameterToString(r.bucketID, "")), -1) + + localVarHeaderParams := make(map[string]string) + localVarQueryParams := _neturl.Values{} + localVarFormParams := _neturl.Values{} + if r.patchBucketRequest == nil { + return localVarReturnValue, nil, reportError("patchBucketRequest is required and must be specified") + } + + // to determine the Content-Type header + localVarHTTPContentTypes := []string{"application/json"} + + // set Content-Type header + localVarHTTPContentType := selectHeaderContentType(localVarHTTPContentTypes) + if localVarHTTPContentType != "" { + localVarHeaderParams["Content-Type"] = localVarHTTPContentType + } + + // to determine the Accept header + localVarHTTPHeaderAccepts := []string{"application/json"} + + // set Accept header + localVarHTTPHeaderAccept := selectHeaderAccept(localVarHTTPHeaderAccepts) + if localVarHTTPHeaderAccept != "" { + localVarHeaderParams["Accept"] = localVarHTTPHeaderAccept + } + if r.zapTraceSpan != nil { + localVarHeaderParams["Zap-Trace-Span"] = parameterToString(*r.zapTraceSpan, "") + } + // body params + localVarPostBody = r.patchBucketRequest + req, err := a.client.prepareRequest(r.ctx, localVarPath, localVarHTTPMethod, localVarPostBody, localVarHeaderParams, localVarQueryParams, localVarFormParams, localVarFormFileName, localVarFileName, localVarFileBytes) + if err != nil { + return localVarReturnValue, nil, err + } + + localVarHTTPResponse, err := a.client.callAPI(req) + if err != nil || localVarHTTPResponse == nil { + return localVarReturnValue, localVarHTTPResponse, err + } + + localVarBody, err := _ioutil.ReadAll(localVarHTTPResponse.Body) + localVarHTTPResponse.Body.Close() + localVarHTTPResponse.Body = _ioutil.NopCloser(bytes.NewBuffer(localVarBody)) + if err != nil { + return localVarReturnValue, localVarHTTPResponse, err + } + + if localVarHTTPResponse.StatusCode >= 300 { + newErr := GenericOpenAPIError{ + body: localVarBody, + error: localVarHTTPResponse.Status, + } + var v Error + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = &v + return localVarReturnValue, localVarHTTPResponse, newErr + } + + err = a.client.decode(&localVarReturnValue, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr := GenericOpenAPIError{ + body: localVarBody, + error: err.Error(), + } + return localVarReturnValue, localVarHTTPResponse, newErr + } + + return localVarReturnValue, localVarHTTPResponse, nil +} + +type ApiPostBucketsRequest struct { + ctx _context.Context + ApiService BucketsApi + postBucketRequest *PostBucketRequest + zapTraceSpan *string +} + +func (r ApiPostBucketsRequest) PostBucketRequest(postBucketRequest PostBucketRequest) ApiPostBucketsRequest { + r.postBucketRequest = &postBucketRequest + return r +} +func (r ApiPostBucketsRequest) GetPostBucketRequest() *PostBucketRequest { + return r.postBucketRequest +} + +func (r ApiPostBucketsRequest) ZapTraceSpan(zapTraceSpan string) ApiPostBucketsRequest { + r.zapTraceSpan = &zapTraceSpan + return r +} +func (r ApiPostBucketsRequest) GetZapTraceSpan() *string { + return r.zapTraceSpan +} + +func (r ApiPostBucketsRequest) Execute() (Bucket, *_nethttp.Response, error) { + return r.ApiService.PostBucketsExecute(r) +} + +/* + * PostBuckets Create a bucket + * @param ctx _context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + * @return ApiPostBucketsRequest + */ +func (a *BucketsApiService) PostBuckets(ctx _context.Context) ApiPostBucketsRequest { + return ApiPostBucketsRequest{ + ApiService: a, + ctx: ctx, + } +} + +/* + * Execute executes the request + * @return Bucket + */ +func (a *BucketsApiService) PostBucketsExecute(r ApiPostBucketsRequest) (Bucket, *_nethttp.Response, error) { + var ( + localVarHTTPMethod = _nethttp.MethodPost + localVarPostBody interface{} + localVarFormFileName string + localVarFileName string + localVarFileBytes []byte + localVarReturnValue Bucket + ) + + localBasePath, err := a.client.cfg.ServerURLWithContext(r.ctx, "BucketsApiService.PostBuckets") + if err != nil { + return localVarReturnValue, nil, GenericOpenAPIError{error: err.Error()} + } + + localVarPath := localBasePath + "/buckets" + + localVarHeaderParams := make(map[string]string) + localVarQueryParams := _neturl.Values{} + localVarFormParams := _neturl.Values{} + if r.postBucketRequest == nil { + return localVarReturnValue, nil, reportError("postBucketRequest is required and must be specified") + } + + // to determine the Content-Type header + localVarHTTPContentTypes := []string{"application/json"} + + // set Content-Type header + localVarHTTPContentType := selectHeaderContentType(localVarHTTPContentTypes) + if localVarHTTPContentType != "" { + localVarHeaderParams["Content-Type"] = localVarHTTPContentType + } + + // to determine the Accept header + localVarHTTPHeaderAccepts := []string{"application/json"} + + // set Accept header + localVarHTTPHeaderAccept := selectHeaderAccept(localVarHTTPHeaderAccepts) + if localVarHTTPHeaderAccept != "" { + localVarHeaderParams["Accept"] = localVarHTTPHeaderAccept + } + if r.zapTraceSpan != nil { + localVarHeaderParams["Zap-Trace-Span"] = parameterToString(*r.zapTraceSpan, "") + } + // body params + localVarPostBody = r.postBucketRequest + req, err := a.client.prepareRequest(r.ctx, localVarPath, localVarHTTPMethod, localVarPostBody, localVarHeaderParams, localVarQueryParams, localVarFormParams, localVarFormFileName, localVarFileName, localVarFileBytes) + if err != nil { + return localVarReturnValue, nil, err + } + + localVarHTTPResponse, err := a.client.callAPI(req) + if err != nil || localVarHTTPResponse == nil { + return localVarReturnValue, localVarHTTPResponse, err + } + + localVarBody, err := _ioutil.ReadAll(localVarHTTPResponse.Body) + localVarHTTPResponse.Body.Close() + localVarHTTPResponse.Body = _ioutil.NopCloser(bytes.NewBuffer(localVarBody)) + if err != nil { + return localVarReturnValue, localVarHTTPResponse, err + } + + if localVarHTTPResponse.StatusCode >= 300 { + newErr := GenericOpenAPIError{ + body: localVarBody, + error: localVarHTTPResponse.Status, + } + if localVarHTTPResponse.StatusCode == 422 { + var v Error + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = &v + return localVarReturnValue, localVarHTTPResponse, newErr + } + var v Error + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = &v + return localVarReturnValue, localVarHTTPResponse, newErr + } + + err = a.client.decode(&localVarReturnValue, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr := GenericOpenAPIError{ + body: localVarBody, + error: err.Error(), + } + return localVarReturnValue, localVarHTTPResponse, newErr + } + + return localVarReturnValue, localVarHTTPResponse, nil +} diff --git a/internal/api/api_organizations.go b/internal/api/api_organizations.go new file mode 100644 index 0000000..f199599 --- /dev/null +++ b/internal/api/api_organizations.go @@ -0,0 +1,380 @@ +/* + * Subset of Influx API covered by Influx CLI + * + * No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator) + * + * API version: 2.0.0 + */ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package api + +import ( + "bytes" + _context "context" + _ioutil "io/ioutil" + _nethttp "net/http" + _neturl "net/url" +) + +// Linger please +var ( + _ _context.Context +) + +type OrganizationsApi interface { + + /* + * GetOrgs List all organizations + * @param ctx _context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + * @return ApiGetOrgsRequest + */ + GetOrgs(ctx _context.Context) ApiGetOrgsRequest + + /* + * GetOrgsExecute executes the request + * @return Organizations + */ + GetOrgsExecute(r ApiGetOrgsRequest) (Organizations, *_nethttp.Response, error) + + /* + * PostOrgs Create an organization + * @param ctx _context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + * @return ApiPostOrgsRequest + */ + PostOrgs(ctx _context.Context) ApiPostOrgsRequest + + /* + * PostOrgsExecute executes the request + * @return Organization + */ + PostOrgsExecute(r ApiPostOrgsRequest) (Organization, *_nethttp.Response, error) +} + +// OrganizationsApiService OrganizationsApi service +type OrganizationsApiService service + +type ApiGetOrgsRequest struct { + ctx _context.Context + ApiService OrganizationsApi + zapTraceSpan *string + offset *int32 + limit *int32 + descending *bool + org *string + orgID *string + userID *string +} + +func (r ApiGetOrgsRequest) ZapTraceSpan(zapTraceSpan string) ApiGetOrgsRequest { + r.zapTraceSpan = &zapTraceSpan + return r +} +func (r ApiGetOrgsRequest) GetZapTraceSpan() *string { + return r.zapTraceSpan +} + +func (r ApiGetOrgsRequest) Offset(offset int32) ApiGetOrgsRequest { + r.offset = &offset + return r +} +func (r ApiGetOrgsRequest) GetOffset() *int32 { + return r.offset +} + +func (r ApiGetOrgsRequest) Limit(limit int32) ApiGetOrgsRequest { + r.limit = &limit + return r +} +func (r ApiGetOrgsRequest) GetLimit() *int32 { + return r.limit +} + +func (r ApiGetOrgsRequest) Descending(descending bool) ApiGetOrgsRequest { + r.descending = &descending + return r +} +func (r ApiGetOrgsRequest) GetDescending() *bool { + return r.descending +} + +func (r ApiGetOrgsRequest) Org(org string) ApiGetOrgsRequest { + r.org = &org + return r +} +func (r ApiGetOrgsRequest) GetOrg() *string { + return r.org +} + +func (r ApiGetOrgsRequest) OrgID(orgID string) ApiGetOrgsRequest { + r.orgID = &orgID + return r +} +func (r ApiGetOrgsRequest) GetOrgID() *string { + return r.orgID +} + +func (r ApiGetOrgsRequest) UserID(userID string) ApiGetOrgsRequest { + r.userID = &userID + return r +} +func (r ApiGetOrgsRequest) GetUserID() *string { + return r.userID +} + +func (r ApiGetOrgsRequest) Execute() (Organizations, *_nethttp.Response, error) { + return r.ApiService.GetOrgsExecute(r) +} + +/* + * GetOrgs List all organizations + * @param ctx _context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + * @return ApiGetOrgsRequest + */ +func (a *OrganizationsApiService) GetOrgs(ctx _context.Context) ApiGetOrgsRequest { + return ApiGetOrgsRequest{ + ApiService: a, + ctx: ctx, + } +} + +/* + * Execute executes the request + * @return Organizations + */ +func (a *OrganizationsApiService) GetOrgsExecute(r ApiGetOrgsRequest) (Organizations, *_nethttp.Response, error) { + var ( + localVarHTTPMethod = _nethttp.MethodGet + localVarPostBody interface{} + localVarFormFileName string + localVarFileName string + localVarFileBytes []byte + localVarReturnValue Organizations + ) + + localBasePath, err := a.client.cfg.ServerURLWithContext(r.ctx, "OrganizationsApiService.GetOrgs") + if err != nil { + return localVarReturnValue, nil, GenericOpenAPIError{error: err.Error()} + } + + localVarPath := localBasePath + "/orgs" + + localVarHeaderParams := make(map[string]string) + localVarQueryParams := _neturl.Values{} + localVarFormParams := _neturl.Values{} + + if r.offset != nil { + localVarQueryParams.Add("offset", parameterToString(*r.offset, "")) + } + if r.limit != nil { + localVarQueryParams.Add("limit", parameterToString(*r.limit, "")) + } + if r.descending != nil { + localVarQueryParams.Add("descending", parameterToString(*r.descending, "")) + } + if r.org != nil { + localVarQueryParams.Add("org", parameterToString(*r.org, "")) + } + if r.orgID != nil { + localVarQueryParams.Add("orgID", parameterToString(*r.orgID, "")) + } + if r.userID != nil { + localVarQueryParams.Add("userID", parameterToString(*r.userID, "")) + } + // to determine the Content-Type header + localVarHTTPContentTypes := []string{} + + // set Content-Type header + localVarHTTPContentType := selectHeaderContentType(localVarHTTPContentTypes) + if localVarHTTPContentType != "" { + localVarHeaderParams["Content-Type"] = localVarHTTPContentType + } + + // to determine the Accept header + localVarHTTPHeaderAccepts := []string{"application/json"} + + // set Accept header + localVarHTTPHeaderAccept := selectHeaderAccept(localVarHTTPHeaderAccepts) + if localVarHTTPHeaderAccept != "" { + localVarHeaderParams["Accept"] = localVarHTTPHeaderAccept + } + if r.zapTraceSpan != nil { + localVarHeaderParams["Zap-Trace-Span"] = parameterToString(*r.zapTraceSpan, "") + } + req, err := a.client.prepareRequest(r.ctx, localVarPath, localVarHTTPMethod, localVarPostBody, localVarHeaderParams, localVarQueryParams, localVarFormParams, localVarFormFileName, localVarFileName, localVarFileBytes) + if err != nil { + return localVarReturnValue, nil, err + } + + localVarHTTPResponse, err := a.client.callAPI(req) + if err != nil || localVarHTTPResponse == nil { + return localVarReturnValue, localVarHTTPResponse, err + } + + localVarBody, err := _ioutil.ReadAll(localVarHTTPResponse.Body) + localVarHTTPResponse.Body.Close() + localVarHTTPResponse.Body = _ioutil.NopCloser(bytes.NewBuffer(localVarBody)) + if err != nil { + return localVarReturnValue, localVarHTTPResponse, err + } + + if localVarHTTPResponse.StatusCode >= 300 { + newErr := GenericOpenAPIError{ + body: localVarBody, + error: localVarHTTPResponse.Status, + } + var v Error + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = &v + return localVarReturnValue, localVarHTTPResponse, newErr + } + + err = a.client.decode(&localVarReturnValue, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr := GenericOpenAPIError{ + body: localVarBody, + error: err.Error(), + } + return localVarReturnValue, localVarHTTPResponse, newErr + } + + return localVarReturnValue, localVarHTTPResponse, nil +} + +type ApiPostOrgsRequest struct { + ctx _context.Context + ApiService OrganizationsApi + organization *Organization + zapTraceSpan *string +} + +func (r ApiPostOrgsRequest) Organization(organization Organization) ApiPostOrgsRequest { + r.organization = &organization + return r +} +func (r ApiPostOrgsRequest) GetOrganization() *Organization { + return r.organization +} + +func (r ApiPostOrgsRequest) ZapTraceSpan(zapTraceSpan string) ApiPostOrgsRequest { + r.zapTraceSpan = &zapTraceSpan + return r +} +func (r ApiPostOrgsRequest) GetZapTraceSpan() *string { + return r.zapTraceSpan +} + +func (r ApiPostOrgsRequest) Execute() (Organization, *_nethttp.Response, error) { + return r.ApiService.PostOrgsExecute(r) +} + +/* + * PostOrgs Create an organization + * @param ctx _context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + * @return ApiPostOrgsRequest + */ +func (a *OrganizationsApiService) PostOrgs(ctx _context.Context) ApiPostOrgsRequest { + return ApiPostOrgsRequest{ + ApiService: a, + ctx: ctx, + } +} + +/* + * Execute executes the request + * @return Organization + */ +func (a *OrganizationsApiService) PostOrgsExecute(r ApiPostOrgsRequest) (Organization, *_nethttp.Response, error) { + var ( + localVarHTTPMethod = _nethttp.MethodPost + localVarPostBody interface{} + localVarFormFileName string + localVarFileName string + localVarFileBytes []byte + localVarReturnValue Organization + ) + + localBasePath, err := a.client.cfg.ServerURLWithContext(r.ctx, "OrganizationsApiService.PostOrgs") + if err != nil { + return localVarReturnValue, nil, GenericOpenAPIError{error: err.Error()} + } + + localVarPath := localBasePath + "/orgs" + + localVarHeaderParams := make(map[string]string) + localVarQueryParams := _neturl.Values{} + localVarFormParams := _neturl.Values{} + if r.organization == nil { + return localVarReturnValue, nil, reportError("organization is required and must be specified") + } + + // to determine the Content-Type header + localVarHTTPContentTypes := []string{"application/json"} + + // set Content-Type header + localVarHTTPContentType := selectHeaderContentType(localVarHTTPContentTypes) + if localVarHTTPContentType != "" { + localVarHeaderParams["Content-Type"] = localVarHTTPContentType + } + + // to determine the Accept header + localVarHTTPHeaderAccepts := []string{"application/json"} + + // set Accept header + localVarHTTPHeaderAccept := selectHeaderAccept(localVarHTTPHeaderAccepts) + if localVarHTTPHeaderAccept != "" { + localVarHeaderParams["Accept"] = localVarHTTPHeaderAccept + } + if r.zapTraceSpan != nil { + localVarHeaderParams["Zap-Trace-Span"] = parameterToString(*r.zapTraceSpan, "") + } + // body params + localVarPostBody = r.organization + req, err := a.client.prepareRequest(r.ctx, localVarPath, localVarHTTPMethod, localVarPostBody, localVarHeaderParams, localVarQueryParams, localVarFormParams, localVarFormFileName, localVarFileName, localVarFileBytes) + if err != nil { + return localVarReturnValue, nil, err + } + + localVarHTTPResponse, err := a.client.callAPI(req) + if err != nil || localVarHTTPResponse == nil { + return localVarReturnValue, localVarHTTPResponse, err + } + + localVarBody, err := _ioutil.ReadAll(localVarHTTPResponse.Body) + localVarHTTPResponse.Body.Close() + localVarHTTPResponse.Body = _ioutil.NopCloser(bytes.NewBuffer(localVarBody)) + if err != nil { + return localVarReturnValue, localVarHTTPResponse, err + } + + if localVarHTTPResponse.StatusCode >= 300 { + newErr := GenericOpenAPIError{ + body: localVarBody, + error: localVarHTTPResponse.Status, + } + var v Error + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.model = &v + return localVarReturnValue, localVarHTTPResponse, newErr + } + + err = a.client.decode(&localVarReturnValue, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr := GenericOpenAPIError{ + body: localVarBody, + error: err.Error(), + } + return localVarReturnValue, localVarHTTPResponse, newErr + } + + return localVarReturnValue, localVarHTTPResponse, nil +} diff --git a/internal/api/client.go b/internal/api/client.go index 7577c4d..c82b307 100644 --- a/internal/api/client.go +++ b/internal/api/client.go @@ -47,8 +47,12 @@ type APIClient struct { // API Services + BucketsApi BucketsApi + HealthApi HealthApi + OrganizationsApi OrganizationsApi + SetupApi SetupApi WriteApi WriteApi @@ -70,7 +74,9 @@ func NewAPIClient(cfg *Configuration) *APIClient { c.common.client = c // API Services + c.BucketsApi = (*BucketsApiService)(&c.common) c.HealthApi = (*HealthApiService)(&c.common) + c.OrganizationsApi = (*OrganizationsApiService)(&c.common) c.SetupApi = (*SetupApiService)(&c.common) c.WriteApi = (*WriteApiService)(&c.common) diff --git a/internal/api/model_buckets.go b/internal/api/model_buckets.go new file mode 100644 index 0000000..5c30056 --- /dev/null +++ b/internal/api/model_buckets.go @@ -0,0 +1,149 @@ +/* + * Subset of Influx API covered by Influx CLI + * + * No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator) + * + * API version: 2.0.0 + */ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package api + +import ( + "encoding/json" +) + +// Buckets struct for Buckets +type Buckets struct { + Links *Links `json:"links,omitempty"` + Buckets *[]Bucket `json:"buckets,omitempty"` +} + +// NewBuckets instantiates a new Buckets object +// This constructor will assign default values to properties that have it defined, +// and makes sure properties required by API are set, but the set of arguments +// will change when the set of required properties is changed +func NewBuckets() *Buckets { + this := Buckets{} + return &this +} + +// NewBucketsWithDefaults instantiates a new Buckets object +// This constructor will only assign default values to properties that have it defined, +// but it doesn't guarantee that properties required by API are set +func NewBucketsWithDefaults() *Buckets { + this := Buckets{} + return &this +} + +// GetLinks returns the Links field value if set, zero value otherwise. +func (o *Buckets) GetLinks() Links { + if o == nil || o.Links == nil { + var ret Links + return ret + } + return *o.Links +} + +// GetLinksOk returns a tuple with the Links field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *Buckets) GetLinksOk() (*Links, bool) { + if o == nil || o.Links == nil { + return nil, false + } + return o.Links, true +} + +// HasLinks returns a boolean if a field has been set. +func (o *Buckets) HasLinks() bool { + if o != nil && o.Links != nil { + return true + } + + return false +} + +// SetLinks gets a reference to the given Links and assigns it to the Links field. +func (o *Buckets) SetLinks(v Links) { + o.Links = &v +} + +// GetBuckets returns the Buckets field value if set, zero value otherwise. +func (o *Buckets) GetBuckets() []Bucket { + if o == nil || o.Buckets == nil { + var ret []Bucket + return ret + } + return *o.Buckets +} + +// GetBucketsOk returns a tuple with the Buckets field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *Buckets) GetBucketsOk() (*[]Bucket, bool) { + if o == nil || o.Buckets == nil { + return nil, false + } + return o.Buckets, true +} + +// HasBuckets returns a boolean if a field has been set. +func (o *Buckets) HasBuckets() bool { + if o != nil && o.Buckets != nil { + return true + } + + return false +} + +// SetBuckets gets a reference to the given []Bucket and assigns it to the Buckets field. +func (o *Buckets) SetBuckets(v []Bucket) { + o.Buckets = &v +} + +func (o Buckets) MarshalJSON() ([]byte, error) { + toSerialize := map[string]interface{}{} + if o.Links != nil { + toSerialize["links"] = o.Links + } + if o.Buckets != nil { + toSerialize["buckets"] = o.Buckets + } + return json.Marshal(toSerialize) +} + +type NullableBuckets struct { + value *Buckets + isSet bool +} + +func (v NullableBuckets) Get() *Buckets { + return v.value +} + +func (v *NullableBuckets) Set(val *Buckets) { + v.value = val + v.isSet = true +} + +func (v NullableBuckets) IsSet() bool { + return v.isSet +} + +func (v *NullableBuckets) Unset() { + v.value = nil + v.isSet = false +} + +func NewNullableBuckets(val *Buckets) *NullableBuckets { + return &NullableBuckets{value: val, isSet: true} +} + +func (v NullableBuckets) MarshalJSON() ([]byte, error) { + return json.Marshal(v.value) +} + +func (v *NullableBuckets) UnmarshalJSON(src []byte) error { + v.isSet = true + return json.Unmarshal(src, &v.value) +} diff --git a/internal/api/model_buckets_links.go b/internal/api/model_buckets_links.go new file mode 100644 index 0000000..4f1bf8b --- /dev/null +++ b/internal/api/model_buckets_links.go @@ -0,0 +1,181 @@ +/* + * Subset of Influx API covered by Influx CLI + * + * No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator) + * + * API version: 2.0.0 + */ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package api + +import ( + "encoding/json" +) + +// BucketsLinks struct for BucketsLinks +type BucketsLinks struct { + // URI of resource. + Next *string `json:"next,omitempty"` + // URI of resource. + Self string `json:"self"` + // URI of resource. + Prev *string `json:"prev,omitempty"` +} + +// NewBucketsLinks instantiates a new BucketsLinks object +// This constructor will assign default values to properties that have it defined, +// and makes sure properties required by API are set, but the set of arguments +// will change when the set of required properties is changed +func NewBucketsLinks(self string) *BucketsLinks { + this := BucketsLinks{} + this.Self = self + return &this +} + +// NewBucketsLinksWithDefaults instantiates a new BucketsLinks object +// This constructor will only assign default values to properties that have it defined, +// but it doesn't guarantee that properties required by API are set +func NewBucketsLinksWithDefaults() *BucketsLinks { + this := BucketsLinks{} + return &this +} + +// GetNext returns the Next field value if set, zero value otherwise. +func (o *BucketsLinks) GetNext() string { + if o == nil || o.Next == nil { + var ret string + return ret + } + return *o.Next +} + +// GetNextOk returns a tuple with the Next field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *BucketsLinks) GetNextOk() (*string, bool) { + if o == nil || o.Next == nil { + return nil, false + } + return o.Next, true +} + +// HasNext returns a boolean if a field has been set. +func (o *BucketsLinks) HasNext() bool { + if o != nil && o.Next != nil { + return true + } + + return false +} + +// SetNext gets a reference to the given string and assigns it to the Next field. +func (o *BucketsLinks) SetNext(v string) { + o.Next = &v +} + +// GetSelf returns the Self field value +func (o *BucketsLinks) GetSelf() string { + if o == nil { + var ret string + return ret + } + + return o.Self +} + +// GetSelfOk returns a tuple with the Self field value +// and a boolean to check if the value has been set. +func (o *BucketsLinks) GetSelfOk() (*string, bool) { + if o == nil { + return nil, false + } + return &o.Self, true +} + +// SetSelf sets field value +func (o *BucketsLinks) SetSelf(v string) { + o.Self = v +} + +// GetPrev returns the Prev field value if set, zero value otherwise. +func (o *BucketsLinks) GetPrev() string { + if o == nil || o.Prev == nil { + var ret string + return ret + } + return *o.Prev +} + +// GetPrevOk returns a tuple with the Prev field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *BucketsLinks) GetPrevOk() (*string, bool) { + if o == nil || o.Prev == nil { + return nil, false + } + return o.Prev, true +} + +// HasPrev returns a boolean if a field has been set. +func (o *BucketsLinks) HasPrev() bool { + if o != nil && o.Prev != nil { + return true + } + + return false +} + +// SetPrev gets a reference to the given string and assigns it to the Prev field. +func (o *BucketsLinks) SetPrev(v string) { + o.Prev = &v +} + +func (o BucketsLinks) MarshalJSON() ([]byte, error) { + toSerialize := map[string]interface{}{} + if o.Next != nil { + toSerialize["next"] = o.Next + } + if true { + toSerialize["self"] = o.Self + } + if o.Prev != nil { + toSerialize["prev"] = o.Prev + } + return json.Marshal(toSerialize) +} + +type NullableBucketsLinks struct { + value *BucketsLinks + isSet bool +} + +func (v NullableBucketsLinks) Get() *BucketsLinks { + return v.value +} + +func (v *NullableBucketsLinks) Set(val *BucketsLinks) { + v.value = val + v.isSet = true +} + +func (v NullableBucketsLinks) IsSet() bool { + return v.isSet +} + +func (v *NullableBucketsLinks) Unset() { + v.value = nil + v.isSet = false +} + +func NewNullableBucketsLinks(val *BucketsLinks) *NullableBucketsLinks { + return &NullableBucketsLinks{value: val, isSet: true} +} + +func (v NullableBucketsLinks) MarshalJSON() ([]byte, error) { + return json.Marshal(v.value) +} + +func (v *NullableBucketsLinks) UnmarshalJSON(src []byte) error { + v.isSet = true + return json.Unmarshal(src, &v.value) +} diff --git a/internal/api/model_links.go b/internal/api/model_links.go new file mode 100644 index 0000000..115e5a3 --- /dev/null +++ b/internal/api/model_links.go @@ -0,0 +1,181 @@ +/* + * Subset of Influx API covered by Influx CLI + * + * No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator) + * + * API version: 2.0.0 + */ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package api + +import ( + "encoding/json" +) + +// Links struct for Links +type Links struct { + // URI of resource. + Next *string `json:"next,omitempty"` + // URI of resource. + Self string `json:"self"` + // URI of resource. + Prev *string `json:"prev,omitempty"` +} + +// NewLinks instantiates a new Links object +// This constructor will assign default values to properties that have it defined, +// and makes sure properties required by API are set, but the set of arguments +// will change when the set of required properties is changed +func NewLinks(self string) *Links { + this := Links{} + this.Self = self + return &this +} + +// NewLinksWithDefaults instantiates a new Links object +// This constructor will only assign default values to properties that have it defined, +// but it doesn't guarantee that properties required by API are set +func NewLinksWithDefaults() *Links { + this := Links{} + return &this +} + +// GetNext returns the Next field value if set, zero value otherwise. +func (o *Links) GetNext() string { + if o == nil || o.Next == nil { + var ret string + return ret + } + return *o.Next +} + +// GetNextOk returns a tuple with the Next field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *Links) GetNextOk() (*string, bool) { + if o == nil || o.Next == nil { + return nil, false + } + return o.Next, true +} + +// HasNext returns a boolean if a field has been set. +func (o *Links) HasNext() bool { + if o != nil && o.Next != nil { + return true + } + + return false +} + +// SetNext gets a reference to the given string and assigns it to the Next field. +func (o *Links) SetNext(v string) { + o.Next = &v +} + +// GetSelf returns the Self field value +func (o *Links) GetSelf() string { + if o == nil { + var ret string + return ret + } + + return o.Self +} + +// GetSelfOk returns a tuple with the Self field value +// and a boolean to check if the value has been set. +func (o *Links) GetSelfOk() (*string, bool) { + if o == nil { + return nil, false + } + return &o.Self, true +} + +// SetSelf sets field value +func (o *Links) SetSelf(v string) { + o.Self = v +} + +// GetPrev returns the Prev field value if set, zero value otherwise. +func (o *Links) GetPrev() string { + if o == nil || o.Prev == nil { + var ret string + return ret + } + return *o.Prev +} + +// GetPrevOk returns a tuple with the Prev field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *Links) GetPrevOk() (*string, bool) { + if o == nil || o.Prev == nil { + return nil, false + } + return o.Prev, true +} + +// HasPrev returns a boolean if a field has been set. +func (o *Links) HasPrev() bool { + if o != nil && o.Prev != nil { + return true + } + + return false +} + +// SetPrev gets a reference to the given string and assigns it to the Prev field. +func (o *Links) SetPrev(v string) { + o.Prev = &v +} + +func (o Links) MarshalJSON() ([]byte, error) { + toSerialize := map[string]interface{}{} + if o.Next != nil { + toSerialize["next"] = o.Next + } + if true { + toSerialize["self"] = o.Self + } + if o.Prev != nil { + toSerialize["prev"] = o.Prev + } + return json.Marshal(toSerialize) +} + +type NullableLinks struct { + value *Links + isSet bool +} + +func (v NullableLinks) Get() *Links { + return v.value +} + +func (v *NullableLinks) Set(val *Links) { + v.value = val + v.isSet = true +} + +func (v NullableLinks) IsSet() bool { + return v.isSet +} + +func (v *NullableLinks) Unset() { + v.value = nil + v.isSet = false +} + +func NewNullableLinks(val *Links) *NullableLinks { + return &NullableLinks{value: val, isSet: true} +} + +func (v NullableLinks) MarshalJSON() ([]byte, error) { + return json.Marshal(v.value) +} + +func (v *NullableLinks) UnmarshalJSON(src []byte) error { + v.isSet = true + return json.Unmarshal(src, &v.value) +} diff --git a/internal/api/model_organizations.go b/internal/api/model_organizations.go new file mode 100644 index 0000000..d621cce --- /dev/null +++ b/internal/api/model_organizations.go @@ -0,0 +1,149 @@ +/* + * Subset of Influx API covered by Influx CLI + * + * No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator) + * + * API version: 2.0.0 + */ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package api + +import ( + "encoding/json" +) + +// Organizations struct for Organizations +type Organizations struct { + Links *Links `json:"links,omitempty"` + Orgs *[]Organization `json:"orgs,omitempty"` +} + +// NewOrganizations instantiates a new Organizations object +// This constructor will assign default values to properties that have it defined, +// and makes sure properties required by API are set, but the set of arguments +// will change when the set of required properties is changed +func NewOrganizations() *Organizations { + this := Organizations{} + return &this +} + +// NewOrganizationsWithDefaults instantiates a new Organizations object +// This constructor will only assign default values to properties that have it defined, +// but it doesn't guarantee that properties required by API are set +func NewOrganizationsWithDefaults() *Organizations { + this := Organizations{} + return &this +} + +// GetLinks returns the Links field value if set, zero value otherwise. +func (o *Organizations) GetLinks() Links { + if o == nil || o.Links == nil { + var ret Links + return ret + } + return *o.Links +} + +// GetLinksOk returns a tuple with the Links field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *Organizations) GetLinksOk() (*Links, bool) { + if o == nil || o.Links == nil { + return nil, false + } + return o.Links, true +} + +// HasLinks returns a boolean if a field has been set. +func (o *Organizations) HasLinks() bool { + if o != nil && o.Links != nil { + return true + } + + return false +} + +// SetLinks gets a reference to the given Links and assigns it to the Links field. +func (o *Organizations) SetLinks(v Links) { + o.Links = &v +} + +// GetOrgs returns the Orgs field value if set, zero value otherwise. +func (o *Organizations) GetOrgs() []Organization { + if o == nil || o.Orgs == nil { + var ret []Organization + return ret + } + return *o.Orgs +} + +// GetOrgsOk returns a tuple with the Orgs field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *Organizations) GetOrgsOk() (*[]Organization, bool) { + if o == nil || o.Orgs == nil { + return nil, false + } + return o.Orgs, true +} + +// HasOrgs returns a boolean if a field has been set. +func (o *Organizations) HasOrgs() bool { + if o != nil && o.Orgs != nil { + return true + } + + return false +} + +// SetOrgs gets a reference to the given []Organization and assigns it to the Orgs field. +func (o *Organizations) SetOrgs(v []Organization) { + o.Orgs = &v +} + +func (o Organizations) MarshalJSON() ([]byte, error) { + toSerialize := map[string]interface{}{} + if o.Links != nil { + toSerialize["links"] = o.Links + } + if o.Orgs != nil { + toSerialize["orgs"] = o.Orgs + } + return json.Marshal(toSerialize) +} + +type NullableOrganizations struct { + value *Organizations + isSet bool +} + +func (v NullableOrganizations) Get() *Organizations { + return v.value +} + +func (v *NullableOrganizations) Set(val *Organizations) { + v.value = val + v.isSet = true +} + +func (v NullableOrganizations) IsSet() bool { + return v.isSet +} + +func (v *NullableOrganizations) Unset() { + v.value = nil + v.isSet = false +} + +func NewNullableOrganizations(val *Organizations) *NullableOrganizations { + return &NullableOrganizations{value: val, isSet: true} +} + +func (v NullableOrganizations) MarshalJSON() ([]byte, error) { + return json.Marshal(v.value) +} + +func (v *NullableOrganizations) UnmarshalJSON(src []byte) error { + v.isSet = true + return json.Unmarshal(src, &v.value) +} diff --git a/internal/api/model_patch_bucket_request.go b/internal/api/model_patch_bucket_request.go new file mode 100644 index 0000000..5b600e6 --- /dev/null +++ b/internal/api/model_patch_bucket_request.go @@ -0,0 +1,186 @@ +/* + * Subset of Influx API covered by Influx CLI + * + * No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator) + * + * API version: 2.0.0 + */ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package api + +import ( + "encoding/json" +) + +// PatchBucketRequest Updates to an existing bucket resource. +type PatchBucketRequest struct { + Name *string `json:"name,omitempty"` + Description *string `json:"description,omitempty"` + // Updates to rules to expire or retain data. No rules means no updates. + RetentionRules *[]PatchRetentionRule `json:"retentionRules,omitempty"` +} + +// NewPatchBucketRequest instantiates a new PatchBucketRequest object +// This constructor will assign default values to properties that have it defined, +// and makes sure properties required by API are set, but the set of arguments +// will change when the set of required properties is changed +func NewPatchBucketRequest() *PatchBucketRequest { + this := PatchBucketRequest{} + return &this +} + +// NewPatchBucketRequestWithDefaults instantiates a new PatchBucketRequest object +// This constructor will only assign default values to properties that have it defined, +// but it doesn't guarantee that properties required by API are set +func NewPatchBucketRequestWithDefaults() *PatchBucketRequest { + this := PatchBucketRequest{} + return &this +} + +// GetName returns the Name field value if set, zero value otherwise. +func (o *PatchBucketRequest) GetName() string { + if o == nil || o.Name == nil { + var ret string + return ret + } + return *o.Name +} + +// GetNameOk returns a tuple with the Name field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *PatchBucketRequest) GetNameOk() (*string, bool) { + if o == nil || o.Name == nil { + return nil, false + } + return o.Name, true +} + +// HasName returns a boolean if a field has been set. +func (o *PatchBucketRequest) HasName() bool { + if o != nil && o.Name != nil { + return true + } + + return false +} + +// SetName gets a reference to the given string and assigns it to the Name field. +func (o *PatchBucketRequest) SetName(v string) { + o.Name = &v +} + +// GetDescription returns the Description field value if set, zero value otherwise. +func (o *PatchBucketRequest) GetDescription() string { + if o == nil || o.Description == nil { + var ret string + return ret + } + return *o.Description +} + +// GetDescriptionOk returns a tuple with the Description field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *PatchBucketRequest) GetDescriptionOk() (*string, bool) { + if o == nil || o.Description == nil { + return nil, false + } + return o.Description, true +} + +// HasDescription returns a boolean if a field has been set. +func (o *PatchBucketRequest) HasDescription() bool { + if o != nil && o.Description != nil { + return true + } + + return false +} + +// SetDescription gets a reference to the given string and assigns it to the Description field. +func (o *PatchBucketRequest) SetDescription(v string) { + o.Description = &v +} + +// GetRetentionRules returns the RetentionRules field value if set, zero value otherwise. +func (o *PatchBucketRequest) GetRetentionRules() []PatchRetentionRule { + if o == nil || o.RetentionRules == nil { + var ret []PatchRetentionRule + return ret + } + return *o.RetentionRules +} + +// GetRetentionRulesOk returns a tuple with the RetentionRules field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *PatchBucketRequest) GetRetentionRulesOk() (*[]PatchRetentionRule, bool) { + if o == nil || o.RetentionRules == nil { + return nil, false + } + return o.RetentionRules, true +} + +// HasRetentionRules returns a boolean if a field has been set. +func (o *PatchBucketRequest) HasRetentionRules() bool { + if o != nil && o.RetentionRules != nil { + return true + } + + return false +} + +// SetRetentionRules gets a reference to the given []PatchRetentionRule and assigns it to the RetentionRules field. +func (o *PatchBucketRequest) SetRetentionRules(v []PatchRetentionRule) { + o.RetentionRules = &v +} + +func (o PatchBucketRequest) MarshalJSON() ([]byte, error) { + toSerialize := map[string]interface{}{} + if o.Name != nil { + toSerialize["name"] = o.Name + } + if o.Description != nil { + toSerialize["description"] = o.Description + } + if o.RetentionRules != nil { + toSerialize["retentionRules"] = o.RetentionRules + } + return json.Marshal(toSerialize) +} + +type NullablePatchBucketRequest struct { + value *PatchBucketRequest + isSet bool +} + +func (v NullablePatchBucketRequest) Get() *PatchBucketRequest { + return v.value +} + +func (v *NullablePatchBucketRequest) Set(val *PatchBucketRequest) { + v.value = val + v.isSet = true +} + +func (v NullablePatchBucketRequest) IsSet() bool { + return v.isSet +} + +func (v *NullablePatchBucketRequest) Unset() { + v.value = nil + v.isSet = false +} + +func NewNullablePatchBucketRequest(val *PatchBucketRequest) *NullablePatchBucketRequest { + return &NullablePatchBucketRequest{value: val, isSet: true} +} + +func (v NullablePatchBucketRequest) MarshalJSON() ([]byte, error) { + return json.Marshal(v.value) +} + +func (v *NullablePatchBucketRequest) UnmarshalJSON(src []byte) error { + v.isSet = true + return json.Unmarshal(src, &v.value) +} diff --git a/internal/api/model_patch_retention_rule.go b/internal/api/model_patch_retention_rule.go new file mode 100644 index 0000000..ffc1311 --- /dev/null +++ b/internal/api/model_patch_retention_rule.go @@ -0,0 +1,182 @@ +/* + * Subset of Influx API covered by Influx CLI + * + * No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator) + * + * API version: 2.0.0 + */ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package api + +import ( + "encoding/json" +) + +// PatchRetentionRule Updates to a rule to expire or retain data. +type PatchRetentionRule struct { + Type string `json:"type"` + // Duration in seconds for how long data will be kept in the database. 0 means infinite. + EverySeconds *int64 `json:"everySeconds,omitempty"` + // Shard duration measured in seconds. + ShardGroupDurationSeconds *int64 `json:"shardGroupDurationSeconds,omitempty"` +} + +// NewPatchRetentionRule instantiates a new PatchRetentionRule object +// This constructor will assign default values to properties that have it defined, +// and makes sure properties required by API are set, but the set of arguments +// will change when the set of required properties is changed +func NewPatchRetentionRule(type_ string) *PatchRetentionRule { + this := PatchRetentionRule{} + this.Type = type_ + return &this +} + +// NewPatchRetentionRuleWithDefaults instantiates a new PatchRetentionRule object +// This constructor will only assign default values to properties that have it defined, +// but it doesn't guarantee that properties required by API are set +func NewPatchRetentionRuleWithDefaults() *PatchRetentionRule { + this := PatchRetentionRule{} + var type_ string = "expire" + this.Type = type_ + return &this +} + +// GetType returns the Type field value +func (o *PatchRetentionRule) GetType() string { + if o == nil { + var ret string + return ret + } + + return o.Type +} + +// GetTypeOk returns a tuple with the Type field value +// and a boolean to check if the value has been set. +func (o *PatchRetentionRule) GetTypeOk() (*string, bool) { + if o == nil { + return nil, false + } + return &o.Type, true +} + +// SetType sets field value +func (o *PatchRetentionRule) SetType(v string) { + o.Type = v +} + +// GetEverySeconds returns the EverySeconds field value if set, zero value otherwise. +func (o *PatchRetentionRule) GetEverySeconds() int64 { + if o == nil || o.EverySeconds == nil { + var ret int64 + return ret + } + return *o.EverySeconds +} + +// GetEverySecondsOk returns a tuple with the EverySeconds field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *PatchRetentionRule) GetEverySecondsOk() (*int64, bool) { + if o == nil || o.EverySeconds == nil { + return nil, false + } + return o.EverySeconds, true +} + +// HasEverySeconds returns a boolean if a field has been set. +func (o *PatchRetentionRule) HasEverySeconds() bool { + if o != nil && o.EverySeconds != nil { + return true + } + + return false +} + +// SetEverySeconds gets a reference to the given int64 and assigns it to the EverySeconds field. +func (o *PatchRetentionRule) SetEverySeconds(v int64) { + o.EverySeconds = &v +} + +// GetShardGroupDurationSeconds returns the ShardGroupDurationSeconds field value if set, zero value otherwise. +func (o *PatchRetentionRule) GetShardGroupDurationSeconds() int64 { + if o == nil || o.ShardGroupDurationSeconds == nil { + var ret int64 + return ret + } + return *o.ShardGroupDurationSeconds +} + +// GetShardGroupDurationSecondsOk returns a tuple with the ShardGroupDurationSeconds field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *PatchRetentionRule) GetShardGroupDurationSecondsOk() (*int64, bool) { + if o == nil || o.ShardGroupDurationSeconds == nil { + return nil, false + } + return o.ShardGroupDurationSeconds, true +} + +// HasShardGroupDurationSeconds returns a boolean if a field has been set. +func (o *PatchRetentionRule) HasShardGroupDurationSeconds() bool { + if o != nil && o.ShardGroupDurationSeconds != nil { + return true + } + + return false +} + +// SetShardGroupDurationSeconds gets a reference to the given int64 and assigns it to the ShardGroupDurationSeconds field. +func (o *PatchRetentionRule) SetShardGroupDurationSeconds(v int64) { + o.ShardGroupDurationSeconds = &v +} + +func (o PatchRetentionRule) MarshalJSON() ([]byte, error) { + toSerialize := map[string]interface{}{} + if true { + toSerialize["type"] = o.Type + } + if o.EverySeconds != nil { + toSerialize["everySeconds"] = o.EverySeconds + } + if o.ShardGroupDurationSeconds != nil { + toSerialize["shardGroupDurationSeconds"] = o.ShardGroupDurationSeconds + } + return json.Marshal(toSerialize) +} + +type NullablePatchRetentionRule struct { + value *PatchRetentionRule + isSet bool +} + +func (v NullablePatchRetentionRule) Get() *PatchRetentionRule { + return v.value +} + +func (v *NullablePatchRetentionRule) Set(val *PatchRetentionRule) { + v.value = val + v.isSet = true +} + +func (v NullablePatchRetentionRule) IsSet() bool { + return v.isSet +} + +func (v *NullablePatchRetentionRule) Unset() { + v.value = nil + v.isSet = false +} + +func NewNullablePatchRetentionRule(val *PatchRetentionRule) *NullablePatchRetentionRule { + return &NullablePatchRetentionRule{value: val, isSet: true} +} + +func (v NullablePatchRetentionRule) MarshalJSON() ([]byte, error) { + return json.Marshal(v.value) +} + +func (v *NullablePatchRetentionRule) UnmarshalJSON(src []byte) error { + v.isSet = true + return json.Unmarshal(src, &v.value) +} diff --git a/internal/api/model_post_bucket_request.go b/internal/api/model_post_bucket_request.go new file mode 100644 index 0000000..2f169d0 --- /dev/null +++ b/internal/api/model_post_bucket_request.go @@ -0,0 +1,237 @@ +/* + * Subset of Influx API covered by Influx CLI + * + * No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator) + * + * API version: 2.0.0 + */ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package api + +import ( + "encoding/json" +) + +// PostBucketRequest struct for PostBucketRequest +type PostBucketRequest struct { + OrgID string `json:"orgID"` + Name string `json:"name"` + Description *string `json:"description,omitempty"` + Rp *string `json:"rp,omitempty"` + // Rules to expire or retain data. No rules means data never expires. + RetentionRules []RetentionRule `json:"retentionRules"` +} + +// NewPostBucketRequest instantiates a new PostBucketRequest object +// This constructor will assign default values to properties that have it defined, +// and makes sure properties required by API are set, but the set of arguments +// will change when the set of required properties is changed +func NewPostBucketRequest(orgID string, name string, retentionRules []RetentionRule) *PostBucketRequest { + this := PostBucketRequest{} + this.OrgID = orgID + this.Name = name + this.RetentionRules = retentionRules + return &this +} + +// NewPostBucketRequestWithDefaults instantiates a new PostBucketRequest object +// This constructor will only assign default values to properties that have it defined, +// but it doesn't guarantee that properties required by API are set +func NewPostBucketRequestWithDefaults() *PostBucketRequest { + this := PostBucketRequest{} + return &this +} + +// GetOrgID returns the OrgID field value +func (o *PostBucketRequest) GetOrgID() string { + if o == nil { + var ret string + return ret + } + + return o.OrgID +} + +// GetOrgIDOk returns a tuple with the OrgID field value +// and a boolean to check if the value has been set. +func (o *PostBucketRequest) GetOrgIDOk() (*string, bool) { + if o == nil { + return nil, false + } + return &o.OrgID, true +} + +// SetOrgID sets field value +func (o *PostBucketRequest) SetOrgID(v string) { + o.OrgID = v +} + +// GetName returns the Name field value +func (o *PostBucketRequest) GetName() string { + if o == nil { + var ret string + return ret + } + + return o.Name +} + +// GetNameOk returns a tuple with the Name field value +// and a boolean to check if the value has been set. +func (o *PostBucketRequest) GetNameOk() (*string, bool) { + if o == nil { + return nil, false + } + return &o.Name, true +} + +// SetName sets field value +func (o *PostBucketRequest) SetName(v string) { + o.Name = v +} + +// GetDescription returns the Description field value if set, zero value otherwise. +func (o *PostBucketRequest) GetDescription() string { + if o == nil || o.Description == nil { + var ret string + return ret + } + return *o.Description +} + +// GetDescriptionOk returns a tuple with the Description field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *PostBucketRequest) GetDescriptionOk() (*string, bool) { + if o == nil || o.Description == nil { + return nil, false + } + return o.Description, true +} + +// HasDescription returns a boolean if a field has been set. +func (o *PostBucketRequest) HasDescription() bool { + if o != nil && o.Description != nil { + return true + } + + return false +} + +// SetDescription gets a reference to the given string and assigns it to the Description field. +func (o *PostBucketRequest) SetDescription(v string) { + o.Description = &v +} + +// GetRp returns the Rp field value if set, zero value otherwise. +func (o *PostBucketRequest) GetRp() string { + if o == nil || o.Rp == nil { + var ret string + return ret + } + return *o.Rp +} + +// GetRpOk returns a tuple with the Rp field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *PostBucketRequest) GetRpOk() (*string, bool) { + if o == nil || o.Rp == nil { + return nil, false + } + return o.Rp, true +} + +// HasRp returns a boolean if a field has been set. +func (o *PostBucketRequest) HasRp() bool { + if o != nil && o.Rp != nil { + return true + } + + return false +} + +// SetRp gets a reference to the given string and assigns it to the Rp field. +func (o *PostBucketRequest) SetRp(v string) { + o.Rp = &v +} + +// GetRetentionRules returns the RetentionRules field value +func (o *PostBucketRequest) GetRetentionRules() []RetentionRule { + if o == nil { + var ret []RetentionRule + return ret + } + + return o.RetentionRules +} + +// GetRetentionRulesOk returns a tuple with the RetentionRules field value +// and a boolean to check if the value has been set. +func (o *PostBucketRequest) GetRetentionRulesOk() (*[]RetentionRule, bool) { + if o == nil { + return nil, false + } + return &o.RetentionRules, true +} + +// SetRetentionRules sets field value +func (o *PostBucketRequest) SetRetentionRules(v []RetentionRule) { + o.RetentionRules = v +} + +func (o PostBucketRequest) MarshalJSON() ([]byte, error) { + toSerialize := map[string]interface{}{} + if true { + toSerialize["orgID"] = o.OrgID + } + if true { + toSerialize["name"] = o.Name + } + if o.Description != nil { + toSerialize["description"] = o.Description + } + if o.Rp != nil { + toSerialize["rp"] = o.Rp + } + if true { + toSerialize["retentionRules"] = o.RetentionRules + } + return json.Marshal(toSerialize) +} + +type NullablePostBucketRequest struct { + value *PostBucketRequest + isSet bool +} + +func (v NullablePostBucketRequest) Get() *PostBucketRequest { + return v.value +} + +func (v *NullablePostBucketRequest) Set(val *PostBucketRequest) { + v.value = val + v.isSet = true +} + +func (v NullablePostBucketRequest) IsSet() bool { + return v.isSet +} + +func (v *NullablePostBucketRequest) Unset() { + v.value = nil + v.isSet = false +} + +func NewNullablePostBucketRequest(val *PostBucketRequest) *NullablePostBucketRequest { + return &NullablePostBucketRequest{value: val, isSet: true} +} + +func (v NullablePostBucketRequest) MarshalJSON() ([]byte, error) { + return json.Marshal(v.value) +} + +func (v *NullablePostBucketRequest) UnmarshalJSON(src []byte) error { + v.isSet = true + return json.Unmarshal(src, &v.value) +} diff --git a/internal/bucket.go b/internal/bucket.go new file mode 100644 index 0000000..8a8dea3 --- /dev/null +++ b/internal/bucket.go @@ -0,0 +1,296 @@ +package internal + +import ( + "context" + "errors" + "fmt" + "time" + + "github.com/influxdata/influx-cli/v2/internal/api" + "github.com/influxdata/influx-cli/v2/internal/duration" +) + +const InfiniteRetention = 0 + +type BucketsClients struct { + OrgApi api.OrganizationsApi + BucketApi api.BucketsApi +} + +type BucketsCreateParams struct { + OrgID string + OrgName string + Name string + Description string + Retention string + ShardGroupDuration string +} + +var ( + ErrMustSpecifyOrg = errors.New("must specify org ID or org name") + ErrMustSpecifyOrgDeleteByName = errors.New("must specify org ID or org name when deleting bucket by name") + ErrMustSpecifyBucket = errors.New("must specify bucket ID or bucket name") +) + +func (c *CLI) BucketsCreate(ctx context.Context, clients *BucketsClients, params *BucketsCreateParams) error { + if params.OrgID == "" && params.OrgName == "" && c.ActiveConfig.Org == "" { + return ErrMustSpecifyOrg + } + + rp, err := duration.RawDurationToTimeDuration(params.Retention) + if err != nil { + return err + } + sgd, err := duration.RawDurationToTimeDuration(params.ShardGroupDuration) + if err != nil { + return err + } + + reqBody := api.PostBucketRequest{ + OrgID: params.OrgID, + Name: params.Name, + RetentionRules: []api.RetentionRule{}, + } + if params.Description != "" { + reqBody.Description = ¶ms.Description + } + // Only append a retention rule if the user wants to explicitly set + // a parameter on the rule. + // + // This is for backwards-compatibility with older versions of the API, + // which didn't support setting shard-group durations and used an empty + // array of rules to represent infinite retention. + if rp > 0 || sgd > 0 { + rule := api.NewRetentionRuleWithDefaults() + if rp > 0 { + rule.SetEverySeconds(int64(rp.Round(time.Second) / time.Second)) + } + if sgd > 0 { + rule.SetShardGroupDurationSeconds(int64(sgd.Round(time.Second) / time.Second)) + } + reqBody.RetentionRules = append(reqBody.RetentionRules, *rule) + } + if reqBody.OrgID == "" { + name := params.OrgName + if name == "" { + name = c.ActiveConfig.Org + } + resp, _, err := clients.OrgApi.GetOrgs(ctx).Org(name).Execute() + if err != nil { + return fmt.Errorf("failed to lookup ID of org %q: %w", name, err) + } + orgs := resp.GetOrgs() + if len(orgs) == 0 { + return fmt.Errorf("no organization found with name %q", name) + } + reqBody.OrgID = orgs[0].GetId() + } + + bucket, _, err := clients.BucketApi.PostBuckets(ctx).PostBucketRequest(reqBody).Execute() + if err != nil { + return fmt.Errorf("failed to create bucket: %w", err) + } + + return c.printBuckets(bucketPrintOptions{bucket: &bucket}) +} + +type BucketsListParams struct { + OrgID string + OrgName string + Name string + ID string +} + +func (c *CLI) BucketsList(ctx context.Context, client api.BucketsApi, params *BucketsListParams) error { + if params.OrgID == "" && params.OrgName == "" && c.ActiveConfig.Org == "" { + return ErrMustSpecifyOrg + } + + req := client.GetBuckets(ctx) + if params.OrgID != "" { + req = req.OrgID(params.OrgID) + } + if params.OrgName != "" { + req = req.Org(params.OrgName) + } + if params.OrgID == "" && params.OrgName == "" { + req = req.Org(c.ActiveConfig.Org) + } + if params.Name != "" { + req = req.Name(params.Name) + } + if params.ID != "" { + req = req.Id(params.ID) + } + + buckets, _, err := req.Execute() + if err != nil { + return fmt.Errorf("failed to list buckets: %w", err) + } + + printOpts := bucketPrintOptions{} + if buckets.Buckets != nil { + printOpts.buckets = *buckets.Buckets + } + return c.printBuckets(printOpts) +} + +type BucketsUpdateParams struct { + ID string + Name string + Description string + Retention string + ShardGroupDuration string +} + +func (c *CLI) BucketsUpdate(ctx context.Context, client api.BucketsApi, params *BucketsUpdateParams) error { + reqBody := api.PatchBucketRequest{} + if params.Name != "" { + reqBody.SetName(params.Name) + } + if params.Description != "" { + reqBody.SetDescription(params.Description) + } + if params.Retention != "" || params.ShardGroupDuration != "" { + patchRule := api.NewPatchRetentionRuleWithDefaults() + if params.Retention != "" { + rp, err := duration.RawDurationToTimeDuration(params.Retention) + if err != nil { + return err + } + patchRule.SetEverySeconds(int64(rp.Round(time.Second) / time.Second)) + } + if params.ShardGroupDuration != "" { + sgd, err := duration.RawDurationToTimeDuration(params.ShardGroupDuration) + if err != nil { + return err + } + patchRule.SetShardGroupDurationSeconds(int64(sgd.Round(time.Second) / time.Second)) + } + reqBody.SetRetentionRules([]api.PatchRetentionRule{*patchRule}) + } + + bucket, _, err := client.PatchBucketsID(ctx, params.ID).PatchBucketRequest(reqBody).Execute() + if err != nil { + return fmt.Errorf("failed to update bucket %q: %w", params.ID, err) + } + + return c.printBuckets(bucketPrintOptions{bucket: &bucket}) +} + +type BucketsDeleteParams struct { + ID string + Name string + OrgID string + OrgName string +} + +func (c *CLI) BucketsDelete(ctx context.Context, client api.BucketsApi, params *BucketsDeleteParams) error { + if params.ID == "" && params.Name == "" { + return ErrMustSpecifyBucket + } + + var bucket api.Bucket + getReq := client.GetBuckets(ctx) + if params.ID != "" { + getReq = getReq.Id(params.ID) + } else { + if params.OrgID == "" && params.OrgName == "" && c.ActiveConfig.Org == "" { + return ErrMustSpecifyOrgDeleteByName + } + getReq = getReq.Name(params.Name) + if params.OrgID != "" { + getReq = getReq.OrgID(params.OrgID) + } + if params.OrgName != "" { + getReq = getReq.Org(params.OrgName) + } + if params.OrgID == "" && params.OrgName == "" { + getReq = getReq.Org(c.ActiveConfig.Org) + } + } + + displayId := params.ID + if displayId == "" { + displayId = params.Name + } + + resp, _, err := getReq.Execute() + if err != nil { + return fmt.Errorf("failed to find bucket %q: %w", displayId, err) + } + buckets := resp.GetBuckets() + if len(buckets) == 0 { + return fmt.Errorf("bucket %q not found", displayId) + } + bucket = buckets[0] + + if _, err := client.DeleteBucketsID(ctx, bucket.GetId()).Execute(); err != nil { + return fmt.Errorf("failed to delete bucket %q: %w", displayId, err) + } + + return c.printBuckets(bucketPrintOptions{bucket: &bucket, deleted: true}) +} + +type bucketPrintOptions struct { + deleted bool + bucket *api.Bucket + buckets []api.Bucket +} + +func (c *CLI) printBuckets(options bucketPrintOptions) error { + if c.PrintAsJSON { + var v interface{} + if options.bucket != nil { + v = options.bucket + } else { + v = options.buckets + } + return c.PrintJSON(v) + } + + headers := []string{"ID", "Name", "Retention", "Shard group duration", "Organization ID"} + if options.deleted { + headers = append(headers, "Deleted") + } + + if options.bucket != nil { + options.buckets = append(options.buckets, *options.bucket) + } + + var rows []map[string]interface{} + for _, bkt := range options.buckets { + var rpDuration time.Duration // zero value implies infinite retention policy + var sgDuration time.Duration // zero value implies the server should pick a value + + if rules := bkt.GetRetentionRules(); len(rules) > 0 { + rpDuration = time.Duration(rules[0].GetEverySeconds()) * time.Second + sgDuration = time.Duration(rules[0].GetShardGroupDurationSeconds()) * time.Second + } + + rp := rpDuration.String() + if rpDuration == InfiniteRetention { + rp = "infinite" + } + sgDur := sgDuration.String() + // ShardGroupDuration will be zero if listing buckets from InfluxDB Cloud. + // Show something more useful here in that case. + if sgDuration == 0 { + sgDur = "n/a" + } + + row := map[string]interface{}{ + "ID": bkt.GetId(), + "Name": bkt.GetName(), + "Retention": rp, + "Shard group duration": sgDur, + "Organization ID": bkt.GetOrgID(), + } + if options.deleted { + row["Deleted"] = true + } + rows = append(rows, row) + } + + return c.PrintTable(headers, rows...) +} diff --git a/internal/bucket_test.go b/internal/bucket_test.go new file mode 100644 index 0000000..a6d8070 --- /dev/null +++ b/internal/bucket_test.go @@ -0,0 +1,807 @@ +package internal_test + +import ( + "context" + "errors" + "net/http" + "strings" + "testing" + + "github.com/influxdata/influx-cli/v2/internal" + "github.com/influxdata/influx-cli/v2/internal/api" + "github.com/influxdata/influx-cli/v2/internal/config" + "github.com/influxdata/influx-cli/v2/internal/mock" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" +) + +func TestBucketsCreate(t *testing.T) { + t.Parallel() + + var testCases = []struct { + name string + configOrgName string + params internal.BucketsCreateParams + buildOrgLookupFn func(*testing.T) func(api.ApiGetOrgsRequest) (api.Organizations, *http.Response, error) + buildBucketCreateFn func(*testing.T) func(api.ApiPostBucketsRequest) (api.Bucket, *http.Response, error) + expectedStdoutPattern string + expectedInErr string + }{ + { + name: "minimal", + params: internal.BucketsCreateParams{ + OrgID: "123", + Name: "my-bucket", + }, + buildOrgLookupFn: func(t *testing.T) func(api.ApiGetOrgsRequest) (api.Organizations, *http.Response, error) { + return func(api.ApiGetOrgsRequest) (api.Organizations, *http.Response, error) { + return api.Organizations{}, nil, errors.New("unexpected org lookup call") + } + }, + buildBucketCreateFn: func(t *testing.T) func(api.ApiPostBucketsRequest) (api.Bucket, *http.Response, error) { + return func(req api.ApiPostBucketsRequest) (api.Bucket, *http.Response, error) { + body := req.GetPostBucketRequest() + require.NotNil(t, body) + require.Equal(t, "123", body.OrgID) + require.Equal(t, "my-bucket", body.Name) + require.Empty(t, body.RetentionRules) + + return api.Bucket{ + Id: api.PtrString("456"), + OrgID: api.PtrString("123"), + Name: "my-bucket", + RetentionRules: nil, + }, nil, nil + } + }, + expectedStdoutPattern: "456\\s+my-bucket\\s+infinite\\s+n/a\\s+123", + }, + { + name: "fully specified", + params: internal.BucketsCreateParams{ + OrgID: "123", + Name: "my-bucket", + Description: "my cool bucket", + Retention: "24h", + ShardGroupDuration: "1h", + }, + buildOrgLookupFn: func(t *testing.T) func(api.ApiGetOrgsRequest) (api.Organizations, *http.Response, error) { + return func(api.ApiGetOrgsRequest) (api.Organizations, *http.Response, error) { + return api.Organizations{}, nil, errors.New("unexpected org lookup call") + } + }, + buildBucketCreateFn: func(t *testing.T) func(api.ApiPostBucketsRequest) (api.Bucket, *http.Response, error) { + return func(req api.ApiPostBucketsRequest) (api.Bucket, *http.Response, error) { + body := req.GetPostBucketRequest() + require.NotNil(t, body) + require.Equal(t, "123", body.OrgID) + require.Equal(t, "my-bucket", body.Name) + require.Equal(t, "my cool bucket", *body.Description) + require.Equal(t, 1, len(body.RetentionRules)) + require.Equal(t, int64(86400), body.RetentionRules[0].EverySeconds) + require.Equal(t, int64(3600), *body.RetentionRules[0].ShardGroupDurationSeconds) + + return api.Bucket{ + Id: api.PtrString("456"), + OrgID: api.PtrString("123"), + Name: "my-bucket", + RetentionRules: body.RetentionRules, + }, nil, nil + } + }, + expectedStdoutPattern: "456\\s+my-bucket\\s+24h0m0s\\s+1h0m0s\\s+123", + }, + { + name: "retention but not shard-group duration", + params: internal.BucketsCreateParams{ + OrgID: "123", + Name: "my-bucket", + Retention: "24h", + }, + buildOrgLookupFn: func(t *testing.T) func(api.ApiGetOrgsRequest) (api.Organizations, *http.Response, error) { + return func(api.ApiGetOrgsRequest) (api.Organizations, *http.Response, error) { + return api.Organizations{}, nil, errors.New("unexpected org lookup call") + } + }, + buildBucketCreateFn: func(t *testing.T) func(api.ApiPostBucketsRequest) (api.Bucket, *http.Response, error) { + return func(req api.ApiPostBucketsRequest) (api.Bucket, *http.Response, error) { + body := req.GetPostBucketRequest() + require.NotNil(t, body) + require.Equal(t, "123", body.OrgID) + require.Equal(t, "my-bucket", body.Name) + require.Nil(t, body.Description) + require.Equal(t, 1, len(body.RetentionRules)) + require.Equal(t, int64(86400), body.RetentionRules[0].EverySeconds) + require.Nil(t, body.RetentionRules[0].ShardGroupDurationSeconds) + + return api.Bucket{ + Id: api.PtrString("456"), + OrgID: api.PtrString("123"), + Name: "my-bucket", + RetentionRules: body.RetentionRules, + }, nil, nil + } + }, + }, + { + name: "look up org by name", + params: internal.BucketsCreateParams{ + OrgName: "my-org", + Name: "my-bucket", + Description: "my cool bucket", + Retention: "24h", + ShardGroupDuration: "1h", + }, + buildOrgLookupFn: func(t *testing.T) func(api.ApiGetOrgsRequest) (api.Organizations, *http.Response, error) { + return func(req api.ApiGetOrgsRequest) (api.Organizations, *http.Response, error) { + require.Equal(t, "my-org", *req.GetOrg()) + return api.Organizations{ + Orgs: &[]api.Organization{{Id: api.PtrString("123")}}, + }, nil, nil + } + }, + buildBucketCreateFn: func(t *testing.T) func(api.ApiPostBucketsRequest) (api.Bucket, *http.Response, error) { + return func(req api.ApiPostBucketsRequest) (api.Bucket, *http.Response, error) { + body := req.GetPostBucketRequest() + require.NotNil(t, body) + require.Equal(t, "123", body.OrgID) + require.Equal(t, "my-bucket", body.Name) + require.Equal(t, "my cool bucket", *body.Description) + require.Equal(t, 1, len(body.RetentionRules)) + require.Equal(t, int64(86400), body.RetentionRules[0].EverySeconds) + require.Equal(t, int64(3600), *body.RetentionRules[0].ShardGroupDurationSeconds) + + return api.Bucket{ + Id: api.PtrString("456"), + OrgID: api.PtrString("123"), + Name: "my-bucket", + RetentionRules: body.RetentionRules, + }, nil, nil + } + }, + expectedStdoutPattern: "456\\s+my-bucket\\s+24h0m0s\\s+1h0m0s\\s+123", + }, + { + name: "look up org by name from config", + params: internal.BucketsCreateParams{ + Name: "my-bucket", + Description: "my cool bucket", + Retention: "24h", + ShardGroupDuration: "1h", + }, + configOrgName: "my-org", + buildOrgLookupFn: func(t *testing.T) func(api.ApiGetOrgsRequest) (api.Organizations, *http.Response, error) { + return func(req api.ApiGetOrgsRequest) (api.Organizations, *http.Response, error) { + require.Equal(t, "my-org", *req.GetOrg()) + return api.Organizations{ + Orgs: &[]api.Organization{{Id: api.PtrString("123")}}, + }, nil, nil + } + }, + buildBucketCreateFn: func(t *testing.T) func(api.ApiPostBucketsRequest) (api.Bucket, *http.Response, error) { + return func(req api.ApiPostBucketsRequest) (api.Bucket, *http.Response, error) { + body := req.GetPostBucketRequest() + require.NotNil(t, body) + require.Equal(t, "123", body.OrgID) + require.Equal(t, "my-bucket", body.Name) + require.Equal(t, "my cool bucket", *body.Description) + require.Equal(t, 1, len(body.RetentionRules)) + require.Equal(t, int64(86400), body.RetentionRules[0].EverySeconds) + require.Equal(t, int64(3600), *body.RetentionRules[0].ShardGroupDurationSeconds) + + return api.Bucket{ + Id: api.PtrString("456"), + OrgID: api.PtrString("123"), + Name: "my-bucket", + RetentionRules: body.RetentionRules, + }, nil, nil + } + }, + expectedStdoutPattern: "456\\s+my-bucket\\s+24h0m0s\\s+1h0m0s\\s+123", + }, + { + name: "no org specified", + params: internal.BucketsCreateParams{ + Name: "my-bucket", + Description: "my cool bucket", + Retention: "24h", + ShardGroupDuration: "1h", + }, + buildOrgLookupFn: func(t *testing.T) func(api.ApiGetOrgsRequest) (api.Organizations, *http.Response, error) { + return func(req api.ApiGetOrgsRequest) (api.Organizations, *http.Response, error) { + return api.Organizations{}, nil, errors.New("shouldn't be called") + } + }, + buildBucketCreateFn: func(t *testing.T) func(api.ApiPostBucketsRequest) (api.Bucket, *http.Response, error) { + return func(req api.ApiPostBucketsRequest) (api.Bucket, *http.Response, error) { + return api.Bucket{}, nil, errors.New("shouldn't be called") + } + }, + expectedInErr: "must specify org ID or org name", + }, + { + name: "no such org", + params: internal.BucketsCreateParams{ + Name: "my-bucket", + OrgName: "fake-org", + Description: "my cool bucket", + Retention: "24h", + ShardGroupDuration: "1h", + }, + buildOrgLookupFn: func(t *testing.T) func(api.ApiGetOrgsRequest) (api.Organizations, *http.Response, error) { + return func(req api.ApiGetOrgsRequest) (api.Organizations, *http.Response, error) { + return api.Organizations{}, nil, nil + } + }, + buildBucketCreateFn: func(t *testing.T) func(api.ApiPostBucketsRequest) (api.Bucket, *http.Response, error) { + return func(req api.ApiPostBucketsRequest) (api.Bucket, *http.Response, error) { + return api.Bucket{}, nil, errors.New("shouldn't be called") + } + }, + expectedInErr: "no organization found", + }, + } + + for _, tc := range testCases { + tc := tc + t.Run(tc.name, func(t *testing.T) { + t.Parallel() + + stdio := mock.NewMockStdio(nil, false) + cli := internal.CLI{ActiveConfig: config.Config{Org: tc.configOrgName}, StdIO: stdio} + clients := internal.BucketsClients{ + OrgApi: &mock.OrganizationsApi{ + GetOrgsExecuteFn: tc.buildOrgLookupFn(t), + }, + BucketApi: &mock.BucketsApi{ + PostBucketsExecuteFn: tc.buildBucketCreateFn(t), + }, + } + + err := cli.BucketsCreate(context.Background(), &clients, &tc.params) + if tc.expectedInErr != "" { + require.Error(t, err) + require.Contains(t, err.Error(), tc.expectedInErr) + require.Empty(t, stdio.Stdout()) + return + } + require.NoError(t, err) + outLines := strings.Split(stdio.Stdout(), "\n") + if outLines[len(outLines)-1] == "" { + outLines = outLines[:len(outLines)-1] + } + require.Equal(t, 2, len(outLines)) + require.Regexp(t, "ID\\s+Name\\s+Retention\\s+Shard group duration\\s+Organization ID", outLines[0]) + require.Regexp(t, tc.expectedStdoutPattern, outLines[1]) + }) + } +} + +func TestBucketsList(t *testing.T) { + t.Parallel() + + var testCases = []struct { + name string + configOrgName string + params internal.BucketsListParams + buildBucketLookupFn func(*testing.T) func(api.ApiGetBucketsRequest) (api.Buckets, *http.Response, error) + expectedStdoutPatterns []string + expectedInErr string + }{ + { + name: "by ID", + params: internal.BucketsListParams{ + ID: "123", + }, + configOrgName: "my-default-org", + buildBucketLookupFn: func(t *testing.T) func(api.ApiGetBucketsRequest) (api.Buckets, *http.Response, error) { + return func(req api.ApiGetBucketsRequest) (api.Buckets, *http.Response, error) { + require.Equal(t, "123", *req.GetId()) + require.Equal(t, "my-default-org", *req.GetOrg()) + require.Nil(t, req.GetName()) + require.Nil(t, req.GetOrgID()) + return api.Buckets{ + Buckets: &[]api.Bucket{ + { + Id: api.PtrString("123"), + Name: "my-bucket", + OrgID: api.PtrString("456"), + RetentionRules: []api.RetentionRule{ + {EverySeconds: 3600}, + }, + }, + }, + }, nil, nil + } + }, + expectedStdoutPatterns: []string{ + "123\\s+my-bucket\\s+1h0m0s\\s+n/a\\s+456", + }, + }, + { + name: "by name", + params: internal.BucketsListParams{ + Name: "my-bucket", + }, + configOrgName: "my-default-org", + buildBucketLookupFn: func(t *testing.T) func(api.ApiGetBucketsRequest) (api.Buckets, *http.Response, error) { + return func(req api.ApiGetBucketsRequest) (api.Buckets, *http.Response, error) { + require.Equal(t, "my-bucket", *req.GetName()) + require.Equal(t, "my-default-org", *req.GetOrg()) + require.Nil(t, req.GetId()) + require.Nil(t, req.GetOrgID()) + return api.Buckets{ + Buckets: &[]api.Bucket{ + { + Id: api.PtrString("123"), + Name: "my-bucket", + OrgID: api.PtrString("456"), + RetentionRules: []api.RetentionRule{ + {EverySeconds: 3600}, + }, + }, + }, + }, nil, nil + } + }, + expectedStdoutPatterns: []string{ + "123\\s+my-bucket\\s+1h0m0s\\s+n/a\\s+456", + }, + }, + { + name: "override org by ID", + params: internal.BucketsListParams{ + OrgID: "456", + }, + configOrgName: "my-default-org", + buildBucketLookupFn: func(t *testing.T) func(api.ApiGetBucketsRequest) (api.Buckets, *http.Response, error) { + return func(req api.ApiGetBucketsRequest) (api.Buckets, *http.Response, error) { + require.Equal(t, "456", *req.GetOrgID()) + require.Nil(t, req.GetId()) + require.Nil(t, req.GetOrg()) + require.Nil(t, req.GetOrg()) + return api.Buckets{}, nil, nil + } + }, + }, + { + name: "override org by name", + params: internal.BucketsListParams{ + OrgName: "my-org", + }, + configOrgName: "my-default-org", + buildBucketLookupFn: func(t *testing.T) func(api.ApiGetBucketsRequest) (api.Buckets, *http.Response, error) { + return func(req api.ApiGetBucketsRequest) (api.Buckets, *http.Response, error) { + require.Equal(t, "my-org", *req.GetOrg()) + require.Nil(t, req.GetId()) + require.Nil(t, req.GetName()) + require.Nil(t, req.GetOrgID()) + return api.Buckets{ + Buckets: &[]api.Bucket{ + { + Id: api.PtrString("123"), + Name: "my-bucket", + OrgID: api.PtrString("456"), + RetentionRules: []api.RetentionRule{ + {EverySeconds: 3600}, + }, + }, + { + Id: api.PtrString("999"), + Name: "bucket2", + OrgID: api.PtrString("456"), + RetentionRules: []api.RetentionRule{ + {EverySeconds: 0, ShardGroupDurationSeconds: api.PtrInt64(60)}, + }, + }, + }, + }, nil, nil + } + }, + expectedStdoutPatterns: []string{ + "123\\s+my-bucket\\s+1h0m0s\\s+n/a\\s+456", + "999\\s+bucket2\\s+infinite\\s+1m0s\\s+456", + }, + }, + { + name: "no org specified", + expectedInErr: "must specify org ID or org name", + buildBucketLookupFn: func(t *testing.T) func(api.ApiGetBucketsRequest) (api.Buckets, *http.Response, error) { + return func(api.ApiGetBucketsRequest) (api.Buckets, *http.Response, error) { + return api.Buckets{}, nil, errors.New("shouldn't be called") + } + }, + }, + } + + for _, tc := range testCases { + tc := tc + t.Run(tc.name, func(t *testing.T) { + t.Parallel() + + stdio := mock.NewMockStdio(nil, false) + cli := internal.CLI{ActiveConfig: config.Config{Org: tc.configOrgName}, StdIO: stdio} + client := mock.BucketsApi{ + GetBucketsExecuteFn: tc.buildBucketLookupFn(t), + } + + err := cli.BucketsList(context.Background(), &client, &tc.params) + if tc.expectedInErr != "" { + require.Error(t, err) + require.Contains(t, err.Error(), tc.expectedInErr) + require.Empty(t, stdio.Stdout()) + return + } + require.NoError(t, err) + outLines := strings.Split(stdio.Stdout(), "\n") + if outLines[len(outLines)-1] == "" { + outLines = outLines[:len(outLines)-1] + } + require.Equal(t, len(tc.expectedStdoutPatterns)+1, len(outLines)) + require.Regexp(t, "ID\\s+Name\\s+Retention\\s+Shard group duration\\s+Organization ID", outLines[0]) + for i, pattern := range tc.expectedStdoutPatterns { + require.Regexp(t, pattern, outLines[i+1]) + } + }) + } +} + +func TestBucketsUpdate(t *testing.T) { + t.Parallel() + + var testCases = []struct { + name string + params internal.BucketsUpdateParams + buildBucketUpdateFn func(*testing.T) func(api.ApiPatchBucketsIDRequest) (api.Bucket, *http.Response, error) + expectedStdoutPattern string + }{ + { + name: "name", + params: internal.BucketsUpdateParams{ + ID: "123", + Name: "cold-storage", + }, + buildBucketUpdateFn: func(t *testing.T) func(api.ApiPatchBucketsIDRequest) (api.Bucket, *http.Response, error) { + return func(req api.ApiPatchBucketsIDRequest) (api.Bucket, *http.Response, error) { + require.Equal(t, "123", req.GetBucketID()) + body := req.GetPatchBucketRequest() + require.Equal(t, "cold-storage", body.GetName()) + require.Empty(t, body.GetDescription()) + require.Empty(t, body.GetRetentionRules()) + + return api.Bucket{ + Id: api.PtrString("123"), + Name: "cold-storage", + OrgID: api.PtrString("456"), + }, nil, nil + } + }, + expectedStdoutPattern: "123\\s+cold-storage\\s+infinite\\s+n/a\\s+456", + }, + { + name: "description", + params: internal.BucketsUpdateParams{ + ID: "123", + Description: "a very useful description", + }, + buildBucketUpdateFn: func(t *testing.T) func(api.ApiPatchBucketsIDRequest) (api.Bucket, *http.Response, error) { + return func(req api.ApiPatchBucketsIDRequest) (api.Bucket, *http.Response, error) { + require.Equal(t, "123", req.GetBucketID()) + body := req.GetPatchBucketRequest() + require.Equal(t, "a very useful description", body.GetDescription()) + require.Empty(t, body.GetName()) + require.Empty(t, body.GetRetentionRules()) + + return api.Bucket{ + Id: api.PtrString("123"), + Name: "my-bucket", + Description: api.PtrString("a very useful description"), + OrgID: api.PtrString("456"), + }, nil, nil + } + }, + expectedStdoutPattern: "123\\s+my-bucket\\s+infinite\\s+n/a\\s+456", + }, + { + name: "retention", + params: internal.BucketsUpdateParams{ + ID: "123", + Retention: "3w", + }, + buildBucketUpdateFn: func(t *testing.T) func(api.ApiPatchBucketsIDRequest) (api.Bucket, *http.Response, error) { + return func(req api.ApiPatchBucketsIDRequest) (api.Bucket, *http.Response, error) { + require.Equal(t, "123", req.GetBucketID()) + body := req.GetPatchBucketRequest() + require.Len(t, body.GetRetentionRules(), 1) + rule := body.GetRetentionRules()[0] + require.Nil(t, rule.ShardGroupDurationSeconds) + require.Equal(t, int64(3*7*24*3600), rule.GetEverySeconds()) + require.Nil(t, body.Name) + require.Nil(t, body.Description) + + return api.Bucket{ + Id: api.PtrString("123"), + Name: "my-bucket", + OrgID: api.PtrString("456"), + RetentionRules: []api.RetentionRule{ + {EverySeconds: rule.GetEverySeconds()}, + }, + }, nil, nil + } + }, + expectedStdoutPattern: "123\\s+my-bucket\\s+504h0m0s\\s+n/a\\s+456", + }, + { + name: "shard-group duration", + params: internal.BucketsUpdateParams{ + ID: "123", + ShardGroupDuration: "10h30m", + }, + buildBucketUpdateFn: func(t *testing.T) func(api.ApiPatchBucketsIDRequest) (api.Bucket, *http.Response, error) { + return func(req api.ApiPatchBucketsIDRequest) (api.Bucket, *http.Response, error) { + require.Equal(t, "123", req.GetBucketID()) + body := req.GetPatchBucketRequest() + require.Len(t, body.GetRetentionRules(), 1) + rule := body.GetRetentionRules()[0] + require.Nil(t, rule.EverySeconds) + require.Equal(t, int64(10*3600+30*60), rule.GetShardGroupDurationSeconds()) + require.Nil(t, body.Name) + require.Nil(t, body.Description) + + return api.Bucket{ + Id: api.PtrString("123"), + Name: "my-bucket", + OrgID: api.PtrString("456"), + RetentionRules: []api.RetentionRule{ + {ShardGroupDurationSeconds: rule.ShardGroupDurationSeconds}, + }, + }, nil, nil + } + }, + expectedStdoutPattern: "123\\s+my-bucket\\s+infinite\\s+10h30m0s\\s+456", + }, + } + + for _, tc := range testCases { + tc := tc + t.Run(tc.name, func(t *testing.T) { + t.Parallel() + + stdio := mock.NewMockStdio(nil, false) + cli := internal.CLI{StdIO: stdio} + client := mock.BucketsApi{ + PatchBucketsIDExecuteFn: tc.buildBucketUpdateFn(t), + } + + err := cli.BucketsUpdate(context.Background(), &client, &tc.params) + require.NoError(t, err) + outLines := strings.Split(stdio.Stdout(), "\n") + if outLines[len(outLines)-1] == "" { + outLines = outLines[:len(outLines)-1] + } + require.Equal(t, 2, len(outLines)) + require.Regexp(t, "ID\\s+Name\\s+Retention\\s+Shard group duration\\s+Organization ID", outLines[0]) + require.Regexp(t, tc.expectedStdoutPattern, outLines[1]) + }) + } +} + +func TestBucketsDelete(t *testing.T) { + t.Parallel() + + var testCases = []struct { + name string + configOrgName string + params internal.BucketsDeleteParams + buildBucketsLookupFn func(*testing.T) func(api.ApiGetBucketsRequest) (api.Buckets, *http.Response, error) + buildBucketDeleteFn func(*testing.T) func(api.ApiDeleteBucketsIDRequest) (*http.Response, error) + expectedStdoutPattern string + expectedInErr string + }{ + { + name: "by ID", + configOrgName: "my-default-org", + params: internal.BucketsDeleteParams{ + ID: "123", + }, + buildBucketsLookupFn: func(t *testing.T) func(api.ApiGetBucketsRequest) (api.Buckets, *http.Response, error) { + return func(req api.ApiGetBucketsRequest) (api.Buckets, *http.Response, error) { + require.Equal(t, "123", *req.GetId()) + require.Nil(t, req.GetName()) + require.Nil(t, req.GetOrgID()) + require.Nil(t, req.GetOrg()) + + return api.Buckets{ + Buckets: &[]api.Bucket{ + { + Id: api.PtrString("123"), + Name: "my-bucket", + OrgID: api.PtrString("456"), + RetentionRules: []api.RetentionRule{ + {EverySeconds: 3600}, + }, + }, + }, + }, nil, nil + } + }, + buildBucketDeleteFn: func(t *testing.T) func(api.ApiDeleteBucketsIDRequest) (*http.Response, error) { + return func(req api.ApiDeleteBucketsIDRequest) (*http.Response, error) { + assert.Equal(t, "123", req.GetBucketID()) + return nil, nil + } + }, + expectedStdoutPattern: "123\\s+my-bucket\\s+1h0m0s\\s+n/a\\s+456", + }, + { + name: "by name and org ID", + configOrgName: "my-default-org", + params: internal.BucketsDeleteParams{ + Name: "my-bucket", + OrgID: "456", + }, + buildBucketsLookupFn: func(t *testing.T) func(api.ApiGetBucketsRequest) (api.Buckets, *http.Response, error) { + return func(req api.ApiGetBucketsRequest) (api.Buckets, *http.Response, error) { + require.Equal(t, "my-bucket", *req.GetName()) + require.Equal(t, "456", *req.GetOrgID()) + require.Nil(t, req.GetId()) + require.Nil(t, req.GetOrg()) + + return api.Buckets{ + Buckets: &[]api.Bucket{ + { + Id: api.PtrString("123"), + Name: "my-bucket", + OrgID: api.PtrString("456"), + RetentionRules: []api.RetentionRule{ + {EverySeconds: 3600}, + }, + }, + }, + }, nil, nil + } + }, + buildBucketDeleteFn: func(t *testing.T) func(api.ApiDeleteBucketsIDRequest) (*http.Response, error) { + return func(req api.ApiDeleteBucketsIDRequest) (*http.Response, error) { + assert.Equal(t, "123", req.GetBucketID()) + return nil, nil + } + }, + expectedStdoutPattern: "123\\s+my-bucket\\s+1h0m0s\\s+n/a\\s+456", + }, + { + name: "by name and org name", + configOrgName: "my-default-org", + params: internal.BucketsDeleteParams{ + Name: "my-bucket", + OrgName: "my-org", + }, + buildBucketsLookupFn: func(t *testing.T) func(api.ApiGetBucketsRequest) (api.Buckets, *http.Response, error) { + return func(req api.ApiGetBucketsRequest) (api.Buckets, *http.Response, error) { + require.Equal(t, "my-bucket", *req.GetName()) + require.Equal(t, "my-org", *req.GetOrg()) + require.Nil(t, req.GetId()) + require.Nil(t, req.GetOrgID()) + + return api.Buckets{ + Buckets: &[]api.Bucket{ + { + Id: api.PtrString("123"), + Name: "my-bucket", + OrgID: api.PtrString("456"), + RetentionRules: []api.RetentionRule{ + {EverySeconds: 3600}, + }, + }, + }, + }, nil, nil + } + }, + buildBucketDeleteFn: func(t *testing.T) func(api.ApiDeleteBucketsIDRequest) (*http.Response, error) { + return func(req api.ApiDeleteBucketsIDRequest) (*http.Response, error) { + assert.Equal(t, "123", req.GetBucketID()) + return nil, nil + } + }, + expectedStdoutPattern: "123\\s+my-bucket\\s+1h0m0s\\s+n/a\\s+456", + }, + { + name: "by name in default org", + configOrgName: "my-default-org", + params: internal.BucketsDeleteParams{ + Name: "my-bucket", + }, + buildBucketsLookupFn: func(t *testing.T) func(api.ApiGetBucketsRequest) (api.Buckets, *http.Response, error) { + return func(req api.ApiGetBucketsRequest) (api.Buckets, *http.Response, error) { + require.Equal(t, "my-bucket", *req.GetName()) + require.Equal(t, "my-default-org", *req.GetOrg()) + require.Nil(t, req.GetId()) + require.Nil(t, req.GetOrgID()) + + return api.Buckets{ + Buckets: &[]api.Bucket{ + { + Id: api.PtrString("123"), + Name: "my-bucket", + OrgID: api.PtrString("456"), + RetentionRules: []api.RetentionRule{ + {EverySeconds: 3600}, + }, + }, + }, + }, nil, nil + } + }, + buildBucketDeleteFn: func(t *testing.T) func(api.ApiDeleteBucketsIDRequest) (*http.Response, error) { + return func(req api.ApiDeleteBucketsIDRequest) (*http.Response, error) { + assert.Equal(t, "123", req.GetBucketID()) + return nil, nil + } + }, + expectedStdoutPattern: "123\\s+my-bucket\\s+1h0m0s\\s+n/a\\s+456", + }, + { + name: "by name without org", + params: internal.BucketsDeleteParams{ + Name: "my-bucket", + }, + buildBucketsLookupFn: func(t *testing.T) func(api.ApiGetBucketsRequest) (api.Buckets, *http.Response, error) { + return func(api.ApiGetBucketsRequest) (api.Buckets, *http.Response, error) { + return api.Buckets{}, nil, errors.New("shouldn't be called") + } + }, + buildBucketDeleteFn: func(t *testing.T) func(api.ApiDeleteBucketsIDRequest) (*http.Response, error) { + return func(api.ApiDeleteBucketsIDRequest) (*http.Response, error) { + return nil, errors.New("shouldn't be called") + } + }, + expectedInErr: "must specify org ID or org name", + }, + { + name: "no such bucket", + params: internal.BucketsDeleteParams{ + ID: "123", + }, + buildBucketsLookupFn: func(t *testing.T) func(api.ApiGetBucketsRequest) (api.Buckets, *http.Response, error) { + return func(api.ApiGetBucketsRequest) (api.Buckets, *http.Response, error) { + return api.Buckets{}, nil, nil + } + }, + buildBucketDeleteFn: func(t *testing.T) func(api.ApiDeleteBucketsIDRequest) (*http.Response, error) { + return func(api.ApiDeleteBucketsIDRequest) (*http.Response, error) { + return nil, errors.New("shouldn't be called") + } + }, + expectedInErr: "not found", + }, + } + + for _, tc := range testCases { + tc := tc + t.Run(tc.name, func(t *testing.T) { + t.Parallel() + + stdio := mock.NewMockStdio(nil, false) + cli := internal.CLI{ActiveConfig: config.Config{Org: tc.configOrgName}, StdIO: stdio} + client := mock.BucketsApi{ + GetBucketsExecuteFn: tc.buildBucketsLookupFn(t), + DeleteBucketsIDExecuteFn: tc.buildBucketDeleteFn(t), + } + + err := cli.BucketsDelete(context.Background(), &client, &tc.params) + if tc.expectedInErr != "" { + require.Error(t, err) + require.Contains(t, err.Error(), tc.expectedInErr) + require.Empty(t, stdio.Stdout()) + return + } + require.NoError(t, err) + outLines := strings.Split(stdio.Stdout(), "\n") + if outLines[len(outLines)-1] == "" { + outLines = outLines[:len(outLines)-1] + } + require.Regexp(t, "ID\\s+Name\\s+Retention\\s+Shard group duration\\s+Organization ID\\s+Deleted", outLines[0]) + require.Regexp(t, tc.expectedStdoutPattern+"\\s+true", outLines[1]) + }) + } +} diff --git a/internal/mock/api_buckets.go b/internal/mock/api_buckets.go new file mode 100644 index 0000000..cee870f --- /dev/null +++ b/internal/mock/api_buckets.go @@ -0,0 +1,58 @@ +package mock + +import ( + "context" + "net/http" + + "github.com/influxdata/influx-cli/v2/internal/api" +) + +var _ api.BucketsApi = (*BucketsApi)(nil) + +type BucketsApi struct { + DeleteBucketsIDExecuteFn func(api.ApiDeleteBucketsIDRequest) (*http.Response, error) + GetBucketsExecuteFn func(api.ApiGetBucketsRequest) (api.Buckets, *http.Response, error) + GetBucketsIDExecuteFn func(api.ApiGetBucketsIDRequest) (api.Bucket, *http.Response, error) + PatchBucketsIDExecuteFn func(api.ApiPatchBucketsIDRequest) (api.Bucket, *http.Response, error) + PostBucketsExecuteFn func(api.ApiPostBucketsRequest) (api.Bucket, *http.Response, error) +} + +func (b *BucketsApi) DeleteBucketsID(_ context.Context, bucketID string) api.ApiDeleteBucketsIDRequest { + return api.ApiDeleteBucketsIDRequest{ApiService: b}.BucketID(bucketID) +} + +func (b *BucketsApi) DeleteBucketsIDExecute(r api.ApiDeleteBucketsIDRequest) (*http.Response, error) { + return b.DeleteBucketsIDExecuteFn(r) +} + +func (b *BucketsApi) GetBuckets(context.Context) api.ApiGetBucketsRequest { + return api.ApiGetBucketsRequest{ApiService: b} +} + +func (b *BucketsApi) GetBucketsExecute(r api.ApiGetBucketsRequest) (api.Buckets, *http.Response, error) { + return b.GetBucketsExecuteFn(r) +} + +func (b *BucketsApi) GetBucketsID(_ context.Context, bucketID string) api.ApiGetBucketsIDRequest { + return api.ApiGetBucketsIDRequest{ApiService: b}.BucketID(bucketID) +} + +func (b *BucketsApi) GetBucketsIDExecute(r api.ApiGetBucketsIDRequest) (api.Bucket, *http.Response, error) { + return b.GetBucketsIDExecuteFn(r) +} + +func (b *BucketsApi) PatchBucketsID(_ context.Context, bucketID string) api.ApiPatchBucketsIDRequest { + return api.ApiPatchBucketsIDRequest{ApiService: b}.BucketID(bucketID) +} + +func (b *BucketsApi) PatchBucketsIDExecute(r api.ApiPatchBucketsIDRequest) (api.Bucket, *http.Response, error) { + return b.PatchBucketsIDExecuteFn(r) +} + +func (b *BucketsApi) PostBuckets(context.Context) api.ApiPostBucketsRequest { + return api.ApiPostBucketsRequest{ApiService: b} +} + +func (b *BucketsApi) PostBucketsExecute(r api.ApiPostBucketsRequest) (api.Bucket, *http.Response, error) { + return b.PostBucketsExecuteFn(r) +} diff --git a/internal/mock/api_organizations.go b/internal/mock/api_organizations.go new file mode 100644 index 0000000..490271c --- /dev/null +++ b/internal/mock/api_organizations.go @@ -0,0 +1,31 @@ +package mock + +import ( + "context" + "net/http" + + "github.com/influxdata/influx-cli/v2/internal/api" +) + +var _ api.OrganizationsApi = (*OrganizationsApi)(nil) + +type OrganizationsApi struct { + GetOrgsExecuteFn func(api.ApiGetOrgsRequest) (api.Organizations, *http.Response, error) + PostOrgsExecuteFn func(api.ApiPostOrgsRequest) (api.Organization, *http.Response, error) +} + +func (o *OrganizationsApi) GetOrgs(context.Context) api.ApiGetOrgsRequest { + return api.ApiGetOrgsRequest{ApiService: o} +} + +func (o *OrganizationsApi) GetOrgsExecute(r api.ApiGetOrgsRequest) (api.Organizations, *http.Response, error) { + return o.GetOrgsExecuteFn(r) +} + +func (o *OrganizationsApi) PostOrgs(context.Context) api.ApiPostOrgsRequest { + return api.ApiPostOrgsRequest{ApiService: o} +} + +func (o *OrganizationsApi) PostOrgsExecute(r api.ApiPostOrgsRequest) (api.Organization, *http.Response, error) { + return o.PostOrgsExecuteFn(r) +} diff --git a/internal/setup.go b/internal/setup.go index 972680a..f89560c 100644 --- a/internal/setup.go +++ b/internal/setup.go @@ -31,10 +31,7 @@ var ( ErrSetupCanceled = errors.New("setup was canceled") ) -const ( - InfiniteRetention = 0 - MinPasswordLen = 8 -) +const MinPasswordLen = 8 func (c *CLI) Setup(ctx context.Context, client api.SetupApi, params *SetupParams) error { // Ensure we'll be able to write onboarding results to local config.