Repository: elastic/ecctl
Pull request #174 (2020-02-11 00:34:32)

cmd: improve UX by defining which commands are admin specific
<!--- Provide a general summary of your changes in the title above. -->

## Description
This PR introduces the text "(Requires platform administration privileges)" to those commands that require it. This improves UX for ESS users. 

## Related Issues
Related: https://github.com/elastic/ecctl/issues/160

## Motivation and Context
After a conversation in https://github.com/elastic/ecctl/pull/169 it was concluded that the best way forward was to use the text mentioned previously.

## Types of Changes
<!--- What types of changes does your code introduce? Put an `x` in -->
<!--- all the boxes that apply: -->
- [ ] Bug fix (non-breaking change which fixes an issue)
- [ ] New feature (non-breaking change which adds functionality)
- [ ] Refactoring (improves code quality but has no user-facing effect)
- [ ] Breaking change (fix or feature that would cause existing functionality to change)
- [x] Documentation

## Readiness Checklist
<!--- Go over all the following points, and put an `x` in all the boxes -->
<!--- that apply.  If you're unsure about any of these, don't hesitate -->
<!--- to ask. We're here to help! -->
- [x] My code follows the code style of this project
- [x] My change requires a change to the documentation
- [x] I have updated the documentation accordingly
- [ ] I have added tests to cover my changes
- [x] All new and existing tests passed


karencfv: Moving the conversation over to this PR. If any changes need to be addressed let's do it here :)

Patch:
diff --git a/build/Makefile.deps b/build/Makefile.deps
index 27ef90c..25989dc 100644
--- a/build/Makefile.deps
+++ b/build/Makefile.deps
@@ -1,12 +1,61 @@
 ## Installs all the required binaries for the makefile targets.
