From 44009c8da24c67129b7f497ac1c106c616658d29 Mon Sep 17 00:00:00 2001 From: Martin Date: Wed, 9 Jan 2019 15:09:07 -0800 Subject: [PATCH] =?UTF-8?q?Initial=20commit=20=F0=9F=8E=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .gitignore | 60 +++++++++++++++++++++++ .goreleaser.yml | 10 ++++ README.md | 11 +++++ copyenv.go | 127 ++++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 208 insertions(+) create mode 100644 .gitignore create mode 100644 .goreleaser.yml create mode 100644 README.md create mode 100644 copyenv.go diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..6af2822 --- /dev/null +++ b/.gitignore @@ -0,0 +1,60 @@ +# Created by https://www.gitignore.io/api/go,osx,visualstudiocode + +### OSX ### +# General +.DS_Store +.AppleDouble +.LSOverride + +# Icon must end with two \r +Icon + +# Thumbnails +._* + +# Files that might appear in the root of a volume +.DocumentRevisions-V100 +.fseventsd +.Spotlight-V100 +.TemporaryItems +.Trashes +.VolumeIcon.icns +.com.apple.timemachine.donotpresent + +# Directories potentially created on remote AFP share +.AppleDB +.AppleDesktop +Network Trash Folder +Temporary Items +.apdisk + +### VisualStudioCode ### +.vscode/* +!.vscode/settings.json +!.vscode/tasks.json +!.vscode/launch.json +!.vscode/extensions.json + +### VisualStudioCode Patch ### +# Ignore all local history of files +.history + +### Go ### +# Binaries for programs and plugins +*.exe +*.exe~ +*.dll +*.so +*.dylib + +# Test binary, built with `go test -c` +*.test + +# Output of the go coverage tool, specifically when used with LiteIDE +*.out + +### Go Patch ### +/vendor/ +/Godeps/ + +copyenv \ No newline at end of file diff --git a/.goreleaser.yml b/.goreleaser.yml new file mode 100644 index 0000000..f7e13d1 --- /dev/null +++ b/.goreleaser.yml @@ -0,0 +1,10 @@ +builds: +- env: + - CGO_ENABLED=0 +archive: + replacements: + darwin: Darwin +checksum: + name_template: 'checksums.txt' +snapshot: + name_template: "{{ .Tag }}-next" diff --git a/README.md b/README.md new file mode 100644 index 0000000..1f3fdd1 --- /dev/null +++ b/README.md @@ -0,0 +1,11 @@ +# Cloud Foundry CLI Copy Env Plugin + +Cloud Foundry CLI plugin to export application VCAP_SERVICES and VCAP_APPLICATION. + +## Usage + +```bash +copyenv APP_NAME [--all] + +export VCAP_SERVICES='...' +``` diff --git a/copyenv.go b/copyenv.go new file mode 100644 index 0000000..fefb17b --- /dev/null +++ b/copyenv.go @@ -0,0 +1,127 @@ +package main + +import ( + "encoding/json" + "errors" + "fmt" + "os" + "strings" + + "code.cloudfoundry.org/cli/plugin" +) + +type CopyEnv struct{} + +func (c *CopyEnv) retrieveAppNameEnv(cliConnection plugin.CliConnection, appName string) ([]string, error) { + var guid string + + apps, err := cliConnection.GetApps() + if err != nil { + msg := fmt.Sprintf("Failed to retrieve enviroment for \"%s\", is the app name correct?", appName) + err = errors.New(msg) + } + + for _, element := range apps { + if element.Name == appName { + guid = element.Guid + break + } + } + + if guid == "" { + msg := fmt.Sprintf("Failed to retrieve enviroment for \"%s\", is the app name correct?", appName) + err = errors.New(msg) + } else { + url := fmt.Sprintf("/v2/apps/%s/env", guid) + output, err := cliConnection.CliCommandWithoutTerminalOutput("curl", url) + + if err != nil { + msg := fmt.Sprintf("Failed to retrieve enviroment for \"%s\", is the app name correct?", appName) + err = errors.New(msg) + } + + return output, err + } + return nil, err +} + +func (c *CopyEnv) extractCredentialsJSON(envParent string, credKey string, output []string) ([]byte, error) { + err := errors.New("Missing service credentials for application") + var envJson []byte + + envKey := strings.Join(output, "") + if strings.Contains(envKey, credKey) { + var f interface{} + err = json.Unmarshal([]byte(envKey), &f) + if err != nil { + return nil, err + } + + envJSON := f.(map[string]interface{}) + envParentJSON := envJSON[envParent].(map[string]interface{}) + envJson, err = json.Marshal(envParentJSON[credKey]) + if err != nil { + return nil, err + } + } + + return envJson, err +} + +func (c *CopyEnv) extractAndExportCredentials(envParent string, credKey string, appEnv []string) { + creds, err := c.extractCredentialsJSON(envParent, credKey, appEnv) + checkErr(err) + vcapServices := fmt.Sprintf("export %s='%s';", credKey, string(creds[:])) + fmt.Println(vcapServices) +} + +func (c *CopyEnv) Run(cliConnection plugin.CliConnection, args []string) { + if len(args) < 2 { + checkErr(errors.New("Missing application name")) + } + + appName := args[1] + + appEnv, err := c.retrieveAppNameEnv(cliConnection, appName) + checkErr(err) + + if len(args) > 2 && args[2] == "--all" { + c.extractAndExportCredentials("application_env_json", "VCAP_APPLICATION", appEnv) + fmt.Println("") + } + c.extractAndExportCredentials("system_env_json", "VCAP_SERVICES", appEnv) +} + +func (c *CopyEnv) GetMetadata() plugin.PluginMetadata { + return plugin.PluginMetadata{ + Name: "copyenv", + Version: plugin.VersionType{ + Major: 1, + Minor: 0, + Build: 0, + }, + Commands: []plugin.Command{ + plugin.Command{ + Name: "copyenv", + HelpText: "Export application VCAP_SERVICES.", + UsageDetails: plugin.Usage{ + Usage: "copyenv APP_NAME [--all] - Retrieve and export remote application VCAP_SERVICES.", + Options: map[string]string{ + "all": "Retrieve both VCAP_SERVICES and VCAP_APPLICATION from remote application", + }, + }, + }, + }, + } +} + +func checkErr(err error) { + if err != nil { + fmt.Fprintln(os.Stderr, "error: ", err) + os.Exit(1) + } +} + +func main() { + plugin.Start(new(CopyEnv)) +}