feat: port delete
from influxdb
(#98)
This commit is contained in:
parent
d8ef442b64
commit
e4af676ae5
3
.gitignore
vendored
3
.gitignore
vendored
@ -15,5 +15,6 @@ bin/
|
||||
# Dependency directories
|
||||
vendor/
|
||||
|
||||
# Docs copied from our openapi repo
|
||||
# Docs generated from our openapi repo
|
||||
internal/api/cli.yml
|
||||
internal/api/cli.gen.yml
|
||||
|
69
cmd/influx/delete.go
Normal file
69
cmd/influx/delete.go
Normal file
@ -0,0 +1,69 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"github.com/influxdata/influx-cli/v2/internal/cmd/delete"
|
||||
"github.com/influxdata/influx-cli/v2/pkg/cli/middleware"
|
||||
"github.com/urfave/cli/v2"
|
||||
)
|
||||
|
||||
func newDeleteCmd() *cli.Command {
|
||||
var params delete.Params
|
||||
return &cli.Command{
|
||||
Name: "delete",
|
||||
Usage: "Delete points from InfluxDB",
|
||||
Description: "Delete points from InfluxDB, by specify start, end time and a sql like predicate string",
|
||||
Flags: append(
|
||||
commonFlagsNoPrint(),
|
||||
&cli.GenericFlag{
|
||||
Name: "org-id",
|
||||
Usage: "The ID of the organization that owns the bucket",
|
||||
EnvVars: []string{"INFLUX_ORG_ID"},
|
||||
Value: ¶ms.OrgID,
|
||||
},
|
||||
&cli.StringFlag{
|
||||
Name: "org",
|
||||
Usage: "The name of the organization that owns the bucket",
|
||||
Aliases: []string{"o"},
|
||||
EnvVars: []string{"INFLUX_ORG"},
|
||||
Destination: ¶ms.OrgName,
|
||||
},
|
||||
&cli.GenericFlag{
|
||||
Name: "bucket-id",
|
||||
Usage: "The ID of the bucket to delete from",
|
||||
EnvVars: []string{"INFLUX_BUCKET_ID"},
|
||||
Value: ¶ms.BucketID,
|
||||
},
|
||||
&cli.StringFlag{
|
||||
Name: "bucket",
|
||||
Usage: "The name of the bucket to delete from",
|
||||
EnvVars: []string{"INFLUX_BUCKET_NAME"},
|
||||
Destination: ¶ms.BucketName,
|
||||
},
|
||||
// NOTE: cli has a Timestamp flag we could use to parse the strings immediately on input,
|
||||
// but the help-text generation is broken for it.
|
||||
&cli.StringFlag{
|
||||
Name: "start",
|
||||
Usage: "The start time in RFC3339Nano format (ex: '2009-01-02T23:00:00Z')",
|
||||
Required: true,
|
||||
Destination: ¶ms.Start,
|
||||
},
|
||||
&cli.StringFlag{
|
||||
Name: "stop",
|
||||
Usage: "The stop time in RFC3339Nano format (ex: '2009-01-02T23:00:00Z')",
|
||||
Required: true,
|
||||
Destination: ¶ms.Stop,
|
||||
},
|
||||
&cli.StringFlag{
|
||||
Name: "predicate",
|
||||
Usage: "sql like predicate string (ex: 'tag1=\"v1\" and (tag2=123)')",
|
||||
Aliases: []string{"p"},
|
||||
Destination: ¶ms.Predicate,
|
||||
},
|
||||
),
|
||||
Before: middleware.WithBeforeFns(withCli(), withApi(true)),
|
||||
Action: func(ctx *cli.Context) error {
|
||||
client := delete.Client{CLI: getCLI(ctx), DeleteApi: getAPI(ctx).DeleteApi}
|
||||
return client.Delete(ctx.Context, ¶ms)
|
||||
},
|
||||
}
|
||||
}
|
@ -41,6 +41,7 @@ var app = cli.App{
|
||||
newQueryCmd(),
|
||||
newConfigCmd(),
|
||||
newOrgCmd(),
|
||||
newDeleteCmd(),
|
||||
},
|
||||
}
|
||||
|
||||
|
@ -17,7 +17,7 @@ docker run --rm -it -u "$(id -u):$(id -g)" \
|
||||
-v "${API_DIR}":/api \
|
||||
${MERGE_DOCKER_IMG} \
|
||||
swagger-cli bundle /api/contract/cli.yml \
|
||||
--outfile /api/cli.yml \
|
||||
--outfile /api/cli.gen.yml \
|
||||
--type yaml
|
||||
|
||||
# Run the generator - This produces many more files than we want to track in git.
|
||||
@ -26,7 +26,7 @@ docker run --rm -it -u "$(id -u):$(id -g)" \
|
||||
${GENERATOR_DOCKER_IMG} \
|
||||
generate \
|
||||
-g go \
|
||||
-i /api/cli.yml \
|
||||
-i /api/cli.gen.yml \
|
||||
-o /api \
|
||||
-t /api/templates \
|
||||
--additional-properties packageName=api,enumClassPrefix=true,generateInterfaces=true
|
||||
|
267
internal/api/api_delete.gen.go
Normal file
267
internal/api/api_delete.gen.go
Normal file
@ -0,0 +1,267 @@
|
||||
/*
|
||||
* 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 (
|
||||
_gzip "compress/gzip"
|
||||
_context "context"
|
||||
_io "io"
|
||||
_ioutil "io/ioutil"
|
||||
_nethttp "net/http"
|
||||
_neturl "net/url"
|
||||
)
|
||||
|
||||
// Linger please
|
||||
var (
|
||||
_ _context.Context
|
||||
)
|
||||
|
||||
type DeleteApi interface {
|
||||
|
||||
/*
|
||||
* PostDelete Delete time series data from InfluxDB
|
||||
* @param ctx _context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background().
|
||||
* @return ApiPostDeleteRequest
|
||||
*/
|
||||
PostDelete(ctx _context.Context) ApiPostDeleteRequest
|
||||
|
||||
/*
|
||||
* PostDeleteExecute executes the request
|
||||
*/
|
||||
PostDeleteExecute(r ApiPostDeleteRequest) error
|
||||
}
|
||||
|
||||
// deleteApiGzipReadCloser supports streaming gzip response-bodies directly from the server.
|
||||
type deleteApiGzipReadCloser struct {
|
||||
underlying _io.ReadCloser
|
||||
gzip _io.ReadCloser
|
||||
}
|
||||
|
||||
func (gzrc *deleteApiGzipReadCloser) Read(p []byte) (int, error) {
|
||||
return gzrc.gzip.Read(p)
|
||||
}
|
||||
func (gzrc *deleteApiGzipReadCloser) Close() error {
|
||||
if err := gzrc.gzip.Close(); err != nil {
|
||||
return err
|
||||
}
|
||||
return gzrc.underlying.Close()
|
||||
}
|
||||
|
||||
// DeleteApiService DeleteApi service
|
||||
type DeleteApiService service
|
||||
|
||||
type ApiPostDeleteRequest struct {
|
||||
ctx _context.Context
|
||||
ApiService DeleteApi
|
||||
deletePredicateRequest *DeletePredicateRequest
|
||||
zapTraceSpan *string
|
||||
org *string
|
||||
bucket *string
|
||||
orgID *string
|
||||
bucketID *string
|
||||
}
|
||||
|
||||
func (r ApiPostDeleteRequest) DeletePredicateRequest(deletePredicateRequest DeletePredicateRequest) ApiPostDeleteRequest {
|
||||
r.deletePredicateRequest = &deletePredicateRequest
|
||||
return r
|
||||
}
|
||||
func (r ApiPostDeleteRequest) GetDeletePredicateRequest() *DeletePredicateRequest {
|
||||
return r.deletePredicateRequest
|
||||
}
|
||||
|
||||
func (r ApiPostDeleteRequest) ZapTraceSpan(zapTraceSpan string) ApiPostDeleteRequest {
|
||||
r.zapTraceSpan = &zapTraceSpan
|
||||
return r
|
||||
}
|
||||
func (r ApiPostDeleteRequest) GetZapTraceSpan() *string {
|
||||
return r.zapTraceSpan
|
||||
}
|
||||
|
||||
func (r ApiPostDeleteRequest) Org(org string) ApiPostDeleteRequest {
|
||||
r.org = &org
|
||||
return r
|
||||
}
|
||||
func (r ApiPostDeleteRequest) GetOrg() *string {
|
||||
return r.org
|
||||
}
|
||||
|
||||
func (r ApiPostDeleteRequest) Bucket(bucket string) ApiPostDeleteRequest {
|
||||
r.bucket = &bucket
|
||||
return r
|
||||
}
|
||||
func (r ApiPostDeleteRequest) GetBucket() *string {
|
||||
return r.bucket
|
||||
}
|
||||
|
||||
func (r ApiPostDeleteRequest) OrgID(orgID string) ApiPostDeleteRequest {
|
||||
r.orgID = &orgID
|
||||
return r
|
||||
}
|
||||
func (r ApiPostDeleteRequest) GetOrgID() *string {
|
||||
return r.orgID
|
||||
}
|
||||
|
||||
func (r ApiPostDeleteRequest) BucketID(bucketID string) ApiPostDeleteRequest {
|
||||
r.bucketID = &bucketID
|
||||
return r
|
||||
}
|
||||
func (r ApiPostDeleteRequest) GetBucketID() *string {
|
||||
return r.bucketID
|
||||
}
|
||||
|
||||
func (r ApiPostDeleteRequest) Execute() error {
|
||||
return r.ApiService.PostDeleteExecute(r)
|
||||
}
|
||||
|
||||
/*
|
||||
* PostDelete Delete time series data from InfluxDB
|
||||
* @param ctx _context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background().
|
||||
* @return ApiPostDeleteRequest
|
||||
*/
|
||||
func (a *DeleteApiService) PostDelete(ctx _context.Context) ApiPostDeleteRequest {
|
||||
return ApiPostDeleteRequest{
|
||||
ApiService: a,
|
||||
ctx: ctx,
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Execute executes the request
|
||||
*/
|
||||
func (a *DeleteApiService) PostDeleteExecute(r ApiPostDeleteRequest) error {
|
||||
var (
|
||||
localVarHTTPMethod = _nethttp.MethodPost
|
||||
localVarPostBody interface{}
|
||||
localVarFormFileName string
|
||||
localVarFileName string
|
||||
localVarFileBytes []byte
|
||||
)
|
||||
|
||||
localBasePath, err := a.client.cfg.ServerURLWithContext(r.ctx, "DeleteApiService.PostDelete")
|
||||
if err != nil {
|
||||
return GenericOpenAPIError{error: err.Error()}
|
||||
}
|
||||
|
||||
localVarPath := localBasePath + "/delete"
|
||||
|
||||
localVarHeaderParams := make(map[string]string)
|
||||
localVarQueryParams := _neturl.Values{}
|
||||
localVarFormParams := _neturl.Values{}
|
||||
if r.deletePredicateRequest == nil {
|
||||
return reportError("deletePredicateRequest is required and must be specified")
|
||||
}
|
||||
|
||||
if r.org != nil {
|
||||
localVarQueryParams.Add("org", parameterToString(*r.org, ""))
|
||||
}
|
||||
if r.bucket != nil {
|
||||
localVarQueryParams.Add("bucket", parameterToString(*r.bucket, ""))
|
||||
}
|
||||
if r.orgID != nil {
|
||||
localVarQueryParams.Add("orgID", parameterToString(*r.orgID, ""))
|
||||
}
|
||||
if r.bucketID != nil {
|
||||
localVarQueryParams.Add("bucketID", parameterToString(*r.bucketID, ""))
|
||||
}
|
||||
// to determine the Content-Type header
|
||||
localVarHTTPContentTypes := []string{"application/json"}
|
||||
|
||||
// set Content-Type header
|
||||
localVarHTTPContentType := selectHeaderContentType(localVarHTTPContentTypes)
|
||||
if localVarHTTPContentType != "" {
|
||||
localVarHeaderParams["Content-Type"] = localVarHTTPContentType
|
||||
}
|
||||
|
||||
// to determine the Accept header
|
||||
localVarHTTPHeaderAccepts := []string{"application/json"}
|
||||
|
||||
// set Accept header
|
||||
localVarHTTPHeaderAccept := selectHeaderAccept(localVarHTTPHeaderAccepts)
|
||||
if localVarHTTPHeaderAccept != "" {
|
||||
localVarHeaderParams["Accept"] = localVarHTTPHeaderAccept
|
||||
}
|
||||
if r.zapTraceSpan != nil {
|
||||
localVarHeaderParams["Zap-Trace-Span"] = parameterToString(*r.zapTraceSpan, "")
|
||||
}
|
||||
// body params
|
||||
localVarPostBody = r.deletePredicateRequest
|
||||
req, err := a.client.prepareRequest(r.ctx, localVarPath, localVarHTTPMethod, localVarPostBody, localVarHeaderParams, localVarQueryParams, localVarFormParams, localVarFormFileName, localVarFileName, localVarFileBytes)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
localVarHTTPResponse, err := a.client.callAPI(req)
|
||||
if err != nil || localVarHTTPResponse == nil {
|
||||
return err
|
||||
}
|
||||
|
||||
var body _io.ReadCloser = localVarHTTPResponse.Body
|
||||
if localVarHTTPResponse.Header.Get("Content-Encoding") == "gzip" {
|
||||
gzr, err := _gzip.NewReader(body)
|
||||
if err != nil {
|
||||
body.Close()
|
||||
return err
|
||||
}
|
||||
body = &deleteApiGzipReadCloser{underlying: body, gzip: gzr}
|
||||
}
|
||||
|
||||
if localVarHTTPResponse.StatusCode >= 300 {
|
||||
localVarBody, err := _ioutil.ReadAll(body)
|
||||
body.Close()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
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 newErr
|
||||
}
|
||||
newErr.model = &v
|
||||
return newErr
|
||||
}
|
||||
if localVarHTTPResponse.StatusCode == 403 {
|
||||
var v Error
|
||||
err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type"))
|
||||
if err != nil {
|
||||
newErr.error = err.Error()
|
||||
return newErr
|
||||
}
|
||||
newErr.model = &v
|
||||
return newErr
|
||||
}
|
||||
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 newErr
|
||||
}
|
||||
newErr.model = &v
|
||||
return newErr
|
||||
}
|
||||
var v Error
|
||||
err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type"))
|
||||
if err != nil {
|
||||
newErr.error = err.Error()
|
||||
return newErr
|
||||
}
|
||||
newErr.model = &v
|
||||
return newErr
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
@ -51,6 +51,8 @@ type APIClient struct {
|
||||
|
||||
BucketsApi BucketsApi
|
||||
|
||||
DeleteApi DeleteApi
|
||||
|
||||
HealthApi HealthApi
|
||||
|
||||
OrganizationsApi OrganizationsApi
|
||||
@ -82,6 +84,7 @@ func NewAPIClient(cfg *Configuration) *APIClient {
|
||||
// API Services
|
||||
c.BucketSchemasApi = (*BucketSchemasApiService)(&c.common)
|
||||
c.BucketsApi = (*BucketsApiService)(&c.common)
|
||||
c.DeleteApi = (*DeleteApiService)(&c.common)
|
||||
c.HealthApi = (*HealthApiService)(&c.common)
|
||||
c.OrganizationsApi = (*OrganizationsApiService)(&c.common)
|
||||
c.QueryApi = (*QueryApiService)(&c.common)
|
||||
|
@ -33,6 +33,8 @@ paths:
|
||||
$ref: "./overrides/paths/query.yml"
|
||||
/users/{userID}:
|
||||
$ref: "./openapi/src/common/paths/users_userID.yml"
|
||||
/delete:
|
||||
$ref: "./openapi/src/common/paths/delete.yml"
|
||||
components:
|
||||
parameters:
|
||||
TraceSpan:
|
||||
@ -45,6 +47,9 @@ components:
|
||||
$ref: "./openapi/src/common/parameters/After.yml"
|
||||
Descending:
|
||||
$ref: "./openapi/src/common/parameters/Descending.yml"
|
||||
responses:
|
||||
ServerError:
|
||||
$ref: "./openapi/src/common/responses/ServerError.yml"
|
||||
schemas:
|
||||
Error:
|
||||
$ref: "./openapi/src/common/schemas/Error.yml"
|
||||
@ -134,3 +139,5 @@ components:
|
||||
$ref: "./openapi/src/common/schemas/Dialect.yml"
|
||||
Extern:
|
||||
$ref: "./overrides/schemas/Extern.yml"
|
||||
DeletePredicateRequest:
|
||||
$ref: "./openapi/src/common/schemas/DeletePredicateRequest.yml"
|
||||
|
@ -1 +1 @@
|
||||
Subproject commit ea92cf2265f9bfa7d9f70a50c4bade78a263e0e7
|
||||
Subproject commit 3574e1bce691016496bd0d433a15e97aa255ccb5
|
175
internal/api/model_delete_predicate_request.gen.go
Normal file
175
internal/api/model_delete_predicate_request.gen.go
Normal file
@ -0,0 +1,175 @@
|
||||
/*
|
||||
* 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"
|
||||
)
|
||||
|
||||
// DeletePredicateRequest The delete predicate request.
|
||||
type DeletePredicateRequest struct {
|
||||
// RFC3339Nano
|
||||
Start time.Time `json:"start"`
|
||||
// RFC3339Nano
|
||||
Stop time.Time `json:"stop"`
|
||||
// InfluxQL-like delete statement
|
||||
Predicate *string `json:"predicate,omitempty"`
|
||||
}
|
||||
|
||||
// NewDeletePredicateRequest instantiates a new DeletePredicateRequest 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 NewDeletePredicateRequest(start time.Time, stop time.Time) *DeletePredicateRequest {
|
||||
this := DeletePredicateRequest{}
|
||||
this.Start = start
|
||||
this.Stop = stop
|
||||
return &this
|
||||
}
|
||||
|
||||
// NewDeletePredicateRequestWithDefaults instantiates a new DeletePredicateRequest 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 NewDeletePredicateRequestWithDefaults() *DeletePredicateRequest {
|
||||
this := DeletePredicateRequest{}
|
||||
return &this
|
||||
}
|
||||
|
||||
// GetStart returns the Start field value
|
||||
func (o *DeletePredicateRequest) GetStart() time.Time {
|
||||
if o == nil {
|
||||
var ret time.Time
|
||||
return ret
|
||||
}
|
||||
|
||||
return o.Start
|
||||
}
|
||||
|
||||
// GetStartOk returns a tuple with the Start field value
|
||||
// and a boolean to check if the value has been set.
|
||||
func (o *DeletePredicateRequest) GetStartOk() (*time.Time, bool) {
|
||||
if o == nil {
|
||||
return nil, false
|
||||
}
|
||||
return &o.Start, true
|
||||
}
|
||||
|
||||
// SetStart sets field value
|
||||
func (o *DeletePredicateRequest) SetStart(v time.Time) {
|
||||
o.Start = v
|
||||
}
|
||||
|
||||
// GetStop returns the Stop field value
|
||||
func (o *DeletePredicateRequest) GetStop() time.Time {
|
||||
if o == nil {
|
||||
var ret time.Time
|
||||
return ret
|
||||
}
|
||||
|
||||
return o.Stop
|
||||
}
|
||||
|
||||
// GetStopOk returns a tuple with the Stop field value
|
||||
// and a boolean to check if the value has been set.
|
||||
func (o *DeletePredicateRequest) GetStopOk() (*time.Time, bool) {
|
||||
if o == nil {
|
||||
return nil, false
|
||||
}
|
||||
return &o.Stop, true
|
||||
}
|
||||
|
||||
// SetStop sets field value
|
||||
func (o *DeletePredicateRequest) SetStop(v time.Time) {
|
||||
o.Stop = v
|
||||
}
|
||||
|
||||
// GetPredicate returns the Predicate field value if set, zero value otherwise.
|
||||
func (o *DeletePredicateRequest) GetPredicate() string {
|
||||
if o == nil || o.Predicate == nil {
|
||||
var ret string
|
||||
return ret
|
||||
}
|
||||
return *o.Predicate
|
||||
}
|
||||
|
||||
// GetPredicateOk returns a tuple with the Predicate field value if set, nil otherwise
|
||||
// and a boolean to check if the value has been set.
|
||||
func (o *DeletePredicateRequest) GetPredicateOk() (*string, bool) {
|
||||
if o == nil || o.Predicate == nil {
|
||||
return nil, false
|
||||
}
|
||||
return o.Predicate, true
|
||||
}
|
||||
|
||||
// HasPredicate returns a boolean if a field has been set.
|
||||
func (o *DeletePredicateRequest) HasPredicate() bool {
|
||||
if o != nil && o.Predicate != nil {
|
||||
return true
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
// SetPredicate gets a reference to the given string and assigns it to the Predicate field.
|
||||
func (o *DeletePredicateRequest) SetPredicate(v string) {
|
||||
o.Predicate = &v
|
||||
}
|
||||
|
||||
func (o DeletePredicateRequest) MarshalJSON() ([]byte, error) {
|
||||
toSerialize := map[string]interface{}{}
|
||||
if true {
|
||||
toSerialize["start"] = o.Start
|
||||
}
|
||||
if true {
|
||||
toSerialize["stop"] = o.Stop
|
||||
}
|
||||
if o.Predicate != nil {
|
||||
toSerialize["predicate"] = o.Predicate
|
||||
}
|
||||
return json.Marshal(toSerialize)
|
||||
}
|
||||
|
||||
type NullableDeletePredicateRequest struct {
|
||||
value *DeletePredicateRequest
|
||||
isSet bool
|
||||
}
|
||||
|
||||
func (v NullableDeletePredicateRequest) Get() *DeletePredicateRequest {
|
||||
return v.value
|
||||
}
|
||||
|
||||
func (v *NullableDeletePredicateRequest) Set(val *DeletePredicateRequest) {
|
||||
v.value = val
|
||||
v.isSet = true
|
||||
}
|
||||
|
||||
func (v NullableDeletePredicateRequest) IsSet() bool {
|
||||
return v.isSet
|
||||
}
|
||||
|
||||
func (v *NullableDeletePredicateRequest) Unset() {
|
||||
v.value = nil
|
||||
v.isSet = false
|
||||
}
|
||||
|
||||
func NewNullableDeletePredicateRequest(val *DeletePredicateRequest) *NullableDeletePredicateRequest {
|
||||
return &NullableDeletePredicateRequest{value: val, isSet: true}
|
||||
}
|
||||
|
||||
func (v NullableDeletePredicateRequest) MarshalJSON() ([]byte, error) {
|
||||
return json.Marshal(v.value)
|
||||
}
|
||||
|
||||
func (v *NullableDeletePredicateRequest) UnmarshalJSON(src []byte) error {
|
||||
v.isSet = true
|
||||
return json.Unmarshal(src, &v.value)
|
||||
}
|
69
internal/cmd/delete/delete.go
Normal file
69
internal/cmd/delete/delete.go
Normal file
@ -0,0 +1,69 @@
|
||||
package delete
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"github.com/influxdata/influx-cli/v2/internal/api"
|
||||
"github.com/influxdata/influx-cli/v2/internal/cmd"
|
||||
)
|
||||
|
||||
type Client struct {
|
||||
cmd.CLI
|
||||
api.DeleteApi
|
||||
}
|
||||
|
||||
type Params struct {
|
||||
cmd.OrgBucketParams
|
||||
Predicate string
|
||||
Start string
|
||||
Stop string
|
||||
}
|
||||
|
||||
var (
|
||||
ErrMustSpecifyOrg = errors.New("must specify org ID or org name")
|
||||
ErrMustSpecifyBucket = errors.New("must specify bucket ID or bucket name")
|
||||
)
|
||||
|
||||
func (c Client) Delete(ctx context.Context, params *Params) error {
|
||||
if !params.OrgID.Valid() && params.OrgName == "" && c.ActiveConfig.Org == "" {
|
||||
return ErrMustSpecifyOrg
|
||||
}
|
||||
if !params.BucketID.Valid() && params.BucketName == "" {
|
||||
return ErrMustSpecifyBucket
|
||||
}
|
||||
start, err := time.Parse(time.RFC3339Nano, params.Start)
|
||||
if err != nil {
|
||||
return fmt.Errorf("start time %q cannot be parsed as RFC3339Nano: %w", params.Start, err)
|
||||
}
|
||||
stop, err := time.Parse(time.RFC3339Nano, params.Stop)
|
||||
if err != nil {
|
||||
return fmt.Errorf("stop time %q cannot be parsed as RFC3339Nano: %w", params.Stop, err)
|
||||
}
|
||||
|
||||
reqBody := api.NewDeletePredicateRequest(start, stop)
|
||||
if params.Predicate != "" {
|
||||
reqBody.SetPredicate(params.Predicate)
|
||||
}
|
||||
|
||||
req := c.PostDelete(ctx).DeletePredicateRequest(*reqBody)
|
||||
if params.OrgID.Valid() {
|
||||
req = req.OrgID(params.OrgID.String())
|
||||
} else if params.OrgName != "" {
|
||||
req = req.Org(params.OrgName)
|
||||
} else {
|
||||
req = req.Org(c.ActiveConfig.Org)
|
||||
}
|
||||
if params.BucketID.Valid() {
|
||||
req = req.BucketID(params.BucketID.String())
|
||||
} else {
|
||||
req = req.Bucket(params.BucketName)
|
||||
}
|
||||
|
||||
if err := req.Execute(); err != nil {
|
||||
return fmt.Errorf("failed to delete data: %w", err)
|
||||
}
|
||||
return nil
|
||||
}
|
224
internal/cmd/delete/delete_test.go
Normal file
224
internal/cmd/delete/delete_test.go
Normal file
@ -0,0 +1,224 @@
|
||||
package delete_test
|
||||
|
||||
import (
|
||||
"context"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/golang/mock/gomock"
|
||||
"github.com/influxdata/influx-cli/v2/internal/api"
|
||||
"github.com/influxdata/influx-cli/v2/internal/cmd"
|
||||
"github.com/influxdata/influx-cli/v2/internal/cmd/delete"
|
||||
"github.com/influxdata/influx-cli/v2/internal/config"
|
||||
"github.com/influxdata/influx-cli/v2/internal/mock"
|
||||
"github.com/influxdata/influx-cli/v2/pkg/influxid"
|
||||
"github.com/stretchr/testify/assert"
|
||||
tmock "github.com/stretchr/testify/mock"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
func TestClient_Delete(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
id1, _ := influxid.IDFromString("1111111111111111")
|
||||
id2, _ := influxid.IDFromString("2222222222222222")
|
||||
|
||||
start, _ := time.Parse(time.RFC3339Nano, "2020-01-01T00:00:00Z")
|
||||
stop, _ := time.Parse(time.RFC3339Nano, "2021-01-01T00:00:00Z")
|
||||
|
||||
testCases := []struct {
|
||||
name string
|
||||
params delete.Params
|
||||
defaultOrgName string
|
||||
registerExpectations func(*testing.T, *mock.MockDeleteApi)
|
||||
expectedErr string
|
||||
}{
|
||||
{
|
||||
name: "by IDs",
|
||||
params: delete.Params{
|
||||
OrgBucketParams: cmd.OrgBucketParams{
|
||||
OrgParams: cmd.OrgParams{
|
||||
OrgID: id1,
|
||||
},
|
||||
BucketParams: cmd.BucketParams{
|
||||
BucketID: id2,
|
||||
},
|
||||
},
|
||||
Start: start.Format(time.RFC3339Nano),
|
||||
Stop: stop.Format(time.RFC3339Nano),
|
||||
},
|
||||
defaultOrgName: "my-default-org",
|
||||
registerExpectations: func(t *testing.T, delApi *mock.MockDeleteApi) {
|
||||
delApi.EXPECT().PostDelete(gomock.Any()).Return(api.ApiPostDeleteRequest{ApiService: delApi})
|
||||
delApi.EXPECT().PostDeleteExecute(tmock.MatchedBy(func(in api.ApiPostDeleteRequest) bool {
|
||||
body := in.GetDeletePredicateRequest()
|
||||
return assert.NotNil(t, body) &&
|
||||
assert.Equal(t, id1.String(), *in.GetOrgID()) &&
|
||||
assert.Nil(t, in.GetOrg()) &&
|
||||
assert.Equal(t, id2.String(), *in.GetBucketID()) &&
|
||||
assert.Nil(t, in.GetBucket()) &&
|
||||
assert.Equal(t, start, body.GetStart()) &&
|
||||
assert.Equal(t, stop, body.GetStop()) &&
|
||||
assert.Nil(t, body.Predicate)
|
||||
})).Return(nil)
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "by org ID, bucket name",
|
||||
params: delete.Params{
|
||||
OrgBucketParams: cmd.OrgBucketParams{
|
||||
OrgParams: cmd.OrgParams{
|
||||
OrgID: id1,
|
||||
},
|
||||
BucketParams: cmd.BucketParams{
|
||||
BucketName: "my-bucket",
|
||||
},
|
||||
},
|
||||
Start: start.Format(time.RFC3339Nano),
|
||||
Stop: stop.Format(time.RFC3339Nano),
|
||||
},
|
||||
defaultOrgName: "my-default-org",
|
||||
registerExpectations: func(t *testing.T, delApi *mock.MockDeleteApi) {
|
||||
delApi.EXPECT().PostDelete(gomock.Any()).Return(api.ApiPostDeleteRequest{ApiService: delApi})
|
||||
delApi.EXPECT().PostDeleteExecute(tmock.MatchedBy(func(in api.ApiPostDeleteRequest) bool {
|
||||
body := in.GetDeletePredicateRequest()
|
||||
return assert.NotNil(t, body) &&
|
||||
assert.Equal(t, id1.String(), *in.GetOrgID()) &&
|
||||
assert.Nil(t, in.GetOrg()) &&
|
||||
assert.Equal(t, "my-bucket", *in.GetBucket()) &&
|
||||
assert.Nil(t, in.GetBucketID()) &&
|
||||
assert.Equal(t, start, body.GetStart()) &&
|
||||
assert.Equal(t, stop, body.GetStop()) &&
|
||||
assert.Nil(t, body.Predicate)
|
||||
})).Return(nil)
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "by org name, bucket ID",
|
||||
params: delete.Params{
|
||||
OrgBucketParams: cmd.OrgBucketParams{
|
||||
OrgParams: cmd.OrgParams{
|
||||
OrgName: "my-org",
|
||||
},
|
||||
BucketParams: cmd.BucketParams{
|
||||
BucketID: id2,
|
||||
},
|
||||
},
|
||||
Start: start.Format(time.RFC3339Nano),
|
||||
Stop: stop.Format(time.RFC3339Nano),
|
||||
Predicate: `foo = "bar"`,
|
||||
},
|
||||
defaultOrgName: "my-default-org",
|
||||
registerExpectations: func(t *testing.T, delApi *mock.MockDeleteApi) {
|
||||
delApi.EXPECT().PostDelete(gomock.Any()).Return(api.ApiPostDeleteRequest{ApiService: delApi})
|
||||
delApi.EXPECT().PostDeleteExecute(tmock.MatchedBy(func(in api.ApiPostDeleteRequest) bool {
|
||||
body := in.GetDeletePredicateRequest()
|
||||
return assert.NotNil(t, body) &&
|
||||
assert.Equal(t, "my-org", *in.GetOrg()) &&
|
||||
assert.Nil(t, in.GetOrgID()) &&
|
||||
assert.Equal(t, id2.String(), *in.GetBucketID()) &&
|
||||
assert.Nil(t, in.GetBucket()) &&
|
||||
assert.Equal(t, start, body.GetStart()) &&
|
||||
assert.Equal(t, stop, body.GetStop()) &&
|
||||
assert.Equal(t, `foo = "bar"`, body.GetPredicate())
|
||||
})).Return(nil)
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "by names",
|
||||
params: delete.Params{
|
||||
OrgBucketParams: cmd.OrgBucketParams{
|
||||
OrgParams: cmd.OrgParams{},
|
||||
BucketParams: cmd.BucketParams{
|
||||
BucketName: "my-bucket",
|
||||
},
|
||||
},
|
||||
Start: start.Format(time.RFC3339Nano),
|
||||
Stop: stop.Format(time.RFC3339Nano),
|
||||
Predicate: `foo = "bar"`,
|
||||
},
|
||||
defaultOrgName: "my-default-org",
|
||||
registerExpectations: func(t *testing.T, delApi *mock.MockDeleteApi) {
|
||||
delApi.EXPECT().PostDelete(gomock.Any()).Return(api.ApiPostDeleteRequest{ApiService: delApi})
|
||||
delApi.EXPECT().PostDeleteExecute(tmock.MatchedBy(func(in api.ApiPostDeleteRequest) bool {
|
||||
body := in.GetDeletePredicateRequest()
|
||||
return assert.NotNil(t, body) &&
|
||||
assert.Equal(t, "my-default-org", *in.GetOrg()) &&
|
||||
assert.Nil(t, in.GetOrgID()) &&
|
||||
assert.Equal(t, "my-bucket", *in.GetBucket()) &&
|
||||
assert.Nil(t, in.GetBucketID()) &&
|
||||
assert.Equal(t, start, body.GetStart()) &&
|
||||
assert.Equal(t, stop, body.GetStop()) &&
|
||||
assert.Equal(t, `foo = "bar"`, body.GetPredicate())
|
||||
})).Return(nil)
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "no org",
|
||||
expectedErr: delete.ErrMustSpecifyOrg.Error(),
|
||||
},
|
||||
{
|
||||
name: "no bucket",
|
||||
defaultOrgName: "my-default-org",
|
||||
expectedErr: delete.ErrMustSpecifyBucket.Error(),
|
||||
},
|
||||
{
|
||||
name: "bad start",
|
||||
params: delete.Params{
|
||||
OrgBucketParams: cmd.OrgBucketParams{
|
||||
BucketParams: cmd.BucketParams{
|
||||
BucketName: "my-bucket",
|
||||
},
|
||||
},
|
||||
Start: "the beginning",
|
||||
Stop: stop.Format(time.RFC3339Nano),
|
||||
Predicate: `foo = "bar"`,
|
||||
},
|
||||
defaultOrgName: "my-default-org",
|
||||
expectedErr: `"the beginning" cannot be parsed`,
|
||||
},
|
||||
{
|
||||
name: "bad stop",
|
||||
params: delete.Params{
|
||||
OrgBucketParams: cmd.OrgBucketParams{
|
||||
OrgParams: cmd.OrgParams{},
|
||||
BucketParams: cmd.BucketParams{
|
||||
BucketName: "my-bucket",
|
||||
},
|
||||
},
|
||||
Start: start.Format(time.RFC3339Nano),
|
||||
Stop: "the end",
|
||||
Predicate: `foo = "bar"`,
|
||||
},
|
||||
defaultOrgName: "my-default-org",
|
||||
expectedErr: `"the end" cannot be parsed`,
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range testCases {
|
||||
tc := tc
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
ctrl := gomock.NewController(t)
|
||||
api := mock.NewMockDeleteApi(ctrl)
|
||||
if tc.registerExpectations != nil {
|
||||
tc.registerExpectations(t, api)
|
||||
}
|
||||
|
||||
client := delete.Client{
|
||||
CLI: cmd.CLI{ActiveConfig: config.Config{Org: tc.defaultOrgName}},
|
||||
DeleteApi: api,
|
||||
}
|
||||
err := client.Delete(context.Background(), &tc.params)
|
||||
|
||||
if tc.expectedErr != "" {
|
||||
require.Error(t, err)
|
||||
require.Contains(t, err.Error(), tc.expectedErr)
|
||||
return
|
||||
}
|
||||
|
||||
require.NoError(t, err)
|
||||
})
|
||||
}
|
||||
}
|
64
internal/mock/api_delete.gen.go
Normal file
64
internal/mock/api_delete.gen.go
Normal file
@ -0,0 +1,64 @@
|
||||
// Code generated by MockGen. DO NOT EDIT.
|
||||
// Source: github.com/influxdata/influx-cli/v2/internal/api (interfaces: DeleteApi)
|
||||
|
||||
// Package mock is a generated GoMock package.
|
||||
package mock
|
||||
|
||||
import (
|
||||
context "context"
|
||||
reflect "reflect"
|
||||
|
||||
gomock "github.com/golang/mock/gomock"
|
||||
api "github.com/influxdata/influx-cli/v2/internal/api"
|
||||
)
|
||||
|
||||
// MockDeleteApi is a mock of DeleteApi interface.
|
||||
type MockDeleteApi struct {
|
||||
ctrl *gomock.Controller
|
||||
recorder *MockDeleteApiMockRecorder
|
||||
}
|
||||
|
||||
// MockDeleteApiMockRecorder is the mock recorder for MockDeleteApi.
|
||||
type MockDeleteApiMockRecorder struct {
|
||||
mock *MockDeleteApi
|
||||
}
|
||||
|
||||
// NewMockDeleteApi creates a new mock instance.
|
||||
func NewMockDeleteApi(ctrl *gomock.Controller) *MockDeleteApi {
|
||||
mock := &MockDeleteApi{ctrl: ctrl}
|
||||
mock.recorder = &MockDeleteApiMockRecorder{mock}
|
||||
return mock
|
||||
}
|
||||
|
||||
// EXPECT returns an object that allows the caller to indicate expected use.
|
||||
func (m *MockDeleteApi) EXPECT() *MockDeleteApiMockRecorder {
|
||||
return m.recorder
|
||||
}
|
||||
|
||||
// PostDelete mocks base method.
|
||||
func (m *MockDeleteApi) PostDelete(arg0 context.Context) api.ApiPostDeleteRequest {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "PostDelete", arg0)
|
||||
ret0, _ := ret[0].(api.ApiPostDeleteRequest)
|
||||
return ret0
|
||||
}
|
||||
|
||||
// PostDelete indicates an expected call of PostDelete.
|
||||
func (mr *MockDeleteApiMockRecorder) PostDelete(arg0 interface{}) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "PostDelete", reflect.TypeOf((*MockDeleteApi)(nil).PostDelete), arg0)
|
||||
}
|
||||
|
||||
// PostDeleteExecute mocks base method.
|
||||
func (m *MockDeleteApi) PostDeleteExecute(arg0 api.ApiPostDeleteRequest) error {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "PostDeleteExecute", arg0)
|
||||
ret0, _ := ret[0].(error)
|
||||
return ret0
|
||||
}
|
||||
|
||||
// PostDeleteExecute indicates an expected call of PostDeleteExecute.
|
||||
func (mr *MockDeleteApiMockRecorder) PostDeleteExecute(arg0 interface{}) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "PostDeleteExecute", reflect.TypeOf((*MockDeleteApi)(nil).PostDeleteExecute), arg0)
|
||||
}
|
@ -9,6 +9,7 @@ package mock
|
||||
//go:generate go run github.com/golang/mock/mockgen -package mock -destination api_write.gen.go github.com/influxdata/influx-cli/v2/internal/api WriteApi
|
||||
//go:generate go run github.com/golang/mock/mockgen -package mock -destination api_query.gen.go github.com/influxdata/influx-cli/v2/internal/api QueryApi
|
||||
//go:generate go run github.com/golang/mock/mockgen -package mock -destination api_users.gen.go github.com/influxdata/influx-cli/v2/internal/api UsersApi
|
||||
//go:generate go run github.com/golang/mock/mockgen -package mock -destination api_delete.gen.go github.com/influxdata/influx-cli/v2/internal/api DeleteApi
|
||||
|
||||
// Other mocks
|
||||
//go:generate go run github.com/golang/mock/mockgen -package mock -destination config.gen.go -mock_names Service=MockConfigService github.com/influxdata/influx-cli/v2/internal/config Service
|
||||
|
Loading…
x
Reference in New Issue
Block a user