-.PHONY: deps
-deps:
-ifndef SKIP_DEPCHECK
-	@ echo "-> Installing project dependencies..."
-	@ GO111MODULE=off go get -u github.com/myitcv/gobin
-	@ $(GOBIN)/gobin github.com/elastic/go-licenser@v0.3.0
-	@ $(GOBIN)/gobin github.com/go-bindata/go-bindata/go-bindata@v0.0.0-20190711162640-ee3c2418e368
-	@ $(GOBIN)/gobin golang.org/x/lint/golint
-	@ curl -sfL https://raw.githubusercontent.com/golangci/golangci-lint/master/install.sh| sh -s -- -b $(GOBIN) v1.21.0
-	@ echo "-> Done."
-endif
+
+OS:=$(shell uname -s | tr '[:upper:]' '[:lower:]')
+ARCH:=$(shell $(PWD)/scripts/uname_arch.sh)
+VERSION_DIR:=$(GOBIN)/versions
+
+VERSION_GOBIN:=v0.0.13
+VERSION_GOLINT:=v0.0.0-20191125180803-fdd1cda4f05f
+VERSION_GOLICENSER:=v0.3.0
+VERSION_GOLANGCILINT:=v1.21.0
+VERSION_GOBINDATA:=v0.0.0-20190711162640-ee3c2418e368
+
+deps: $(GOBIN)/gobin $(GOBIN)/golint $(GOBIN)/go-licenser $(GOBIN)/golangci-lint $(GOBIN)/go-bindata
+
+$(GOBIN):
+	@ mkdir -p $(GOBIN)
+
+$(VERSION_DIR): | $(GOBIN)
+	@ mkdir -p $(GOBIN)/versions
+
+
+$(VERSION_DIR)/.version-gobin-$(VERSION_GOBIN): | $(VERSION_DIR)
+	@ rm -f $(VERSION_DIR)/.version-gobin-*
+	@ echo $(VERSION_GOBIN) > $(VERSION_DIR)/.version-gobin-$(VERSION_GOBIN)
+
+$(GOBIN)/gobin: $(VERSION_DIR)/.version-gobin-$(VERSION_GOBIN) | $(GOBIN)
+	@ echo "-> Installing gobin..."
+	@ curl -sL -o $(GOBIN)/gobin https://github.com/myitcv/gobin/releases/download/$(VERSION_GOBIN)/$(OS)-$(ARCH)
+	@ chmod +x $(GOBIN)/gobin
+
+$(VERSION_DIR)/.version-golint-$(VERSION_GOLINT): | $(VERSION_DIR)
+	@ rm -f $(VERSION_DIR)/.version-golint-*
+	@ echo $(VERSION_GOLINT) > $(VERSION_DIR)/.version-golint-$(VERSION_GOLINT)
+
+$(GOBIN)/golint: $(GOBIN)/gobin $(VERSION_DIR)/.version-golint-$(VERSION_GOLINT) | $(GOBIN)
+	@ echo "-> Installing golint..."
+	@ $(GOBIN)/gobin golang.org/x/lint/golint@$(VERSION_GOLINT)
+
+$(VERSION_DIR)/.version-go-licenser-$(VERSION_GOLICENSER): | $(VERSION_DIR)
+	@ rm -f $(VERSION_DIR)/.version-go-licenser-*
+	@ echo $(VERSION_GOLICENSER) > $(VERSION_DIR)/.version-go-licenser-$(VERSION_GOLICENSER)
+
+$(GOBIN)/go-licenser: $(GOBIN)/gobin $(VERSION_DIR)/.version-go-licenser-$(VERSION_GOLICENSER) | $(GOBIN)
+	@ echo "-> Installing go-licenser..."
+	@ $(GOBIN)/gobin github.com/elastic/go-licenser@$(VERSION_GOLICENSER)
+
+$(VERSION_DIR)/.version-golangci-lint-$(VERSION_GOLANGCILINT): | $(VERSION_DIR)
+	@ rm -f $(VERSION_DIR)/.version-golangci-lint-*
+	@ echo $(VERSION_GOLANGCILINT) > $(VERSION_DIR)/.version-golangci-lint-$(VERSION_GOLANGCILINT)
+
+$(GOBIN)/golangci-lint: $(VERSION_DIR)/.version-golangci-lint-$(VERSION_GOLANGCILINT) | $(GOBIN)
+	@ echo "-> Installing golangci-lint..."
+	@ curl -sfL https://raw.githubusercontent.com/golangci/golangci-lint/master/install.sh| sh -s -- -b $(GOBIN) $(VERSION_GOLANGCILINT)
+
+$(VERSION_DIR)/.version-go-bindata-$(VERSION_GOBINDATA):
+	@ rm -f $(VERSION_DIR)/.version-go-bindata-*
+	@ echo $(VERSION_GOBINDATA) > $(VERSION_DIR)/.version-go-bindata-$(VERSION_GOBINDATA)
+
+$(GOBIN)/go-bindata: $(GOBIN)/gobin $(VERSION_DIR)/.version-go-bindata-$(VERSION_GOBINDATA) | $(GOBIN)
+	@ echo "-> Installing go-bindata..."
+	@ $(GOBIN)/gobin github.com/go-bindata/go-bindata/go-bindata@$(VERSION_GOBINDATA)
diff --git a/cmd/platform/allocator/command.go b/cmd/platform/allocator/command.go
index 7b51fb8..011e1e1 100644
--- a/cmd/platform/allocator/command.go
+++ b/cmd/platform/allocator/command.go
@@ -21,12 +21,13 @@ import (
 	"github.com/spf13/cobra"
 
 	cmdallocatormetadata "github.com/elastic/ecctl/cmd/platform/allocator/metadata"
+	cmdutil "github.com/elastic/ecctl/cmd/util"
 )
 
 // Command represents the allocator command
 var Command = &cobra.Command{
 	Use:     "allocator",
-	Short:   "Manages allocators (for ECE installations only)",
+	Short:   cmdutil.AdminReqDescription("Manages allocators"),
 	PreRunE: cobra.MaximumNArgs(0),
 	Run: func(cmd *cobra.Command, args []string) {
 		cmd.Help()
diff --git a/cmd/platform/constructor/command.go b/cmd/platform/constructor/command.go
index 6970621..6c8357a 100644
--- a/cmd/platform/constructor/command.go
+++ b/cmd/platform/constructor/command.go
@@ -23,6 +23,7 @@ import (
 
 	"github.com/spf13/cobra"
 
+	cmdutil "github.com/elastic/ecctl/cmd/util"
 	"github.com/elastic/ecctl/pkg/ecctl"
 	"github.com/elastic/ecctl/pkg/platform/constructor"
 )
@@ -36,7 +37,7 @@ const (
 // Command represents the constructor command
 var Command = &cobra.Command{
 	Use:     "constructor",
-	Short:   "Manages constructors (for ECE installations only)",
+	Short:   cmdutil.AdminReqDescription("Manages constructors"),
 	PreRunE: cobra.MaximumNArgs(0),
 	Run: func(cmd *cobra.Command, args []string) {
 		cmd.Help()
diff --git a/cmd/platform/enrollment-token/command.go b/cmd/platform/enrollment-token/command.go
index 3e51611..3c158cb 100644
--- a/cmd/platform/enrollment-token/command.go
+++ b/cmd/platform/enrollment-token/command.go
@@ -23,6 +23,7 @@ import (
 
 	"github.com/spf13/cobra"
 
+	cmdutil "github.com/elastic/ecctl/cmd/util"
 	"github.com/elastic/ecctl/pkg/ecctl"
 	enrollmenttoken "github.com/elastic/ecctl/pkg/platform/enrollment-token"
 )
@@ -35,7 +36,7 @@ const (
 // Command represents the enrollment-token subcomand.
 var Command = &cobra.Command{
 	Use:     "enrollment-token",
-	Short:   "Manages tokens (for ECE installations only)",
+	Short:   cmdutil.AdminReqDescription("Manages tokens"),
 	PreRunE: cobra.MaximumNArgs(0),
 	Run: func(cmd *cobra.Command, args []string) {
 		cmd.Help()
diff --git a/cmd/platform/instance-configuration/command.go b/cmd/platform/instance-configuration/command.go
index 888ad38..ac042ae 100644
--- a/cmd/platform/instance-configuration/command.go
+++ b/cmd/platform/instance-configuration/command.go
@@ -22,9 +22,10 @@ import (
 	"path/filepath"
 
 	"github.com/elastic/cloud-sdk-go/pkg/input"
-	"github.com/elastic/cloud-sdk-go/pkg/util/cmdutil"
+	sdkcmdutil "github.com/elastic/cloud-sdk-go/pkg/util/cmdutil"
 	"github.com/spf13/cobra"
 
+	cmdutil "github.com/elastic/ecctl/cmd/util"
 	"github.com/elastic/ecctl/pkg/ecctl"
 	"github.com/elastic/ecctl/pkg/platform/instanceconfig"
 )
@@ -32,7 +33,7 @@ import (
 // Command is the top instance-config subcommand.
 var Command = &cobra.Command{
 	Use:     "instance-configuration",
-	Short:   "Manages instance configurations (for ECE installations only)",
+	Short:   cmdutil.AdminReqDescription("Manages instance configurations"),
 	PreRunE: cobra.MaximumNArgs(0),
 	Run:     func(cmd *cobra.Command, args []string) { cmd.Help() },
 }
@@ -60,7 +61,7 @@ var platformInstanceConfigurationCreateCmd = &cobra.Command{
 	PreRunE: cobra.MaximumNArgs(0),
 
 	RunE: func(cmd *cobra.Command, args []string) error {
-		if err := cmdutil.FileOrStdin(cmd, "file"); err != nil {
+		if err := sdkcmdutil.FileOrStdin(cmd, "file"); err != nil {
 			return err
 		}
 
@@ -127,7 +128,7 @@ var platformInstanceConfigurationUpdateCmd = &cobra.Command{
 	Short:   "Overwrites an instance configuration",
 	PreRunE: cobra.MinimumNArgs(1),
 	RunE: func(cmd *cobra.Command, args []string) error {
-		if err := cmdutil.FileOrStdin(cmd, "file"); err != nil {
+		if err := sdkcmdutil.FileOrStdin(cmd, "file"); err != nil {
 			return err
 		}
 
diff --git a/cmd/platform/platform.go b/cmd/platform/platform.go
index 7e247d3..8bc7e87 100644
--- a/cmd/platform/platform.go
+++ b/cmd/platform/platform.go
@@ -30,6 +30,7 @@ import (
 	cmdrole "github.com/elastic/ecctl/cmd/platform/role"
 	cmdrunner "github.com/elastic/ecctl/cmd/platform/runner"
 	cmdstack "github.com/elastic/ecctl/cmd/platform/stack"
+	cmdutil "github.com/elastic/ecctl/cmd/util"
 	"github.com/elastic/ecctl/pkg/ecctl"
 	"github.com/elastic/ecctl/pkg/platform"
 )
@@ -46,7 +47,7 @@ var Command = &cobra.Command{
 
 var infoCmd = &cobra.Command{
 	Use:     "info",
-	Short:   "Shows information about the platform (for ECE installations only)",
+	Short:   cmdutil.AdminReqDescription("Shows information about the platform"),
 	PreRunE: cobra.MaximumNArgs(0),
 	RunE: func(cmd *cobra.Command, args []string) error {
 		p, err := platform.GetInfo(platform.GetInfoParams{
diff --git a/cmd/platform/proxy/command.go b/cmd/platform/proxy/command.go
index 52834b4..c14e14b 100644
--- a/cmd/platform/proxy/command.go
+++ b/cmd/platform/proxy/command.go
@@ -23,6 +23,7 @@ import (
 	"github.com/spf13/cobra"
 
 	cmdfilteredgroup "github.com/elastic/ecctl/cmd/platform/proxy/filteredgroup"
+	cmdutil "github.com/elastic/ecctl/cmd/util"
 	"github.com/elastic/ecctl/pkg/ecctl"
 	"github.com/elastic/ecctl/pkg/platform/proxy"
 )
@@ -35,7 +36,7 @@ const (
 // Command represents the proxy command
 var Command = &cobra.Command{
 	Use:     "proxy",
-	Short:   "Manages proxies (for ECE installations only)",
+	Short:   cmdutil.AdminReqDescription("Manages proxies"),
 	PreRunE: cobra.MaximumNArgs(0),
 	Run: func(cmd *cobra.Command, args []string) {
 		cmd.Help()
diff --git a/cmd/platform/repository/command.go b/cmd/platform/repository/command.go
index a74cb6e..fde31a0 100644
--- a/cmd/platform/repository/command.go
+++ b/cmd/platform/repository/command.go
@@ -23,20 +23,22 @@ import (
 	"path/filepath"
 
 	"github.com/elastic/cloud-sdk-go/pkg/input"
-	"github.com/elastic/cloud-sdk-go/pkg/util/cmdutil"
+	sdkcmdutil "github.com/elastic/cloud-sdk-go/pkg/util/cmdutil"
 	"github.com/spf13/cobra"
 
+	cmdutil "github.com/elastic/ecctl/cmd/util"
 	"github.com/elastic/ecctl/pkg/ecctl"
 	"github.com/elastic/ecctl/pkg/platform/snaprepo"
 	"github.com/elastic/ecctl/pkg/util"
 )
 
 const (
-	snapshotShortHelp       = "Manages snapshot repositories (for ECE installations only)"
 	snapshotCreateShortHelp = "Creates / updates a snapshot repository"
 )
 
 var (
+	snapshotShortHelp = cmdutil.AdminReqDescription("Manages snapshot repositories")
+
 	snapshotLongHelp = `
 Manages snapshot repositories that are used by Elasticsearch clusters
 to perform snapshot operations.
@@ -146,7 +148,7 @@ func setSnapshot(cmd *cobra.Command, args []string) error {
 		}
 	}
 
-	if err := cmdutil.FileOrStdin(cmd, "settings"); err != nil {
+	if err := sdkcmdutil.FileOrStdin(cmd, "settings"); err != nil {
 		return err
 	}
 
diff --git a/cmd/platform/role/command.go b/cmd/platform/role/command.go
index 66672da..0dd83da 100644
--- a/cmd/platform/role/command.go
+++ b/cmd/platform/role/command.go
@@ -19,12 +19,14 @@ package cmdrole
 
 import (
 	"github.com/spf13/cobra"
+
+	cmdutil "github.com/elastic/ecctl/cmd/util"
 )
 
 // Command is the top level role command.
 var Command = &cobra.Command{
 	Use:     "role",
-	Short:   "Manages platform roles (for ECE installations only)",
+	Short:   cmdutil.AdminReqDescription("Manages platform roles"),
 	PreRunE: cobra.MaximumNArgs(0),
 	Run: func(cmd *cobra.Command, args []string) {
 		cmd.Help()
diff --git a/cmd/platform/runner/command.go b/cmd/platform/runner/command.go
index 61083fb..d19fad2 100644
--- a/cmd/platform/runner/command.go
+++ b/cmd/platform/runner/command.go
@@ -19,12 +19,14 @@ package cmdrunner
 
 import (
 	"github.com/spf13/cobra"
+
+	cmdutil "github.com/elastic/ecctl/cmd/util"
 )
 
 // Command is the top level runner command.
 var Command = &cobra.Command{
 	Use:     "runner",
-	Short:   "Manages platform runners (for ECE installations only)",
+	Short:   cmdutil.AdminReqDescription("Manages platform runners"),
 	PreRunE: cobra.MaximumNArgs(0),
 	Run: func(cmd *cobra.Command, args []string) {
 		cmd.Help()
diff --git a/cmd/platform/stack/command.go b/cmd/platform/stack/command.go
index 11ac65b..642fd0c 100644
--- a/cmd/platform/stack/command.go
+++ b/cmd/platform/stack/command.go
@@ -23,6 +23,7 @@ import (
 
 	"github.com/spf13/cobra"
 
+	cmdutil "github.com/elastic/ecctl/cmd/util"
 	"github.com/elastic/ecctl/pkg/ecctl"
 	"github.com/elastic/ecctl/pkg/platform/stack"
 )
@@ -76,7 +77,7 @@ func listStackPacks(cmd *cobra.Command, args []string) error {
 
 var stackUploadCmd = &cobra.Command{
 	Use:     "upload",
-	Short:   "Uploads an Elastic StackPack (for ECE installations only)",
+	Short:   cmdutil.AdminReqDescription("Uploads an Elastic StackPack"),
 	PreRunE: cobra.MinimumNArgs(1),
 
 	RunE: func(cmd *cobra.Command, args []string) error {
@@ -95,7 +96,7 @@ var stackUploadCmd = &cobra.Command{
 
 var stackDeleteCmd = &cobra.Command{
 	Use:     "delete",
-	Short:   "Deletes an Elastic StackPack (for ECE installations only)",
+	Short:   cmdutil.AdminReqDescription("Deletes an Elastic StackPack"),
 	PreRunE: cobra.MinimumNArgs(1),
 
 	RunE: func(cmd *cobra.Command, args []string) error {
diff --git a/cmd/user/command.go b/cmd/user/command.go
index 87740df..9069221 100644
--- a/cmd/user/command.go
+++ b/cmd/user/command.go
@@ -21,12 +21,13 @@ import (
 	"github.com/spf13/cobra"
 
 	cmduserkey "github.com/elastic/ecctl/cmd/user/key"
+	cmdutil "github.com/elastic/ecctl/cmd/util"
 )
 
 // Command is the user subcommand
 var Command = &cobra.Command{
 	Use:     "user",
-	Short:   "Manages the platform users (for ECE installations only)",
+	Short:   cmdutil.AdminReqDescription("Manages the platform users"),
 	PreRunE: cobra.MaximumNArgs(0),
 	Run: func(cmd *cobra.Command, args []string) {
 		cmd.Help()
diff --git a/cmd/util/help_text.go b/cmd/util/help_text.go
new file mode 100644
index 0000000..512f5b8
--- /dev/null
+++ b/cmd/util/help_text.go
@@ -0,0 +1,30 @@
+// 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 cmdutil
+
+import (
+	"fmt"
+)
+
+// PlatformAdminRequired is an additional helper text for commands
+const PlatformAdminRequired = "(Requires platform administration privileges)"
+
+// AdminReqDescription adds a text about required admin permissions to a string
+func AdminReqDescription(desc string) string {
+	return fmt.Sprintf("%s %v", desc, PlatformAdminRequired)
+}
diff --git a/docs/ecctl.md b/docs/ecctl.md
index 23c6f68..a146240 100644
--- a/docs/ecctl.md
+++ b/docs/ecctl.md
@@ -34,6 +34,6 @@ Elastic Cloud Control
 * [ecctl generate](ecctl_generate.md)	 - Generates completions and docs
 * [ecctl init](ecctl_init.md)	 - Creates an initial configuration file.
 * [ecctl platform](ecctl_platform.md)	 - Manages the platform
-* [ecctl user](ecctl_user.md)	 - Manages the platform users (for ECE installations only)
+* [ecctl user](ecctl_user.md)	 - Manages the platform users (Requires platform administration privileges)
 * [ecctl version](ecctl_version.md)	 - Shows ecctl version
 
diff --git a/docs/ecctl_platform.md b/docs/ecctl_platform.md
index f8a5903..f503560 100644
--- a/docs/ecctl_platform.md
+++ b/docs/ecctl_platform.md
@@ -39,15 +39,15 @@ ecctl platform [flags]
 ### SEE ALSO
 
 * [ecctl](ecctl.md)	 - Elastic Cloud Control
-* [ecctl platform allocator](ecctl_platform_allocator.md)	 - Manages allocators (for ECE installations only)
-* [ecctl platform constructor](ecctl_platform_constructor.md)	 - Manages constructors (for ECE installations only)
+* [ecctl platform allocator](ecctl_platform_allocator.md)	 - Manages allocators (Requires platform administration privileges)
+* [ecctl platform constructor](ecctl_platform_constructor.md)	 - Manages constructors (Requires platform administration privileges)
 * [ecctl platform deployment-template](ecctl_platform_deployment-template.md)	 - Manages deployment templates
-* [ecctl platform enrollment-token](ecctl_platform_enrollment-token.md)	 - Manages tokens (for ECE installations only)
-* [ecctl platform info](ecctl_platform_info.md)	 - Shows information about the platform (for ECE installations only)
-* [ecctl platform instance-configuration](ecctl_platform_instance-configuration.md)	 - Manages instance configurations (for ECE installations only)
-* [ecctl platform proxy](ecctl_platform_proxy.md)	 - Manages proxies (for ECE installations only)
-* [ecctl platform repository](ecctl_platform_repository.md)	 - Manages snapshot repositories (for ECE installations only)
-* [ecctl platform role](ecctl_platform_role.md)	 - Manages platform roles (for ECE installations only)
-* [ecctl platform runner](ecctl_platform_runner.md)	 - Manages platform runners (for ECE installations only)
+* [ecctl platform enrollment-token](ecctl_platform_enrollment-token.md)	 - Manages tokens (Requires platform administration privileges)
+* [ecctl platform info](ecctl_platform_info.md)	 - Shows information about the platform (Requires platform administration privileges)
+* [ecctl platform instance-configuration](ecctl_platform_instance-configuration.md)	 - Manages instance configurations (Requires platform administration privileges)
+* [ecctl platform proxy](ecctl_platform_proxy.md)	 - Manages proxies (Requires platform administration privileges)
+* [ecctl platform repository](ecctl_platform_repository.md)	 - Manages snapshot repositories (Requires platform administration privileges)
+* [ecctl platform role](ecctl_platform_role.md)	 - Manages platform roles (Requires platform administration privileges)
+* [ecctl platform runner](ecctl_platform_runner.md)	 - Manages platform runners (Requires platform administration privileges)
 * [ecctl platform stack](ecctl_platform_stack.md)	 - Manages Elastic StackPacks
 
diff --git a/docs/ecctl_platform_allocator.md b/docs/ecctl_platform_allocator.md
index 26d0416..6ee823f 100644
--- a/docs/ecctl_platform_allocator.md
+++ b/docs/ecctl_platform_allocator.md
@@ -1,10 +1,10 @@
 ## ecctl platform allocator
 
-Manages allocators (for ECE installations only)
+Manages allocators (Requires platform administration privileges)
 
 ### Synopsis
 
-Manages allocators (for ECE installations only)
+Manages allocators (Requires platform administration privileges)
 
 ```
 ecctl platform allocator [flags]
diff --git a/docs/ecctl_platform_allocator_list.md b/docs/ecctl_platform_allocator_list.md
index c0a3df2..43985de 100644
--- a/docs/ecctl_platform_allocator_list.md
+++ b/docs/ecctl_platform_allocator_list.md
@@ -63,5 +63,5 @@ ecctl platform allocator list [flags]
 
 ### SEE ALSO
 
-* [ecctl platform allocator](ecctl_platform_allocator.md)	 - Manages allocators (for ECE installations only)
+* [ecctl platform allocator](ecctl_platform_allocator.md)	 - Manages allocators (Requires platform administration privileges)
 
diff --git a/docs/ecctl_platform_allocator_maintenance.md b/docs/ecctl_platform_allocator_maintenance.md
index 5142974..d91f495 100644
--- a/docs/ecctl_platform_allocator_maintenance.md
+++ b/docs/ecctl_platform_allocator_maintenance.md
@@ -39,5 +39,5 @@ ecctl platform allocator maintenance <allocator id> [flags]
 
 ### SEE ALSO
 
-* [ecctl platform allocator](ecctl_platform_allocator.md)	 - Manages allocators (for ECE installations only)
+* [ecctl platform allocator](ecctl_platform_allocator.md)	 - Manages allocators (Requires platform administration privileges)
 
diff --git a/docs/ecctl_platform_allocator_metadata.md b/docs/ecctl_platform_allocator_metadata.md
index f8b57da..d0430a0 100644
--- a/docs/ecctl_platform_allocator_metadata.md
+++ b/docs/ecctl_platform_allocator_metadata.md
@@ -38,7 +38,7 @@ ecctl platform allocator metadata [flags]
 
 ### SEE ALSO
 
-* [ecctl platform allocator](ecctl_platform_allocator.md)	 - Manages allocators (for ECE installations only)
+* [ecctl platform allocator](ecctl_platform_allocator.md)	 - Manages allocators (Requires platform administration privileges)
 * [ecctl platform allocator metadata delete](ecctl_platform_allocator_metadata_delete.md)	 - Deletes a single metadata item from a given allocators metadata
 * [ecctl platform allocator metadata set](ecctl_platform_allocator_metadata_set.md)	 - Sets or updates a single metadata item to a given allocators metadata
 * [ecctl platform allocator metadata show](ecctl_platform_allocator_metadata_show.md)	 - Shows allocator metadata
diff --git a/docs/ecctl_platform_allocator_search.md b/docs/ecctl_platform_allocator_search.md
index 8de2d84..e8253d4 100644
--- a/docs/ecctl_platform_allocator_search.md
+++ b/docs/ecctl_platform_allocator_search.md
@@ -40,5 +40,5 @@ ecctl platform allocator search [flags]
 
 ### SEE ALSO
 
-* [ecctl platform allocator](ecctl_platform_allocator.md)	 - Manages allocators (for ECE installations only)
+* [ecctl platform allocator](ecctl_platform_allocator.md)	 - Manages allocators (Requires platform administration privileges)
 
diff --git a/docs/ecctl_platform_allocator_show.md b/docs/ecctl_platform_allocator_show.md
index 441383f..a2e07e2 100644
--- a/docs/ecctl_platform_allocator_show.md
+++ b/docs/ecctl_platform_allocator_show.md
@@ -39,5 +39,5 @@ ecctl platform allocator show <allocator id> [flags]
 
 ### SEE ALSO
 
-* [ecctl platform allocator](ecctl_platform_allocator.md)	 - Manages allocators (for ECE installations only)
+* [ecctl platform allocator](ecctl_platform_allocator.md)	 - Manages allocators (Requires platform administration privileges)
 
diff --git a/docs/ecctl_platform_allocator_vacate.md b/docs/ecctl_platform_allocator_vacate.md
index 2ba04c5..3657a93 100644
--- a/docs/ecctl_platform_allocator_vacate.md
+++ b/docs/ecctl_platform_allocator_vacate.md
@@ -89,5 +89,5 @@ ecctl platform allocator vacate <source> [flags]
 
 ### SEE ALSO
 
-* [ecctl platform allocator](ecctl_platform_allocator.md)	 - Manages allocators (for ECE installations only)
+* [ecctl platform allocator](ecctl_platform_allocator.md)	 - Manages allocators (Requires platform administration privileges)
 
diff --git a/docs/ecctl_platform_constructor.md b/docs/ecctl_platform_constructor.md
index c765ab8..c219cb0 100644
--- a/docs/ecctl_platform_constructor.md
+++ b/docs/ecctl_platform_constructor.md
@@ -1,10 +1,10 @@
 ## ecctl platform constructor
 
-Manages constructors (for ECE installations only)
+Manages constructors (Requires platform administration privileges)
 
 ### Synopsis
 
-Manages constructors (for ECE installations only)
+Manages constructors (Requires platform administration privileges)
 
 ```
 ecctl platform constructor [flags]
diff --git a/docs/ecctl_platform_constructor_list.md b/docs/ecctl_platform_constructor_list.md
index 7d1e473..01af63c 100644
--- a/docs/ecctl_platform_constructor_list.md
+++ b/docs/ecctl_platform_constructor_list.md
@@ -38,5 +38,5 @@ ecctl platform constructor list [flags]
 
 ### SEE ALSO
 
-* [ecctl platform constructor](ecctl_platform_constructor.md)	 - Manages constructors (for ECE installations only)
+* [ecctl platform constructor](ecctl_platform_constructor.md)	 - Manages constructors (Requires platform administration privileges)
 
diff --git a/docs/ecctl_platform_constructor_maintenance.md b/docs/ecctl_platform_constructor_maintenance.md
index b3327da..eba7e27 100644
--- a/docs/ecctl_platform_constructor_maintenance.md
+++ b/docs/ecctl_platform_constructor_maintenance.md
@@ -39,5 +39,5 @@ ecctl platform constructor maintenance <constructor id> [flags]
 
 ### SEE ALSO
 
-* [ecctl platform constructor](ecctl_platform_constructor.md)	 - Manages constructors (for ECE installations only)
+* [ecctl platform constructor](ecctl_platform_constructor.md)	 - Manages constructors (Requires platform administration privileges)
 
diff --git a/docs/ecctl_platform_constructor_resync.md b/docs/ecctl_platform_constructor_resync.md
index 6b8fd46..d7705e7 100644
--- a/docs/ecctl_platform_constructor_resync.md
+++ b/docs/ecctl_platform_constructor_resync.md
@@ -39,5 +39,5 @@ ecctl platform constructor resync {<constructor id> | --all} [flags]
 
 ### SEE ALSO
 
-* [ecctl platform constructor](ecctl_platform_constructor.md)	 - Manages constructors (for ECE installations only)
+* [ecctl platform constructor](ecctl_platform_constructor.md)	 - Manages constructors (Requires platform administration privileges)
 
diff --git a/docs/ecctl_platform_constructor_show.md b/docs/ecctl_platform_constructor_show.md
index 8dd90f8..3f06e3b 100644
--- a/docs/ecctl_platform_constructor_show.md
+++ b/docs/ecctl_platform_constructor_show.md
@@ -38,5 +38,5 @@ ecctl platform constructor show <constructor id> [flags]
 
 ### SEE ALSO
 
-* [ecctl platform constructor](ecctl_platform_constructor.md)	 - Manages constructors (for ECE installations only)
+* [ecctl platform constructor](ecctl_platform_constructor.md)	 - Manages constructors (Requires platform administration privileges)
 
diff --git a/docs/ecctl_platform_enrollment-token.md b/docs/ecctl_platform_enrollment-token.md
index 8f14484..ad0a635 100644
--- a/docs/ecctl_platform_enrollment-token.md
+++ b/docs/ecctl_platform_enrollment-token.md
@@ -1,10 +1,10 @@
 ## ecctl platform enrollment-token
 
-Manages tokens (for ECE installations only)
+Manages tokens (Requires platform administration privileges)
 
 ### Synopsis
 
-Manages tokens (for ECE installations only)
+Manages tokens (Requires platform administration privileges)
 
 ```
 ecctl platform enrollment-token [flags]
diff --git a/docs/ecctl_platform_enrollment-token_create.md b/docs/ecctl_platform_enrollment-token_create.md
index 512fcba..a6ae742 100644
--- a/docs/ecctl_platform_enrollment-token_create.md
+++ b/docs/ecctl_platform_enrollment-token_create.md
@@ -49,5 +49,5 @@ ecctl platform enrollment-token create --role <ROLE> [flags]
 
 ### SEE ALSO
 
-* [ecctl platform enrollment-token](ecctl_platform_enrollment-token.md)	 - Manages tokens (for ECE installations only)
+* [ecctl platform enrollment-token](ecctl_platform_enrollment-token.md)	 - Manages tokens (Requires platform administration privileges)
 
diff --git a/docs/ecctl_platform_enrollment-token_delete.md b/docs/ecctl_platform_enrollment-token_delete.md
index 298a727..055211f 100644
--- a/docs/ecctl_platform_enrollment-token_delete.md
+++ b/docs/ecctl_platform_enrollment-token_delete.md
@@ -38,5 +38,5 @@ ecctl platform enrollment-token delete <enrollment-token> [flags]
 
 ### SEE ALSO
 
-* [ecctl platform enrollment-token](ecctl_platform_enrollment-token.md)	 - Manages tokens (for ECE installations only)
+* [ecctl platform enrollment-token](ecctl_platform_enrollment-token.md)	 - Manages tokens (Requires platform administration privileges)
 
diff --git a/docs/ecctl_platform_enrollment-token_list.md b/docs/ecctl_platform_enrollment-token_list.md
index 4b4f395..4d102eb 100644
--- a/docs/ecctl_platform_enrollment-token_list.md
+++ b/docs/ecctl_platform_enrollment-token_list.md
@@ -38,5 +38,5 @@ ecctl platform enrollment-token list [flags]
 
 ### SEE ALSO
 
-* [ecctl platform enrollment-token](ecctl_platform_enrollment-token.md)	 - Manages tokens (for ECE installations only)
+* [ecctl platform enrollment-token](ecctl_platform_enrollment-token.md)	 - Manages tokens (Requires platform administration privileges)
 
diff --git a/docs/ecctl_platform_info.md b/docs/ecctl_platform_info.md
index 8735942..ea712cc 100644
--- a/docs/ecctl_platform_info.md
+++ b/docs/ecctl_platform_info.md
@@ -1,10 +1,10 @@
 ## ecctl platform info
 
-Shows information about the platform (for ECE installations only)
+Shows information about the platform (Requires platform administration privileges)
 
 ### Synopsis
 
-Shows information about the platform (for ECE installations only)
+Shows information about the platform (Requires platform administration privileges)
 
 ```
 ecctl platform info [flags]
diff --git a/docs/ecctl_platform_instance-configuration.md b/docs/ecctl_platform_instance-configuration.md
index 1ed7c4d..e462041 100644
--- a/docs/ecctl_platform_instance-configuration.md
+++ b/docs/ecctl_platform_instance-configuration.md
@@ -1,10 +1,10 @@
 ## ecctl platform instance-configuration
 
-Manages instance configurations (for ECE installations only)
+Manages instance configurations (Requires platform administration privileges)
 
 ### Synopsis
 
-Manages instance configurations (for ECE installations only)
+Manages instance configurations (Requires platform administration privileges)
 
 ```
 ecctl platform instance-configuration [flags]
diff --git a/docs/ecctl_platform_instance-configuration_create.md b/docs/ecctl_platform_instance-configuration_create.md
index 83510e9..616c3fd 100644
--- a/docs/ecctl_platform_instance-configuration_create.md
+++ b/docs/ecctl_platform_instance-configuration_create.md
@@ -40,5 +40,5 @@ ecctl platform instance-configuration create -f <config.json> [flags]
 
 ### SEE ALSO
 
-* [ecctl platform instance-configuration](ecctl_platform_instance-configuration.md)	 - Manages instance configurations (for ECE installations only)
+* [ecctl platform instance-configuration](ecctl_platform_instance-configuration.md)	 - Manages instance configurations (Requires platform administration privileges)
 
diff --git a/docs/ecctl_platform_instance-configuration_delete.md b/docs/ecctl_platform_instance-configuration_delete.md
index 9c1705b..ab96869 100644
--- a/docs/ecctl_platform_instance-configuration_delete.md
+++ b/docs/ecctl_platform_instance-configuration_delete.md
@@ -38,5 +38,5 @@ ecctl platform instance-configuration delete <config id> [flags]
 
 ### SEE ALSO
 
-* [ecctl platform instance-configuration](ecctl_platform_instance-configuration.md)	 - Manages instance configurations (for ECE installations only)
+* [ecctl platform instance-configuration](ecctl_platform_instance-configuration.md)	 - Manages instance configurations (Requires platform administration privileges)
 
diff --git a/docs/ecctl_platform_instance-configuration_list.md b/docs/ecctl_platform_instance-configuration_list.md
index 9cb36ac..abf7f43 100644
--- a/docs/ecctl_platform_instance-configuration_list.md
+++ b/docs/ecctl_platform_instance-configuration_list.md
@@ -38,5 +38,5 @@ ecctl platform instance-configuration list [flags]
 
 ### SEE ALSO
 
-* [ecctl platform instance-configuration](ecctl_platform_instance-configuration.md)	 - Manages instance configurations (for ECE installations only)
+* [ecctl platform instance-configuration](ecctl_platform_instance-configuration.md)	 - Manages instance configurations (Requires platform administration privileges)
 
diff --git a/docs/ecctl_platform_instance-configuration_pull.md b/docs/ecctl_platform_instance-configuration_pull.md
index f577fd3..ddea147 100644
--- a/docs/ecctl_platform_instance-configuration_pull.md
+++ b/docs/ecctl_platform_instance-configuration_pull.md
@@ -39,5 +39,5 @@ ecctl platform instance-configuration pull --path <path> [flags]
 
 ### SEE ALSO
 
-* [ecctl platform instance-configuration](ecctl_platform_instance-configuration.md)	 - Manages instance configurations (for ECE installations only)
+* [ecctl platform instance-configuration](ecctl_platform_instance-configuration.md)	 - Manages instance configurations (Requires platform administration privileges)
 
diff --git a/docs/ecctl_platform_instance-configuration_show.md b/docs/ecctl_platform_instance-configuration_show.md
index 65d79d9..13a2693 100644
--- a/docs/ecctl_platform_instance-configuration_show.md
+++ b/docs/ecctl_platform_instance-configuration_show.md
@@ -38,5 +38,5 @@ ecctl platform instance-configuration show <config id> [flags]
 
 ### SEE ALSO
 
-* [ecctl platform instance-configuration](ecctl_platform_instance-configuration.md)	 - Manages instance configurations (for ECE installations only)
+* [ecctl platform instance-configuration](ecctl_platform_instance-configuration.md)	 - Manages instance configurations (Requires platform administration privileges)
 
diff --git a/docs/ecctl_platform_instance-configuration_update.md b/docs/ecctl_platform_instance-configuration_update.md
index a30a9d8..f2477a8 100644
--- a/docs/ecctl_platform_instance-configuration_update.md
+++ b/docs/ecctl_platform_instance-configuration_update.md
@@ -39,5 +39,5 @@ ecctl platform instance-configuration update <config id> -f <config.json> [flags
 
 ### SEE ALSO
 
-* [ecctl platform instance-configuration](ecctl_platform_instance-configuration.md)	 - Manages instance configurations (for ECE installations only)
+* [ecctl platform instance-configuration](ecctl_platform_instance-configuration.md)	 - Manages instance configurations (Requires platform administration privileges)
 
diff --git a/docs/ecctl_platform_proxy.md b/docs/ecctl_platform_proxy.md
index e8ffb4b..28fc2d2 100644
--- a/docs/ecctl_platform_proxy.md
+++ b/docs/ecctl_platform_proxy.md
@@ -1,10 +1,10 @@
 ## ecctl platform proxy
 
-Manages proxies (for ECE installations only)
+Manages proxies (Requires platform administration privileges)
 
 ### Synopsis
 
-Manages proxies (for ECE installations only)
+Manages proxies (Requires platform administration privileges)
 
 ```
 ecctl platform proxy [flags]
diff --git a/docs/ecctl_platform_proxy_filtered-group.md b/docs/ecctl_platform_proxy_filtered-group.md
index 03f8fbf..0616057 100644
--- a/docs/ecctl_platform_proxy_filtered-group.md
+++ b/docs/ecctl_platform_proxy_filtered-group.md
@@ -38,7 +38,7 @@ ecctl platform proxy filtered-group [flags]
 
 ### SEE ALSO
 
-* [ecctl platform proxy](ecctl_platform_proxy.md)	 - Manages proxies (for ECE installations only)
+* [ecctl platform proxy](ecctl_platform_proxy.md)	 - Manages proxies (Requires platform administration privileges)
 * [ecctl platform proxy filtered-group create](ecctl_platform_proxy_filtered-group_create.md)	 - Creates proxies filtered group
 * [ecctl platform proxy filtered-group delete](ecctl_platform_proxy_filtered-group_delete.md)	 - Deletes proxies filtered group
 * [ecctl platform proxy filtered-group list](ecctl_platform_proxy_filtered-group_list.md)	 - Returns all proxies filtered groups in the platform
diff --git a/docs/ecctl_platform_proxy_list.md b/docs/ecctl_platform_proxy_list.md
index 8fbd676..cdb44f1 100644
--- a/docs/ecctl_platform_proxy_list.md
+++ b/docs/ecctl_platform_proxy_list.md
@@ -38,5 +38,5 @@ ecctl platform proxy list [flags]
 
 ### SEE ALSO
 
-* [ecctl platform proxy](ecctl_platform_proxy.md)	 - Manages proxies (for ECE installations only)
+* [ecctl platform proxy](ecctl_platform_proxy.md)	 - Manages proxies (Requires platform administration privileges)
 
diff --git a/docs/ecctl_platform_proxy_show.md b/docs/ecctl_platform_proxy_show.md
index 370bac4..f92b594 100644
--- a/docs/ecctl_platform_proxy_show.md
+++ b/docs/ecctl_platform_proxy_show.md
@@ -38,5 +38,5 @@ ecctl platform proxy show <proxy id> [flags]
 
 ### SEE ALSO
 
-* [ecctl platform proxy](ecctl_platform_proxy.md)	 - Manages proxies (for ECE installations only)
+* [ecctl platform proxy](ecctl_platform_proxy.md)	 - Manages proxies (Requires platform administration privileges)
 
diff --git a/docs/ecctl_platform_repository.md b/docs/ecctl_platform_repository.md
index 7787342..3449382 100644
--- a/docs/ecctl_platform_repository.md
+++ b/docs/ecctl_platform_repository.md
@@ -1,6 +1,6 @@
 ## ecctl platform repository
 
-Manages snapshot repositories (for ECE installations only)
+Manages snapshot repositories (Requires platform administration privileges)
 
 ### Synopsis
 
diff --git a/docs/ecctl_platform_repository_create.md b/docs/ecctl_platform_repository_create.md
index af73f2c..8f290bc 100644
--- a/docs/ecctl_platform_repository_create.md
+++ b/docs/ecctl_platform_repository_create.md
@@ -60,5 +60,5 @@ ecctl platform repository create custom --type fs --settings settings.yml
 
 ### SEE ALSO
 
-* [ecctl platform repository](ecctl_platform_repository.md)	 - Manages snapshot repositories (for ECE installations only)
+* [ecctl platform repository](ecctl_platform_repository.md)	 - Manages snapshot repositories (Requires platform administration privileges)
 
diff --git a/docs/ecctl_platform_repository_delete.md b/docs/ecctl_platform_repository_delete.md
index d830ec2..81fbf05 100644
--- a/docs/ecctl_platform_repository_delete.md
+++ b/docs/ecctl_platform_repository_delete.md
@@ -38,5 +38,5 @@ ecctl platform repository delete <repository name> [flags]
 
 ### SEE ALSO
 
-* [ecctl platform repository](ecctl_platform_repository.md)	 - Manages snapshot repositories (for ECE installations only)
+* [ecctl platform repository](ecctl_platform_repository.md)	 - Manages snapshot repositories (Requires platform administration privileges)
 
diff --git a/docs/ecctl_platform_repository_list.md b/docs/ecctl_platform_repository_list.md
index 823f34d..cff492b 100644
--- a/docs/ecctl_platform_repository_list.md
+++ b/docs/ecctl_platform_repository_list.md
@@ -38,5 +38,5 @@ ecctl platform repository list [flags]
 
 ### SEE ALSO
 
-* [ecctl platform repository](ecctl_platform_repository.md)	 - Manages snapshot repositories (for ECE installations only)
+* [ecctl platform repository](ecctl_platform_repository.md)	 - Manages snapshot repositories (Requires platform administration privileges)
 
diff --git a/docs/ecctl_platform_repository_show.md b/docs/ecctl_platform_repository_show.md
index a5e6a80..5d4e922 100644
--- a/docs/ecctl_platform_repository_show.md
+++ b/docs/ecctl_platform_repository_show.md
@@ -38,5 +38,5 @@ ecctl platform repository show <repository name> [flags]
 
 ### SEE ALSO
 
-* [ecctl platform repository](ecctl_platform_repository.md)	 - Manages snapshot repositories (for ECE installations only)
+* [ecctl platform repository](ecctl_platform_repository.md)	 - Manages snapshot repositories (Requires platform administration privileges)
 
diff --git a/docs/ecctl_platform_role.md b/docs/ecctl_platform_role.md
index d15f4d9..0e27ae4 100644
--- a/docs/ecctl_platform_role.md
+++ b/docs/ecctl_platform_role.md
@@ -1,10 +1,10 @@
 ## ecctl platform role
 
-Manages platform roles (for ECE installations only)
+Manages platform roles (Requires platform administration privileges)
 
 ### Synopsis
 
-Manages platform roles (for ECE installations only)
+Manages platform roles (Requires platform administration privileges)
 
 ```
 ecctl platform role [flags]
diff --git a/docs/ecctl_platform_role_create.md b/docs/ecctl_platform_role_create.md
index d57a1c2..6b569b1 100644
--- a/docs/ecctl_platform_role_create.md
+++ b/docs/ecctl_platform_role_create.md
@@ -39,5 +39,5 @@ ecctl platform role create --file <filename.json> [flags]
 
 ### SEE ALSO
 
-* [ecctl platform role](ecctl_platform_role.md)	 - Manages platform roles (for ECE installations only)
+* [ecctl platform role](ecctl_platform_role.md)	 - Manages platform roles (Requires platform administration privileges)
 
diff --git a/docs/ecctl_platform_role_delete.md b/docs/ecctl_platform_role_delete.md
index cee6cc3..a2e252d 100644
--- a/docs/ecctl_platform_role_delete.md
+++ b/docs/ecctl_platform_role_delete.md
@@ -38,5 +38,5 @@ ecctl platform role delete <role> [flags]
 
 ### SEE ALSO
 
-* [ecctl platform role](ecctl_platform_role.md)	 - Manages platform roles (for ECE installations only)
+* [ecctl platform role](ecctl_platform_role.md)	 - Manages platform roles (Requires platform administration privileges)
 
diff --git a/docs/ecctl_platform_role_list.md b/docs/ecctl_platform_role_list.md
index 95dbef2..3881d13 100644
--- a/docs/ecctl_platform_role_list.md
+++ b/docs/ecctl_platform_role_list.md
@@ -38,5 +38,5 @@ ecctl platform role list [flags]
 
 ### SEE ALSO
 
-* [ecctl platform role](ecctl_platform_role.md)	 - Manages platform roles (for ECE installations only)
+* [ecctl platform role](ecctl_platform_role.md)	 - Manages platform roles (Requires platform administration privileges)
 
diff --git a/docs/ecctl_platform_role_show.md b/docs/ecctl_platform_role_show.md
index 250bd04..4297872 100644
--- a/docs/ecctl_platform_role_show.md
+++ b/docs/ecctl_platform_role_show.md
@@ -38,5 +38,5 @@ ecctl platform role show <role> [flags]
 
 ### SEE ALSO
 
-* [ecctl platform role](ecctl_platform_role.md)	 - Manages platform roles (for ECE installations only)
+* [ecctl platform role](ecctl_platform_role.md)	 - Manages platform roles (Requires platform administration privileges)
 
diff --git a/docs/ecctl_platform_runner.md b/docs/ecctl_platform_runner.md
index 4896da6..63d91f7 100644
--- a/docs/ecctl_platform_runner.md
+++ b/docs/ecctl_platform_runner.md
@@ -1,10 +1,10 @@
 ## ecctl platform runner
 
-Manages platform runners (for ECE installations only)
+Manages platform runners (Requires platform administration privileges)
 
 ### Synopsis
 
-Manages platform runners (for ECE installations only)
+Manages platform runners (Requires platform administration privileges)
 
 ```
 ecctl platform runner [flags]
diff --git a/docs/ecctl_platform_runner_list.md b/docs/ecctl_platform_runner_list.md
index f6b41fe..e4ca00d 100644
--- a/docs/ecctl_platform_runner_list.md
+++ b/docs/ecctl_platform_runner_list.md
@@ -38,5 +38,5 @@ ecctl platform runner list [flags]
 
 ### SEE ALSO
 
-* [ecctl platform runner](ecctl_platform_runner.md)	 - Manages platform runners (for ECE installations only)
+* [ecctl platform runner](ecctl_platform_runner.md)	 - Manages platform runners (Requires platform administration privileges)
 
diff --git a/docs/ecctl_platform_runner_show.md b/docs/ecctl_platform_runner_show.md
index 6bd5432..95090d7 100644
--- a/docs/ecctl_platform_runner_show.md
+++ b/docs/ecctl_platform_runner_show.md
@@ -38,5 +38,5 @@ ecctl platform runner show <runner id> [flags]
 
 ### SEE ALSO
 
-* [ecctl platform runner](ecctl_platform_runner.md)	 - Manages platform runners (for ECE installations only)
+* [ecctl platform runner](ecctl_platform_runner.md)	 - Manages platform runners (Requires platform administration privileges)
 
diff --git a/docs/ecctl_platform_stack.md b/docs/ecctl_platform_stack.md
index ed980cb..d97b1f1 100644
--- a/docs/ecctl_platform_stack.md
+++ b/docs/ecctl_platform_stack.md
@@ -39,8 +39,8 @@ ecctl platform stack [flags]
 ### SEE ALSO
 
 * [ecctl platform](ecctl_platform.md)	 - Manages the platform
-* [ecctl platform stack delete](ecctl_platform_stack_delete.md)	 - Deletes an Elastic StackPack (for ECE installations only)
+* [ecctl platform stack delete](ecctl_platform_stack_delete.md)	 - Deletes an Elastic StackPack (Requires platform administration privileges)
 * [ecctl platform stack list](ecctl_platform_stack_list.md)	 - Lists Elastic StackPacks
 * [ecctl platform stack show](ecctl_platform_stack_show.md)	 - Shows information about an Elastic StackPack
-* [ecctl platform stack upload](ecctl_platform_stack_upload.md)	 - Uploads an Elastic StackPack (for ECE installations only)
+* [ecctl platform stack upload](ecctl_platform_stack_upload.md)	 - Uploads an Elastic StackPack (Requires platform administration privileges)
 
diff --git a/docs/ecctl_platform_stack_delete.md b/docs/ecctl_platform_stack_delete.md
index 8a28a08..8e57ab7 100644
--- a/docs/ecctl_platform_stack_delete.md
+++ b/docs/ecctl_platform_stack_delete.md
@@ -1,10 +1,10 @@
 ## ecctl platform stack delete
 
-Deletes an Elastic StackPack (for ECE installations only)
+Deletes an Elastic StackPack (Requires platform administration privileges)
 
 ### Synopsis
 
-Deletes an Elastic StackPack (for ECE installations only)
+Deletes an Elastic StackPack (Requires platform administration privileges)
 
 ```
 ecctl platform stack delete [flags]
diff --git a/docs/ecctl_platform_stack_upload.md b/docs/ecctl_platform_stack_upload.md
index 703dbe9..efeefad 100644
--- a/docs/ecctl_platform_stack_upload.md
+++ b/docs/ecctl_platform_stack_upload.md
@@ -1,10 +1,10 @@
 ## ecctl platform stack upload
 
-Uploads an Elastic StackPack (for ECE installations only)
+Uploads an Elastic StackPack (Requires platform administration privileges)
 
 ### Synopsis
 
-Uploads an Elastic StackPack (for ECE installations only)
+Uploads an Elastic StackPack (Requires platform administration privileges)
 
 ```
 ecctl platform stack upload [flags]
diff --git a/docs/ecctl_user.md b/docs/ecctl_user.md
index bcf6c07..94ea056 100644
--- a/docs/ecctl_user.md
+++ b/docs/ecctl_user.md
@@ -1,10 +1,10 @@
 ## ecctl user
 
-Manages the platform users (for ECE installations only)
+Manages the platform users (Requires platform administration privileges)
 
 ### Synopsis
 
-Manages the platform users (for ECE installations only)
+Manages the platform users (Requires platform administration privileges)
 
 ```
 ecctl user [flags]
diff --git a/docs/ecctl_user_create.md b/docs/ecctl_user_create.md
index d23b803..5f2d99b 100644
--- a/docs/ecctl_user_create.md
+++ b/docs/ecctl_user_create.md
@@ -53,5 +53,5 @@ ecctl user create --username <username> --role <role> [flags]
 
 ### SEE ALSO
 
-* [ecctl user](ecctl_user.md)	 - Manages the platform users (for ECE installations only)
+* [ecctl user](ecctl_user.md)	 - Manages the platform users (Requires platform administration privileges)
 
diff --git a/docs/ecctl_user_delete.md b/docs/ecctl_user_delete.md
index 490322f..0aaf066 100644
--- a/docs/ecctl_user_delete.md
+++ b/docs/ecctl_user_delete.md
@@ -38,5 +38,5 @@ ecctl user delete <user name> <user name>... [flags]
 
 ### SEE ALSO
 
-* [ecctl user](ecctl_user.md)	 - Manages the platform users (for ECE installations only)
+* [ecctl user](ecctl_user.md)	 - Manages the platform users (Requires platform administration privileges)
 
diff --git a/docs/ecctl_user_disable.md b/docs/ecctl_user_disable.md
index ae0c056..8acb6d4 100644
--- a/docs/ecctl_user_disable.md
+++ b/docs/ecctl_user_disable.md
@@ -38,5 +38,5 @@ ecctl user disable <username> [flags]
 
 ### SEE ALSO
 
-* [ecctl user](ecctl_user.md)	 - Manages the platform users (for ECE installations only)
+* [ecctl user](ecctl_user.md)	 - Manages the platform users (Requires platform administration privileges)
 
diff --git a/docs/ecctl_user_enable.md b/docs/ecctl_user_enable.md
index b036730..d1f7c4c 100644
--- a/docs/ecctl_user_enable.md
+++ b/docs/ecctl_user_enable.md
@@ -38,5 +38,5 @@ ecctl user enable <username> [flags]
 
 ### SEE ALSO
 
-* [ecctl user](ecctl_user.md)	 - Manages the platform users (for ECE installations only)
+* [ecctl user](ecctl_user.md)	 - Manages the platform users (Requires platform administration privileges)
 
diff --git a/docs/ecctl_user_key.md b/docs/ecctl_user_key.md
index 265e712..92faf0a 100644
--- a/docs/ecctl_user_key.md
+++ b/docs/ecctl_user_key.md
@@ -38,7 +38,7 @@ ecctl user key [flags]
 
 ### SEE ALSO
 
-* [ecctl user](ecctl_user.md)	 - Manages the platform users (for ECE installations only)
+* [ecctl user](ecctl_user.md)	 - Manages the platform users (Requires platform administration privileges)
 * [ecctl user key delete](ecctl_user_key_delete.md)	 - Deletes an existing API key for the specified user
 * [ecctl user key list](ecctl_user_key_list.md)	 - Lists the API keys for the specified user, or all platform users
 * [ecctl user key show](ecctl_user_key_show.md)	 - Shows the API key details for the specified user
diff --git a/docs/ecctl_user_list.md b/docs/ecctl_user_list.md
index 3ee4a43..b1e62b9 100644
--- a/docs/ecctl_user_list.md
+++ b/docs/ecctl_user_list.md
@@ -38,5 +38,5 @@ ecctl user list [flags]
 
 ### SEE ALSO
 
-* [ecctl user](ecctl_user.md)	 - Manages the platform users (for ECE installations only)
+* [ecctl user](ecctl_user.md)	 - Manages the platform users (Requires platform administration privileges)
 
diff --git a/docs/ecctl_user_show.md b/docs/ecctl_user_show.md
index e0b4806..0a6a9c0 100644
--- a/docs/ecctl_user_show.md
+++ b/docs/ecctl_user_show.md
@@ -39,5 +39,5 @@ ecctl user show <user name> [flags]
 
 ### SEE ALSO
 
-* [ecctl user](ecctl_user.md)	 - Manages the platform users (for ECE installations only)
+* [ecctl user](ecctl_user.md)	 - Manages the platform users (Requires platform administration privileges)
 
diff --git a/docs/ecctl_user_update.md b/docs/ecctl_user_update.md
index 610fe2b..44e0180 100644
--- a/docs/ecctl_user_update.md
+++ b/docs/ecctl_user_update.md
@@ -58,5 +58,5 @@ ecctl user update <username> --role <role> [flags]
 
 ### SEE ALSO
 
-* [ecctl user](ecctl_user.md)	 - Manages the platform users (for ECE installations only)
+* [ecctl user](ecctl_user.md)	 - Manages the platform users (Requires platform administration privileges)
 
diff --git a/pkg/ecctl/init.go b/pkg/ecctl/init.go
index 0e7868d..c2e1101 100644
--- a/pkg/ecctl/init.go
+++ b/pkg/ecctl/init.go
@@ -49,14 +49,24 @@ const (
 )
 
 const (
-	disclaimer      = "Welcome to the Elastic Cloud CLI! This command will guide you through authenticating and setting some default values.\n\n"
+	_ = iota
+	essInfraChoice
+	eceInfraChoice
+	esspInfraChoice
+)
+
+const (
+	disclaimer      = "Welcome to Elastic Cloud Control (ecctl)! This command will guide you through authenticating and setting some default values.\n\n"
 	redacted        = "[REDACTED]"
 	settingsPathMsg = "Found existing settings in %s. Here's a JSON representation of what they look like:\n"
 
 	missingConfigMsg  = `Missing configuration file, would you like to initialise it? [y/n]: `
 	existingConfigMsg = `Would you like to change your current settings? [y/n]: `
 
-	hostMsg = "Enter the URL of your ECE installation: "
+	essHostAddress = "https://api.elastic-cloud.com"
+	eceHostMsg     = "Enter the URL of your ECE installation: "
+	esspHostMsg    = "Enter the URL of your ESSP installation: "
+	essChoiceMsg   = "Using \"%s\" as the API endpoint.\n"
 
 	apiKeyMsg = "Paste your API Key and press enter: "
 	userMsg   = "Type in your username: "
@@ -67,6 +77,14 @@ const (
 )
 
 var (
+	hostChoiceMsg = `
+Select which type of Elastic Cloud offering will you be working with:
+  [1] Elasticsearch Service (default).
+  [2] Elastic Cloud Enterprise (ECE).
+  [3] Elasticsearch Service Private (ESSP).
+
+Please enter your choice: `
+
 	authChoiceMsg = `
 Which authentication mechanism would you like to use?
   [1] API Keys (Recommended).
@@ -186,7 +204,10 @@ func InitConfig(params InitConfigParams) error {
 	// Insecure is set to true by default to allow API calls against HTTPS
 	// endpoints with self-signed certificates.
 	cfg.Insecure = true
-	cfg.Host = scanner.Scan(hostMsg)
+
+	if err := askInfraSelection(&cfg, scanner, params.Writer, params.ErrWriter); err != nil {
+		return err
+	}
 
 	if err := askOutputFormat(&cfg, scanner, params.Writer, params.ErrWriter); err != nil {
 		return err
@@ -206,7 +227,7 @@ func InitConfig(params InitConfigParams) error {
 		return err
 	}
 
-	// It's better to write the config as is since it ommits defaults and
+	// It's better to write the config as is since it omits defaults and
 	// empties vs viper's behaviour in `WriteConfig`.
 	return writeConfig(cfg, params.FilePath, ".json")
 }
@@ -243,6 +264,29 @@ func printConfig(writer io.Writer, v *viper.Viper) error {
 	return enc.Encode(c)
 }
 
+func askInfraSelection(cfg *Config, scanner *input.Scanner, writer, errWriter io.Writer) error {
+	infraChoiceRaw := scanner.Scan(hostChoiceMsg)
+	fmt.Fprintln(writer)
+	infraChoice, err := strconv.Atoi(infraChoiceRaw)
+	if err != nil {
+		return err
+	}
+
+	cfg.Host = essHostAddress
+	switch infraChoice {
+	case essInfraChoice:
+		fmt.Fprintf(writer, essChoiceMsg, essHostAddress)
+	case eceInfraChoice:
+		cfg.Host = scanner.Scan(eceHostMsg)
+	case esspInfraChoice:
+		cfg.Host = scanner.Scan(esspHostMsg)
+	default:
+		fmt.Fprintf(errWriter, "invalid choice, defaulting to %s", essHostAddress)
+	}
+
+	return nil
+}
+
 func askOutputFormat(cfg *Config, scanner *input.Scanner, writer, errWriter io.Writer) error {
 	formatChoiceRaw := scanner.Scan(formatChoiceMsg)
 	fmt.Fprintln(writer)
diff --git a/pkg/platform/allocator/vacate.go b/pkg/platform/allocator/vacate.go
index 0f969cc..8cd1f74 100644
--- a/pkg/platform/allocator/vacate.go
+++ b/pkg/platform/allocator/vacate.go
@@ -174,6 +174,9 @@ func waitVacateCompletion(p *pool.Pool, hasWork bool) error {
 	return errs.ErrorOrNil()
 }
 
+// nolint since the linter says it's too complex, it's because of the for loop
+// combination with ifs. It's better to have this grouped rather than scattered
+// around.
 func addAllocatorMovesToPool(params addAllocatorMovesToPoolParams) ([]pool.Validator, bool) {
 	var leftovers []pool.Validator
 	var vacates = make([]pool.Validator, 0)
@@ -219,6 +222,18 @@ func addAllocatorMovesToPool(params addAllocatorMovesToPoolParams) ([]pool.Valid
 		vacates = append(vacates, newVacateClusterParams(params, *move.ClusterID, kind))
 	}
 
+	for _, move := range params.Moves.AppsearchClusters {
+		if len(filter) > 0 && !slice.HasString(filter, *move.ClusterID) {
+			continue
+		}
+
+		var kind = "appsearch"
+		if kindFilter != "" && kind != kindFilter {
+			break
+		}
+		vacates = append(vacates, newVacateClusterParams(params, *move.ClusterID, kind))
+	}
+
 	if leftover, _ := params.Pool.Add(vacates...); len(leftover) > 0 {
 		leftovers = append(leftovers, leftover...)
 	}
@@ -353,6 +368,10 @@ func newMoveClusterParams(params *VacateClusterParams) (*platform_infrastructure
 		moveParams.SetClusterType(ec.String("apm"))
 	}
 
+	if len(req.AppsearchClusters) > 0 {
+		moveParams.SetClusterType(ec.String("appsearch"))
+	}
+
 	return moveParams, nil
 }
 
@@ -384,7 +403,14 @@ func trackMovedCluster(params *VacateClusterParams) error {
 		MaxRetries:    params.MaxPollRetries,
 	})
 	if err != nil {
-		return errors.Wrap(err, vacateWrapMessage(params, "track"))
+		// Remove this after AppSearch is supported in the plan tracker
+		// https://github.com/elastic/cloud-sdk-go/issues/34
+		if params.Kind == "appsearch" {
+			wrapMessage := "instance is being moved but tracking is not supported, please check the vacate progress from the UI"
+			return errors.New(vacateWrapMessage(params, wrapMessage))
+		}
+		wrapMessage := "plan tracker returned an error but vacate is in progress"
+		return errors.Wrap(err, vacateWrapMessage(params, wrapMessage))
 	}
 
 	return plan.Stream(channel, params.Output)
@@ -392,6 +418,8 @@ func trackMovedCluster(params *VacateClusterParams) error {
 
 // CheckVacateFailures iterates over the list of failures returning
 // a multierror with any of the failures found.
+//
+// nolint because of the complexity score here
 func CheckVacateFailures(failures *models.MoveClustersDetails, filter []string) error {
 	if failures == nil {
 		return nil
@@ -451,6 +479,24 @@ func CheckVacateFailures(failures *models.MoveClustersDetails, filter []string)
 		}
 	}
 
+	for _, failure := range failures.AppsearchClusters {
+		if len(filter) > 0 && !slice.HasString(filter, *failure.ClusterID) {
+			continue
+		}
+
+		var ferr error
+		if len(failure.Errors) > 0 {
+			var err = failure.Errors[0]
+			ferr = fmt.Errorf("code: %s, message: %s", *err.Code, *err.Message)
+		}
+
+		if !strings.Contains(ferr.Error(), PlanPendingMessage) {
+			merr = multierror.Append(merr,
+				fmt.Errorf("cluster [%s][appsearch] failed vacating, reason: %s", *failure.ClusterID, ferr),
+			)
+		}
+	}
+
 	return merr.ErrorOrNil()
 }
 
@@ -513,5 +559,19 @@ func ComputeVacateRequest(pr *models.MoveClustersDetails, clusters, to []string,
 		)
 	}
 
+	for _, c := range pr.AppsearchClusters {
+		if len(clusters) > 0 && !slice.HasString(clusters, *c.ClusterID) {
+			continue
+		}
+
+		c.CalculatedPlan.PlanConfiguration.PreferredAllocators = to
+		req.AppsearchClusters = append(req.AppsearchClusters,
+			&models.MoveAppSearchConfiguration{
+				ClusterIds:   []string{*c.ClusterID},
+				PlanOverride: c.CalculatedPlan,
+			},
+		)
+	}
+
 	return &req
 }
diff --git a/pkg/platform/allocator/vacate_params.go b/pkg/platform/allocator/vacate_params.go
index 0caf034..113107d 100644
--- a/pkg/platform/allocator/vacate_params.go
+++ b/pkg/platform/allocator/vacate_params.go
@@ -40,7 +40,7 @@ var (
 	errOutputDeviceCannotBeNil      = errors.New("output device cannot be nil")
 	errCannotOverrideAllocatorDown  = errors.New("cannot set the AllocatorDown when multiple allocators are specified")
 
-	allowedClusterKinds = []string{"apm", "elasticsearch", "kibana"}
+	allowedClusterKinds = []string{"apm", "elasticsearch", "kibana", "appsearch"}
 )
 
 // VacateParams used to vacate N allocators or clusters.
diff --git a/scripts/uname_arch.sh b/scripts/uname_arch.sh
new file mode 100755
index 0000000..3f63c6a
--- /dev/null
+++ b/scripts/uname_arch.sh
@@ -0,0 +1,14 @@
+#!/usr/bin/env bash
+
+arch=$(uname -m)
+case $arch in
+  x86_64) arch="amd64" ;;
+  x86) arch="386" ;;
+  i686) arch="386" ;;
+  i386) arch="386" ;;
+  aarch64) arch="arm64" ;;
+  armv5*) arch="armv5" ;;
+  armv6*) arch="armv6" ;;
+  armv7*) arch="armv7" ;;
+esac
+echo ${arch}


Test patch:
diff --git a/cmd/util/help_text_test.go b/cmd/util/help_text_test.go
new file mode 100644
index 0000000..3aae8af
--- /dev/null
+++ b/cmd/util/help_text_test.go
@@ -0,0 +1,51 @@
+// 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 cmdutil
+
+import (
+	"reflect"
+	"testing"
+)
+
+func TestAdminReqDescription(t *testing.T) {
+	type args struct {
+		msg string
+	}
+	tests := []struct {
+		name string
+		args args
+		want string
+	}{
+		{
+			name: "Returns a string with the expected appended text",
+			args: args{
+				msg: "Manages resources",
+			},
+			want: "Manages resources (Requires platform administration privileges)",
+		},
+	}
+	for _, tt := range tests {
+		t.Run(tt.name, func(t *testing.T) {
+			got := AdminReqDescription(tt.args.msg)
+
+			if !reflect.DeepEqual(got, tt.want) {
+				t.Errorf("AdminReqDescription() expected = %v, but got %v", tt.want, got)
+			}
+		})
+	}
+}
diff --git a/pkg/ecctl/init_test.go b/pkg/ecctl/init_test.go
index 075766c..68914dd 100644
--- a/pkg/ecctl/init_test.go
+++ b/pkg/ecctl/init_test.go
@@ -241,7 +241,7 @@ func TestInitConfig(t *testing.T) {
 				FilePath: filepath.Join(testFiles, "newConfig"),
 				Reader: io.MultiReader(
 					strings.NewReader("y\n"),
-					strings.NewReader("https://ahost\n"),
+					strings.NewReader("1\n"),
 					strings.NewReader("1\n"),
 					strings.NewReader("1\n"),
 					strings.NewReader("anapikey\n"),
@@ -257,13 +257,14 @@ func TestInitConfig(t *testing.T) {
 			}},
 			wantSettings: map[string]interface{}{
 				"apikey":   "somekey",
-				"host":     "https://ahost",
+				"host":     "https://api.elastic-cloud.com",
 				"insecure": true,
 				"output":   "text",
 			},
-			wantOutput: disclaimer + missingConfigMsg + hostMsg +
-				formatChoiceMsg + "\n" + authChoiceMsg + "\n" + apiKeyMsg + "\n" +
-				"\n" + fmt.Sprintf(validCredentialsMsg, "anacleto") + finalMsg + "\n",
+			wantOutput: disclaimer + missingConfigMsg + hostChoiceMsg + "\n" +
+				fmt.Sprintf(essChoiceMsg, essHostAddress) + formatChoiceMsg +
+				"\n" + authChoiceMsg + "\n" + apiKeyMsg + "\n" + "\n" +
+				fmt.Sprintf(validCredentialsMsg, "anacleto") + finalMsg + "\n",
 		},
 		{
 			name: "doesn't find a config file and user creates a new one with user/pass",
@@ -272,6 +273,7 @@ func TestInitConfig(t *testing.T) {
 				FilePath: filepath.Join(testFiles, "newConfigUserPass"),
 				Reader: io.MultiReader(
 					strings.NewReader("y\n"),
+					strings.NewReader("2\n"),
 					strings.NewReader("https://ahost\n"),
 					strings.NewReader("1\n"),
 					strings.NewReader("2\n"),
@@ -298,7 +300,7 @@ func TestInitConfig(t *testing.T) {
 				"pass":     "apassword",
 				"user":     "auser",
 			},
-			wantOutput: disclaimer + missingConfigMsg + hostMsg +
+			wantOutput: disclaimer + missingConfigMsg + hostChoiceMsg + "\n" + eceHostMsg +
 				formatChoiceMsg + "\n" + authChoiceMsg + "\n" + userMsg + passMsg +
 				"\n" + "\n" + fmt.Sprintf(validCredentialsMsg, "auser") + finalMsg + "\n",
 		},
@@ -309,6 +311,7 @@ func TestInitConfig(t *testing.T) {
 				FilePath: filepath.Join(testFiles, "doesnt_matter"),
 				Reader: io.MultiReader(
 					strings.NewReader("y\n"),
+					strings.NewReader("3\n"),
 					strings.NewReader("https://ahost\n"),
 					strings.NewReader("1\n"),
 					strings.NewReader("1\n"),
@@ -331,9 +334,9 @@ func TestInitConfig(t *testing.T) {
 			},
 			wantOutput: disclaimer +
 				fmt.Sprintf(settingsPathMsg, "test_files/userpassmodif.yaml") +
-				userPassConfigToModifyContents + "\n" + existingConfigMsg + hostMsg +
-				formatChoiceMsg + "\n" + authChoiceMsg + "\n" + apiKeyMsg + "\n" +
-				"\n" + fmt.Sprintf(validCredentialsMsg, "anacleto") + finalMsg + "\n",
+				userPassConfigToModifyContents + "\n" + existingConfigMsg + hostChoiceMsg +
+				"\n" + esspHostMsg + formatChoiceMsg + "\n" + authChoiceMsg + "\n" + apiKeyMsg +
+				"\n" + "\n" + fmt.Sprintf(validCredentialsMsg, "anacleto") + finalMsg + "\n",
 		},
 		{
 			name: "finds a config file and user changes the values, from apikey to user/pass",
@@ -342,6 +345,7 @@ func TestInitConfig(t *testing.T) {
 				FilePath: filepath.Join(testFiles, "doesnt_matter"),
 				Reader: io.MultiReader(
 					strings.NewReader("y\n"),
+					strings.NewReader("2\n"),
 					strings.NewReader("https://ahost\n"),
 					strings.NewReader("1\n"),
 					strings.NewReader("2\n"),
@@ -370,9 +374,9 @@ func TestInitConfig(t *testing.T) {
 			},
 			wantOutput: disclaimer +
 				fmt.Sprintf(settingsPathMsg, "test_files/apikeymodif.yaml") +
-				apiKeyConfigToModifyContents + "\n" + existingConfigMsg + hostMsg +
-				formatChoiceMsg + "\n" + authChoiceMsg + "\n" + userMsg + passMsg +
-				"\n" + "\n" + fmt.Sprintf(validCredentialsMsg, "auser") + finalMsg + "\n",
+				apiKeyConfigToModifyContents + "\n" + existingConfigMsg + hostChoiceMsg +
+				"\n" + eceHostMsg + formatChoiceMsg + "\n" + authChoiceMsg + "\n" + userMsg +
+				passMsg + "\n" + "\n" + fmt.Sprintf(validCredentialsMsg, "auser") + finalMsg + "\n",
 		},
 	}
 	for _, tt := range tests {
diff --git a/pkg/platform/allocator/vacate_full_test.go b/pkg/platform/allocator/vacate_full_test.go
index eaf16e7..0f37ac5 100644
--- a/pkg/platform/allocator/vacate_full_test.go
+++ b/pkg/platform/allocator/vacate_full_test.go
@@ -141,6 +141,67 @@ func TestVacate(t *testing.T) {
 				"\x1b[92;mCluster [3ee11eb40eda22cac0cce259625c6734][Apm]: finished running all the plan steps\x1b[0m (Total plan duration )",
 			),
 		},
+		{
+			name: "Succeeds moving a single Appsearch cluster from a single allocator (without tracking)",
+			args: args{
+				buf: sdkSync.NewBuffer(),
+				params: newVacateTestCase(t, vacateCase{
+					skipTracking: true,
+					topology: []vacateCaseClusters{
+						{
+							Allocator: "allocatorID",
+							appsearch: []vacateCaseClusterConfig{
+								{
+									ID: "3ee11eb40eda22cac0cce259625c6734",
+									steps: [][]*models.ClusterPlanStepInfo{
+										{
+											newPlanStep("step1", "success"),
+											newPlanStep("step2", "pending"),
+										},
+									},
+									plan: []*models.ClusterPlanStepInfo{
+										newPlanStep("step1", "success"),
+										newPlanStep("step2", "success"),
+									},
+								},
+							},
+						},
+					},
+				}),
+			},
+		},
+		{
+			name: "Succeeds moving a single Appsearch cluster from a single allocator, but returns error due to unsupported tracking type",
+			args: args{
+				buf: sdkSync.NewBuffer(),
+				params: newVacateTestCase(t, vacateCase{
+					topology: []vacateCaseClusters{
+						{
+							Allocator: "allocatorID",
+							appsearch: []vacateCaseClusterConfig{
+								{
+									ID: "3ee11eb40eda22cac0cce259625c6734",
+									steps: [][]*models.ClusterPlanStepInfo{
+										{
+											newPlanStep("step1", "success"),
+											newPlanStep("step2", "pending"),
+										},
+									},
+									plan: []*models.ClusterPlanStepInfo{
+										newPlanStep("step1", "success"),
+										newPlanStep("step2", "success"),
+									},
+								},
+							},
+						},
+					},
+				}),
+			},
+			err: `1 error occurred:
+	* allocator allocatorID: cluster [3ee11eb40eda22cac0cce259625c6734][appsearch]: instance is being moved but tracking is not supported, please check the vacate progress from the UI
+
+`,
+		},
 		{
 			name: "Succeeds moving a multiple clusters from a single allocator",
 			args: args{
diff --git a/pkg/platform/allocator/vacate_responses_test.go b/pkg/platform/allocator/vacate_responses_test.go
index 9624185..0c5907a 100644
--- a/pkg/platform/allocator/vacate_responses_test.go
+++ b/pkg/platform/allocator/vacate_responses_test.go
@@ -42,6 +42,35 @@ import (
 
 const planStepLogErrorMessage = "Unexpected error during step: [perform-snapshot]: [no.found.constructor.models.TimeoutException: Timeout]"
 
+type vacateCase struct {
+	topology     []vacateCaseClusters
+	skipTracking bool
+}
+
+type vacateCaseClusters struct {
+	// Allocator ID
+	Allocator string
+	// Elasticsearch clusters that will be simulated
+	elasticsearch []vacateCaseClusterConfig
+	// Kibana instances that will be simulated
+	kibana []vacateCaseClusterConfig
+	// APM clusters that will be simulated
+	apm []vacateCaseClusterConfig
+	// AppSearch clusters that will be simulated
+	appsearch []vacateCaseClusterConfig
+}
+
+type vacateCaseClusterConfig struct {
+	// ID of the cluster
+	ID string
+	// Fails the `_move` api call to actually move a cluster
+	fail bool
+	// Plan steps that are fetched by the
+	steps [][]*models.ClusterPlanStepInfo
+	// Current plan steps the move
+	plan []*models.ClusterPlanStepInfo
+}
+
 func newBody(t *testing.T, v interface{}) string {
 	b, err := json.Marshal(v)
 	if err != nil {
@@ -119,6 +148,25 @@ func newApmMove(t *testing.T, clusterID, allocator string) io.ReadCloser {
 	)))
 }
 
+func newAppsearchMove(t *testing.T, clusterID, allocator string) io.ReadCloser {
+	return ioutil.NopCloser(strings.NewReader(newBody(t,
+		models.MoveClustersCommandResponse{
+			Moves: &models.MoveClustersDetails{
+				AppsearchClusters: []*models.MoveAppSearchDetails{{
+					ClusterID: ec.String(clusterID),
+					CalculatedPlan: &models.TransientAppSearchPlanConfiguration{
+						PlanConfiguration: &models.AppSearchPlanControlConfiguration{
+							MoveAllocators: []*models.AllocatorMoveRequest{
+								{From: ec.String(allocator)},
+							},
+						},
+					},
+				}},
+			},
+		},
+	)))
+}
+
 func newKibanaMoveFailure(t *testing.T, clusterID, allocator string) io.ReadCloser {
 	return ioutil.NopCloser(strings.NewReader(newBody(t,
 		models.MoveClustersCommandResponse{
@@ -148,7 +196,7 @@ func newKibanaMoveFailure(t *testing.T, clusterID, allocator string) io.ReadClos
 	)))
 }
 
-func newMulipleMoves(t *testing.T, allocator string, es, kibana, apm []string) io.ReadCloser {
+func newMulipleMoves(t *testing.T, allocator string, es, kibana, apm, appsearch []string) io.ReadCloser {
 	var res = models.MoveClustersCommandResponse{Moves: &models.MoveClustersDetails{}}
 	for _, id := range es {
 		res.Moves.ElasticsearchClusters = append(res.Moves.ElasticsearchClusters,
@@ -193,31 +241,45 @@ func newMulipleMoves(t *testing.T, allocator string, es, kibana, apm []string) i
 			},
 		)
 	}
+
+	for _, id := range appsearch {
+		res.Moves.AppsearchClusters = append(res.Moves.AppsearchClusters,
+			&models.MoveAppSearchDetails{
+				ClusterID: ec.String(id),
+				CalculatedPlan: &models.TransientAppSearchPlanConfiguration{
+					PlanConfiguration: &models.AppSearchPlanControlConfiguration{
+						MoveAllocators: []*models.AllocatorMoveRequest{
+							{From: ec.String(allocator)},
+						},
+					},
+				},
+			},
+		)
+	}
 	return ioutil.NopCloser(strings.NewReader(newBody(t, res)))
 }
 
 func newPollerBody(t *testing.T, pending, current *models.ElasticsearchClusterPlanInfo) io.ReadCloser {
 	payload := &models.ElasticsearchClusterPlansInfo{Pending: pending, Current: current}
-	var response, err = json.MarshalIndent(payload, "", "  ")
-	if err != nil {
-		t.Fatal(err)
-	}
-	response = append(response, []byte("\n\n")...)
-	return ioutil.NopCloser(bytes.NewReader(response))
+	return newPayloadFromStruct(t, payload)
 }
 
 func newApmPollerBody(t *testing.T, pending, current *models.ApmPlanInfo) io.ReadCloser {
 	payload := &models.ApmPlansInfo{Pending: pending, Current: current}
-	var response, err = json.MarshalIndent(payload, "", "  ")
-	if err != nil {
-		t.Fatal(err)
-	}
-	response = append(response, []byte("\n\n")...)
-	return ioutil.NopCloser(bytes.NewReader(response))
+	return newPayloadFromStruct(t, payload)
+}
+
+func newAppSearchPollerBody(t *testing.T, pending, current *models.AppSearchPlanInfo) io.ReadCloser {
+	payload := &models.AppSearchPlansInfo{Pending: pending, Current: current}
+	return newPayloadFromStruct(t, payload)
 }
 
 func newKibanaPollerBody(t *testing.T, pending, current *models.KibanaClusterPlanInfo) io.ReadCloser {
 	payload := &models.KibanaClusterPlansInfo{Pending: pending, Current: current}
+	return newPayloadFromStruct(t, payload)
+}
+
+func newPayloadFromStruct(t *testing.T, payload interface{}) io.ReadCloser {
 	var response, err = json.MarshalIndent(payload, "", "  ")
 	if err != nil {
 		t.Fatal(err)
@@ -331,32 +393,6 @@ func newAllocator(t *testing.T, id, clusterID, kind string) io.ReadCloser {
 	return ioutil.NopCloser(strings.NewReader(newBody(t, res)))
 }
 
-type vacateCase struct {
-	topology []vacateCaseClusters
-}
-
-type vacateCaseClusters struct {
-	// Allocator ID
-	Allocator string
-	// Elasticsearch clusters that will be simulated
-	elasticsearch []vacateCaseClusterConfig
-	// Kibana instances that will be simulated
-	kibana []vacateCaseClusterConfig
-	// APM clusters that will be simulated
-	apm []vacateCaseClusterConfig
-}
-
-type vacateCaseClusterConfig struct {
-	// ID of the cluster
-	ID string
-	// Fails the `_move` api call to actually move a cluster
-	fail bool
-	// Plan steps that are fetched by the
-	steps [][]*models.ClusterPlanStepInfo
-	// Current plan steps the move
-	plan []*models.ClusterPlanStepInfo
-}
-
 // newVacateTestCase builds a test case from a vacateCase topology
 func newVacateTestCase(t *testing.T, tc vacateCase) *VacateParams {
 	var responses = make([]mock.Response, 0, len(tc.topology))
@@ -370,6 +406,7 @@ func newVacateTestCase(t *testing.T, tc vacateCase) *VacateParams {
 		var esmoves []string
 		var kibanaMoves []string
 		var apmMoves []string
+		var appsearchMoves []string
 
 		// Get all moves
 		for ii := range topology.elasticsearch {
@@ -381,9 +418,12 @@ func newVacateTestCase(t *testing.T, tc vacateCase) *VacateParams {
 		for ii := range topology.apm {
 			apmMoves = append(apmMoves, topology.apm[ii].ID)
 		}
+		for ii := range topology.appsearch {
+			appsearchMoves = append(appsearchMoves, topology.appsearch[ii].ID)
+		}
 
 		responses = append(responses, mock.Response{Response: http.Response{
-			Body:       newMulipleMoves(t, alloc, esmoves, kibanaMoves, apmMoves),
+			Body:       newMulipleMoves(t, alloc, esmoves, kibanaMoves, apmMoves, appsearchMoves),
 			StatusCode: 202,
 		}})
 	}
@@ -407,8 +447,14 @@ func newVacateTestCase(t *testing.T, tc vacateCase) *VacateParams {
 			_, r := newAPMVacateMove(t, alloc, topology.apm[ii])
 			responses = append(responses, r...)
 		}
+
+		for ii := range topology.appsearch {
+			_, r := newAppsearchVacateMove(t, alloc, topology.appsearch[ii])
+			responses = append(responses, r...)
+		}
 	}
 	return &VacateParams{
+		SkipTracking:   tc.skipTracking,
 		Output:         output.NewDevice(sdkSync.NewBuffer()),
 		Allocators:     allocators,
 		API:            api.NewMock(responses...),
@@ -424,7 +470,7 @@ func newAPMVacateMove(t *testing.T, alloc string, move vacateCaseClusterConfig)
 		Body:       newAllocator(t, alloc, move.ID, "apm"),
 		StatusCode: 200,
 	}}, mock.Response{Response: http.Response{
-		Body:       newKibanaMove(t, move.ID, alloc),
+		Body:       newApmMove(t, move.ID, alloc),
 		StatusCode: 202,
 	}})
 
@@ -629,3 +675,74 @@ func newElasticsearchVacateMove(t *testing.T, alloc string, move vacateCaseClust
 
 	return api.NewMock(responses...), responses
 }
+
+func newAppsearchVacateMove(t *testing.T, alloc string, move vacateCaseClusterConfig) (*api.API, []mock.Response) {
+	var responses = make([]mock.Response, 0, 4)
+	responses = append(responses, mock.Response{Response: http.Response{
+		Body:       newAllocator(t, alloc, move.ID, "appsearch"),
+		StatusCode: 200,
+	}}, mock.Response{Response: http.Response{
+		Body:       newAppsearchMove(t, move.ID, alloc),
+		StatusCode: 202,
+	}})
+
+	if move.fail {
+		body := ioutil.NopCloser(strings.NewReader(newBody(t, &models.MoveClustersCommandResponse{
+			Failures: &models.MoveClustersDetails{
+				ApmClusters: []*models.MoveApmClusterDetails{{
+					ClusterID: ec.String(move.ID),
+					CalculatedPlan: &models.TransientApmPlanConfiguration{
+						PlanConfiguration: &models.ApmPlanControlConfiguration{
+							MoveAllocators: []*models.AllocatorMoveRequest{{From: ec.String(alloc)}},
+						},
+					},
+					Errors: []*models.BasicFailedReplyElement{
+						{
+							Code:    ec.String("a code"),
+							Message: ec.String("a message"),
+						},
+					},
+				}},
+			}})))
+		// Return a response with a failed move
+		responses = append(responses, mock.Response{Response: http.Response{
+			Body:       body,
+			StatusCode: 202,
+		}})
+		// No extra responses should be given back for this cluster
+		// when a move failures happens.
+		return api.NewMock(responses...), responses
+	}
+
+	responses = append(responses, mock.Response{Response: http.Response{
+		Body:       newAppsearchMove(t, move.ID, alloc),
+		StatusCode: 202,
+	}})
+
+	// Define steps
+	for iii := range move.steps {
+		var step = move.steps[iii]
+		responses = append(responses, mock.Response{Response: http.Response{
+			StatusCode: 200,
+			Body: newAppSearchPollerBody(t,
+				&models.AppSearchPlanInfo{PlanAttemptLog: step},
+				nil,
+			),
+		}})
+	}
+
+	// Plan finished
+	responses = append(responses,
+		util.PlanNotFound,
+		util.PlanNotFound,
+		mock.Response{Response: http.Response{
+			StatusCode: 200,
+			Body: newAppSearchPollerBody(t,
+				nil,
+				&models.AppSearchPlanInfo{PlanAttemptLog: move.plan},
+			),
+		}},
+	)
+
+	return api.NewMock(responses...), responses
+}
diff --git a/pkg/platform/allocator/vacate_test.go b/pkg/platform/allocator/vacate_test.go
index 5773c25..f3bf658 100644
--- a/pkg/platform/allocator/vacate_test.go
+++ b/pkg/platform/allocator/vacate_test.go
@@ -97,6 +97,18 @@ func TestComputeVacateRequest(t *testing.T) {
 							},
 						},
 					},
+					AppsearchClusters: []*models.MoveAppSearchDetails{
+						{
+							ClusterID: ec.String("d8ad23ad6f064709bbae7ab87a7e1bc9"),
+							CalculatedPlan: &models.TransientAppSearchPlanConfiguration{
+								PlanConfiguration: &models.AppSearchPlanControlConfiguration{
+									Timeout:             4096,
+									ReallocateInstances: ec.Bool(false),
+									ExtendedMaintenance: ec.Bool(false),
+								},
+							},
+						},
+					},
 				},
 				clusters: nil,
 				to:       nil,
@@ -148,6 +160,20 @@ func TestComputeVacateRequest(t *testing.T) {
 						},
 					},
 				},
+				AppsearchClusters: []*models.MoveAppSearchConfiguration{
+					{
+						ClusterIds: []string{
+							"d8ad23ad6f064709bbae7ab87a7e1bc9",
+						},
+						PlanOverride: &models.TransientAppSearchPlanConfiguration{
+							PlanConfiguration: &models.AppSearchPlanControlConfiguration{
+								Timeout:             4096,
+								ReallocateInstances: ec.Bool(false),
+								ExtendedMaintenance: ec.Bool(false),
+							},
+						},
+					},
+				},
 			},
 		},
 		{
@@ -579,7 +605,7 @@ func TestCheckVacateFailures(t *testing.T) {
 			}},
 		},
 		{
-			name: "Returns na apm error on Kibana vacate failure",
+			name: "Returns an error on APM vacate failure",
 			args: args{
 				failures: &models.MoveClustersDetails{
 					ApmClusters: []*models.MoveApmClusterDetails{
@@ -599,6 +625,27 @@ func TestCheckVacateFailures(t *testing.T) {
 				errors.New("cluster [123456789][apm] failed vacating, reason: code: unknown, message: an apm error message"),
 			}},
 		},
+		{
+			name: "Returns an error on AppSearch vacate failure",
+			args: args{
+				failures: &models.MoveClustersDetails{
+					AppsearchClusters: []*models.MoveAppSearchDetails{
+						{
+							ClusterID: ec.String("123456789"),
+							Errors: []*models.BasicFailedReplyElement{
+								{
+									Code:    ec.String("unknown"),
+									Message: ec.String("an apm error message"),
+								},
+							},
+						},
+					},
+				},
+			},
+			err: &multierror.Error{Errors: []error{
+				errors.New("cluster [123456789][appsearch] failed vacating, reason: code: unknown, message: an apm error message"),
+			}},
+		},
 		{
 			name: "Returns an elasticsearch & kibana error on multiple ES & Kibana vacate failures",
 			args: args{
@@ -823,6 +870,24 @@ func TestVacateCluster(t *testing.T) {
 				},
 			},
 		},
+		{
+			name: "Succeeds with an appsearch instance with no tracking",
+			args: args{
+				buf: new(bytes.Buffer),
+				params: &VacateClusterParams{
+					ID:             "someID",
+					ClusterID:      "2ee11eb40eda22cac0cce259625c6734",
+					Kind:           "appsearch",
+					Output:         new(output.Device),
+					TrackFrequency: time.Nanosecond,
+					SkipTracking:   true,
+					MaxPollRetries: 1,
+					API: discardResponses(
+						newKibanaVacateMove(t, "someID", vacateCaseClusterConfig{}),
+					),
+				},
+			},
+		},
 		{
 			name: "Moving kibana instance fails",
 			args: args{
@@ -1131,7 +1196,61 @@ func Test_addAllocatorMovesToPool(t *testing.T) {
 			wantMoved:     true,
 		},
 		{
-			name: "Move clusters when a matching filter is specified",
+			name: "Move clusters when no filter is specified (Apm)",
+			args: args{params: addAllocatorMovesToPoolParams{
+				ID: "allocator-1",
+				Pool: func() *pool.Pool {
+					p, _ := pool.NewPool(pool.Params{
+						Size:    1,
+						Run:     VacateClusterInPool,
+						Timeout: pool.DefaultTimeout,
+					})
+					return p
+				}(),
+				VacateParams: &VacateParams{},
+				Moves: &models.MoveClustersDetails{
+					ApmClusters: []*models.MoveApmClusterDetails{
+						{
+							ClusterID: ec.String("d7ad23ad6f064709bbae7ab87a7e1bc9"),
+							CalculatedPlan: &models.TransientApmPlanConfiguration{
+								PlanConfiguration: &models.ApmPlanControlConfiguration{},
+							},
+						},
+					},
+				},
+			}},
+			wantLeftovers: nil,
+			wantMoved:     true,
+		},
+		{
+			name: "Move clusters when no filter is specified (AppSearch)",
+			args: args{params: addAllocatorMovesToPoolParams{
+				ID: "allocator-1",
+				Pool: func() *pool.Pool {
+					p, _ := pool.NewPool(pool.Params{
+						Size:    1,
+						Run:     VacateClusterInPool,
+						Timeout: pool.DefaultTimeout,
+					})
+					return p
+				}(),
+				VacateParams: &VacateParams{},
+				Moves: &models.MoveClustersDetails{
+					AppsearchClusters: []*models.MoveAppSearchDetails{
+						{
+							ClusterID: ec.String("d7ad23ad6f064709bbae7ab87a7e1bc9"),
+							CalculatedPlan: &models.TransientAppSearchPlanConfiguration{
+								PlanConfiguration: &models.AppSearchPlanControlConfiguration{},
+							},
+						},
+					},
+				},
+			}},
+			wantLeftovers: nil,
+			wantMoved:     true,
+		},
+		{
+			name: "Move clusters when a matching filter is specified (Kibana)",
 			args: args{params: addAllocatorMovesToPoolParams{
 				ID: "allocator-1",
 				Pool: func() *pool.Pool {
@@ -1166,7 +1285,7 @@ func Test_addAllocatorMovesToPool(t *testing.T) {
 			wantMoved:     true,
 		},
 		{
-			name: "Move clusters when a matching filter is specified",
+			name: "Move clusters when a matching filter is specified (Elasticsearch)",
 			args: args{params: addAllocatorMovesToPoolParams{
 				ID: "allocator-1",
 				Pool: func() *pool.Pool {
@@ -1200,6 +1319,33 @@ func Test_addAllocatorMovesToPool(t *testing.T) {
 			wantLeftovers: nil,
 			wantMoved:     true,
 		},
+		{
+			name: "Move clusters when no filter is specified (AppSearch)",
+			args: args{params: addAllocatorMovesToPoolParams{
+				ID: "allocator-1",
+				Pool: func() *pool.Pool {
+					p, _ := pool.NewPool(pool.Params{
+						Size:    1,
+						Run:     VacateClusterInPool,
+						Timeout: pool.DefaultTimeout,
+					})
+					return p
+				}(),
+				VacateParams: &VacateParams{KindFilter: "appsearch"},
+				Moves: &models.MoveClustersDetails{
+					AppsearchClusters: []*models.MoveAppSearchDetails{
+						{
+							ClusterID: ec.String("d7ad23ad6f064709bbae7ab87a7e1bc9"),
+							CalculatedPlan: &models.TransientAppSearchPlanConfiguration{
+								PlanConfiguration: &models.AppSearchPlanControlConfiguration{},
+							},
+						},
+					},
+				},
+			}},
+			wantLeftovers: nil,
+			wantMoved:     true,
+		},
 		{
 			name: "Skip move clusters when a non-matching filter is specified",
 			args: args{params: addAllocatorMovesToPoolParams{