Skip to content

Commit

Permalink
cmd: Add deployment resource delete command (#88)
Browse files Browse the repository at this point in the history
Adds an `ecctl deployment resource delete` command which deletes a
previously shut down deployment resource. If ref-id not specified
it's auto-discovered via an API call.

Required flags: `--type`
Optional flags: `--ref-id`

Signed-off-by: Marc Lopez <marc5.12@outlook.com>
  • Loading branch information
marclop committed Dec 17, 2019
1 parent bd7c910 commit 7c2be04
Show file tree
Hide file tree
Showing 5 changed files with 319 additions and 0 deletions.
54 changes: 54 additions & 0 deletions cmd/deployment/resource/delete.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
// Licensed to Elasticsearch B.V. under one or more contributor
// license agreements. See the NOTICE file distributed with
// this work for additional information regarding copyright
// ownership. Elasticsearch B.V. licenses this file to you under
// the Apache License, Version 2.0 (the "License"); you may
// not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied. See the License for the
// specific language governing permissions and limitations
// under the License.

package cmddeploymentresource

import (
"github.com/spf13/cobra"

cmdutil "github.com/elastic/ecctl/cmd/util"
"github.com/elastic/ecctl/pkg/deployment"
"github.com/elastic/ecctl/pkg/deployment/depresource"
"github.com/elastic/ecctl/pkg/ecctl"
)

// deleteCmd is the deployment subcommand
var deleteCmd = &cobra.Command{
Use: "delete <deployment id> --type <type> --ref-id <ref-id>",
Short: "Deletes a previously shut down deployment resource",
PreRunE: cmdutil.MinimumNArgsAndUUID(1),
RunE: func(cmd *cobra.Command, args []string) error {
resType, _ := cmd.Flags().GetString("type")
refID, _ := cmd.Flags().GetString("ref-id")

return depresource.DeleteStateless(depresource.DeleteStatelessParams{
ResourceParams: deployment.ResourceParams{
API: ecctl.Get().API,
DeploymentID: args[0],
Type: resType,
RefID: refID,
},
})
},
}

func init() {
Command.AddCommand(deleteCmd)
deleteCmd.Flags().String("type", "", "Required stateless deployment type to upgrade (kibana, apm, or appsearch)")
deleteCmd.MarkFlagRequired("type")
deleteCmd.Flags().String("ref-id", "", "Optional deployment RefId, auto-discovered if not specified")
}
1 change: 1 addition & 0 deletions docs/ecctl_deployment_resource.md
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ ecctl deployment resource [flags]
### SEE ALSO

* [ecctl deployment](ecctl_deployment.md) - Manages deployments
* [ecctl deployment resource delete](ecctl_deployment_resource_delete.md) - Deletes a previously shut down deployment resource
* [ecctl deployment resource restore](ecctl_deployment_resource_restore.md) - Restores a previously shut down deployment resource
* [ecctl deployment resource shutdown](ecctl_deployment_resource_shutdown.md) - Shuts down a deployment resource by its type and ref-id
* [ecctl deployment resource start](ecctl_deployment_resource_start.md) - Starts a previously stopped deployment resource
Expand Down
44 changes: 44 additions & 0 deletions docs/ecctl_deployment_resource_delete.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
## ecctl deployment resource delete

Deletes a previously shut down deployment resource

### Synopsis

Deletes a previously shut down deployment resource

```
ecctl deployment resource delete <deployment id> --type <type> --ref-id <ref-id> [flags]
```

### Options

```
-h, --help help for delete
--ref-id string Optional deployment RefId, auto-discovered if not specified
--type string Required stateless deployment type to upgrade (kibana, apm, or appsearch)
```

### Options inherited from parent commands

```
--apikey string API key to use to authenticate (If empty will look for EC_APIKEY environment variable)
--config string Config name, used to have multiple configs in $HOME/.ecctl/<env> (default "config")
--force Do not ask for confirmation
--format string Formats the output using a Go template
--host string Base URL to use
--insecure Skips all TLS validation
--message string A message to set on cluster operation
--output string Output format [text|json] (default "text")
--pass string Password to use to authenticate (If empty will look for EC_PASS environment variable)
--pprof Enables pprofing and saves the profile to pprof-20060102150405
-q, --quiet Suppresses the configuration file used for the run, if any
--timeout duration Timeout to use on all HTTP calls (default 30s)
--trace Enables tracing saves the trace to trace-20060102150405
--user string Username to use to authenticate (If empty will look for EC_USER environment variable)
--verbose Enable verbose mode
```

### SEE ALSO

* [ecctl deployment resource](ecctl_deployment_resource.md) - Manages deployment resources

64 changes: 64 additions & 0 deletions pkg/deployment/depresource/delete_stateless.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
// Licensed to Elasticsearch B.V. under one or more contributor
// license agreements. See the NOTICE file distributed with
// this work for additional information regarding copyright
// ownership. Elasticsearch B.V. licenses this file to you under
// the Apache License, Version 2.0 (the "License"); you may
// not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied. See the License for the
// specific language governing permissions and limitations
// under the License.

package depresource

import (
"errors"

"github.com/elastic/cloud-sdk-go/pkg/client/deployments"
"github.com/hashicorp/go-multierror"

"github.com/elastic/ecctl/pkg/deployment"
"github.com/elastic/ecctl/pkg/util"
)

// DeleteStatelessParams is consumed by Delete
type DeleteStatelessParams struct {
deployment.ResourceParams
}

// Validate ensures the parameters are usable by the consuming function.
func (params DeleteStatelessParams) Validate() error {
var merr = new(multierror.Error)

merr = multierror.Append(merr, params.ResourceParams.Validate())

if params.Type == "elasticsearch" {
merr = multierror.Append(merr, errors.New("deployment resource type \"elasticsearch\" is not supported"))
}

return merr.ErrorOrNil()
}

// DeleteStateless upgrades a stateless deployment resource like APM, Kibana
// and AppSearch.
func DeleteStateless(params DeleteStatelessParams) error {
if err := params.Validate(); err != nil {
return err
}

return util.ReturnErrOnly(
params.V1API.Deployments.DeleteDeploymentStatelessResource(
deployments.NewDeleteDeploymentStatelessResourceParams().
WithStatelessResourceKind(params.Type).
WithDeploymentID(params.DeploymentID).
WithRefID(params.RefID),
params.AuthWriter,
),
)
}
156 changes: 156 additions & 0 deletions pkg/deployment/depresource/delete_stateless_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,156 @@
// Licensed to Elasticsearch B.V. under one or more contributor
// license agreements. See the NOTICE file distributed with
// this work for additional information regarding copyright
// ownership. Elasticsearch B.V. licenses this file to you under
// the Apache License, Version 2.0 (the "License"); you may
// not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied. See the License for the
// specific language governing permissions and limitations
// under the License.

package depresource

import (
"encoding/json"
"errors"
"reflect"
"testing"

"github.com/elastic/cloud-sdk-go/pkg/api"
"github.com/elastic/cloud-sdk-go/pkg/api/mock"
"github.com/elastic/cloud-sdk-go/pkg/models"
"github.com/elastic/cloud-sdk-go/pkg/util/ec"
"github.com/hashicorp/go-multierror"

"github.com/elastic/ecctl/pkg/deployment"
"github.com/elastic/ecctl/pkg/util"
)

func TestDeleteStateless(t *testing.T) {
var internalError = models.BasicFailedReply{
Errors: []*models.BasicFailedReplyElement{
{},
},
}
internalErrorBytes, _ := json.MarshalIndent(internalError, "", " ")
type args struct {
params DeleteStatelessParams
}
tests := []struct {
name string
args args
want *models.DeploymentResourceUpgradeResponse
err error
}{
{
name: "fails due to parameter validation",
args: args{},
err: &multierror.Error{Errors: []error{
util.ErrAPIReq,
errors.New("id \"\" is invalid"),
errors.New("deployment resource type cannot be empty"),
errors.New("failed auto-discovering the resource ref id: api reference is required for command"),
errors.New("failed auto-discovering the resource ref id: id \"\" is invalid"),
}},
},
{
name: "fails due to parameter validation on invalid type",
args: args{params: DeleteStatelessParams{
ResourceParams: deployment.ResourceParams{
Type: "elasticsearch",
},
}},
err: &multierror.Error{Errors: []error{
util.ErrAPIReq,
errors.New("id \"\" is invalid"),
errors.New("failed auto-discovering the resource ref id: api reference is required for command"),
errors.New("failed auto-discovering the resource ref id: id \"\" is invalid"),
errors.New("deployment resource type \"elasticsearch\" is not supported"),
}},
},
{
name: "fails due to API error",
args: args{params: DeleteStatelessParams{
ResourceParams: deployment.ResourceParams{
API: api.NewMock(mock.New404Response(mock.NewStructBody(internalError))),
DeploymentID: util.ValidClusterID,
RefID: "kibana",
Type: "kibana",
},
}},
err: errors.New(string(internalErrorBytes)),
},
{
name: "succeeds on APM resource",
args: args{params: DeleteStatelessParams{
ResourceParams: deployment.ResourceParams{
API: api.NewMock(mock.New200Response(mock.NewStringBody(""))),
DeploymentID: util.ValidClusterID,
RefID: "kibana",
Type: "kibana",
},
}},
},
{
name: "fails due to API error on APM resource",
args: args{params: DeleteStatelessParams{
ResourceParams: deployment.ResourceParams{
API: api.NewMock(mock.New404Response(mock.NewStructBody(internalError))),
DeploymentID: util.ValidClusterID,
RefID: "apm",
Type: "apm",
},
}},
err: errors.New(string(internalErrorBytes)),
},
{
name: "succeeds",
args: args{params: DeleteStatelessParams{
ResourceParams: deployment.ResourceParams{
API: api.NewMock(mock.New200Response(mock.NewStringBody(""))),
DeploymentID: util.ValidClusterID,
RefID: "apm",
Type: "apm",
},
}},
},
{
name: "succeeds with refID autodiscovery",
args: args{params: DeleteStatelessParams{
ResourceParams: deployment.ResourceParams{
API: api.NewMock(
mock.New200Response(mock.NewStructBody(models.DeploymentGetResponse{
Healthy: ec.Bool(true),
ID: ec.String(util.ValidClusterID),
Resources: &models.DeploymentResources{
Apm: []*models.ApmResourceInfo{{
ID: ec.String(util.ValidClusterID),
RefID: ec.String("apm"),
}},
},
})),
mock.New200Response(mock.NewStringBody("")),
),
DeploymentID: util.ValidClusterID,
Type: "apm",
},
}},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
err := DeleteStateless(tt.args.params)
if !reflect.DeepEqual(err, tt.err) {
t.Errorf("DeleteStateless() error = %v, wantErr %v", err, tt.err)
return
}
})
}
}

0 comments on commit 7c2be04

Please sign in to comment.