diff --git a/cmd/influx/bucket.go b/cmd/influx/bucket.go index c09e906..04337cf 100644 --- a/cmd/influx/bucket.go +++ b/cmd/influx/bucket.go @@ -2,6 +2,7 @@ package main import ( "github.com/influxdata/influx-cli/v2/internal" + "github.com/influxdata/influx-cli/v2/internal/api" "github.com/influxdata/influx-cli/v2/pkg/cli/middleware" "github.com/urfave/cli/v2" ) @@ -44,7 +45,9 @@ func newBucketCmd() *cli.Command { } func newBucketCreateCmd() *cli.Command { - var params internal.BucketsCreateParams + params := internal.BucketsCreateParams{ + SchemaType: api.SCHEMATYPE_IMPLICIT, + } return &cli.Command{ Name: "create", Usage: "Create bucket", @@ -91,6 +94,12 @@ func newBucketCreateCmd() *cli.Command { EnvVars: []string{"INFLUX_ORG"}, Destination: ¶ms.OrgName, }, + &cli.GenericFlag{ + Name: "schema-type", + Usage: "The schema type (implicit, explicit)", + DefaultText: "implicit", + Value: ¶ms.SchemaType, + }, ), Action: func(ctx *cli.Context) error { clients := getBucketsClient(ctx) diff --git a/cmd/influx/bucket_schema.go b/cmd/influx/bucket_schema.go new file mode 100644 index 0000000..f33d9ad --- /dev/null +++ b/cmd/influx/bucket_schema.go @@ -0,0 +1,189 @@ +package main + +import ( + "github.com/influxdata/influx-cli/v2/internal" + "github.com/influxdata/influx-cli/v2/internal/cmd/bucket_schema" + "github.com/influxdata/influx-cli/v2/pkg/cli/middleware" + "github.com/influxdata/influx-cli/v2/pkg/influxid" + "github.com/urfave/cli/v2" +) + +func withBucketSchemaClient() cli.BeforeFunc { + return middleware.WithBeforeFns( + withCli(), + withApi(true), + func(ctx *cli.Context) error { + c := getCLI(ctx) + client := getAPI(ctx) + ctx.App.Metadata["measurement_schema"] = bucket_schema.Client{ + BucketApi: client.BucketsApi, + BucketSchemasApi: client.BucketSchemasApi, + CLI: c, + } + return nil + }) +} + +func getBucketSchemaClient(ctx *cli.Context) bucket_schema.Client { + i, ok := ctx.App.Metadata["measurement_schema"].(bucket_schema.Client) + if !ok { + panic("missing measurement schema client") + } + return i +} + +func newBucketSchemaCmd() *cli.Command { + return &cli.Command{ + Name: "bucket-schema", + Usage: "Bucket schema management commands", + Subcommands: []*cli.Command{ + newBucketSchemaCreateCmd(), + newBucketSchemaUpdateCmd(), + newBucketSchemaListCmd(), + }, + } +} + +func newBucketSchemaCreateCmd() *cli.Command { + var params struct { + internal.OrgBucketParams + Name string + ColumnsFile string + ColumnsFormat bucket_schema.ColumnsFormat + ExtendedOutput bool + } + return &cli.Command{ + Name: "create", + Usage: "Create a measurement schema for a bucket", + Before: withBucketSchemaClient(), + Flags: append( + commonFlags, + append( + getOrgBucketFlags(¶ms.OrgBucketParams), + &cli.StringFlag{ + Name: "name", + Usage: "Name of the measurement", + Destination: ¶ms.Name, + }, + &cli.StringFlag{ + Name: "columns-file", + Usage: "A path referring to list of column definitions", + Destination: ¶ms.ColumnsFile, + }, + &cli.GenericFlag{ + Name: "columns-format", + Usage: "The format of the columns file. \"auto\" will attempt to guess the format.", + DefaultText: "auto", + Value: ¶ms.ColumnsFormat, + }, + &cli.BoolFlag{ + Name: "extended-output", + Usage: "Print column information for each measurement", + Aliases: []string{"x"}, + Destination: ¶ms.ExtendedOutput, + }, + )..., + ), + Action: func(ctx *cli.Context) error { + return getBucketSchemaClient(ctx). + Create(ctx.Context, bucket_schema.CreateParams{ + OrgBucketParams: params.OrgBucketParams, + Name: params.Name, + Stdin: ctx.App.Reader, + ColumnsFile: params.ColumnsFile, + ColumnsFormat: params.ColumnsFormat, + ExtendedOutput: params.ExtendedOutput, + }) + }, + } +} + +func newBucketSchemaUpdateCmd() *cli.Command { + var params struct { + internal.OrgBucketParams + ID influxid.ID + Name string + ColumnsFile string + ColumnsFormat bucket_schema.ColumnsFormat + ExtendedOutput bool + } + return &cli.Command{ + Name: "update", + Usage: "Update a measurement schema for a bucket", + Before: withBucketSchemaClient(), + Flags: append( + commonFlags, + append( + getOrgBucketFlags(¶ms.OrgBucketParams), + &cli.GenericFlag{ + Name: "id", + Usage: "ID of the measurement", + Value: ¶ms.ID, + }, + &cli.StringFlag{ + Name: "name", + Usage: "Name of the measurement", + Destination: ¶ms.Name, + }, + &cli.StringFlag{ + Name: "columns-file", + Usage: "A path referring to list of column definitions", + Destination: ¶ms.ColumnsFile, + }, + &cli.GenericFlag{ + Name: "columns-format", + Usage: "The format of the columns file. \"auto\" will attempt to guess the format.", + DefaultText: "auto", + Value: ¶ms.ColumnsFormat, + }, + &cli.BoolFlag{ + Name: "extended-output", + Usage: "Print column information for each measurement", + Aliases: []string{"x"}, + Destination: ¶ms.ExtendedOutput, + }, + )..., + ), + Action: func(ctx *cli.Context) error { + return getBucketSchemaClient(ctx). + Update(ctx.Context, bucket_schema.UpdateParams{ + OrgBucketParams: params.OrgBucketParams, + ID: params.ID.String(), + Name: params.Name, + Stdin: ctx.App.Reader, + ColumnsFile: params.ColumnsFile, + ColumnsFormat: params.ColumnsFormat, + ExtendedOutput: params.ExtendedOutput, + }) + }, + } +} + +func newBucketSchemaListCmd() *cli.Command { + var params bucket_schema.ListParams + return &cli.Command{ + Name: "list", + Usage: "List schemas for a bucket", + Before: withBucketSchemaClient(), + Flags: append( + commonFlags, + append( + getOrgBucketFlags(¶ms.OrgBucketParams), + &cli.StringFlag{ + Name: "name", + Usage: "Name of single measurement to find", + Destination: ¶ms.Name, + }, + &cli.BoolFlag{ + Name: "extended-output", + Usage: "Print column information for each measurement", + Aliases: []string{"x"}, + Destination: ¶ms.ExtendedOutput, + }, + )..., + ), + Action: func(ctx *cli.Context) error { + return getBucketSchemaClient(ctx).List(ctx.Context, params) + }, + } +} diff --git a/cmd/influx/main.go b/cmd/influx/main.go index cb01350..cda7df5 100644 --- a/cmd/influx/main.go +++ b/cmd/influx/main.go @@ -198,6 +198,7 @@ var app = cli.App{ newWriteCmd(), newBucketCmd(), newCompletionCmd(), + newBucketSchemaCmd(), }, } diff --git a/cmd/influx/params.go b/cmd/influx/params.go new file mode 100644 index 0000000..49099d4 --- /dev/null +++ b/cmd/influx/params.go @@ -0,0 +1,36 @@ +package main + +import ( + "github.com/influxdata/influx-cli/v2/internal" + "github.com/urfave/cli/v2" +) + +func getOrgBucketFlags(c *internal.OrgBucketParams) []cli.Flag { + return []cli.Flag{ + &cli.GenericFlag{ + Name: "bucket-id", + Usage: "The bucket ID, required if name isn't provided", + Aliases: []string{"i"}, + Value: &c.BucketID, + }, + &cli.StringFlag{ + Name: "bucket", + Usage: "The bucket name, org or org-id will be required by choosing this", + Aliases: []string{"n"}, + Destination: &c.BucketName, + }, + &cli.GenericFlag{ + Name: "org-id", + Usage: "The ID of the organization", + EnvVars: []string{"INFLUX_ORG_ID"}, + Value: &c.OrgID, + }, + &cli.StringFlag{ + Name: "org", + Usage: "The name of the organization", + Aliases: []string{"o"}, + EnvVars: []string{"INFLUX_ORG"}, + Destination: &c.OrgName, + }, + } +} diff --git a/etc/generate-openapi.sh b/etc/generate-openapi.sh index a6af133..32cda5e 100755 --- a/etc/generate-openapi.sh +++ b/etc/generate-openapi.sh @@ -6,7 +6,7 @@ declare -r API_DIR="${ROOT_DIR}/internal/api" declare -r GENERATED_PATTERN='^// Code generated .* DO NOT EDIT\.$' declare -r GENERATOR_DOCKER_IMG=openapitools/openapi-generator-cli:v5.1.0 -declare -r OPENAPI_COMMIT=e41d5e327a67e472a46cd6edfe673496e1b066dd +declare -r OPENAPI_COMMIT=af4e3efa496c8adcd2838145652fdd8d63a90702 # Clean up all the generated files in the target directory. rm $(grep -Elr "${GENERATED_PATTERN}" "${API_DIR}") diff --git a/go.mod b/go.mod index 26e5947..4c091fd 100644 --- a/go.mod +++ b/go.mod @@ -5,8 +5,12 @@ go 1.16 require ( github.com/AlecAivazis/survey/v2 v2.2.9 github.com/BurntSushi/toml v0.3.1 + github.com/MakeNowJust/heredoc/v2 v2.0.1 github.com/daixiang0/gci v0.2.8 github.com/fujiwara/shapeio v1.0.0 + github.com/gocarina/gocsv v0.0.0-20210408192840-02d7211d929d + github.com/golang/mock v1.5.0 + github.com/google/go-cmp v0.5.5 github.com/kr/pretty v0.1.0 // indirect github.com/stretchr/testify v1.7.0 github.com/urfave/cli/v2 v2.3.0 diff --git a/go.sum b/go.sum index ae78736..52ea1fb 100644 --- a/go.sum +++ b/go.sum @@ -2,6 +2,8 @@ github.com/AlecAivazis/survey/v2 v2.2.9 h1:LWvJtUswz/W9/zVVXELrmlvdwWcKE60ZAw0FW github.com/AlecAivazis/survey/v2 v2.2.9/go.mod h1:9DYvHgXtiXm6nCn+jXnOXLKbH+Yo9u8fAS/SduGdoPk= github.com/BurntSushi/toml v0.3.1 h1:WXkYYl6Yr3qBf1K79EBnL4mak0OimBfB0XUf9Vl28OQ= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= +github.com/MakeNowJust/heredoc/v2 v2.0.1 h1:rlCHh70XXXv7toz95ajQWOWQnN4WNLt0TdpZYIR/J6A= +github.com/MakeNowJust/heredoc/v2 v2.0.1/go.mod h1:6/2Abh5s+hc3g9nbWLe9ObDIOhaRrqsyY9MWy+4JdRM= github.com/Netflix/go-expect v0.0.0-20180615182759-c93bf25de8e8 h1:xzYJEypr/85nBpB11F9br+3HUrpgb+fcm5iADzXXYEw= github.com/Netflix/go-expect v0.0.0-20180615182759-c93bf25de8e8/go.mod h1:oX5x61PbNXchhh0oikYAH+4Pcfw5LKv21+Jnpr6r6Pc= github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d h1:U+s90UTSYgptZMwQh2aRr3LuazLJIa+Pg3Kc1ylSYVY= @@ -15,6 +17,12 @@ github.com/dustin/go-humanize v1.0.0 h1:VSnTsYCnlFHaM2/igO1h6X3HA71jcobQuxemgkq4 github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk= github.com/fujiwara/shapeio v1.0.0 h1:xG5D9oNqCSUUbryZ/jQV3cqe1v2suEjwPIcEg1gKM8M= github.com/fujiwara/shapeio v1.0.0/go.mod h1:LmEmu6L/8jetyj1oewewFb7bZCNRwE7wLCUNzDLaLVA= +github.com/gocarina/gocsv v0.0.0-20210408192840-02d7211d929d h1:r3mStZSyjKhEcgbJ5xtv7kT5PZw/tDiFBTMgQx2qsXE= +github.com/gocarina/gocsv v0.0.0-20210408192840-02d7211d929d/go.mod h1:5YoVOkjYAQumqlV356Hj3xeYh4BdZuLE0/nRkf2NKkI= +github.com/golang/mock v1.5.0 h1:jlYHihg//f7RRwuPfptm04yp4s7O6Kw8EZiVYIGcH0g= +github.com/golang/mock v1.5.0/go.mod h1:CWnOUgYIOo4TcNZ0wHX3YZCqsaM1I1Jvs6v3mP3KVu8= +github.com/google/go-cmp v0.5.5 h1:Khx7svrCpmxxtHBq5j2mp/xVjsi8hQMfNLvJFAlrGgU= +github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/hinshun/vt10x v0.0.0-20180616224451-1954e6464174 h1:WlZsjVhE8Af9IcZDGgJGQpNflI3+MJSBhsgT5PCtzBQ= github.com/hinshun/vt10x v0.0.0-20180616224451-1954e6464174/go.mod h1:DqJ97dSdRW1W22yXSB90986pcOyQ7r45iio1KN2ez1A= github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51 h1:Z9n2FFNUXsshfwJMBgNA0RU6/i7WVaAegv3PtuIHPMs= @@ -39,6 +47,7 @@ github.com/russross/blackfriday/v2 v2.0.1 h1:lPqVAte+HuHNfhJ/0LC98ESWRz8afy9tM/0 github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= github.com/shurcooL/sanitized_anchor_name v1.0.0 h1:PdmoCO6wvbs+7yrJyMORt4/BmY5IYyJwS/kOiWx8mHo= github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc= +github.com/stretchr/objx v0.1.0 h1:4G4v2dO3VZwixGIRoQ5Lfboy6nUhCyYzaqnIAPPhYs4= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/testify v1.2.1/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY= @@ -77,6 +86,7 @@ golang.org/x/tools v0.1.0 h1:po9/4sTYwZU9lPhi1tOrb4hCv3qrhiQ77LZfGa2OjwY= golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= diff --git a/internal/api/api_bucket_schemas.gen.go b/internal/api/api_bucket_schemas.gen.go new file mode 100644 index 0000000..1412ccc --- /dev/null +++ b/internal/api/api_bucket_schemas.gen.go @@ -0,0 +1,718 @@ +/* + * 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 BucketSchemasApi interface { + + /* + * CreateMeasurementSchema Create a new measurement schema for this 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 + * @return ApiCreateMeasurementSchemaRequest + */ + CreateMeasurementSchema(ctx _context.Context, bucketID string) ApiCreateMeasurementSchemaRequest + + /* + * CreateMeasurementSchemaExecute executes the request + * @return MeasurementSchema + */ + CreateMeasurementSchemaExecute(r ApiCreateMeasurementSchemaRequest) (MeasurementSchema, *_nethttp.Response, error) + + /* + * GetMeasurementSchema Fetch schema information for a measurement + * @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 + * @param measurementID The ID of the measurement + * @return ApiGetMeasurementSchemaRequest + */ + GetMeasurementSchema(ctx _context.Context, bucketID string, measurementID string) ApiGetMeasurementSchemaRequest + + /* + * GetMeasurementSchemaExecute executes the request + * @return MeasurementSchema + */ + GetMeasurementSchemaExecute(r ApiGetMeasurementSchemaRequest) (MeasurementSchema, *_nethttp.Response, error) + + /* + * GetMeasurementSchemas Retrieve a list of measurement schemas defined for this 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 + * @return ApiGetMeasurementSchemasRequest + */ + GetMeasurementSchemas(ctx _context.Context, bucketID string) ApiGetMeasurementSchemasRequest + + /* + * GetMeasurementSchemasExecute executes the request + * @return MeasurementSchemaList + */ + GetMeasurementSchemasExecute(r ApiGetMeasurementSchemasRequest) (MeasurementSchemaList, *_nethttp.Response, error) + + /* + * UpdateMeasurementSchema Update existing measurement schema + * @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 + * @param measurementID The ID of the measurement + * @return ApiUpdateMeasurementSchemaRequest + */ + UpdateMeasurementSchema(ctx _context.Context, bucketID string, measurementID string) ApiUpdateMeasurementSchemaRequest + + /* + * UpdateMeasurementSchemaExecute executes the request + * @return MeasurementSchema + */ + UpdateMeasurementSchemaExecute(r ApiUpdateMeasurementSchemaRequest) (MeasurementSchema, *_nethttp.Response, error) +} + +// BucketSchemasApiService BucketSchemasApi service +type BucketSchemasApiService service + +type ApiCreateMeasurementSchemaRequest struct { + ctx _context.Context + ApiService BucketSchemasApi + bucketID string + org *string + orgID *string + measurementSchemaCreateRequest *MeasurementSchemaCreateRequest +} + +func (r ApiCreateMeasurementSchemaRequest) BucketID(bucketID string) ApiCreateMeasurementSchemaRequest { + r.bucketID = bucketID + return r +} +func (r ApiCreateMeasurementSchemaRequest) GetBucketID() string { + return r.bucketID +} + +func (r ApiCreateMeasurementSchemaRequest) Org(org string) ApiCreateMeasurementSchemaRequest { + r.org = &org + return r +} +func (r ApiCreateMeasurementSchemaRequest) GetOrg() *string { + return r.org +} + +func (r ApiCreateMeasurementSchemaRequest) OrgID(orgID string) ApiCreateMeasurementSchemaRequest { + r.orgID = &orgID + return r +} +func (r ApiCreateMeasurementSchemaRequest) GetOrgID() *string { + return r.orgID +} + +func (r ApiCreateMeasurementSchemaRequest) MeasurementSchemaCreateRequest(measurementSchemaCreateRequest MeasurementSchemaCreateRequest) ApiCreateMeasurementSchemaRequest { + r.measurementSchemaCreateRequest = &measurementSchemaCreateRequest + return r +} +func (r ApiCreateMeasurementSchemaRequest) GetMeasurementSchemaCreateRequest() *MeasurementSchemaCreateRequest { + return r.measurementSchemaCreateRequest +} + +func (r ApiCreateMeasurementSchemaRequest) Execute() (MeasurementSchema, *_nethttp.Response, error) { + return r.ApiService.CreateMeasurementSchemaExecute(r) +} + +/* + * CreateMeasurementSchema Create a new measurement schema for this 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 + * @return ApiCreateMeasurementSchemaRequest + */ +func (a *BucketSchemasApiService) CreateMeasurementSchema(ctx _context.Context, bucketID string) ApiCreateMeasurementSchemaRequest { + return ApiCreateMeasurementSchemaRequest{ + ApiService: a, + ctx: ctx, + bucketID: bucketID, + } +} + +/* + * Execute executes the request + * @return MeasurementSchema + */ +func (a *BucketSchemasApiService) CreateMeasurementSchemaExecute(r ApiCreateMeasurementSchemaRequest) (MeasurementSchema, *_nethttp.Response, error) { + var ( + localVarHTTPMethod = _nethttp.MethodPost + localVarPostBody interface{} + localVarFormFileName string + localVarFileName string + localVarFileBytes []byte + localVarReturnValue MeasurementSchema + ) + + localBasePath, err := a.client.cfg.ServerURLWithContext(r.ctx, "BucketSchemasApiService.CreateMeasurementSchema") + if err != nil { + return localVarReturnValue, nil, GenericOpenAPIError{error: err.Error()} + } + + localVarPath := localBasePath + "/buckets/{bucketID}/schema/measurements" + localVarPath = strings.Replace(localVarPath, "{"+"bucketID"+"}", _neturl.PathEscape(parameterToString(r.bucketID, "")), -1) + + localVarHeaderParams := make(map[string]string) + localVarQueryParams := _neturl.Values{} + localVarFormParams := _neturl.Values{} + + if r.org != nil { + localVarQueryParams.Add("org", parameterToString(*r.org, "")) + } + if r.orgID != nil { + localVarQueryParams.Add("orgID", parameterToString(*r.orgID, "")) + } + // 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 + } + // body params + localVarPostBody = r.measurementSchemaCreateRequest + 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 == 400 { + 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 ApiGetMeasurementSchemaRequest struct { + ctx _context.Context + ApiService BucketSchemasApi + bucketID string + measurementID string + org *string + orgID *string +} + +func (r ApiGetMeasurementSchemaRequest) BucketID(bucketID string) ApiGetMeasurementSchemaRequest { + r.bucketID = bucketID + return r +} +func (r ApiGetMeasurementSchemaRequest) GetBucketID() string { + return r.bucketID +} + +func (r ApiGetMeasurementSchemaRequest) MeasurementID(measurementID string) ApiGetMeasurementSchemaRequest { + r.measurementID = measurementID + return r +} +func (r ApiGetMeasurementSchemaRequest) GetMeasurementID() string { + return r.measurementID +} + +func (r ApiGetMeasurementSchemaRequest) Org(org string) ApiGetMeasurementSchemaRequest { + r.org = &org + return r +} +func (r ApiGetMeasurementSchemaRequest) GetOrg() *string { + return r.org +} + +func (r ApiGetMeasurementSchemaRequest) OrgID(orgID string) ApiGetMeasurementSchemaRequest { + r.orgID = &orgID + return r +} +func (r ApiGetMeasurementSchemaRequest) GetOrgID() *string { + return r.orgID +} + +func (r ApiGetMeasurementSchemaRequest) Execute() (MeasurementSchema, *_nethttp.Response, error) { + return r.ApiService.GetMeasurementSchemaExecute(r) +} + +/* + * GetMeasurementSchema Fetch schema information for a measurement + * @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 + * @param measurementID The ID of the measurement + * @return ApiGetMeasurementSchemaRequest + */ +func (a *BucketSchemasApiService) GetMeasurementSchema(ctx _context.Context, bucketID string, measurementID string) ApiGetMeasurementSchemaRequest { + return ApiGetMeasurementSchemaRequest{ + ApiService: a, + ctx: ctx, + bucketID: bucketID, + measurementID: measurementID, + } +} + +/* + * Execute executes the request + * @return MeasurementSchema + */ +func (a *BucketSchemasApiService) GetMeasurementSchemaExecute(r ApiGetMeasurementSchemaRequest) (MeasurementSchema, *_nethttp.Response, error) { + var ( + localVarHTTPMethod = _nethttp.MethodGet + localVarPostBody interface{} + localVarFormFileName string + localVarFileName string + localVarFileBytes []byte + localVarReturnValue MeasurementSchema + ) + + localBasePath, err := a.client.cfg.ServerURLWithContext(r.ctx, "BucketSchemasApiService.GetMeasurementSchema") + if err != nil { + return localVarReturnValue, nil, GenericOpenAPIError{error: err.Error()} + } + + localVarPath := localBasePath + "/buckets/{bucketID}/schema/measurements/{measurementID}" + localVarPath = strings.Replace(localVarPath, "{"+"bucketID"+"}", _neturl.PathEscape(parameterToString(r.bucketID, "")), -1) + localVarPath = strings.Replace(localVarPath, "{"+"measurementID"+"}", _neturl.PathEscape(parameterToString(r.measurementID, "")), -1) + + localVarHeaderParams := make(map[string]string) + localVarQueryParams := _neturl.Values{} + localVarFormParams := _neturl.Values{} + + if r.org != nil { + localVarQueryParams.Add("org", parameterToString(*r.org, "")) + } + if r.orgID != nil { + localVarQueryParams.Add("orgID", parameterToString(*r.orgID, "")) + } + // 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 + } + 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, + } + 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 ApiGetMeasurementSchemasRequest struct { + ctx _context.Context + ApiService BucketSchemasApi + bucketID string + org *string + orgID *string + name *string +} + +func (r ApiGetMeasurementSchemasRequest) BucketID(bucketID string) ApiGetMeasurementSchemasRequest { + r.bucketID = bucketID + return r +} +func (r ApiGetMeasurementSchemasRequest) GetBucketID() string { + return r.bucketID +} + +func (r ApiGetMeasurementSchemasRequest) Org(org string) ApiGetMeasurementSchemasRequest { + r.org = &org + return r +} +func (r ApiGetMeasurementSchemasRequest) GetOrg() *string { + return r.org +} + +func (r ApiGetMeasurementSchemasRequest) OrgID(orgID string) ApiGetMeasurementSchemasRequest { + r.orgID = &orgID + return r +} +func (r ApiGetMeasurementSchemasRequest) GetOrgID() *string { + return r.orgID +} + +func (r ApiGetMeasurementSchemasRequest) Name(name string) ApiGetMeasurementSchemasRequest { + r.name = &name + return r +} +func (r ApiGetMeasurementSchemasRequest) GetName() *string { + return r.name +} + +func (r ApiGetMeasurementSchemasRequest) Execute() (MeasurementSchemaList, *_nethttp.Response, error) { + return r.ApiService.GetMeasurementSchemasExecute(r) +} + +/* + * GetMeasurementSchemas Retrieve a list of measurement schemas defined for this 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 + * @return ApiGetMeasurementSchemasRequest + */ +func (a *BucketSchemasApiService) GetMeasurementSchemas(ctx _context.Context, bucketID string) ApiGetMeasurementSchemasRequest { + return ApiGetMeasurementSchemasRequest{ + ApiService: a, + ctx: ctx, + bucketID: bucketID, + } +} + +/* + * Execute executes the request + * @return MeasurementSchemaList + */ +func (a *BucketSchemasApiService) GetMeasurementSchemasExecute(r ApiGetMeasurementSchemasRequest) (MeasurementSchemaList, *_nethttp.Response, error) { + var ( + localVarHTTPMethod = _nethttp.MethodGet + localVarPostBody interface{} + localVarFormFileName string + localVarFileName string + localVarFileBytes []byte + localVarReturnValue MeasurementSchemaList + ) + + localBasePath, err := a.client.cfg.ServerURLWithContext(r.ctx, "BucketSchemasApiService.GetMeasurementSchemas") + if err != nil { + return localVarReturnValue, nil, GenericOpenAPIError{error: err.Error()} + } + + localVarPath := localBasePath + "/buckets/{bucketID}/schema/measurements" + localVarPath = strings.Replace(localVarPath, "{"+"bucketID"+"}", _neturl.PathEscape(parameterToString(r.bucketID, "")), -1) + + localVarHeaderParams := make(map[string]string) + localVarQueryParams := _neturl.Values{} + localVarFormParams := _neturl.Values{} + + 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, "")) + } + // 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 + } + 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 == 404 { + 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 ApiUpdateMeasurementSchemaRequest struct { + ctx _context.Context + ApiService BucketSchemasApi + bucketID string + measurementID string + org *string + orgID *string + measurementSchemaUpdateRequest *MeasurementSchemaUpdateRequest +} + +func (r ApiUpdateMeasurementSchemaRequest) BucketID(bucketID string) ApiUpdateMeasurementSchemaRequest { + r.bucketID = bucketID + return r +} +func (r ApiUpdateMeasurementSchemaRequest) GetBucketID() string { + return r.bucketID +} + +func (r ApiUpdateMeasurementSchemaRequest) MeasurementID(measurementID string) ApiUpdateMeasurementSchemaRequest { + r.measurementID = measurementID + return r +} +func (r ApiUpdateMeasurementSchemaRequest) GetMeasurementID() string { + return r.measurementID +} + +func (r ApiUpdateMeasurementSchemaRequest) Org(org string) ApiUpdateMeasurementSchemaRequest { + r.org = &org + return r +} +func (r ApiUpdateMeasurementSchemaRequest) GetOrg() *string { + return r.org +} + +func (r ApiUpdateMeasurementSchemaRequest) OrgID(orgID string) ApiUpdateMeasurementSchemaRequest { + r.orgID = &orgID + return r +} +func (r ApiUpdateMeasurementSchemaRequest) GetOrgID() *string { + return r.orgID +} + +func (r ApiUpdateMeasurementSchemaRequest) MeasurementSchemaUpdateRequest(measurementSchemaUpdateRequest MeasurementSchemaUpdateRequest) ApiUpdateMeasurementSchemaRequest { + r.measurementSchemaUpdateRequest = &measurementSchemaUpdateRequest + return r +} +func (r ApiUpdateMeasurementSchemaRequest) GetMeasurementSchemaUpdateRequest() *MeasurementSchemaUpdateRequest { + return r.measurementSchemaUpdateRequest +} + +func (r ApiUpdateMeasurementSchemaRequest) Execute() (MeasurementSchema, *_nethttp.Response, error) { + return r.ApiService.UpdateMeasurementSchemaExecute(r) +} + +/* + * UpdateMeasurementSchema Update existing measurement schema + * @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 + * @param measurementID The ID of the measurement + * @return ApiUpdateMeasurementSchemaRequest + */ +func (a *BucketSchemasApiService) UpdateMeasurementSchema(ctx _context.Context, bucketID string, measurementID string) ApiUpdateMeasurementSchemaRequest { + return ApiUpdateMeasurementSchemaRequest{ + ApiService: a, + ctx: ctx, + bucketID: bucketID, + measurementID: measurementID, + } +} + +/* + * Execute executes the request + * @return MeasurementSchema + */ +func (a *BucketSchemasApiService) UpdateMeasurementSchemaExecute(r ApiUpdateMeasurementSchemaRequest) (MeasurementSchema, *_nethttp.Response, error) { + var ( + localVarHTTPMethod = _nethttp.MethodPatch + localVarPostBody interface{} + localVarFormFileName string + localVarFileName string + localVarFileBytes []byte + localVarReturnValue MeasurementSchema + ) + + localBasePath, err := a.client.cfg.ServerURLWithContext(r.ctx, "BucketSchemasApiService.UpdateMeasurementSchema") + if err != nil { + return localVarReturnValue, nil, GenericOpenAPIError{error: err.Error()} + } + + localVarPath := localBasePath + "/buckets/{bucketID}/schema/measurements/{measurementID}" + localVarPath = strings.Replace(localVarPath, "{"+"bucketID"+"}", _neturl.PathEscape(parameterToString(r.bucketID, "")), -1) + localVarPath = strings.Replace(localVarPath, "{"+"measurementID"+"}", _neturl.PathEscape(parameterToString(r.measurementID, "")), -1) + + localVarHeaderParams := make(map[string]string) + localVarQueryParams := _neturl.Values{} + localVarFormParams := _neturl.Values{} + + if r.org != nil { + localVarQueryParams.Add("org", parameterToString(*r.org, "")) + } + if r.orgID != nil { + localVarQueryParams.Add("orgID", parameterToString(*r.orgID, "")) + } + // 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 + } + // body params + localVarPostBody = r.measurementSchemaUpdateRequest + 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 == 400 { + 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.gen.go b/internal/api/client.gen.go index c82b307..0b5280b 100644 --- a/internal/api/client.gen.go +++ b/internal/api/client.gen.go @@ -47,6 +47,8 @@ type APIClient struct { // API Services + BucketSchemasApi BucketSchemasApi + BucketsApi BucketsApi HealthApi HealthApi @@ -74,6 +76,7 @@ func NewAPIClient(cfg *Configuration) *APIClient { c.common.client = c // API Services + c.BucketSchemasApi = (*BucketSchemasApiService)(&c.common) c.BucketsApi = (*BucketsApiService)(&c.common) c.HealthApi = (*HealthApiService)(&c.common) c.OrganizationsApi = (*OrganizationsApiService)(&c.common) diff --git a/internal/api/model_bucket.gen.go b/internal/api/model_bucket.gen.go index 694cb7f..d624db9 100644 --- a/internal/api/model_bucket.gen.go +++ b/internal/api/model_bucket.gen.go @@ -24,6 +24,7 @@ type Bucket struct { Description *string `json:"description,omitempty"` OrgID *string `json:"orgID,omitempty"` Rp *string `json:"rp,omitempty"` + SchemaType *SchemaType `json:"schemaType,omitempty"` CreatedAt *time.Time `json:"createdAt,omitempty"` UpdatedAt *time.Time `json:"updatedAt,omitempty"` // Rules to expire or retain data. No rules means data never expires. @@ -270,6 +271,38 @@ func (o *Bucket) SetRp(v string) { o.Rp = &v } +// GetSchemaType returns the SchemaType field value if set, zero value otherwise. +func (o *Bucket) GetSchemaType() SchemaType { + if o == nil || o.SchemaType == nil { + var ret SchemaType + return ret + } + return *o.SchemaType +} + +// GetSchemaTypeOk returns a tuple with the SchemaType field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *Bucket) GetSchemaTypeOk() (*SchemaType, bool) { + if o == nil || o.SchemaType == nil { + return nil, false + } + return o.SchemaType, true +} + +// HasSchemaType returns a boolean if a field has been set. +func (o *Bucket) HasSchemaType() bool { + if o != nil && o.SchemaType != nil { + return true + } + + return false +} + +// SetSchemaType gets a reference to the given SchemaType and assigns it to the SchemaType field. +func (o *Bucket) SetSchemaType(v SchemaType) { + o.SchemaType = &v +} + // GetCreatedAt returns the CreatedAt field value if set, zero value otherwise. func (o *Bucket) GetCreatedAt() time.Time { if o == nil || o.CreatedAt == nil { @@ -413,6 +446,9 @@ func (o Bucket) MarshalJSON() ([]byte, error) { if o.Rp != nil { toSerialize["rp"] = o.Rp } + if o.SchemaType != nil { + toSerialize["schemaType"] = o.SchemaType + } if o.CreatedAt != nil { toSerialize["createdAt"] = o.CreatedAt } diff --git a/internal/api/model_column_data_type.gen.go b/internal/api/model_column_data_type.gen.go new file mode 100644 index 0000000..502f783 --- /dev/null +++ b/internal/api/model_column_data_type.gen.go @@ -0,0 +1,86 @@ +/* + * 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" + "fmt" +) + +// ColumnDataType the model 'ColumnDataType' +type ColumnDataType string + +// List of ColumnDataType +const ( + COLUMNDATATYPE_INTEGER ColumnDataType = "integer" + COLUMNDATATYPE_FLOAT ColumnDataType = "float" + COLUMNDATATYPE_BOOLEAN ColumnDataType = "boolean" + COLUMNDATATYPE_STRING ColumnDataType = "string" + COLUMNDATATYPE_UNSIGNED ColumnDataType = "unsigned" +) + +func (v *ColumnDataType) UnmarshalJSON(src []byte) error { + var value string + err := json.Unmarshal(src, &value) + if err != nil { + return err + } + enumTypeValue := ColumnDataType(value) + for _, existing := range []ColumnDataType{"integer", "float", "boolean", "string", "unsigned"} { + if existing == enumTypeValue { + *v = enumTypeValue + return nil + } + } + + return fmt.Errorf("%+v is not a valid ColumnDataType", value) +} + +// Ptr returns reference to ColumnDataType value +func (v ColumnDataType) Ptr() *ColumnDataType { + return &v +} + +type NullableColumnDataType struct { + value *ColumnDataType + isSet bool +} + +func (v NullableColumnDataType) Get() *ColumnDataType { + return v.value +} + +func (v *NullableColumnDataType) Set(val *ColumnDataType) { + v.value = val + v.isSet = true +} + +func (v NullableColumnDataType) IsSet() bool { + return v.isSet +} + +func (v *NullableColumnDataType) Unset() { + v.value = nil + v.isSet = false +} + +func NewNullableColumnDataType(val *ColumnDataType) *NullableColumnDataType { + return &NullableColumnDataType{value: val, isSet: true} +} + +func (v NullableColumnDataType) MarshalJSON() ([]byte, error) { + return json.Marshal(v.value) +} + +func (v *NullableColumnDataType) UnmarshalJSON(src []byte) error { + v.isSet = true + return json.Unmarshal(src, &v.value) +} diff --git a/internal/api/model_column_semantic_type.gen.go b/internal/api/model_column_semantic_type.gen.go new file mode 100644 index 0000000..d5d2739 --- /dev/null +++ b/internal/api/model_column_semantic_type.gen.go @@ -0,0 +1,84 @@ +/* + * 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" + "fmt" +) + +// ColumnSemanticType the model 'ColumnSemanticType' +type ColumnSemanticType string + +// List of ColumnSemanticType +const ( + COLUMNSEMANTICTYPE_TIMESTAMP ColumnSemanticType = "timestamp" + COLUMNSEMANTICTYPE_TAG ColumnSemanticType = "tag" + COLUMNSEMANTICTYPE_FIELD ColumnSemanticType = "field" +) + +func (v *ColumnSemanticType) UnmarshalJSON(src []byte) error { + var value string + err := json.Unmarshal(src, &value) + if err != nil { + return err + } + enumTypeValue := ColumnSemanticType(value) + for _, existing := range []ColumnSemanticType{"timestamp", "tag", "field"} { + if existing == enumTypeValue { + *v = enumTypeValue + return nil + } + } + + return fmt.Errorf("%+v is not a valid ColumnSemanticType", value) +} + +// Ptr returns reference to ColumnSemanticType value +func (v ColumnSemanticType) Ptr() *ColumnSemanticType { + return &v +} + +type NullableColumnSemanticType struct { + value *ColumnSemanticType + isSet bool +} + +func (v NullableColumnSemanticType) Get() *ColumnSemanticType { + return v.value +} + +func (v *NullableColumnSemanticType) Set(val *ColumnSemanticType) { + v.value = val + v.isSet = true +} + +func (v NullableColumnSemanticType) IsSet() bool { + return v.isSet +} + +func (v *NullableColumnSemanticType) Unset() { + v.value = nil + v.isSet = false +} + +func NewNullableColumnSemanticType(val *ColumnSemanticType) *NullableColumnSemanticType { + return &NullableColumnSemanticType{value: val, isSet: true} +} + +func (v NullableColumnSemanticType) MarshalJSON() ([]byte, error) { + return json.Marshal(v.value) +} + +func (v *NullableColumnSemanticType) UnmarshalJSON(src []byte) error { + v.isSet = true + return json.Unmarshal(src, &v.value) +} diff --git a/internal/api/model_measurement_schema.gen.go b/internal/api/model_measurement_schema.gen.go new file mode 100644 index 0000000..d3907a7 --- /dev/null +++ b/internal/api/model_measurement_schema.gen.go @@ -0,0 +1,224 @@ +/* + * 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" + "time" +) + +// MeasurementSchema The schema definition for a single measurement +type MeasurementSchema struct { + Id string `json:"id"` + Name string `json:"name"` + // An ordered collection of column definitions + Columns []MeasurementSchemaColumn `json:"columns"` + CreatedAt time.Time `json:"createdAt"` + UpdatedAt time.Time `json:"updatedAt"` +} + +// NewMeasurementSchema instantiates a new MeasurementSchema 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 NewMeasurementSchema(id string, name string, columns []MeasurementSchemaColumn, createdAt time.Time, updatedAt time.Time) *MeasurementSchema { + this := MeasurementSchema{} + this.Id = id + this.Name = name + this.Columns = columns + this.CreatedAt = createdAt + this.UpdatedAt = updatedAt + return &this +} + +// NewMeasurementSchemaWithDefaults instantiates a new MeasurementSchema 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 NewMeasurementSchemaWithDefaults() *MeasurementSchema { + this := MeasurementSchema{} + return &this +} + +// GetId returns the Id field value +func (o *MeasurementSchema) GetId() string { + if o == nil { + var ret string + return ret + } + + return o.Id +} + +// GetIdOk returns a tuple with the Id field value +// and a boolean to check if the value has been set. +func (o *MeasurementSchema) GetIdOk() (*string, bool) { + if o == nil { + return nil, false + } + return &o.Id, true +} + +// SetId sets field value +func (o *MeasurementSchema) SetId(v string) { + o.Id = v +} + +// GetName returns the Name field value +func (o *MeasurementSchema) 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 *MeasurementSchema) GetNameOk() (*string, bool) { + if o == nil { + return nil, false + } + return &o.Name, true +} + +// SetName sets field value +func (o *MeasurementSchema) SetName(v string) { + o.Name = v +} + +// GetColumns returns the Columns field value +func (o *MeasurementSchema) GetColumns() []MeasurementSchemaColumn { + if o == nil { + var ret []MeasurementSchemaColumn + return ret + } + + return o.Columns +} + +// GetColumnsOk returns a tuple with the Columns field value +// and a boolean to check if the value has been set. +func (o *MeasurementSchema) GetColumnsOk() (*[]MeasurementSchemaColumn, bool) { + if o == nil { + return nil, false + } + return &o.Columns, true +} + +// SetColumns sets field value +func (o *MeasurementSchema) SetColumns(v []MeasurementSchemaColumn) { + o.Columns = v +} + +// GetCreatedAt returns the CreatedAt field value +func (o *MeasurementSchema) GetCreatedAt() time.Time { + if o == nil { + var ret time.Time + return ret + } + + return o.CreatedAt +} + +// GetCreatedAtOk returns a tuple with the CreatedAt field value +// and a boolean to check if the value has been set. +func (o *MeasurementSchema) GetCreatedAtOk() (*time.Time, bool) { + if o == nil { + return nil, false + } + return &o.CreatedAt, true +} + +// SetCreatedAt sets field value +func (o *MeasurementSchema) SetCreatedAt(v time.Time) { + o.CreatedAt = v +} + +// GetUpdatedAt returns the UpdatedAt field value +func (o *MeasurementSchema) GetUpdatedAt() time.Time { + if o == nil { + var ret time.Time + return ret + } + + return o.UpdatedAt +} + +// GetUpdatedAtOk returns a tuple with the UpdatedAt field value +// and a boolean to check if the value has been set. +func (o *MeasurementSchema) GetUpdatedAtOk() (*time.Time, bool) { + if o == nil { + return nil, false + } + return &o.UpdatedAt, true +} + +// SetUpdatedAt sets field value +func (o *MeasurementSchema) SetUpdatedAt(v time.Time) { + o.UpdatedAt = v +} + +func (o MeasurementSchema) MarshalJSON() ([]byte, error) { + toSerialize := map[string]interface{}{} + if true { + toSerialize["id"] = o.Id + } + if true { + toSerialize["name"] = o.Name + } + if true { + toSerialize["columns"] = o.Columns + } + if true { + toSerialize["createdAt"] = o.CreatedAt + } + if true { + toSerialize["updatedAt"] = o.UpdatedAt + } + return json.Marshal(toSerialize) +} + +type NullableMeasurementSchema struct { + value *MeasurementSchema + isSet bool +} + +func (v NullableMeasurementSchema) Get() *MeasurementSchema { + return v.value +} + +func (v *NullableMeasurementSchema) Set(val *MeasurementSchema) { + v.value = val + v.isSet = true +} + +func (v NullableMeasurementSchema) IsSet() bool { + return v.isSet +} + +func (v *NullableMeasurementSchema) Unset() { + v.value = nil + v.isSet = false +} + +func NewNullableMeasurementSchema(val *MeasurementSchema) *NullableMeasurementSchema { + return &NullableMeasurementSchema{value: val, isSet: true} +} + +func (v NullableMeasurementSchema) MarshalJSON() ([]byte, error) { + return json.Marshal(v.value) +} + +func (v *NullableMeasurementSchema) UnmarshalJSON(src []byte) error { + v.isSet = true + return json.Unmarshal(src, &v.value) +} diff --git a/internal/api/model_measurement_schema_column.gen.go b/internal/api/model_measurement_schema_column.gen.go new file mode 100644 index 0000000..f57e2df --- /dev/null +++ b/internal/api/model_measurement_schema_column.gen.go @@ -0,0 +1,171 @@ +/* + * 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" +) + +// MeasurementSchemaColumn Definition of a measurement column +type MeasurementSchemaColumn struct { + Name string `json:"name"` + Type ColumnSemanticType `json:"type"` + DataType *ColumnDataType `json:"dataType,omitempty"` +} + +// NewMeasurementSchemaColumn instantiates a new MeasurementSchemaColumn 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 NewMeasurementSchemaColumn(name string, type_ ColumnSemanticType) *MeasurementSchemaColumn { + this := MeasurementSchemaColumn{} + this.Name = name + this.Type = type_ + return &this +} + +// NewMeasurementSchemaColumnWithDefaults instantiates a new MeasurementSchemaColumn 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 NewMeasurementSchemaColumnWithDefaults() *MeasurementSchemaColumn { + this := MeasurementSchemaColumn{} + return &this +} + +// GetName returns the Name field value +func (o *MeasurementSchemaColumn) 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 *MeasurementSchemaColumn) GetNameOk() (*string, bool) { + if o == nil { + return nil, false + } + return &o.Name, true +} + +// SetName sets field value +func (o *MeasurementSchemaColumn) SetName(v string) { + o.Name = v +} + +// GetType returns the Type field value +func (o *MeasurementSchemaColumn) GetType() ColumnSemanticType { + if o == nil { + var ret ColumnSemanticType + 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 *MeasurementSchemaColumn) GetTypeOk() (*ColumnSemanticType, bool) { + if o == nil { + return nil, false + } + return &o.Type, true +} + +// SetType sets field value +func (o *MeasurementSchemaColumn) SetType(v ColumnSemanticType) { + o.Type = v +} + +// GetDataType returns the DataType field value if set, zero value otherwise. +func (o *MeasurementSchemaColumn) GetDataType() ColumnDataType { + if o == nil || o.DataType == nil { + var ret ColumnDataType + return ret + } + return *o.DataType +} + +// GetDataTypeOk returns a tuple with the DataType field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *MeasurementSchemaColumn) GetDataTypeOk() (*ColumnDataType, bool) { + if o == nil || o.DataType == nil { + return nil, false + } + return o.DataType, true +} + +// HasDataType returns a boolean if a field has been set. +func (o *MeasurementSchemaColumn) HasDataType() bool { + if o != nil && o.DataType != nil { + return true + } + + return false +} + +// SetDataType gets a reference to the given ColumnDataType and assigns it to the DataType field. +func (o *MeasurementSchemaColumn) SetDataType(v ColumnDataType) { + o.DataType = &v +} + +func (o MeasurementSchemaColumn) MarshalJSON() ([]byte, error) { + toSerialize := map[string]interface{}{} + if true { + toSerialize["name"] = o.Name + } + if true { + toSerialize["type"] = o.Type + } + if o.DataType != nil { + toSerialize["dataType"] = o.DataType + } + return json.Marshal(toSerialize) +} + +type NullableMeasurementSchemaColumn struct { + value *MeasurementSchemaColumn + isSet bool +} + +func (v NullableMeasurementSchemaColumn) Get() *MeasurementSchemaColumn { + return v.value +} + +func (v *NullableMeasurementSchemaColumn) Set(val *MeasurementSchemaColumn) { + v.value = val + v.isSet = true +} + +func (v NullableMeasurementSchemaColumn) IsSet() bool { + return v.isSet +} + +func (v *NullableMeasurementSchemaColumn) Unset() { + v.value = nil + v.isSet = false +} + +func NewNullableMeasurementSchemaColumn(val *MeasurementSchemaColumn) *NullableMeasurementSchemaColumn { + return &NullableMeasurementSchemaColumn{value: val, isSet: true} +} + +func (v NullableMeasurementSchemaColumn) MarshalJSON() ([]byte, error) { + return json.Marshal(v.value) +} + +func (v *NullableMeasurementSchemaColumn) UnmarshalJSON(src []byte) error { + v.isSet = true + return json.Unmarshal(src, &v.value) +} diff --git a/internal/api/model_measurement_schema_create_request.gen.go b/internal/api/model_measurement_schema_create_request.gen.go new file mode 100644 index 0000000..934936a --- /dev/null +++ b/internal/api/model_measurement_schema_create_request.gen.go @@ -0,0 +1,136 @@ +/* + * 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" +) + +// MeasurementSchemaCreateRequest Create a new measurement schema +type MeasurementSchemaCreateRequest struct { + Name string `json:"name"` + // An ordered collection of column definitions + Columns []MeasurementSchemaColumn `json:"columns"` +} + +// NewMeasurementSchemaCreateRequest instantiates a new MeasurementSchemaCreateRequest 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 NewMeasurementSchemaCreateRequest(name string, columns []MeasurementSchemaColumn) *MeasurementSchemaCreateRequest { + this := MeasurementSchemaCreateRequest{} + this.Name = name + this.Columns = columns + return &this +} + +// NewMeasurementSchemaCreateRequestWithDefaults instantiates a new MeasurementSchemaCreateRequest 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 NewMeasurementSchemaCreateRequestWithDefaults() *MeasurementSchemaCreateRequest { + this := MeasurementSchemaCreateRequest{} + return &this +} + +// GetName returns the Name field value +func (o *MeasurementSchemaCreateRequest) 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 *MeasurementSchemaCreateRequest) GetNameOk() (*string, bool) { + if o == nil { + return nil, false + } + return &o.Name, true +} + +// SetName sets field value +func (o *MeasurementSchemaCreateRequest) SetName(v string) { + o.Name = v +} + +// GetColumns returns the Columns field value +func (o *MeasurementSchemaCreateRequest) GetColumns() []MeasurementSchemaColumn { + if o == nil { + var ret []MeasurementSchemaColumn + return ret + } + + return o.Columns +} + +// GetColumnsOk returns a tuple with the Columns field value +// and a boolean to check if the value has been set. +func (o *MeasurementSchemaCreateRequest) GetColumnsOk() (*[]MeasurementSchemaColumn, bool) { + if o == nil { + return nil, false + } + return &o.Columns, true +} + +// SetColumns sets field value +func (o *MeasurementSchemaCreateRequest) SetColumns(v []MeasurementSchemaColumn) { + o.Columns = v +} + +func (o MeasurementSchemaCreateRequest) MarshalJSON() ([]byte, error) { + toSerialize := map[string]interface{}{} + if true { + toSerialize["name"] = o.Name + } + if true { + toSerialize["columns"] = o.Columns + } + return json.Marshal(toSerialize) +} + +type NullableMeasurementSchemaCreateRequest struct { + value *MeasurementSchemaCreateRequest + isSet bool +} + +func (v NullableMeasurementSchemaCreateRequest) Get() *MeasurementSchemaCreateRequest { + return v.value +} + +func (v *NullableMeasurementSchemaCreateRequest) Set(val *MeasurementSchemaCreateRequest) { + v.value = val + v.isSet = true +} + +func (v NullableMeasurementSchemaCreateRequest) IsSet() bool { + return v.isSet +} + +func (v *NullableMeasurementSchemaCreateRequest) Unset() { + v.value = nil + v.isSet = false +} + +func NewNullableMeasurementSchemaCreateRequest(val *MeasurementSchemaCreateRequest) *NullableMeasurementSchemaCreateRequest { + return &NullableMeasurementSchemaCreateRequest{value: val, isSet: true} +} + +func (v NullableMeasurementSchemaCreateRequest) MarshalJSON() ([]byte, error) { + return json.Marshal(v.value) +} + +func (v *NullableMeasurementSchemaCreateRequest) UnmarshalJSON(src []byte) error { + v.isSet = true + return json.Unmarshal(src, &v.value) +} diff --git a/internal/api/model_measurement_schema_list.gen.go b/internal/api/model_measurement_schema_list.gen.go new file mode 100644 index 0000000..20b2ee2 --- /dev/null +++ b/internal/api/model_measurement_schema_list.gen.go @@ -0,0 +1,106 @@ +/* + * 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" +) + +// MeasurementSchemaList A list of measurement schemas returning summary information +type MeasurementSchemaList struct { + MeasurementSchemas []MeasurementSchema `json:"measurementSchemas"` +} + +// NewMeasurementSchemaList instantiates a new MeasurementSchemaList 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 NewMeasurementSchemaList(measurementSchemas []MeasurementSchema) *MeasurementSchemaList { + this := MeasurementSchemaList{} + this.MeasurementSchemas = measurementSchemas + return &this +} + +// NewMeasurementSchemaListWithDefaults instantiates a new MeasurementSchemaList 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 NewMeasurementSchemaListWithDefaults() *MeasurementSchemaList { + this := MeasurementSchemaList{} + return &this +} + +// GetMeasurementSchemas returns the MeasurementSchemas field value +func (o *MeasurementSchemaList) GetMeasurementSchemas() []MeasurementSchema { + if o == nil { + var ret []MeasurementSchema + return ret + } + + return o.MeasurementSchemas +} + +// GetMeasurementSchemasOk returns a tuple with the MeasurementSchemas field value +// and a boolean to check if the value has been set. +func (o *MeasurementSchemaList) GetMeasurementSchemasOk() (*[]MeasurementSchema, bool) { + if o == nil { + return nil, false + } + return &o.MeasurementSchemas, true +} + +// SetMeasurementSchemas sets field value +func (o *MeasurementSchemaList) SetMeasurementSchemas(v []MeasurementSchema) { + o.MeasurementSchemas = v +} + +func (o MeasurementSchemaList) MarshalJSON() ([]byte, error) { + toSerialize := map[string]interface{}{} + if true { + toSerialize["measurementSchemas"] = o.MeasurementSchemas + } + return json.Marshal(toSerialize) +} + +type NullableMeasurementSchemaList struct { + value *MeasurementSchemaList + isSet bool +} + +func (v NullableMeasurementSchemaList) Get() *MeasurementSchemaList { + return v.value +} + +func (v *NullableMeasurementSchemaList) Set(val *MeasurementSchemaList) { + v.value = val + v.isSet = true +} + +func (v NullableMeasurementSchemaList) IsSet() bool { + return v.isSet +} + +func (v *NullableMeasurementSchemaList) Unset() { + v.value = nil + v.isSet = false +} + +func NewNullableMeasurementSchemaList(val *MeasurementSchemaList) *NullableMeasurementSchemaList { + return &NullableMeasurementSchemaList{value: val, isSet: true} +} + +func (v NullableMeasurementSchemaList) MarshalJSON() ([]byte, error) { + return json.Marshal(v.value) +} + +func (v *NullableMeasurementSchemaList) UnmarshalJSON(src []byte) error { + v.isSet = true + return json.Unmarshal(src, &v.value) +} diff --git a/internal/api/model_measurement_schema_update_request.gen.go b/internal/api/model_measurement_schema_update_request.gen.go new file mode 100644 index 0000000..62cdc96 --- /dev/null +++ b/internal/api/model_measurement_schema_update_request.gen.go @@ -0,0 +1,107 @@ +/* + * 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" +) + +// MeasurementSchemaUpdateRequest Update an existing measurement schema +type MeasurementSchemaUpdateRequest struct { + // An ordered collection of column definitions + Columns []MeasurementSchemaColumn `json:"columns"` +} + +// NewMeasurementSchemaUpdateRequest instantiates a new MeasurementSchemaUpdateRequest 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 NewMeasurementSchemaUpdateRequest(columns []MeasurementSchemaColumn) *MeasurementSchemaUpdateRequest { + this := MeasurementSchemaUpdateRequest{} + this.Columns = columns + return &this +} + +// NewMeasurementSchemaUpdateRequestWithDefaults instantiates a new MeasurementSchemaUpdateRequest 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 NewMeasurementSchemaUpdateRequestWithDefaults() *MeasurementSchemaUpdateRequest { + this := MeasurementSchemaUpdateRequest{} + return &this +} + +// GetColumns returns the Columns field value +func (o *MeasurementSchemaUpdateRequest) GetColumns() []MeasurementSchemaColumn { + if o == nil { + var ret []MeasurementSchemaColumn + return ret + } + + return o.Columns +} + +// GetColumnsOk returns a tuple with the Columns field value +// and a boolean to check if the value has been set. +func (o *MeasurementSchemaUpdateRequest) GetColumnsOk() (*[]MeasurementSchemaColumn, bool) { + if o == nil { + return nil, false + } + return &o.Columns, true +} + +// SetColumns sets field value +func (o *MeasurementSchemaUpdateRequest) SetColumns(v []MeasurementSchemaColumn) { + o.Columns = v +} + +func (o MeasurementSchemaUpdateRequest) MarshalJSON() ([]byte, error) { + toSerialize := map[string]interface{}{} + if true { + toSerialize["columns"] = o.Columns + } + return json.Marshal(toSerialize) +} + +type NullableMeasurementSchemaUpdateRequest struct { + value *MeasurementSchemaUpdateRequest + isSet bool +} + +func (v NullableMeasurementSchemaUpdateRequest) Get() *MeasurementSchemaUpdateRequest { + return v.value +} + +func (v *NullableMeasurementSchemaUpdateRequest) Set(val *MeasurementSchemaUpdateRequest) { + v.value = val + v.isSet = true +} + +func (v NullableMeasurementSchemaUpdateRequest) IsSet() bool { + return v.isSet +} + +func (v *NullableMeasurementSchemaUpdateRequest) Unset() { + v.value = nil + v.isSet = false +} + +func NewNullableMeasurementSchemaUpdateRequest(val *MeasurementSchemaUpdateRequest) *NullableMeasurementSchemaUpdateRequest { + return &NullableMeasurementSchemaUpdateRequest{value: val, isSet: true} +} + +func (v NullableMeasurementSchemaUpdateRequest) MarshalJSON() ([]byte, error) { + return json.Marshal(v.value) +} + +func (v *NullableMeasurementSchemaUpdateRequest) UnmarshalJSON(src []byte) error { + v.isSet = true + return json.Unmarshal(src, &v.value) +} diff --git a/internal/api/model_post_bucket_request.gen.go b/internal/api/model_post_bucket_request.gen.go index 2f169d0..9ba0581 100644 --- a/internal/api/model_post_bucket_request.gen.go +++ b/internal/api/model_post_bucket_request.gen.go @@ -22,6 +22,7 @@ type PostBucketRequest struct { Rp *string `json:"rp,omitempty"` // Rules to expire or retain data. No rules means data never expires. RetentionRules []RetentionRule `json:"retentionRules"` + SchemaType *SchemaType `json:"schemaType,omitempty"` } // NewPostBucketRequest instantiates a new PostBucketRequest object @@ -180,6 +181,38 @@ func (o *PostBucketRequest) SetRetentionRules(v []RetentionRule) { o.RetentionRules = v } +// GetSchemaType returns the SchemaType field value if set, zero value otherwise. +func (o *PostBucketRequest) GetSchemaType() SchemaType { + if o == nil || o.SchemaType == nil { + var ret SchemaType + return ret + } + return *o.SchemaType +} + +// GetSchemaTypeOk returns a tuple with the SchemaType field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *PostBucketRequest) GetSchemaTypeOk() (*SchemaType, bool) { + if o == nil || o.SchemaType == nil { + return nil, false + } + return o.SchemaType, true +} + +// HasSchemaType returns a boolean if a field has been set. +func (o *PostBucketRequest) HasSchemaType() bool { + if o != nil && o.SchemaType != nil { + return true + } + + return false +} + +// SetSchemaType gets a reference to the given SchemaType and assigns it to the SchemaType field. +func (o *PostBucketRequest) SetSchemaType(v SchemaType) { + o.SchemaType = &v +} + func (o PostBucketRequest) MarshalJSON() ([]byte, error) { toSerialize := map[string]interface{}{} if true { @@ -197,6 +230,9 @@ func (o PostBucketRequest) MarshalJSON() ([]byte, error) { if true { toSerialize["retentionRules"] = o.RetentionRules } + if o.SchemaType != nil { + toSerialize["schemaType"] = o.SchemaType + } return json.Marshal(toSerialize) } diff --git a/internal/api/model_schema_type.gen.go b/internal/api/model_schema_type.gen.go new file mode 100644 index 0000000..580dd6c --- /dev/null +++ b/internal/api/model_schema_type.gen.go @@ -0,0 +1,83 @@ +/* + * 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" + "fmt" +) + +// SchemaType the model 'SchemaType' +type SchemaType string + +// List of SchemaType +const ( + SCHEMATYPE_IMPLICIT SchemaType = "implicit" + SCHEMATYPE_EXPLICIT SchemaType = "explicit" +) + +func (v *SchemaType) UnmarshalJSON(src []byte) error { + var value string + err := json.Unmarshal(src, &value) + if err != nil { + return err + } + enumTypeValue := SchemaType(value) + for _, existing := range []SchemaType{"implicit", "explicit"} { + if existing == enumTypeValue { + *v = enumTypeValue + return nil + } + } + + return fmt.Errorf("%+v is not a valid SchemaType", value) +} + +// Ptr returns reference to SchemaType value +func (v SchemaType) Ptr() *SchemaType { + return &v +} + +type NullableSchemaType struct { + value *SchemaType + isSet bool +} + +func (v NullableSchemaType) Get() *SchemaType { + return v.value +} + +func (v *NullableSchemaType) Set(val *SchemaType) { + v.value = val + v.isSet = true +} + +func (v NullableSchemaType) IsSet() bool { + return v.isSet +} + +func (v *NullableSchemaType) Unset() { + v.value = nil + v.isSet = false +} + +func NewNullableSchemaType(val *SchemaType) *NullableSchemaType { + return &NullableSchemaType{value: val, isSet: true} +} + +func (v NullableSchemaType) MarshalJSON() ([]byte, error) { + return json.Marshal(v.value) +} + +func (v *NullableSchemaType) UnmarshalJSON(src []byte) error { + v.isSet = true + return json.Unmarshal(src, &v.value) +} diff --git a/internal/api/schema_type.go b/internal/api/schema_type.go new file mode 100644 index 0000000..3ac76d4 --- /dev/null +++ b/internal/api/schema_type.go @@ -0,0 +1,23 @@ +package api + +import ( + "fmt" +) + +func (v SchemaType) String() string { + return string(v) +} + +// Set implements the cli.Generic interface for parsing +// flags. +func (v *SchemaType) Set(s string) error { + switch s { + case string(SCHEMATYPE_IMPLICIT): + *v = SCHEMATYPE_IMPLICIT + case string(SCHEMATYPE_EXPLICIT): + *v = SCHEMATYPE_EXPLICIT + default: + return fmt.Errorf("unsupported schema type: %q", s) + } + return nil +} diff --git a/internal/api/unmarshal_csv.go b/internal/api/unmarshal_csv.go new file mode 100644 index 0000000..7308334 --- /dev/null +++ b/internal/api/unmarshal_csv.go @@ -0,0 +1,39 @@ +package api + +import ( + "fmt" + "strings" +) + +// UnmarshalCSV implements the gocsv.TypeUnmarshaller interface +// for decoding CSV. +func (v *ColumnSemanticType) UnmarshalCSV(s string) error { + types := []string{string(COLUMNSEMANTICTYPE_TIMESTAMP), string(COLUMNSEMANTICTYPE_TAG), string(COLUMNSEMANTICTYPE_FIELD)} + for _, t := range types { + if s == t { + *v = ColumnSemanticType(t) + return nil + } + } + return fmt.Errorf("%q is not a valid column type. Valid values are [%s]", s, strings.Join(types, ", ")) +} + +// UnmarshalCSV implements the gocsv.TypeUnmarshaller interface +// for decoding CSV. +func (v *ColumnDataType) UnmarshalCSV(s string) error { + types := []string{ + string(COLUMNDATATYPE_INTEGER), + string(COLUMNDATATYPE_FLOAT), + string(COLUMNDATATYPE_BOOLEAN), + string(COLUMNDATATYPE_STRING), + string(COLUMNDATATYPE_UNSIGNED), + } + + for _, t := range types { + if s == t { + *v = ColumnDataType(t) + return nil + } + } + return fmt.Errorf("%q is not a valid column data type. Valid values are [%s]", s, strings.Join(types, ", ")) +} diff --git a/internal/bucket.go b/internal/bucket.go index 8a8dea3..c95531f 100644 --- a/internal/bucket.go +++ b/internal/bucket.go @@ -24,6 +24,7 @@ type BucketsCreateParams struct { Description string Retention string ShardGroupDuration string + SchemaType api.SchemaType } var ( @@ -50,6 +51,7 @@ func (c *CLI) BucketsCreate(ctx context.Context, clients *BucketsClients, params OrgID: params.OrgID, Name: params.Name, RetentionRules: []api.RetentionRule{}, + SchemaType: ¶ms.SchemaType, } if params.Description != "" { reqBody.Description = ¶ms.Description @@ -249,7 +251,7 @@ func (c *CLI) printBuckets(options bucketPrintOptions) error { return c.PrintJSON(v) } - headers := []string{"ID", "Name", "Retention", "Shard group duration", "Organization ID"} + headers := []string{"ID", "Name", "Retention", "Shard group duration", "Organization ID", "Schema Type"} if options.deleted { headers = append(headers, "Deleted") } @@ -279,12 +281,19 @@ func (c *CLI) printBuckets(options bucketPrintOptions) error { sgDur = "n/a" } + schemaType := bkt.GetSchemaType() + if schemaType == "" { + // schemaType will be empty when querying OSS. + schemaType = api.SCHEMATYPE_IMPLICIT + } + row := map[string]interface{}{ "ID": bkt.GetId(), "Name": bkt.GetName(), "Retention": rp, "Shard group duration": sgDur, "Organization ID": bkt.GetOrgID(), + "Schema Type": schemaType, } if options.deleted { row["Deleted"] = true diff --git a/internal/bucket_test.go b/internal/bucket_test.go index a6d8070..92011d2 100644 --- a/internal/bucket_test.go +++ b/internal/bucket_test.go @@ -94,9 +94,9 @@ func TestBucketsCreate(t *testing.T) { { name: "retention but not shard-group duration", params: internal.BucketsCreateParams{ - OrgID: "123", - Name: "my-bucket", - Retention: "24h", + 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) { @@ -123,6 +123,38 @@ func TestBucketsCreate(t *testing.T) { } }, }, + { + name: "create bucket with explicit schema", + params: internal.BucketsCreateParams{ + OrgID: "123", + Name: "my-bucket", + Retention: "24h", + SchemaType: api.SCHEMATYPE_EXPLICIT, + }, + 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.NotNil(t, body.SchemaType) + assert.Equal(t, api.SCHEMATYPE_EXPLICIT, *body.SchemaType) + + return api.Bucket{ + Id: api.PtrString("456"), + OrgID: api.PtrString("123"), + Name: "my-bucket", + RetentionRules: body.RetentionRules, + SchemaType: api.SCHEMATYPE_EXPLICIT.Ptr(), + }, nil, nil + } + }, + expectedStdoutPattern: `456\s+my-bucket\s+24h0m0s\s+n/a\s+123\s+explicit`, + }, { name: "look up org by name", params: internal.BucketsCreateParams{ @@ -403,6 +435,56 @@ func TestBucketsList(t *testing.T) { "999\\s+bucket2\\s+infinite\\s+1m0s\\s+456", }, }, + { + name: "list multiple bucket schema types", + 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("001"), + Name: "omit-schema-type", + OrgID: api.PtrString("456"), + RetentionRules: []api.RetentionRule{ + {EverySeconds: 3600}, + }, + }, + { + Id: api.PtrString("002"), + Name: "implicit-schema-type", + OrgID: api.PtrString("456"), + RetentionRules: []api.RetentionRule{ + {EverySeconds: 3600}, + }, + SchemaType: api.SCHEMATYPE_IMPLICIT.Ptr(), + }, + { + Id: api.PtrString("003"), + Name: "explicit-schema-type", + OrgID: api.PtrString("456"), + RetentionRules: []api.RetentionRule{ + {EverySeconds: 3600}, + }, + SchemaType: api.SCHEMATYPE_EXPLICIT.Ptr(), + }, + }, + }, nil, nil + } + }, + expectedStdoutPatterns: []string{ + `001\s+omit-schema-type\s+1h0m0s\s+n/a\s+456\s+implicit`, + `002\s+implicit-schema-type\s+1h0m0s\s+n/a\s+456\s+implicit`, + `003\s+explicit-schema-type\s+1h0m0s\s+n/a\s+456\s+explicit`, + }, + }, { name: "no org specified", expectedInErr: "must specify org ID or org name", @@ -631,7 +713,7 @@ func TestBucketsDelete(t *testing.T) { return nil, nil } }, - expectedStdoutPattern: "123\\s+my-bucket\\s+1h0m0s\\s+n/a\\s+456", + expectedStdoutPattern: "123\\s+my-bucket\\s+1h0m0s\\s+n/a\\s+456\\s+implicit", }, { name: "by name and org ID", @@ -667,7 +749,7 @@ func TestBucketsDelete(t *testing.T) { return nil, nil } }, - expectedStdoutPattern: "123\\s+my-bucket\\s+1h0m0s\\s+n/a\\s+456", + expectedStdoutPattern: "123\\s+my-bucket\\s+1h0m0s\\s+n/a\\s+456\\s+implicit", }, { name: "by name and org name", @@ -703,7 +785,7 @@ func TestBucketsDelete(t *testing.T) { return nil, nil } }, - expectedStdoutPattern: "123\\s+my-bucket\\s+1h0m0s\\s+n/a\\s+456", + expectedStdoutPattern: "123\\s+my-bucket\\s+1h0m0s\\s+n/a\\s+456\\s+implicit", }, { name: "by name in default org", @@ -738,7 +820,7 @@ func TestBucketsDelete(t *testing.T) { return nil, nil } }, - expectedStdoutPattern: "123\\s+my-bucket\\s+1h0m0s\\s+n/a\\s+456", + expectedStdoutPattern: "123\\s+my-bucket\\s+1h0m0s\\s+n/a\\s+456\\s+implicit", }, { name: "by name without org", @@ -800,7 +882,7 @@ func TestBucketsDelete(t *testing.T) { 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, `ID\s+Name\s+Retention\s+Shard group duration\s+Organization ID\s+Schema Type\s+Deleted`, outLines[0]) require.Regexp(t, tc.expectedStdoutPattern+"\\s+true", outLines[1]) }) } diff --git a/internal/cmd/bucket_schema/client.go b/internal/cmd/bucket_schema/client.go new file mode 100644 index 0000000..a2b5823 --- /dev/null +++ b/internal/cmd/bucket_schema/client.go @@ -0,0 +1,294 @@ +package bucket_schema + +import ( + "bytes" + "context" + "errors" + "fmt" + "io" + "os" + + "github.com/influxdata/influx-cli/v2/internal" + "github.com/influxdata/influx-cli/v2/internal/api" +) + +type Client struct { + BucketApi api.BucketsApi + BucketSchemasApi api.BucketSchemasApi + CLI *internal.CLI +} + +type orgBucketID struct { + OrgID string + BucketID string +} + +func (c Client) resolveMeasurement(ctx context.Context, ids orgBucketID, name string) (string, error) { + res, _, err := c.BucketSchemasApi. + GetMeasurementSchemas(ctx, ids.BucketID). + OrgID(ids.OrgID). + Name(name). + Execute() + if err != nil { + return "", fmt.Errorf("failed to find measurement schema: %w", err) + } + + if len(res.MeasurementSchemas) == 0 { + return "", fmt.Errorf("measurement schema %q not found", name) + } + + return res.MeasurementSchemas[0].Id, nil +} + +func (c Client) resolveOrgBucketIds(ctx context.Context, params internal.OrgBucketParams) (*orgBucketID, error) { + if params.OrgID.Valid() && params.BucketID.Valid() { + return &orgBucketID{OrgID: params.OrgID.String(), BucketID: params.BucketID.String()}, nil + } + + if params.BucketName == "" { + return nil, errors.New("bucket missing: specify bucket ID or bucket name") + } + + if !params.OrgID.Valid() && params.OrgName == "" && c.CLI.ActiveConfig.Org == "" { + return nil, errors.New("org missing: specify org ID or org name") + } + + req := c.BucketApi.GetBuckets(ctx).Name(params.BucketName) + if params.OrgID.Valid() { + req = req.OrgID(params.OrgID.String()) + } else if params.OrgName != "" { + req = req.Org(params.OrgName) + } else { + req = req.Org(c.CLI.ActiveConfig.Org) + } + + resp, _, err := req.Execute() + if err != nil { + return nil, fmt.Errorf("failed to find bucket %q: %w", params.BucketName, err) + } + buckets := resp.GetBuckets() + if len(buckets) == 0 { + return nil, fmt.Errorf("bucket %q not found", params.BucketName) + } + + return &orgBucketID{OrgID: buckets[0].GetOrgID(), BucketID: buckets[0].GetId()}, nil +} + +func (c Client) readColumns(stdin io.Reader, f ColumnsFormat, path string) ([]api.MeasurementSchemaColumn, error) { + var ( + r io.Reader + name string + ) + + if path == "" { + r = stdin + name = "stdin" + } else { + data, err := os.ReadFile(path) + if err != nil { + return nil, fmt.Errorf("unable to read file %q: %w", path, err) + } + r = bytes.NewReader(data) + name = path + } + + reader, err := f.DecoderFn(name) + if err != nil { + return nil, err + } + + return reader(r) +} + +type CreateParams struct { + internal.OrgBucketParams + Name string + Stdin io.Reader + ColumnsFile string + ColumnsFormat ColumnsFormat + ExtendedOutput bool +} + +func (c Client) Create(ctx context.Context, params CreateParams) error { + cols, err := c.readColumns(params.Stdin, params.ColumnsFormat, params.ColumnsFile) + if err != nil { + return err + } + + ids, err := c.resolveOrgBucketIds(ctx, params.OrgBucketParams) + if err != nil { + return err + } + + res, _, err := c.BucketSchemasApi. + CreateMeasurementSchema(ctx, ids.BucketID). + OrgID(ids.OrgID). + MeasurementSchemaCreateRequest(api.MeasurementSchemaCreateRequest{ + Name: params.Name, + Columns: cols, + }). + Execute() + + if err != nil { + return fmt.Errorf("failed to create measurement: %w", err) + } + + return c.printMeasurements(ids.BucketID, []api.MeasurementSchema{res}, params.ExtendedOutput) +} + +type UpdateParams struct { + internal.OrgBucketParams + Name string + ID string + Stdin io.Reader + ColumnsFile string + ColumnsFormat ColumnsFormat + ExtendedOutput bool +} + +func (c Client) Update(ctx context.Context, params UpdateParams) error { + cols, err := c.readColumns(params.Stdin, params.ColumnsFormat, params.ColumnsFile) + if err != nil { + return err + } + + ids, err := c.resolveOrgBucketIds(ctx, params.OrgBucketParams) + if err != nil { + return err + } + + var id string + if params.ID == "" && params.Name == "" { + return errors.New("measurement id or name required") + } else if params.ID != "" { + id = params.ID + } else { + id, err = c.resolveMeasurement(ctx, *ids, params.Name) + if err != nil { + return err + } + } + + res, _, err := c.BucketSchemasApi. + UpdateMeasurementSchema(ctx, ids.BucketID, id). + OrgID(ids.OrgID). + MeasurementSchemaUpdateRequest(api.MeasurementSchemaUpdateRequest{ + Columns: cols, + }). + Execute() + + if err != nil { + return fmt.Errorf("failed to update measurement schema: %w", err) + } + + return c.printMeasurements(ids.BucketID, []api.MeasurementSchema{res}, params.ExtendedOutput) +} + +type ListParams struct { + internal.OrgBucketParams + Name string + ExtendedOutput bool +} + +func (c Client) List(ctx context.Context, params ListParams) error { + ids, err := c.resolveOrgBucketIds(ctx, params.OrgBucketParams) + if err != nil { + return err + } + + req := c.BucketSchemasApi. + GetMeasurementSchemas(ctx, ids.BucketID). + OrgID(ids.OrgID) + + if params.Name != "" { + req = req.Name(params.Name) + } + + res, _, err := req.Execute() + if err != nil { + return fmt.Errorf("failed to list measurement schemas: %w", err) + } + return c.printMeasurements(ids.BucketID, res.MeasurementSchemas, params.ExtendedOutput) +} + +// Constants for table column headers +const ( + IDHdr = "ID" + MeasurementNameHdr = "Measurement Name" + ColumnNameHdr = "Column Name" + ColumnTypeHdr = "Column Type" + ColumnDataTypeHdr = "Column Data Type" + BucketIDHdr = "Bucket ID" +) + +func (c Client) printMeasurements(bucketID string, m []api.MeasurementSchema, extended bool) error { + if len(m) == 0 { + return nil + } + + if c.CLI.PrintAsJSON { + return c.CLI.PrintJSON(m) + } + + var headers []string + if extended { + headers = []string{ + IDHdr, + MeasurementNameHdr, + ColumnNameHdr, + ColumnTypeHdr, + ColumnDataTypeHdr, + BucketIDHdr, + } + } else { + headers = []string{ + IDHdr, + MeasurementNameHdr, + BucketIDHdr, + } + } + + var makeRow measurementRowFn + if extended { + makeRow = makeExtendedMeasurementRows + } else { + makeRow = makeMeasurementRows + } + + var rows []map[string]interface{} + + for i := range m { + rows = append(rows, makeRow(bucketID, &m[i])...) + } + + return c.CLI.PrintTable(headers, rows...) +} + +type measurementRowFn func(bucketID string, m *api.MeasurementSchema) []map[string]interface{} + +func makeMeasurementRows(bucketID string, m *api.MeasurementSchema) []map[string]interface{} { + return []map[string]interface{}{ + { + IDHdr: m.Id, + MeasurementNameHdr: m.Name, + BucketIDHdr: bucketID, + }, + } +} + +func makeExtendedMeasurementRows(bucketID string, m *api.MeasurementSchema) []map[string]interface{} { + rows := make([]map[string]interface{}, 0, len(m.Columns)) + + for i := range m.Columns { + col := &m.Columns[i] + rows = append(rows, map[string]interface{}{ + IDHdr: m.Id, + MeasurementNameHdr: m.Name, + ColumnNameHdr: col.Name, + ColumnTypeHdr: col.Type, + ColumnDataTypeHdr: col.GetDataType(), + BucketIDHdr: bucketID, + }) + } + return rows +} diff --git a/internal/cmd/bucket_schema/client_test.go b/internal/cmd/bucket_schema/client_test.go new file mode 100644 index 0000000..b46181a --- /dev/null +++ b/internal/cmd/bucket_schema/client_test.go @@ -0,0 +1,739 @@ +package bucket_schema_test + +import ( + "bytes" + "context" + "os" + "path/filepath" + "regexp" + "strings" + "testing" + "time" + + "github.com/golang/mock/gomock" + "github.com/google/go-cmp/cmp" + "github.com/influxdata/influx-cli/v2/internal" + "github.com/influxdata/influx-cli/v2/internal/api" + "github.com/influxdata/influx-cli/v2/internal/cmd/bucket_schema" + "github.com/influxdata/influx-cli/v2/internal/mock" + "github.com/stretchr/testify/assert" + tmock "github.com/stretchr/testify/mock" + "github.com/stretchr/testify/require" +) + +func matchLines(t *testing.T, lines []string, mockIO *mock.Stdio) { + if len(lines) > 0 { + outLines := strings.Split(mockIO.Stdout(), "\n") + expLines := make([]*regexp.Regexp, 0, len(lines)) + for _, expLine := range lines { + expLines = append(expLines, regexp.MustCompile(expLine)) + } + + for _, outLine := range outLines { + if outLine == "" { + continue + } + var any bool + for _, expLine := range expLines { + any = any || expLine.MatchString(outLine) + } + assert.True(t, any, "line %q was unexpected", outLine) + } + } +} + +func TestClient_Create(t *testing.T) { + var ( + orgID = "dead" + bucketID = "f00d" + measurementID = "1010" + createdAt = time.Date(2004, 4, 9, 2, 15, 0, 0, time.UTC) + ) + + type setupArgs struct { + buckets *mock.MockBucketsApi + schemas *mock.MockBucketSchemasApi + cli *internal.CLI + params bucket_schema.CreateParams + cols []api.MeasurementSchemaColumn + stdio *mock.Stdio + } + + type optFn func(t *testing.T, a *setupArgs) + + type args struct { + OrgName string + BucketName string + Name string + ColumnsFile string + ExtendedOutput bool + } + + withArgs := func(args args) optFn { + return func(t *testing.T, a *setupArgs) { + t.Helper() + var colFile string + if args.ColumnsFile != "" { + colFile = filepath.Join("testdata", args.ColumnsFile) + } + + a.params = bucket_schema.CreateParams{ + OrgBucketParams: internal.OrgBucketParams{ + OrgParams: internal.OrgParams{OrgName: args.OrgName}, + BucketParams: internal.BucketParams{BucketName: args.BucketName}, + }, + Name: args.Name, + ColumnsFile: colFile, + ExtendedOutput: args.ExtendedOutput, + } + } + } + + expGetBuckets := func(n ...string) optFn { + return func(t *testing.T, a *setupArgs) { + t.Helper() + require.True(t, len(n) <= 1, "either zero or one bucket name") + var buckets []api.Bucket + if len(n) == 1 { + bucket := api.NewBucket(n[0], nil) + bucket.SetOrgID(orgID) + bucket.SetId(bucketID) + bucket.SetName(n[0]) + buckets = []api.Bucket{*bucket} + } + + req := api.ApiGetBucketsRequest{ApiService: a.buckets} + + a.buckets.EXPECT(). + GetBuckets(gomock.Any()). + Return(req) + + a.buckets.EXPECT(). + GetBucketsExecute(tmock.MatchedBy(func(in api.ApiGetBucketsRequest) bool { + return cmp.Equal(in.GetOrg(), &a.params.OrgName) && cmp.Equal(in.GetName(), &a.params.BucketName) + })). + Return(api.Buckets{Buckets: &buckets}, nil, nil) + } + } + + withCols := func(p string) optFn { + return func(t *testing.T, a *setupArgs) { + data, err := os.ReadFile(filepath.Join("testdata", p)) + require.NoError(t, err) + + var f bucket_schema.ColumnsFormat + decoder, err := f.DecoderFn(p) + require.NoError(t, err) + cols, err := decoder(bytes.NewReader(data)) + require.NoError(t, err) + a.cols = cols + } + } + + expCreate := func() optFn { + return func(t *testing.T, a *setupArgs) { + t.Helper() + + req := api.ApiCreateMeasurementSchemaRequest{ApiService: a.schemas}.BucketID(bucketID) + + a.schemas.EXPECT(). + CreateMeasurementSchema(gomock.Any(), bucketID). + Return(req) + + a.schemas.EXPECT(). + CreateMeasurementSchemaExecute(tmock.MatchedBy(func(in api.ApiCreateMeasurementSchemaRequest) bool { + return cmp.Equal(in.GetOrgID(), &orgID) && cmp.Equal(in.GetBucketID(), bucketID) + })). + Return(api.MeasurementSchema{ + Id: measurementID, + Name: a.params.Name, + Columns: a.cols, + CreatedAt: createdAt, + UpdatedAt: createdAt, + }, nil, nil) + } + } + + opts := func(opts ...optFn) []optFn { return opts } + + lines := func(lines ...string) []string { return lines } + + cases := []struct { + name string + opts []optFn + expErr string + expLines []string + }{ + { + name: "unable to guess from stdin", + expErr: `unable to guess format for file "stdin"`, + }, + { + name: "org arg missing", + opts: opts( + withArgs(args{BucketName: "my-bucket", ColumnsFile: "columns.csv"}), + ), + expErr: "org missing: specify org ID or org name", + }, + { + name: "bucket arg missing", + opts: opts( + withArgs(args{OrgName: "my-org", ColumnsFile: "columns.csv"}), + ), + expErr: "bucket missing: specify bucket ID or bucket name", + }, + { + name: "bucket not found", + opts: opts( + withArgs(args{OrgName: "my-org", BucketName: "my-bucket", ColumnsFile: "columns.csv"}), + + expGetBuckets(), + ), + expErr: `bucket "my-bucket" not found`, + }, + { + name: "create succeeds with csv", + opts: opts( + withArgs(args{OrgName: "my-org", BucketName: "my-bucket", Name: "cpu", ColumnsFile: "columns.csv"}), + withCols("columns.csv"), + + expGetBuckets("my-bucket"), + expCreate(), + ), + expLines: lines( + `^ID\s+Measurement Name\s+Bucket ID$`, + `^1010\s+cpu\s+f00d$`, + ), + }, + { + name: "create succeeds with json", + opts: opts( + withArgs(args{OrgName: "my-org", BucketName: "my-bucket", Name: "cpu", ColumnsFile: "columns.json"}), + withCols("columns.csv"), + + expGetBuckets("my-bucket"), + expCreate(), + ), + expLines: lines( + `^ID\s+Measurement Name\s+Bucket ID$`, + `^1010\s+cpu\s+f00d$`, + ), + }, + { + name: "create succeeds with ndjson", + opts: opts( + withArgs(args{OrgName: "my-org", BucketName: "my-bucket", Name: "cpu", ColumnsFile: "columns.ndjson"}), + withCols("columns.csv"), + + expGetBuckets("my-bucket"), + expCreate(), + ), + expLines: lines( + `^ID\s+Measurement Name\s+Bucket ID$`, + `^1010\s+cpu\s+f00d$`, + ), + }, + { + name: "create succeeds with extended output", + opts: opts( + withArgs(args{OrgName: "my-org", BucketName: "my-bucket", Name: "cpu", ColumnsFile: "columns.csv", ExtendedOutput: true}), + withCols("columns.csv"), + + expGetBuckets("my-bucket"), + expCreate(), + ), + expLines: lines( + `^ID\s+Measurement Name\s+Column Name\s+Column Type\s+Column Data Type\s+Bucket ID$`, + `^1010\s+cpu\s+\w+\s+(timestamp|tag|field)\s+(|float)\s+f00d$`, + ), + }, + } + + for _, tc := range cases { + t.Run(tc.name, func(t *testing.T) { + ctrl := gomock.NewController(t) + mockIO := mock.NewMockStdio(nil, true) + args := &setupArgs{ + buckets: mock.NewMockBucketsApi(ctrl), + schemas: mock.NewMockBucketSchemasApi(ctrl), + stdio: mockIO, + cli: &internal.CLI{StdIO: mockIO}, + } + + for _, opt := range tc.opts { + opt(t, args) + } + + c := bucket_schema.Client{ + BucketApi: args.buckets, + BucketSchemasApi: args.schemas, + CLI: args.cli, + } + + ctx := context.Background() + err := c.Create(ctx, args.params) + if tc.expErr != "" { + assert.EqualError(t, err, tc.expErr) + } else { + require.NoError(t, err) + matchLines(t, tc.expLines, mockIO) + } + }) + } +} + +func TestClient_Update(t *testing.T) { + var ( + orgID = "dead" + bucketID = "f00d" + measurementID = "1010" + createdAt = time.Date(2004, 4, 9, 2, 15, 0, 0, time.UTC) + updatedAt = time.Date(2009, 9, 1, 2, 15, 0, 0, time.UTC) + ) + + type setupArgs struct { + buckets *mock.MockBucketsApi + schemas *mock.MockBucketSchemasApi + cli *internal.CLI + params bucket_schema.UpdateParams + cols []api.MeasurementSchemaColumn + stdio *mock.Stdio + } + + type optFn func(t *testing.T, a *setupArgs) + + type args struct { + OrgName string + BucketName string + Name string + ColumnsFile string + ExtendedOutput bool + } + + withArgs := func(args args) optFn { + return func(t *testing.T, a *setupArgs) { + t.Helper() + var colFile string + if args.ColumnsFile != "" { + colFile = filepath.Join("testdata", args.ColumnsFile) + } + + a.params = bucket_schema.UpdateParams{ + OrgBucketParams: internal.OrgBucketParams{ + OrgParams: internal.OrgParams{OrgName: args.OrgName}, + BucketParams: internal.BucketParams{BucketName: args.BucketName}, + }, + Name: args.Name, + ColumnsFile: colFile, + ExtendedOutput: args.ExtendedOutput, + } + } + } + + expGetBuckets := func(n ...string) optFn { + return func(t *testing.T, a *setupArgs) { + t.Helper() + require.True(t, len(n) <= 1, "either zero or one bucket name") + var buckets []api.Bucket + if len(n) == 1 { + bucket := api.NewBucket(n[0], nil) + bucket.SetOrgID(orgID) + bucket.SetId(bucketID) + bucket.SetName(n[0]) + buckets = []api.Bucket{*bucket} + } + + req := api.ApiGetBucketsRequest{ApiService: a.buckets} + + a.buckets.EXPECT(). + GetBuckets(gomock.Any()). + Return(req) + + a.buckets.EXPECT(). + GetBucketsExecute(tmock.MatchedBy(func(in api.ApiGetBucketsRequest) bool { + return (in.GetOrg() != nil && *in.GetOrg() == a.params.OrgName) && + (in.GetName() != nil && *in.GetName() == a.params.BucketName) + })). + Return(api.Buckets{Buckets: &buckets}, nil, nil) + } + } + + withCols := func(p string) optFn { + return func(t *testing.T, a *setupArgs) { + data, err := os.ReadFile(filepath.Join("testdata", p)) + require.NoError(t, err) + + var f bucket_schema.ColumnsFormat + decoder, err := f.DecoderFn(p) + require.NoError(t, err) + cols, err := decoder(bytes.NewReader(data)) + require.NoError(t, err) + a.cols = cols + } + } + + expGetMeasurementSchema := func() optFn { + return func(t *testing.T, a *setupArgs) { + t.Helper() + + req := api.ApiGetMeasurementSchemasRequest{ApiService: a.schemas}.BucketID(bucketID) + + a.schemas.EXPECT(). + GetMeasurementSchemas(gomock.Any(), bucketID). + Return(req) + + a.schemas.EXPECT(). + GetMeasurementSchemasExecute(tmock.MatchedBy(func(in api.ApiGetMeasurementSchemasRequest) bool { + return (in.GetOrgID() != nil && *in.GetOrgID() == orgID) && + in.GetBucketID() == bucketID && + (in.GetName() != nil && *in.GetName() == a.params.Name) + })). + Return(api.MeasurementSchemaList{ + MeasurementSchemas: []api.MeasurementSchema{ + { + Id: measurementID, + Name: a.params.Name, + Columns: a.cols, + CreatedAt: createdAt, + UpdatedAt: updatedAt, + }, + }, + }, nil, nil) + } + } + + expUpdate := func() optFn { + return func(t *testing.T, a *setupArgs) { + t.Helper() + + req := api.ApiUpdateMeasurementSchemaRequest{ApiService: a.schemas}.BucketID(bucketID).MeasurementID(measurementID) + + a.schemas.EXPECT(). + UpdateMeasurementSchema(gomock.Any(), bucketID, measurementID). + Return(req) + + a.schemas.EXPECT(). + UpdateMeasurementSchemaExecute(tmock.MatchedBy(func(in api.ApiUpdateMeasurementSchemaRequest) bool { + return cmp.Equal(in.GetOrgID(), &orgID) && + cmp.Equal(in.GetBucketID(), bucketID) && + cmp.Equal(in.GetMeasurementID(), measurementID) && + cmp.Equal(in.GetMeasurementSchemaUpdateRequest().Columns, a.cols) + })). + Return(api.MeasurementSchema{ + Id: measurementID, + Name: a.params.Name, + Columns: a.cols, + CreatedAt: createdAt, + UpdatedAt: updatedAt, + }, nil, nil) + } + } + + opts := func(opts ...optFn) []optFn { return opts } + + lines := func(lines ...string) []string { return lines } + + cases := []struct { + name string + opts []optFn + expErr string + expLines []string + }{ + { + name: "unable to guess from stdin", + expErr: `unable to guess format for file "stdin"`, + }, + { + name: "org arg missing", + opts: opts( + withArgs(args{BucketName: "my-bucket", ColumnsFile: "columns.csv"}), + ), + expErr: "org missing: specify org ID or org name", + }, + { + name: "bucket arg missing", + opts: opts( + withArgs(args{OrgName: "my-org", ColumnsFile: "columns.csv"}), + ), + expErr: "bucket missing: specify bucket ID or bucket name", + }, + { + name: "bucket not found", + opts: opts( + withArgs(args{OrgName: "my-org", BucketName: "my-bucket", ColumnsFile: "columns.csv"}), + expGetBuckets(), + ), + expErr: `bucket "my-bucket" not found`, + }, + { + name: "update succeeds", + opts: opts( + withArgs(args{OrgName: "my-org", BucketName: "my-bucket", Name: "cpu", ColumnsFile: "columns.csv"}), + withCols("columns.csv"), + + expGetBuckets("my-bucket"), + expGetMeasurementSchema(), + expUpdate(), + ), + expLines: lines( + `^ID\s+Measurement Name\s+Bucket ID$`, + `^1010\s+cpu\s+f00d$`, + ), + }, + { + name: "update succeeds extended output", + opts: opts( + withArgs(args{OrgName: "my-org", BucketName: "my-bucket", Name: "cpu", ColumnsFile: "columns.csv", ExtendedOutput: true}), + withCols("columns.csv"), + + expGetBuckets("my-bucket"), + expGetMeasurementSchema(), + expUpdate(), + ), + expLines: lines( + `^ID\s+Measurement Name\s+Column Name\s+Column Type\s+Column Data Type\s+Bucket ID$`, + `^1010\s+cpu\s+\w+\s+(timestamp|tag|field)\s+(|float)\s+f00d$`, + ), + }, + } + + for _, tc := range cases { + t.Run(tc.name, func(t *testing.T) { + ctrl := gomock.NewController(t) + mockIO := mock.NewMockStdio(nil, true) + args := &setupArgs{ + buckets: mock.NewMockBucketsApi(ctrl), + schemas: mock.NewMockBucketSchemasApi(ctrl), + stdio: mockIO, + cli: &internal.CLI{StdIO: mockIO}, + } + + for _, opt := range tc.opts { + opt(t, args) + } + + c := bucket_schema.Client{ + BucketApi: args.buckets, + BucketSchemasApi: args.schemas, + CLI: args.cli, + } + + ctx := context.Background() + err := c.Update(ctx, args.params) + if tc.expErr != "" { + assert.EqualError(t, err, tc.expErr) + } else { + require.NoError(t, err) + matchLines(t, tc.expLines, mockIO) + } + }) + } +} + +func TestClient_List(t *testing.T) { + var ( + orgID = "dead" + bucketID = "f00d" + measurementID = "1010" + createdAt = time.Date(2004, 4, 9, 2, 15, 0, 0, time.UTC) + updatedAt = time.Date(2009, 9, 1, 2, 15, 0, 0, time.UTC) + ) + + type setupArgs struct { + buckets *mock.MockBucketsApi + schemas *mock.MockBucketSchemasApi + cli *internal.CLI + params bucket_schema.ListParams + cols []api.MeasurementSchemaColumn + stdio *mock.Stdio + } + + type optFn func(t *testing.T, a *setupArgs) + + type args struct { + OrgName string + BucketName string + Name string + ExtendedOutput bool + } + + withArgs := func(args args) optFn { + return func(t *testing.T, a *setupArgs) { + t.Helper() + a.params = bucket_schema.ListParams{ + OrgBucketParams: internal.OrgBucketParams{ + OrgParams: internal.OrgParams{OrgName: args.OrgName}, + BucketParams: internal.BucketParams{BucketName: args.BucketName}, + }, + Name: args.Name, + ExtendedOutput: args.ExtendedOutput, + } + } + } + + expGetBuckets := func(n ...string) optFn { + return func(t *testing.T, a *setupArgs) { + t.Helper() + require.True(t, len(n) <= 1, "either zero or one bucket name") + var buckets []api.Bucket + if len(n) == 1 { + bucket := api.NewBucket(n[0], nil) + bucket.SetOrgID(orgID) + bucket.SetId(bucketID) + bucket.SetName(n[0]) + buckets = []api.Bucket{*bucket} + } + + req := api.ApiGetBucketsRequest{ApiService: a.buckets} + + a.buckets.EXPECT(). + GetBuckets(gomock.Any()). + Return(req) + + a.buckets.EXPECT(). + GetBucketsExecute(tmock.MatchedBy(func(in api.ApiGetBucketsRequest) bool { + return (in.GetOrg() != nil && *in.GetOrg() == a.params.OrgName) && + (in.GetName() != nil && *in.GetName() == a.params.BucketName) + })). + Return(api.Buckets{Buckets: &buckets}, nil, nil) + } + } + + withCols := func(p string) optFn { + return func(t *testing.T, a *setupArgs) { + data, err := os.ReadFile(filepath.Join("testdata", p)) + require.NoError(t, err) + + var f bucket_schema.ColumnsFormat + decoder, err := f.DecoderFn(p) + require.NoError(t, err) + cols, err := decoder(bytes.NewReader(data)) + require.NoError(t, err) + a.cols = cols + } + } + + expGetMeasurementSchemas := func() optFn { + return func(t *testing.T, a *setupArgs) { + t.Helper() + + req := api.ApiGetMeasurementSchemasRequest{ApiService: a.schemas}.BucketID(bucketID) + + a.schemas.EXPECT(). + GetMeasurementSchemas(gomock.Any(), bucketID). + Return(req) + + a.schemas.EXPECT(). + GetMeasurementSchemasExecute(tmock.MatchedBy(func(in api.ApiGetMeasurementSchemasRequest) bool { + return (in.GetOrgID() != nil && *in.GetOrgID() == orgID) && + in.GetBucketID() == bucketID && + (in.GetName() != nil && *in.GetName() == a.params.Name) + })). + Return(api.MeasurementSchemaList{ + MeasurementSchemas: []api.MeasurementSchema{ + { + Id: measurementID, + Name: a.params.Name, + Columns: a.cols, + CreatedAt: createdAt, + UpdatedAt: updatedAt, + }, + }, + }, nil, nil) + } + } + + opts := func(opts ...optFn) []optFn { return opts } + + lines := func(lines ...string) []string { return lines } + + cases := []struct { + name string + opts []optFn + expErr string + expLines []string + }{ + { + name: "org arg missing", + opts: opts( + withArgs(args{BucketName: "my-bucket"}), + ), + expErr: "org missing: specify org ID or org name", + }, + { + name: "bucket arg missing", + opts: opts( + withArgs(args{OrgName: "my-org"}), + ), + expErr: "bucket missing: specify bucket ID or bucket name", + }, + { + name: "bucket not found", + opts: opts( + withArgs(args{OrgName: "my-org", BucketName: "my-bucket"}), + expGetBuckets(), + ), + expErr: `bucket "my-bucket" not found`, + }, + { + name: "update succeeds", + opts: opts( + withArgs(args{OrgName: "my-org", BucketName: "my-bucket", Name: "cpu"}), + withCols("columns.csv"), + + expGetBuckets("my-bucket"), + expGetMeasurementSchemas(), + ), + expLines: lines( + `^ID\s+Measurement Name\s+Bucket ID$`, + `^1010\s+cpu\s+f00d$`, + ), + }, + { + name: "update succeeds extended output", + opts: opts( + withArgs(args{OrgName: "my-org", BucketName: "my-bucket", Name: "cpu", ExtendedOutput: true}), + withCols("columns.csv"), + + expGetBuckets("my-bucket"), + expGetMeasurementSchemas(), + ), + expLines: lines( + `^ID\s+Measurement Name\s+Column Name\s+Column Type\s+Column Data Type\s+Bucket ID$`, + `^1010\s+cpu\s+\w+\s+(timestamp|tag|field)\s+(|float)\s+f00d$`, + ), + }, + } + + for _, tc := range cases { + t.Run(tc.name, func(t *testing.T) { + ctrl := gomock.NewController(t) + mockIO := mock.NewMockStdio(nil, true) + args := &setupArgs{ + buckets: mock.NewMockBucketsApi(ctrl), + schemas: mock.NewMockBucketSchemasApi(ctrl), + stdio: mockIO, + cli: &internal.CLI{StdIO: mockIO}, + } + + for _, opt := range tc.opts { + opt(t, args) + } + + c := bucket_schema.Client{ + BucketApi: args.buckets, + BucketSchemasApi: args.schemas, + CLI: args.cli, + } + + ctx := context.Background() + err := c.List(ctx, args.params) + if tc.expErr != "" { + assert.EqualError(t, err, tc.expErr) + } else { + require.NoError(t, err) + matchLines(t, tc.expLines, mockIO) + } + }) + } +} diff --git a/internal/cmd/bucket_schema/csv.go b/internal/cmd/bucket_schema/csv.go new file mode 100644 index 0000000..4df84c4 --- /dev/null +++ b/internal/cmd/bucket_schema/csv.go @@ -0,0 +1,35 @@ +package bucket_schema + +import ( + "fmt" + "io" + + "github.com/gocarina/gocsv" + "github.com/influxdata/influx-cli/v2/internal/api" +) + +type csvColumn struct { + Name string `csv:"name"` + Type api.ColumnSemanticType `csv:"type"` + DataType *api.ColumnDataType `csv:"data_type,omitempty"` +} + +func decodeCSV(r io.Reader) ([]api.MeasurementSchemaColumn, error) { + var cols []csvColumn + gocsv.FailIfUnmatchedStructTags = true + err := gocsv.Unmarshal(r, &cols) + if err != nil { + return nil, fmt.Errorf("failed to decode CSV: %w", err) + } + + rows := make([]api.MeasurementSchemaColumn, 0, len(cols)) + for i := range cols { + c := &cols[i] + rows = append(rows, api.MeasurementSchemaColumn{ + Name: c.Name, + Type: c.Type, + DataType: c.DataType, + }) + } + return rows, nil +} diff --git a/internal/cmd/bucket_schema/csv_test.go b/internal/cmd/bucket_schema/csv_test.go new file mode 100644 index 0000000..ac6a1c3 --- /dev/null +++ b/internal/cmd/bucket_schema/csv_test.go @@ -0,0 +1,85 @@ +package bucket_schema + +import ( + "strings" + "testing" + + "github.com/MakeNowJust/heredoc/v2" + "github.com/influxdata/influx-cli/v2/internal/api" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" +) + +func TestDecodeCSV(t *testing.T) { + tests := []struct { + name string + data string + exp []api.MeasurementSchemaColumn + expErr string + }{ + { + name: "valid", + data: heredoc.Doc(` + name,type,data_type + time,timestamp, + host,tag, + usage_user,field,float + `), + exp: cols(colTs(), colT("host"), colFF("usage_user")), + }, + { + name: "valid with alternate order", + data: heredoc.Doc(` + type,data_type,name + timestamp,,time + tag,,host + field,float,usage_user + `), + exp: cols(colTs(), colT("host"), colFF("usage_user")), + }, + { + name: "invalid column type", + data: heredoc.Doc(` + name,type,data_type + time,foo, + `), + expErr: `failed to decode CSV: record on line 0; parse error on line 2, column 2: "foo" is not a valid column type. Valid values are [timestamp, tag, field]`, + }, + { + name: "invalid column data type", + data: heredoc.Doc(` + name,type,data_type + time,field,floaty + `), + expErr: `failed to decode CSV: record on line 0; parse error on line 2, column 3: "floaty" is not a valid column data type. Valid values are [integer, float, boolean, string, unsigned]`, + }, + { + name: "invalid headers", + data: heredoc.Doc(` + name,foo + time,field + `), + expErr: `failed to decode CSV: found unmatched struct field with tags [type data_type]`, + }, + { + name: "invalid CSV", + data: heredoc.Doc(` + type,type,data_type + time,timestamp + `), + expErr: `failed to decode CSV: record on line 2: wrong number of fields`, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + r := strings.NewReader(tt.data) + got, err := decodeCSV(r) + if tt.expErr != "" { + assert.EqualError(t, err, tt.expErr) + } else { + require.NoError(t, err) + assert.Equal(t, tt.exp, got) + } + }) + } +} diff --git a/internal/cmd/bucket_schema/format.go b/internal/cmd/bucket_schema/format.go new file mode 100644 index 0000000..fcce266 --- /dev/null +++ b/internal/cmd/bucket_schema/format.go @@ -0,0 +1,86 @@ +package bucket_schema + +import ( + "fmt" + "io" + "path/filepath" + "strconv" + "strings" + + "github.com/influxdata/influx-cli/v2/internal/api" +) + +// ColumnsFormat is a type which defines the supported formats +// +type ColumnsFormat int + +const ( + ColumnsFormatAuto ColumnsFormat = iota + ColumnsFormatCSV + ColumnsFormatNDJson + ColumnsFormatJson +) + +func (f *ColumnsFormat) Set(v string) error { + switch v { + case "auto": + *f = ColumnsFormatAuto + case "csv": + *f = ColumnsFormatCSV + case "ndjson": + *f = ColumnsFormatNDJson + case "json": + *f = ColumnsFormatJson + default: + return fmt.Errorf("invalid columns-format: %s, expected [csv, ndjson, json, auto]", v) + } + return nil +} + +func (f ColumnsFormat) String() string { + switch f { + case ColumnsFormatAuto: + return "auto" + case ColumnsFormatCSV: + return "csv" + case ColumnsFormatNDJson: + return "ndjson" + case ColumnsFormatJson: + return "json" + default: + return "schema.Format(" + strconv.FormatInt(int64(f), 10) + ")" + } +} + +// DecoderFn uses f and path to return a function capable of decoding +// measurement schema columns from a given io.Reader. If no combination +// of decoder exists for f and path, DecoderFn returns an error. +func (f ColumnsFormat) DecoderFn(path string) (ColumnsDecoderFn, error) { + ff := f + if ff == ColumnsFormatAuto { + ext := filepath.Ext(path) + switch { + case strings.EqualFold(ext, ".csv"): + ff = ColumnsFormatCSV + case strings.EqualFold(ext, ".json"): + ff = ColumnsFormatJson + case strings.EqualFold(ext, ".ndjson") || strings.EqualFold(ext, ".jsonl"): + ff = ColumnsFormatNDJson + } + } + + switch ff { + case ColumnsFormatCSV: + return decodeCSV, nil + case ColumnsFormatNDJson: + return decodeNDJson, nil + case ColumnsFormatJson: + return decodeJson, nil + } + + return nil, fmt.Errorf("unable to guess format for file %q", path) +} + +// ColumnsDecoderFn is a function which decodes a slice of api.MeasurementSchemaColumn +// elements from r. +type ColumnsDecoderFn func(r io.Reader) ([]api.MeasurementSchemaColumn, error) diff --git a/internal/cmd/bucket_schema/json.go b/internal/cmd/bucket_schema/json.go new file mode 100644 index 0000000..2e879a5 --- /dev/null +++ b/internal/cmd/bucket_schema/json.go @@ -0,0 +1,17 @@ +package bucket_schema + +import ( + "encoding/json" + "fmt" + "io" + + "github.com/influxdata/influx-cli/v2/internal/api" +) + +func decodeJson(r io.Reader) ([]api.MeasurementSchemaColumn, error) { + var rows []api.MeasurementSchemaColumn + if err := json.NewDecoder(r).Decode(&rows); err != nil { + return nil, fmt.Errorf("error decoding JSON: %w", err) + } + return rows, nil +} diff --git a/internal/cmd/bucket_schema/json_test.go b/internal/cmd/bucket_schema/json_test.go new file mode 100644 index 0000000..ed31fc0 --- /dev/null +++ b/internal/cmd/bucket_schema/json_test.go @@ -0,0 +1,70 @@ +package bucket_schema + +import ( + "strings" + "testing" + + "github.com/MakeNowJust/heredoc/v2" + "github.com/influxdata/influx-cli/v2/internal/api" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" +) + +func TestDecodeJson(t *testing.T) { + tests := []struct { + name string + data string + exp []api.MeasurementSchemaColumn + expErr string + }{ + { + name: "valid", + data: heredoc.Doc(` + [ + { "name": "time", "type": "timestamp" }, + { "name": "host", "type": "tag" }, + { "name": "usage_user", "type": "field", "dataType": "float" } + ] + `), + exp: cols(colTs(), colT("host"), colFF("usage_user")), + }, + { + name: "invalid column type", + data: heredoc.Doc(` + [ + { "name": "time", "type": "foo" } + ] + `), + expErr: `error decoding JSON: foo is not a valid ColumnSemanticType`, + }, + { + name: "invalid column data type", + data: heredoc.Doc(` + [ + { "name": "time", "type": "field", "dataType": "floaty" } + ] + `), + expErr: `error decoding JSON: floaty is not a valid ColumnDataType`, + }, + { + name: "invalid JSON", + data: heredoc.Doc(` + [ + { "name": "time", "type": "field", "dataType": "floaty" } + `), + expErr: `error decoding JSON: unexpected EOF`, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + r := strings.NewReader(tt.data) + got, err := decodeJson(r) + if tt.expErr != "" { + assert.EqualError(t, err, tt.expErr) + } else { + require.NoError(t, err) + assert.Equal(t, tt.exp, got) + } + }) + } +} diff --git a/internal/cmd/bucket_schema/nsjson.go b/internal/cmd/bucket_schema/nsjson.go new file mode 100644 index 0000000..bf00be5 --- /dev/null +++ b/internal/cmd/bucket_schema/nsjson.go @@ -0,0 +1,28 @@ +package bucket_schema + +import ( + "bufio" + "bytes" + "encoding/json" + "fmt" + "io" + + "github.com/influxdata/influx-cli/v2/internal/api" +) + +func decodeNDJson(r io.Reader) ([]api.MeasurementSchemaColumn, error) { + scan := bufio.NewScanner(r) + var rows []api.MeasurementSchemaColumn + n := 1 + for scan.Scan() { + if line := bytes.TrimSpace(scan.Bytes()); len(line) > 0 { + var row api.MeasurementSchemaColumn + if err := json.Unmarshal(line, &row); err != nil { + return nil, fmt.Errorf("error decoding JSON at line %d: %w", n, err) + } + rows = append(rows, row) + } + n++ + } + return rows, nil +} diff --git a/internal/cmd/bucket_schema/nsjson_test.go b/internal/cmd/bucket_schema/nsjson_test.go new file mode 100644 index 0000000..c31ba9b --- /dev/null +++ b/internal/cmd/bucket_schema/nsjson_test.go @@ -0,0 +1,78 @@ +package bucket_schema + +import ( + "strings" + "testing" + + "github.com/MakeNowJust/heredoc/v2" + "github.com/influxdata/influx-cli/v2/internal/api" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" +) + +func colTs() api.MeasurementSchemaColumn { + return api.MeasurementSchemaColumn{Name: "time", Type: api.COLUMNSEMANTICTYPE_TIMESTAMP} +} + +func colT(n string) api.MeasurementSchemaColumn { + return api.MeasurementSchemaColumn{Name: n, Type: api.COLUMNSEMANTICTYPE_TAG} +} + +func colFF(n string) api.MeasurementSchemaColumn { + return api.MeasurementSchemaColumn{Name: n, Type: api.COLUMNSEMANTICTYPE_FIELD, DataType: api.COLUMNDATATYPE_FLOAT.Ptr()} +} + +func cols(c ...api.MeasurementSchemaColumn) []api.MeasurementSchemaColumn { return c } + +func TestDecodeNDJson(t *testing.T) { + tests := []struct { + name string + data string + exp []api.MeasurementSchemaColumn + expErr string + }{ + { + name: "valid", + data: heredoc.Doc(` + { "name": "time", "type": "timestamp" } + { "name": "host", "type": "tag" } + { "name": "usage_user", "type": "field", "dataType": "float" } + `), + exp: cols(colTs(), colT("host"), colFF("usage_user")), + }, + { + name: "invalid column type", + data: heredoc.Doc(` + { "name": "time", "type": "foo" } + `), + expErr: `error decoding JSON at line 1: foo is not a valid ColumnSemanticType`, + }, + { + name: "invalid column data type", + data: heredoc.Doc(` + { "name": "time", "type": "field", "dataType": "floaty" } + `), + expErr: `error decoding JSON at line 1: floaty is not a valid ColumnDataType`, + }, + { + name: "invalid JSON", + data: heredoc.Doc(` + { "name": "usage_user", "type": "field", "dataType": "float" } + { "name": "time", "type": "field", "dataType": "float" + `), + expErr: `error decoding JSON at line 2: unexpected end of JSON input`, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + r := strings.NewReader(tt.data) + got, err := decodeNDJson(r) + if tt.expErr != "" { + assert.EqualError(t, err, tt.expErr) + } else { + require.NoError(t, err) + assert.Equal(t, tt.exp, got) + } + }) + } +} diff --git a/internal/cmd/bucket_schema/testdata/columns.csv b/internal/cmd/bucket_schema/testdata/columns.csv new file mode 100644 index 0000000..23b21c3 --- /dev/null +++ b/internal/cmd/bucket_schema/testdata/columns.csv @@ -0,0 +1,4 @@ +name,type,data_type +time,timestamp, +host,tag, +usage_user,field,float \ No newline at end of file diff --git a/internal/cmd/bucket_schema/testdata/columns.json b/internal/cmd/bucket_schema/testdata/columns.json new file mode 100644 index 0000000..99117b2 --- /dev/null +++ b/internal/cmd/bucket_schema/testdata/columns.json @@ -0,0 +1,5 @@ +[ + { "name": "time", "type": "timestamp" }, + { "name": "host", "type": "tag" }, + { "name": "usage_user", "type": "field", "dataType": "float" } +] \ No newline at end of file diff --git a/internal/cmd/bucket_schema/testdata/columns.ndjson b/internal/cmd/bucket_schema/testdata/columns.ndjson new file mode 100644 index 0000000..476152e --- /dev/null +++ b/internal/cmd/bucket_schema/testdata/columns.ndjson @@ -0,0 +1,3 @@ +{ "name": "time", "type": "timestamp" } +{ "name": "host", "type": "tag" } +{ "name": "usage_user", "type": "field", "dataType": "float" } \ No newline at end of file diff --git a/internal/mock/api_bucket_schemas.gen.go b/internal/mock/api_bucket_schemas.gen.go new file mode 100644 index 0000000..c360888 --- /dev/null +++ b/internal/mock/api_bucket_schemas.gen.go @@ -0,0 +1,157 @@ +// Code generated by MockGen. DO NOT EDIT. +// Source: github.com/influxdata/influx-cli/v2/internal/api (interfaces: BucketSchemasApi) + +// Package mock is a generated GoMock package. +package mock + +import ( + context "context" + http "net/http" + reflect "reflect" + + gomock "github.com/golang/mock/gomock" + api "github.com/influxdata/influx-cli/v2/internal/api" +) + +// MockBucketSchemasApi is a mock of BucketSchemasApi interface. +type MockBucketSchemasApi struct { + ctrl *gomock.Controller + recorder *MockBucketSchemasApiMockRecorder +} + +// MockBucketSchemasApiMockRecorder is the mock recorder for MockBucketSchemasApi. +type MockBucketSchemasApiMockRecorder struct { + mock *MockBucketSchemasApi +} + +// NewMockBucketSchemasApi creates a new mock instance. +func NewMockBucketSchemasApi(ctrl *gomock.Controller) *MockBucketSchemasApi { + mock := &MockBucketSchemasApi{ctrl: ctrl} + mock.recorder = &MockBucketSchemasApiMockRecorder{mock} + return mock +} + +// EXPECT returns an object that allows the caller to indicate expected use. +func (m *MockBucketSchemasApi) EXPECT() *MockBucketSchemasApiMockRecorder { + return m.recorder +} + +// CreateMeasurementSchema mocks base method. +func (m *MockBucketSchemasApi) CreateMeasurementSchema(arg0 context.Context, arg1 string) api.ApiCreateMeasurementSchemaRequest { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "CreateMeasurementSchema", arg0, arg1) + ret0, _ := ret[0].(api.ApiCreateMeasurementSchemaRequest) + return ret0 +} + +// CreateMeasurementSchema indicates an expected call of CreateMeasurementSchema. +func (mr *MockBucketSchemasApiMockRecorder) CreateMeasurementSchema(arg0, arg1 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "CreateMeasurementSchema", reflect.TypeOf((*MockBucketSchemasApi)(nil).CreateMeasurementSchema), arg0, arg1) +} + +// CreateMeasurementSchemaExecute mocks base method. +func (m *MockBucketSchemasApi) CreateMeasurementSchemaExecute(arg0 api.ApiCreateMeasurementSchemaRequest) (api.MeasurementSchema, *http.Response, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "CreateMeasurementSchemaExecute", arg0) + ret0, _ := ret[0].(api.MeasurementSchema) + ret1, _ := ret[1].(*http.Response) + ret2, _ := ret[2].(error) + return ret0, ret1, ret2 +} + +// CreateMeasurementSchemaExecute indicates an expected call of CreateMeasurementSchemaExecute. +func (mr *MockBucketSchemasApiMockRecorder) CreateMeasurementSchemaExecute(arg0 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "CreateMeasurementSchemaExecute", reflect.TypeOf((*MockBucketSchemasApi)(nil).CreateMeasurementSchemaExecute), arg0) +} + +// GetMeasurementSchema mocks base method. +func (m *MockBucketSchemasApi) GetMeasurementSchema(arg0 context.Context, arg1, arg2 string) api.ApiGetMeasurementSchemaRequest { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "GetMeasurementSchema", arg0, arg1, arg2) + ret0, _ := ret[0].(api.ApiGetMeasurementSchemaRequest) + return ret0 +} + +// GetMeasurementSchema indicates an expected call of GetMeasurementSchema. +func (mr *MockBucketSchemasApiMockRecorder) GetMeasurementSchema(arg0, arg1, arg2 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetMeasurementSchema", reflect.TypeOf((*MockBucketSchemasApi)(nil).GetMeasurementSchema), arg0, arg1, arg2) +} + +// GetMeasurementSchemaExecute mocks base method. +func (m *MockBucketSchemasApi) GetMeasurementSchemaExecute(arg0 api.ApiGetMeasurementSchemaRequest) (api.MeasurementSchema, *http.Response, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "GetMeasurementSchemaExecute", arg0) + ret0, _ := ret[0].(api.MeasurementSchema) + ret1, _ := ret[1].(*http.Response) + ret2, _ := ret[2].(error) + return ret0, ret1, ret2 +} + +// GetMeasurementSchemaExecute indicates an expected call of GetMeasurementSchemaExecute. +func (mr *MockBucketSchemasApiMockRecorder) GetMeasurementSchemaExecute(arg0 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetMeasurementSchemaExecute", reflect.TypeOf((*MockBucketSchemasApi)(nil).GetMeasurementSchemaExecute), arg0) +} + +// GetMeasurementSchemas mocks base method. +func (m *MockBucketSchemasApi) GetMeasurementSchemas(arg0 context.Context, arg1 string) api.ApiGetMeasurementSchemasRequest { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "GetMeasurementSchemas", arg0, arg1) + ret0, _ := ret[0].(api.ApiGetMeasurementSchemasRequest) + return ret0 +} + +// GetMeasurementSchemas indicates an expected call of GetMeasurementSchemas. +func (mr *MockBucketSchemasApiMockRecorder) GetMeasurementSchemas(arg0, arg1 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetMeasurementSchemas", reflect.TypeOf((*MockBucketSchemasApi)(nil).GetMeasurementSchemas), arg0, arg1) +} + +// GetMeasurementSchemasExecute mocks base method. +func (m *MockBucketSchemasApi) GetMeasurementSchemasExecute(arg0 api.ApiGetMeasurementSchemasRequest) (api.MeasurementSchemaList, *http.Response, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "GetMeasurementSchemasExecute", arg0) + ret0, _ := ret[0].(api.MeasurementSchemaList) + ret1, _ := ret[1].(*http.Response) + ret2, _ := ret[2].(error) + return ret0, ret1, ret2 +} + +// GetMeasurementSchemasExecute indicates an expected call of GetMeasurementSchemasExecute. +func (mr *MockBucketSchemasApiMockRecorder) GetMeasurementSchemasExecute(arg0 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetMeasurementSchemasExecute", reflect.TypeOf((*MockBucketSchemasApi)(nil).GetMeasurementSchemasExecute), arg0) +} + +// UpdateMeasurementSchema mocks base method. +func (m *MockBucketSchemasApi) UpdateMeasurementSchema(arg0 context.Context, arg1, arg2 string) api.ApiUpdateMeasurementSchemaRequest { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "UpdateMeasurementSchema", arg0, arg1, arg2) + ret0, _ := ret[0].(api.ApiUpdateMeasurementSchemaRequest) + return ret0 +} + +// UpdateMeasurementSchema indicates an expected call of UpdateMeasurementSchema. +func (mr *MockBucketSchemasApiMockRecorder) UpdateMeasurementSchema(arg0, arg1, arg2 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "UpdateMeasurementSchema", reflect.TypeOf((*MockBucketSchemasApi)(nil).UpdateMeasurementSchema), arg0, arg1, arg2) +} + +// UpdateMeasurementSchemaExecute mocks base method. +func (m *MockBucketSchemasApi) UpdateMeasurementSchemaExecute(arg0 api.ApiUpdateMeasurementSchemaRequest) (api.MeasurementSchema, *http.Response, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "UpdateMeasurementSchemaExecute", arg0) + ret0, _ := ret[0].(api.MeasurementSchema) + ret1, _ := ret[1].(*http.Response) + ret2, _ := ret[2].(error) + return ret0, ret1, ret2 +} + +// UpdateMeasurementSchemaExecute indicates an expected call of UpdateMeasurementSchemaExecute. +func (mr *MockBucketSchemasApiMockRecorder) UpdateMeasurementSchemaExecute(arg0 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "UpdateMeasurementSchemaExecute", reflect.TypeOf((*MockBucketSchemasApi)(nil).UpdateMeasurementSchemaExecute), arg0) +} diff --git a/internal/mock/api_buckets.gen.go b/internal/mock/api_buckets.gen.go new file mode 100644 index 0000000..b981fce --- /dev/null +++ b/internal/mock/api_buckets.gen.go @@ -0,0 +1,186 @@ +// Code generated by MockGen. DO NOT EDIT. +// Source: github.com/influxdata/influx-cli/v2/internal/api (interfaces: BucketsApi) + +// Package mock is a generated GoMock package. +package mock + +import ( + context "context" + http "net/http" + reflect "reflect" + + gomock "github.com/golang/mock/gomock" + api "github.com/influxdata/influx-cli/v2/internal/api" +) + +// MockBucketsApi is a mock of BucketsApi interface. +type MockBucketsApi struct { + ctrl *gomock.Controller + recorder *MockBucketsApiMockRecorder +} + +// MockBucketsApiMockRecorder is the mock recorder for MockBucketsApi. +type MockBucketsApiMockRecorder struct { + mock *MockBucketsApi +} + +// NewMockBucketsApi creates a new mock instance. +func NewMockBucketsApi(ctrl *gomock.Controller) *MockBucketsApi { + mock := &MockBucketsApi{ctrl: ctrl} + mock.recorder = &MockBucketsApiMockRecorder{mock} + return mock +} + +// EXPECT returns an object that allows the caller to indicate expected use. +func (m *MockBucketsApi) EXPECT() *MockBucketsApiMockRecorder { + return m.recorder +} + +// DeleteBucketsID mocks base method. +func (m *MockBucketsApi) DeleteBucketsID(arg0 context.Context, arg1 string) api.ApiDeleteBucketsIDRequest { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "DeleteBucketsID", arg0, arg1) + ret0, _ := ret[0].(api.ApiDeleteBucketsIDRequest) + return ret0 +} + +// DeleteBucketsID indicates an expected call of DeleteBucketsID. +func (mr *MockBucketsApiMockRecorder) DeleteBucketsID(arg0, arg1 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "DeleteBucketsID", reflect.TypeOf((*MockBucketsApi)(nil).DeleteBucketsID), arg0, arg1) +} + +// DeleteBucketsIDExecute mocks base method. +func (m *MockBucketsApi) DeleteBucketsIDExecute(arg0 api.ApiDeleteBucketsIDRequest) (*http.Response, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "DeleteBucketsIDExecute", arg0) + ret0, _ := ret[0].(*http.Response) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// DeleteBucketsIDExecute indicates an expected call of DeleteBucketsIDExecute. +func (mr *MockBucketsApiMockRecorder) DeleteBucketsIDExecute(arg0 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "DeleteBucketsIDExecute", reflect.TypeOf((*MockBucketsApi)(nil).DeleteBucketsIDExecute), arg0) +} + +// GetBuckets mocks base method. +func (m *MockBucketsApi) GetBuckets(arg0 context.Context) api.ApiGetBucketsRequest { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "GetBuckets", arg0) + ret0, _ := ret[0].(api.ApiGetBucketsRequest) + return ret0 +} + +// GetBuckets indicates an expected call of GetBuckets. +func (mr *MockBucketsApiMockRecorder) GetBuckets(arg0 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetBuckets", reflect.TypeOf((*MockBucketsApi)(nil).GetBuckets), arg0) +} + +// GetBucketsExecute mocks base method. +func (m *MockBucketsApi) GetBucketsExecute(arg0 api.ApiGetBucketsRequest) (api.Buckets, *http.Response, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "GetBucketsExecute", arg0) + ret0, _ := ret[0].(api.Buckets) + ret1, _ := ret[1].(*http.Response) + ret2, _ := ret[2].(error) + return ret0, ret1, ret2 +} + +// GetBucketsExecute indicates an expected call of GetBucketsExecute. +func (mr *MockBucketsApiMockRecorder) GetBucketsExecute(arg0 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetBucketsExecute", reflect.TypeOf((*MockBucketsApi)(nil).GetBucketsExecute), arg0) +} + +// GetBucketsID mocks base method. +func (m *MockBucketsApi) GetBucketsID(arg0 context.Context, arg1 string) api.ApiGetBucketsIDRequest { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "GetBucketsID", arg0, arg1) + ret0, _ := ret[0].(api.ApiGetBucketsIDRequest) + return ret0 +} + +// GetBucketsID indicates an expected call of GetBucketsID. +func (mr *MockBucketsApiMockRecorder) GetBucketsID(arg0, arg1 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetBucketsID", reflect.TypeOf((*MockBucketsApi)(nil).GetBucketsID), arg0, arg1) +} + +// GetBucketsIDExecute mocks base method. +func (m *MockBucketsApi) GetBucketsIDExecute(arg0 api.ApiGetBucketsIDRequest) (api.Bucket, *http.Response, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "GetBucketsIDExecute", arg0) + ret0, _ := ret[0].(api.Bucket) + ret1, _ := ret[1].(*http.Response) + ret2, _ := ret[2].(error) + return ret0, ret1, ret2 +} + +// GetBucketsIDExecute indicates an expected call of GetBucketsIDExecute. +func (mr *MockBucketsApiMockRecorder) GetBucketsIDExecute(arg0 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetBucketsIDExecute", reflect.TypeOf((*MockBucketsApi)(nil).GetBucketsIDExecute), arg0) +} + +// PatchBucketsID mocks base method. +func (m *MockBucketsApi) PatchBucketsID(arg0 context.Context, arg1 string) api.ApiPatchBucketsIDRequest { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "PatchBucketsID", arg0, arg1) + ret0, _ := ret[0].(api.ApiPatchBucketsIDRequest) + return ret0 +} + +// PatchBucketsID indicates an expected call of PatchBucketsID. +func (mr *MockBucketsApiMockRecorder) PatchBucketsID(arg0, arg1 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "PatchBucketsID", reflect.TypeOf((*MockBucketsApi)(nil).PatchBucketsID), arg0, arg1) +} + +// PatchBucketsIDExecute mocks base method. +func (m *MockBucketsApi) PatchBucketsIDExecute(arg0 api.ApiPatchBucketsIDRequest) (api.Bucket, *http.Response, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "PatchBucketsIDExecute", arg0) + ret0, _ := ret[0].(api.Bucket) + ret1, _ := ret[1].(*http.Response) + ret2, _ := ret[2].(error) + return ret0, ret1, ret2 +} + +// PatchBucketsIDExecute indicates an expected call of PatchBucketsIDExecute. +func (mr *MockBucketsApiMockRecorder) PatchBucketsIDExecute(arg0 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "PatchBucketsIDExecute", reflect.TypeOf((*MockBucketsApi)(nil).PatchBucketsIDExecute), arg0) +} + +// PostBuckets mocks base method. +func (m *MockBucketsApi) PostBuckets(arg0 context.Context) api.ApiPostBucketsRequest { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "PostBuckets", arg0) + ret0, _ := ret[0].(api.ApiPostBucketsRequest) + return ret0 +} + +// PostBuckets indicates an expected call of PostBuckets. +func (mr *MockBucketsApiMockRecorder) PostBuckets(arg0 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "PostBuckets", reflect.TypeOf((*MockBucketsApi)(nil).PostBuckets), arg0) +} + +// PostBucketsExecute mocks base method. +func (m *MockBucketsApi) PostBucketsExecute(arg0 api.ApiPostBucketsRequest) (api.Bucket, *http.Response, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "PostBucketsExecute", arg0) + ret0, _ := ret[0].(api.Bucket) + ret1, _ := ret[1].(*http.Response) + ret2, _ := ret[2].(error) + return ret0, ret1, ret2 +} + +// PostBucketsExecute indicates an expected call of PostBucketsExecute. +func (mr *MockBucketsApiMockRecorder) PostBucketsExecute(arg0 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "PostBucketsExecute", reflect.TypeOf((*MockBucketsApi)(nil).PostBucketsExecute), arg0) +} diff --git a/internal/mock/gen.go b/internal/mock/gen.go new file mode 100644 index 0000000..63d0716 --- /dev/null +++ b/internal/mock/gen.go @@ -0,0 +1,4 @@ +package mock + +//go:generate mockgen -package mock -destination api_bucket_schemas.gen.go github.com/influxdata/influx-cli/v2/internal/api BucketSchemasApi +//go:generate mockgen -package mock -destination api_buckets.gen.go github.com/influxdata/influx-cli/v2/internal/api BucketsApi diff --git a/internal/params.go b/internal/params.go new file mode 100644 index 0000000..81f0440 --- /dev/null +++ b/internal/params.go @@ -0,0 +1,20 @@ +package internal + +import ( + "github.com/influxdata/influx-cli/v2/pkg/influxid" +) + +type OrgParams struct { + OrgID influxid.ID + OrgName string +} + +type BucketParams struct { + BucketID influxid.ID + BucketName string +} + +type OrgBucketParams struct { + OrgParams + BucketParams +}