From b827135200fbe7fff2ffd82581f5a435b344da07 Mon Sep 17 00:00:00 2001 From: Travis Reeder Date: Tue, 24 Jan 2017 08:08:40 -0800 Subject: [PATCH] Switch to go-swagger for client lib and checks for IRON_TOKEN (#406) * wip - for review, using go-swagger client and checking for IRON_TOKEN and passing as auth header. * wip - auth header * add golang builder * finish client builder * change gh username * fix git command * update readme and small fixes * some improvements * using go-swagger * fn new client * revert swagger * make fn routes and apps work with new client (go-swagger) * some fixes in fn apps * update functions_go --- clients/README.md | 6 + clients/build.rb | 31 ++-- clients/main.go | 315 +++++++++++++++++++++++++++++++++++ fn/api.go | 37 +++++ fn/apps.go | 191 +++++++++++++--------- fn/glide.lock | 91 +++++++++-- fn/glide.yaml | 2 +- fn/routes.go | 409 ++++++++++++++++++++++++++-------------------- 8 files changed, 794 insertions(+), 288 deletions(-) create mode 100644 clients/main.go create mode 100644 fn/api.go diff --git a/clients/README.md b/clients/README.md index f7dacb1a7..401f6d46a 100644 --- a/clients/README.md +++ b/clients/README.md @@ -24,6 +24,12 @@ ruby build.rb Boom. That's it. +## Building with the Go Builder + +```sh +go run main.go +``` + ## Troubleshooting Sometimes this will fail due to github caching or something and versions will be off. Just bump version and retry. diff --git a/clients/build.rb b/clients/build.rb index 9743bc2da..81f5926c3 100644 --- a/clients/build.rb +++ b/clients/build.rb @@ -22,7 +22,7 @@ ctx.verify_mode = OpenSSL::SSL::VERIFY_NONE def clone(lang) Dir.chdir 'tmp' ldir = "functions_#{lang}" - if !Dir.exists? ldir + if !Dir.exist? ldir cmd = "git clone https://github.com/iron-io/#{ldir}" stream_exec(cmd) else @@ -84,18 +84,25 @@ languages.each do |l| next end p options - gen = JSON.parse(HTTP.post("https://generator.swagger.io/api/gen/clients/#{l}", - json: { - swaggerUrl: swaggerUrl, - options: options, - }, - ssl_context: ctx).body) - p gen + if l == 'go' + puts "SKIPPING GO, it's manual for now." + # This is using https://goswagger.io/ instead + # TODO: run this build command instead: this works if run manually + # glide install -v && docker run --rm -it -v $HOME/dev/go:/go -w /go/src/github.com/iron-io/functions_go quay.io/goswagger/swagger generate client -f https://raw.githubusercontent.com/iron-io/functions/master/docs/swagger.yml -A functions + else + gen = JSON.parse(HTTP.post("https://generator.swagger.io/api/gen/clients/#{l}", + json: { + swaggerUrl: swaggerUrl, + options: options, + }, + ssl_context: ctx).body) + p gen - lv = "#{lshort}-#{version}" - zipfile = "tmp/#{lv}.zip" - stream_exec "curl -o #{zipfile} #{gen['link']} -k" - stream_exec "unzip -o #{zipfile} -d tmp/#{lv}" + lv = "#{lshort}-#{version}" + zipfile = "tmp/#{lv}.zip" + stream_exec "curl -o #{zipfile} #{gen['link']} -k" + stream_exec "unzip -o #{zipfile} -d tmp/#{lv}" + end # delete the skip_files skip_files.each do |sf| diff --git a/clients/main.go b/clients/main.go new file mode 100644 index 000000000..9b622e946 --- /dev/null +++ b/clients/main.go @@ -0,0 +1,315 @@ +package main + +import ( + "bytes" + "encoding/json" + "fmt" + + "github.com/go-openapi/loads/fmts" + "github.com/go-openapi/spec" + "io/ioutil" + "log" + "net/http" + "os" + "os/exec" + "os/user" + "path/filepath" + "strings" +) + +const ( + swaggerURL = "../docs/swagger.yml" + rootTmpDir = "tmp" +) + +var cwd string + +func main() { + os.RemoveAll(rootTmpDir) + cwd, _ = os.Getwd() + defer func() { + os.RemoveAll(rootTmpDir) + }() + + // Download swagger yaml and convert to JSON + d, err := fmts.YAMLDoc(swaggerURL) + if err != nil { + log.Fatalf("Failed to convert swagger yaml to json: %v", err) + } + + var sw spec.Swagger + if err := json.Unmarshal(d, &sw); err != nil { + log.Fatalf("Failed to convert swagger yaml to json: %v", err) + } + + version := sw.Info.Version + fmt.Printf("VERSION: %s\n", version) + + swg, err := ioutil.ReadFile(swaggerURL) + if err != nil { + log.Fatalf("Failed to load swagger file: %v", err) + } + gistURL := createGist(swg) + + var only string + if len(os.Args) > 1 && os.Args[1] != "" { + only = os.Args[1] + } + + var languages []string + if only != "" { + languages = append(languages, only) + } else { + // Download available languages from swagger generator api + languages = getLanguages() + } + + for _, language := range languages { + var skipFiles []string + tmpDir := filepath.Join(rootTmpDir, language) + srcDir := filepath.Join(tmpDir, "src") + clientDir := filepath.Join(tmpDir, fmt.Sprintf("%s-client", language)) + short := language + + options := make(map[string]interface{}) + var deploy [][]string + + // Specfic language configurations + switch language { + case "go": + options["packageName"] = "functions" + options["packageVersion"] = version + case "ruby": + skipFiles = append(skipFiles, "#{gem_name}.gemspec") + deploy = append(deploy, []string{"gem", "build #{gem_name}.gemspec", "gem push #{gem_name}-#{version}.gem"}) + options["gemName"] = "iron_functions" + options["moduleName"] = "IronFunctions" + options["gemVersion"] = version + options["gemHomepage"] = "https://github.com/iron-io/functions_ruby" + options["gemSummary"] = "Ruby gem for IronFunctions" + options["gemDescription"] = "Ruby gem for IronFunctions." + options["gemAuthorEmail"] = "travis@iron.io" + case "javascript": + short = "js" + options["projectName"] = "iron_functions" + deploy = append(deploy, []string{"npm", "publish"}) + default: + continue + } + + log.Printf("Generating `%s` client...\n", language) + err = os.MkdirAll(clientDir, 0777) + if err != nil { + log.Printf("Failed to create temporary directory for %s client. Skipping...", language) + } + + // Generate client + if language == "go" { + err := genSwaggerClient(clientDir) + if err != nil { + log.Printf("Failed to (swagger-go) generated %s client. Skipping...", language) + continue + } + } else { + gen, err := generateClient(gistURL, language, options) + if err != nil { + log.Printf("Failed to generated %s client. Skipping...", language) + continue + } + + // Download generated client + log.Printf("Downloading `%s` client...\n", language) + gf, err := getFile(strings.Replace(gen.Link, "https", "http", 1)) + if err != nil { + log.Printf("Failed to download generated %s client. Skipping...", language) + } + ioutil.WriteFile(filepath.Join(tmpDir, "gen.zip"), gf, 0777) + + // Unzip + log.Printf("Unzipping `%s` client...\n", language) + exec.Command("unzip", "-o", filepath.Join(tmpDir, "gen.zip"), "-d", tmpDir).Run() + os.Remove(filepath.Join(tmpDir, "gen.zip")) + } + + branch := fmt.Sprintf("update-version-%s", version) + + log.Printf("Cloning previous `%s` source...\n", language) + exec.Command("git", "clone", fmt.Sprintf("git@github.com:iron-io/functions_%s.git", short), srcDir).Run() + + // Skip language specific files + for _, skip := range skipFiles { + os.Remove(filepath.Join(tmpDir, clientDir, skip)) + } + + // Copying new client + log.Printf("Copying new `%s` client to src directory\n", language) + + // Only solution I found + filepath.Walk(clientDir, func(path string, info os.FileInfo, err error) error { + if path == clientDir { + return nil + } + exec.Command("cp", "-r", path, srcDir).Run() + if info.IsDir() { + return filepath.SkipDir + } + return nil + }) + + f, err := os.OpenFile(filepath.Join(srcDir, "VERSION"), os.O_TRUNC|os.O_WRONLY, 0644) + if err != nil { + log.Printf("Failed to save new `%s` VERSION file. Skipping...", language) + continue + } + f.WriteString(version) + f.Close() + + os.Chdir(srcDir) + exec.Command("git", "checkout", "-b", branch).Run() + exec.Command("git", "add", ".").Run() + exec.Command("git", "commit", "-am", fmt.Sprintf("Updated to api version %s", version)).Run() + + log.Printf("Pushing new `%s` client\n", language) + r := exec.Command("git", "push", "origin", branch).Run() + if r != nil && r.Error() != "" { + log.Printf("Failed to push new version: %s\n", r.Error()) + break + } + + log.Printf("Releasing new `%s` client\n", language) + for _, d := range deploy { + exec.Command(d[0], d[1]) + } + + log.Printf("Updated `%s` client to `%s` \n", language, version) + + os.Chdir(cwd) + } +} + +type generatedClient struct { + Link string `json:"link"` +} + +func generateClient(url, lang string, options map[string]interface{}) (gc generatedClient, err error) { + payload := map[string]interface{}{ + "swaggerUrl": url, + "options": options, + } + + data, err := json.Marshal(payload) + if err != nil { + return + } + + resp, err := http.Post(fmt.Sprintf("http://generator.swagger.io/api/gen/clients/%s", lang), "application/json", bytes.NewBuffer(data)) + if err != nil { + return + } + result, err := ioutil.ReadAll(resp.Body) + if err != nil { + return + } + + err = json.Unmarshal(result, &gc) + if err != nil { + return + } + + return +} + +func getFile(url string) ([]byte, error) { + resp, err := http.Get(url) + if err != nil { + return nil, err + } + data, err := ioutil.ReadAll(resp.Body) + if err != nil { + return nil, err + } + + return data, nil +} + +func getLanguages() (langs []string) { + data, err := getFile("http://generator.swagger.io/api/gen/clients") + if err != nil { + log.Fatalf("Failed to load swagger languages: %v", err) + os.Exit(-1) + } + + err = json.Unmarshal(data, &langs) + if err != nil { + log.Fatalf("Failed to load swagger languages: %v", err) + os.Exit(-1) + } + + return +} + +type GistFile struct { + Content string `json:"content"` +} + +type Gist struct { + Description string `json:"description"` + Public bool `json:"public"` + Files map[string]GistFile `json:"files"` +} + +type GistResponse struct { + Files map[string]struct { + RawURL string `json:"raw_url"` + } `json:"files"` +} + +func createGist(b []byte) string { + var responseObj GistResponse + + gist := Gist{ + "", + false, + map[string]GistFile{ + "swaggerSpec": {string(b)}, + }, + } + + b, err := json.Marshal(gist) + if err != nil { + log.Fatal("JSON Error: ", err) + } + + br := bytes.NewBuffer(b) + resp, err := http.Post("https://api.github.com/gists", "application/json", br) + if err != nil { + log.Fatal("HTTP Error: ", err) + } + + err = json.NewDecoder(resp.Body).Decode(&responseObj) + if err != nil { + log.Fatal("Response JSON Error: ", err) + } + + return responseObj.Files["swaggerSpec"].RawURL +} + +const ( + goSwaggerImage = "quay.io/goswagger/swagger" +) + +func genSwaggerClient(target string) error { + u, err := user.Current() + if err != nil { + return err + } + + cmd := exec.Command("docker", "run", "--rm", "-u", fmt.Sprintf("%s:%s", u.Uid, u.Gid), "-v", fmt.Sprintf("%s/%s:/go/src/github.com/iron-io/functions_go", cwd, target), "-v", fmt.Sprintf("%s/%s:/go/swagger.spec", cwd, swaggerURL), "-w", "/go/src", "quay.io/goswagger/swagger", "generate", "client", "-f", "/go/swagger.spec", "-t", "github.com/iron-io/functions_go", "-A", "functions") + d, err := cmd.CombinedOutput() + if err != nil { + log.Printf("Error running go-swagger: %s\n", d) + return err + } + + return nil +} diff --git a/fn/api.go b/fn/api.go new file mode 100644 index 000000000..76ba40dde --- /dev/null +++ b/fn/api.go @@ -0,0 +1,37 @@ +package main + +import ( + "os" + + httptransport "github.com/go-openapi/runtime/client" + "github.com/go-openapi/strfmt" + fnclient "github.com/iron-io/functions_go/client" + "log" + "net/url" +) + +func host() string { + apiURL := os.Getenv("API_URL") + if apiURL == "" { + apiURL = "http://localhost:8080" + } + + u, err := url.Parse(apiURL) + if err != nil { + log.Fatalln("Couldn't parse API URL:", err) + } + + return u.Host +} + +func apiClient() *fnclient.Functions { + transport := httptransport.New(host(), "/v1", []string{"http"}) + if os.Getenv("IRON_TOKEN") != "" { + transport.DefaultAuthentication = httptransport.BearerToken(os.Getenv("IRON_TOKEN")) + } + + // create the API client, with the transport + client := fnclient.New(transport, strfmt.Default) + + return client +} diff --git a/fn/apps.go b/fn/apps.go index dffeee948..8513da47d 100644 --- a/fn/apps.go +++ b/fn/apps.go @@ -4,20 +4,22 @@ import ( "encoding/json" "errors" "fmt" - "net/http" "os" "text/tabwriter" - "github.com/iron-io/functions_go" + "context" + fnclient "github.com/iron-io/functions_go/client" + apiapps "github.com/iron-io/functions_go/client/apps" + "github.com/iron-io/functions_go/models" "github.com/urfave/cli" ) type appsCmd struct { - *functions.AppsApi + client *fnclient.Functions } func apps() cli.Command { - a := appsCmd{AppsApi: functions.NewAppsApi()} + a := appsCmd{client: apiClient()} return cli.Command{ Name: "apps", @@ -90,25 +92,26 @@ func apps() cli.Command { } func (a *appsCmd) list(c *cli.Context) error { - if err := resetBasePath(a.Configuration); err != nil { - return fmt.Errorf("error setting endpoint: %v", err) - } + resp, err := a.client.Apps.GetApps(&apiapps.GetAppsParams{ + Context: context.Background(), + }) - wrapper, _, err := a.AppsGet() if err != nil { - return fmt.Errorf("error getting app: %v", err) + switch err.(type) { + case *apiapps.GetAppsAppNotFound: + return fmt.Errorf("error: %v", err.(*apiapps.GetAppsAppNotFound).Payload.Error.Message) + case *apiapps.GetAppsAppDefault: + return fmt.Errorf("unexpected error: %v", err.(*apiapps.GetAppsAppDefault).Payload.Error.Message) + } + return fmt.Errorf("unexpected error: %v", err) } - if msg := wrapper.Error_.Message; msg != "" { - return errors.New(msg) - } - - if len(wrapper.Apps) == 0 { + if len(resp.Payload.Apps) == 0 { fmt.Println("no apps found") return nil } - for _, app := range wrapper.Apps { + for _, app := range resp.Payload.Apps { fmt.Println(app.Name) } @@ -120,24 +123,29 @@ func (a *appsCmd) create(c *cli.Context) error { return errors.New("error: app creating takes one argument, an app name") } - if err := resetBasePath(a.Configuration); err != nil { - return fmt.Errorf("error setting endpoint: %v", err) - } - - body := functions.AppWrapper{App: functions.App{ + body := &models.AppWrapper{App: &models.App{ Name: c.Args().Get(0), Config: extractEnvConfig(c.StringSlice("config")), }} - wrapper, _, err := a.AppsPost(body) + + resp, err := a.client.Apps.PostApps(&apiapps.PostAppsParams{ + Context: context.Background(), + Body: body, + }) + if err != nil { - return fmt.Errorf("error creating app: %v", err) + switch err.(type) { + case *apiapps.PostAppsBadRequest: + return fmt.Errorf("error: %v", err.(*apiapps.PostAppsBadRequest).Payload.Error.Message) + case *apiapps.PostAppsConflict: + return fmt.Errorf("error: %v", err.(*apiapps.PostAppsConflict).Payload.Error.Message) + case *apiapps.PostAppsDefault: + return fmt.Errorf("unexpected error: %v", err.(*apiapps.PostAppsDefault).Payload.Error.Message) + } + return fmt.Errorf("unexpected error: %v", err) } - if msg := wrapper.Error_.Message; msg != "" { - return errors.New(msg) - } - - fmt.Println(wrapper.App.Name, "created") + fmt.Println(resp.Payload.App.Name, "created") return nil } @@ -146,21 +154,24 @@ func (a *appsCmd) configList(c *cli.Context) error { return errors.New("error: app description takes one argument, an app name") } - if err := resetBasePath(a.Configuration); err != nil { - return fmt.Errorf("error setting endpoint: %v", err) - } - appName := c.Args().Get(0) - wrapper, _, err := a.AppsAppGet(appName) + + resp, err := a.client.Apps.GetAppsApp(&apiapps.GetAppsAppParams{ + Context: context.Background(), + App: appName, + }) + if err != nil { - return fmt.Errorf("error creating app: %v", err) + switch err.(type) { + case *apiapps.GetAppsAppNotFound: + return fmt.Errorf("error: %v", err.(*apiapps.GetAppsAppNotFound).Payload.Error.Message) + case *apiapps.GetAppsAppDefault: + return fmt.Errorf("unexpected error: %v", err.(*apiapps.GetAppsAppDefault).Payload.Error.Message) + } + return fmt.Errorf("unexpected error: %v", err) } - if msg := wrapper.Error_.Message; msg != "" { - return errors.New(msg) - } - - config := wrapper.App.Config + config := resp.Payload.App.Config if len(config) == 0 { return errors.New("this application has no configurations") } @@ -171,11 +182,11 @@ func (a *appsCmd) configList(c *cli.Context) error { os.Exit(1) } } else if c.Bool("shell") { - for k, v := range wrapper.App.Config { + for k, v := range resp.Payload.App.Config { fmt.Print("export ", k, "=", v, "\n") } } else { - fmt.Println(wrapper.App.Name, "configuration:") + fmt.Println(resp.Payload.App.Name, "configuration:") w := tabwriter.NewWriter(os.Stdout, 0, 8, 1, ' ', 0) for k, v := range config { fmt.Fprint(w, k, ":\t", v, "\n") @@ -190,24 +201,26 @@ func (a *appsCmd) configSet(c *cli.Context) error { return errors.New("error: application configuration setting takes three arguments: an app name, a key and a value") } - if err := resetBasePath(a.Configuration); err != nil { - return fmt.Errorf("error setting endpoint: %v", err) - } - appName := c.Args().Get(0) key := c.Args().Get(1) value := c.Args().Get(2) - wrapper, _, err := a.AppsAppGet(appName) + resp, err := a.client.Apps.GetAppsApp(&apiapps.GetAppsAppParams{ + Context: context.Background(), + App: appName, + }) + if err != nil { - return fmt.Errorf("error creating app: %v", err) + switch err.(type) { + case *apiapps.GetAppsAppNotFound: + return fmt.Errorf("error: %v", err.(*apiapps.GetAppsAppNotFound).Payload.Error.Message) + case *apiapps.GetAppsAppDefault: + return fmt.Errorf("unexpected error: %v", err.(*apiapps.GetAppsAppDefault).Payload.Error.Message) + } + return fmt.Errorf("unexpected error: %v", err) } - if msg := wrapper.Error_.Message; msg != "" { - return errors.New(msg) - } - - config := wrapper.App.Config + config := resp.Payload.App.Config if config == nil { config = make(map[string]string) @@ -215,11 +228,11 @@ func (a *appsCmd) configSet(c *cli.Context) error { config[key] = value - if err := a.storeApp(appName, config); err != nil { + if err := a.patchApp(appName, config); err != nil { return fmt.Errorf("error updating app configuration: %v", err) } - fmt.Println(wrapper.App.Name, "updated", key, "with", value) + fmt.Println(resp.Payload.App.Name, "updated", key, "with", value) return nil } @@ -228,23 +241,25 @@ func (a *appsCmd) configUnset(c *cli.Context) error { return errors.New("error: application configuration setting takes three arguments: an app name, a key and a value") } - if err := resetBasePath(a.Configuration); err != nil { - return fmt.Errorf("error setting endpoint: %v", err) - } - appName := c.Args().Get(0) key := c.Args().Get(1) - wrapper, _, err := a.AppsAppGet(appName) + resp, err := a.client.Apps.GetAppsApp(&apiapps.GetAppsAppParams{ + Context: context.Background(), + App: appName, + }) + if err != nil { - return fmt.Errorf("error creating app: %v", err) + switch err.(type) { + case *apiapps.GetAppsAppNotFound: + return fmt.Errorf("error: %v", err.(*apiapps.GetAppsAppNotFound).Payload.Error.Message) + case *apiapps.GetAppsAppDefault: + return fmt.Errorf("unexpected error: %v", err.(*apiapps.GetAppsAppDefault).Payload.Error.Message) + } + return fmt.Errorf("unexpected error: %v", err) } - if msg := wrapper.Error_.Message; msg != "" { - return errors.New(msg) - } - - config := wrapper.App.Config + config := resp.Payload.App.Config if config == nil { config = make(map[string]string) @@ -256,23 +271,37 @@ func (a *appsCmd) configUnset(c *cli.Context) error { delete(config, key) - if err := a.storeApp(appName, config); err != nil { + if err := a.patchApp(appName, config); err != nil { return fmt.Errorf("error updating app configuration: %v", err) } - fmt.Println(wrapper.App.Name, "removed", key) + fmt.Println(resp.Payload.App.Name, "removed", key) return nil } -func (a *appsCmd) storeApp(appName string, config map[string]string) error { - body := functions.AppWrapper{App: functions.App{ - Name: appName, +func (a *appsCmd) patchApp(appName string, config map[string]string) error { + body := &models.AppWrapper{App: &models.App{ Config: config, }} - if _, _, err := a.AppsPost(body); err != nil { - return fmt.Errorf("error updating app configuration: %v", err) + _, err := a.client.Apps.PatchAppsApp(&apiapps.PatchAppsAppParams{ + Context: context.Background(), + App: appName, + Body: body, + }) + + if err != nil { + switch err.(type) { + case *apiapps.PatchAppsAppBadRequest: + return errors.New(err.(*apiapps.PatchAppsAppBadRequest).Payload.Error.Message) + case *apiapps.PatchAppsAppNotFound: + return errors.New(err.(*apiapps.PatchAppsAppNotFound).Payload.Error.Message) + case *apiapps.PatchAppsAppDefault: + return errors.New(err.(*apiapps.PatchAppsAppDefault).Payload.Error.Message) + } + return fmt.Errorf("unexpected error: %v", err) } + return nil } @@ -282,17 +311,19 @@ func (a *appsCmd) delete(c *cli.Context) error { return errors.New("error: deleting an app takes one argument, an app name") } - if err := resetBasePath(a.Configuration); err != nil { - return fmt.Errorf("error setting endpoint: %v", err) - } + _, err := a.client.Apps.DeleteAppsApp(&apiapps.DeleteAppsAppParams{ + Context: context.Background(), + App: appName, + }) - resp, err := a.AppsAppDelete(appName) if err != nil { - return fmt.Errorf("error deleting app: %v", err) - } - - if resp.StatusCode == http.StatusBadRequest { - return errors.New("could not delete this application - pending routes") + switch err.(type) { + case *apiapps.DeleteAppsAppNotFound: + return errors.New(err.(*apiapps.DeleteAppsAppNotFound).Payload.Error.Message) + case *apiapps.DeleteAppsAppDefault: + return errors.New(err.(*apiapps.DeleteAppsAppDefault).Payload.Error.Message) + } + return fmt.Errorf("unexpected error: %v", err) } fmt.Println(appName, "deleted") diff --git a/fn/glide.lock b/fn/glide.lock index cab0f9592..f435b04ea 100644 --- a/fn/glide.lock +++ b/fn/glide.lock @@ -1,8 +1,10 @@ -hash: 9356255bb45ddb833b045e985b2dbf0721791b431849a4f36a50b0897e888c3c -updated: 2016-12-29T19:40:42.322381915-02:00 +hash: a586a0b85eb753b0b618a3e763123480deb2ba6389496c1f1b897a9305326026 +updated: 2016-12-07T11:54:35.937180292-08:00 imports: +- name: github.com/asaskevich/govalidator + version: 7b3beb6df3c42abd3509abfc3bcacc0fbfb7c877 - name: github.com/aws/aws-sdk-go - version: 90dec2183a5f5458ee79cbaf4b8e9ab910bc81a6 + version: db9509b01e2e00890091ca164aebf0b1ca62eef8 subpackages: - aws - aws/awserr @@ -12,33 +14,42 @@ imports: - aws/corehandlers - aws/credentials - aws/credentials/ec2rolecreds + - aws/credentials/endpointcreds + - aws/credentials/stscreds - aws/defaults - aws/ec2metadata + - aws/endpoints - aws/request - aws/session - aws/signer/v4 - - private/endpoints - private/protocol - private/protocol/json/jsonutil - private/protocol/jsonrpc + - private/protocol/query + - private/protocol/query/queryutil - private/protocol/rest - private/protocol/restjson + - private/protocol/xml/xmlutil - service/lambda + - service/sts - name: github.com/Azure/go-ansiterm version: fa152c58bc15761d0200cb75fe958b89a9d4888e subpackages: - winterm - name: github.com/coreos/go-semver - version: 8ab6407b697782a06568d4b7f1db25550ec2e4c6 + version: 9474efc580562cce8f761659fbce31b6feb8ce88 subpackages: - semver - name: github.com/docker/docker - version: fae5a9e053ad06bea0429babae2507762d8cc1de + version: eefbf1ddd3ee4e6b6e6dc7e938e77a96ceb40163 subpackages: + - api/types - api/types/blkiodev - api/types/container - api/types/filters - api/types/mount + - api/types/network + - api/types/registry - api/types/strslice - api/types/swarm - api/types/versions @@ -58,26 +69,55 @@ imports: - pkg/term - pkg/term/windows - name: github.com/docker/go-connections - version: f512407a188ecb16f31a33dbc9c4e4814afc1b03 + version: 4ccf312bf1d35e5dbda654e57a9be4c3f3cd0366 subpackages: - nat - name: github.com/docker/go-units - version: 8a7beacffa3009a9ac66bad506b18ffdd110cf97 + version: e30f1e79f3cd72542f2026ceec18d3bd67ab859c - name: github.com/fsouza/go-dockerclient - version: ece08f96ac5f26f4073ab5c38f198c3e5000c554 + version: a633c5ee3344bd557a9a22e9b7259cab6447cd22 - name: github.com/giantswarm/semver-bump version: 7ec6ac8985c24dd50b4942f9a908d13cdfe70f23 subpackages: - bump - storage - name: github.com/go-ini/ini - version: 6e4869b434bd001f6983749881c7ead3545887d8 + version: 2ba15ac2dc9cdf88c110ec2dc0ced7fa45f5678c +- name: github.com/go-openapi/analysis + version: 7222828b8ce19afee3c595aef6643b9e42150120 +- name: github.com/go-openapi/errors + version: 49fe8b3a0e0d32a617d8d50c67f856ad6e45b28b +- name: github.com/go-openapi/jsonpointer + version: 8d96a2dc61536b690bd36b2e9df0b3c0b62825b2 +- name: github.com/go-openapi/jsonreference + version: 36d33bfe519efae5632669801b180bf1a245da3b +- name: github.com/go-openapi/loads + version: 315567415dfd74b651f7a62cabfc82a57ed7b9ad +- name: github.com/go-openapi/runtime + version: 14b161b40ece9dac8e244ab2fde2d209e108c6f5 + subpackages: + - client +- name: github.com/go-openapi/spec + version: f7ae86df5bc115a2744343016c789a89f065a4bd +- name: github.com/go-openapi/strfmt + version: 34fc3ba7c0f5fb615fda47a2b4fbd4c641b215f2 +- name: github.com/go-openapi/swag + version: 3b6d86cd965820f968760d5d419cb4add096bdd7 +- name: github.com/go-openapi/validate + version: 027696d4b54399770f1cdcc6c6daa56975f9e14e - name: github.com/go-resty/resty version: 24dc7ba4bc1ef9215048b28e7248f99c42901db5 - name: github.com/hashicorp/go-cleanhttp version: ad28ea4487f05916463e2423a55166280e8254b5 - name: github.com/iron-io/functions_go - version: f38f2174656467ec3ed404b7294e9ee172573e43 + version: 69e4dec8454c3c710045263c2ede76139c141146 + subpackages: + - client + - client/apps + - client/routes + - client/tasks + - client/version + - models - name: github.com/iron-io/iron_go3 version: b50ecf8ff90187fc5fabccd9d028dd461adce4ee subpackages: @@ -85,7 +125,7 @@ imports: - config - worker - name: github.com/iron-io/lambda - version: d883e4b5ef216c3fcda72cf6628d9d72dd53be49 + version: 4a046af3249dd5933a8d328f965e9717c97fef24 subpackages: - lambda - name: github.com/jmespath/go-jmespath @@ -96,30 +136,49 @@ imports: version: 08cceb5d0b5331634b9826762a8fd53b29b86ad8 subpackages: - errors +- name: github.com/mailru/easyjson + version: 159cdb893c982e3d1bc6450322fedd514f9c9de3 + subpackages: + - buffer + - jlexer + - jwriter - name: github.com/Microsoft/go-winio - version: ce2922f643c8fd76b46cadc7f404a06282678b34 + version: 24a3e3d3fc7451805e09d11e11e95d9a0a4f205e +- name: github.com/mitchellh/mapstructure + version: f3009df150dadf309fdee4a54ed65c124afad715 - name: github.com/opencontainers/runc - version: 49ed0a10e4edba88f9221ec730d668099f6d6de8 + version: 8893fa693bf9bf29e5a156369bc51b887df43924 subpackages: - libcontainer/system - libcontainer/user +- name: github.com/PuerkitoBio/purell + version: 0bcb03f4b4d0a9428594752bd2a3b9aa0a9d4bd4 +- name: github.com/PuerkitoBio/urlesc + version: 5bd2802263f21d8788851d5305584c82a5c75d7e - name: github.com/satori/go.uuid version: 879c5887cd475cd7864858769793b2ceb0d44feb - name: github.com/Sirupsen/logrus version: d26492970760ca5d33129d2d799e34be5c4782eb - name: github.com/urfave/cli - version: d86a009f5e13f83df65d0d6cee9a2e3f1445f0da + version: 0bdeddeeb0f650497d603c4ad7b20cfe685682f6 - name: golang.org/x/net version: f315505cf3349909cdf013ea56690da34e96a451 subpackages: - context - context/ctxhttp + - idna - publicsuffix - name: golang.org/x/sys - version: c200b10b5d5e122be351b67af224adc6128af5bf + version: d5645953809d8b4752afb2c3224b1f1ad73dfa70 subpackages: - unix - windows +- name: golang.org/x/text + version: 5c6cf4f9a2357d38515014cea8c488ed22bdab90 + subpackages: + - transform + - unicode/norm + - width - name: gopkg.in/yaml.v2 version: a5b47d31c556af34a302ce5d659e6fea44d90de0 testImports: [] diff --git a/fn/glide.yaml b/fn/glide.yaml index a4c115c41..3a07c9ed5 100644 --- a/fn/glide.yaml +++ b/fn/glide.yaml @@ -20,4 +20,4 @@ import: - lambda - package: github.com/urfave/cli - package: gopkg.in/yaml.v2 -- package: github.com/jmoiron/jsonq \ No newline at end of file +- package: github.com/jmoiron/jsonq diff --git a/fn/routes.go b/fn/routes.go index 8e5dc3c70..27ff3f5b6 100644 --- a/fn/routes.go +++ b/fn/routes.go @@ -1,6 +1,7 @@ package main import ( + "context" "encoding/json" "errors" "fmt" @@ -13,17 +14,20 @@ import ( "text/tabwriter" "time" - functions "github.com/iron-io/functions_go" + fnclient "github.com/iron-io/functions_go/client" + apiroutes "github.com/iron-io/functions_go/client/routes" + "github.com/iron-io/functions_go/models" "github.com/jmoiron/jsonq" "github.com/urfave/cli" ) type routesCmd struct { - *functions.RoutesApi + client *fnclient.Functions } func routes() cli.Command { - r := routesCmd{RoutesApi: functions.NewRoutesApi()} + + r := routesCmd{client: apiClient()} return cli.Command{ Name: "routes", @@ -167,7 +171,7 @@ func routes() cli.Command { } func call() cli.Command { - r := routesCmd{RoutesApi: functions.NewRoutesApi()} + r := routesCmd{client: apiClient()} return cli.Command{ Name: "call", @@ -183,35 +187,33 @@ func (a *routesCmd) list(c *cli.Context) error { return errors.New("error: routes listing takes one argument, an app name") } - if err := resetBasePath(a.Configuration); err != nil { - return fmt.Errorf("error setting endpoint: %v", err) - } - appName := c.Args().Get(0) - wrapper, _, err := a.AppsAppRoutesGet(appName) - if err != nil { - return fmt.Errorf("error getting routes: %v", err) - } - if msg := wrapper.Error_.Message; msg != "" { - return errors.New(msg) - } + resp, err := a.client.Routes.GetAppsAppRoutes(&apiroutes.GetAppsAppRoutesParams{ + Context: context.Background(), + App: appName, + }) - baseURL, err := url.Parse(a.Configuration.BasePath) if err != nil { - return fmt.Errorf("error parsing base path: %v", err) + switch err.(type) { + case *apiroutes.GetAppsAppRoutesNotFound: + return fmt.Errorf("error: %v", err.(*apiroutes.GetAppsAppRoutesNotFound).Payload.Error.Message) + case *apiroutes.GetAppsAppRoutesDefault: + return fmt.Errorf("unexpected error: %v", err.(*apiroutes.GetAppsAppRoutesDefault).Payload.Error.Message) + } + return fmt.Errorf("unexpected error: %v", err) } w := tabwriter.NewWriter(os.Stdout, 0, 8, 0, '\t', 0) fmt.Fprint(w, "path", "\t", "image", "\t", "endpoint", "\n") - for _, route := range wrapper.Routes { + for _, route := range resp.Payload.Routes { u, err := url.Parse("../") u.Path = path.Join(u.Path, "r", appName, route.Path) if err != nil { return fmt.Errorf("error parsing functions route path: %v", err) } - fmt.Fprint(w, route.Path, "\t", route.Image, "\t", baseURL.ResolveReference(u).String(), "\n") + fmt.Fprint(w, route.Path, "\t", route.Image, "\n") } w.Flush() @@ -223,23 +225,17 @@ func (a *routesCmd) call(c *cli.Context) error { return errors.New("error: routes listing takes three arguments: an app name and a route") } - if err := resetBasePath(a.Configuration); err != nil { - return fmt.Errorf("error setting endpoint: %v", err) - } - appName := c.Args().Get(0) route := c.Args().Get(1) - baseURL, err := url.Parse(a.Configuration.BasePath) - if err != nil { - return fmt.Errorf("error parsing base path: %v", err) + u := url.URL{ + Scheme: "http", + Host: host(), } - - u, err := url.Parse("../") u.Path = path.Join(u.Path, "r", appName, route) content := stdin() - return callfn(baseURL.ResolveReference(u).String(), content, os.Stdout, c.StringSlice("e")) + return callfn(u.String(), content, os.Stdout, c.StringSlice("e")) } func callfn(u string, content io.Reader, output io.Writer, env []string) error { @@ -281,10 +277,6 @@ func (a *routesCmd) create(c *cli.Context) error { return errors.New("error: routes creation takes at least one argument: an app name") } - if err := resetBasePath(a.Configuration); err != nil { - return fmt.Errorf("error setting endpoint: %v", err) - } - appName := c.Args().Get(0) route := c.Args().Get(1) image := c.Args().Get(2) @@ -298,9 +290,8 @@ func (a *routesCmd) create(c *cli.Context) error { if err != nil { if _, ok := err.(*notFoundError); ok { return errors.New("error: image name is missing or no function file found") - } else { - return err } + return err } image = ff.FullName() if ff.Format != nil { @@ -334,29 +325,39 @@ func (a *routesCmd) create(c *cli.Context) error { timeout = t } - body := functions.RouteWrapper{ - Route: functions.Route{ + to := int64(timeout.Seconds()) + body := &models.RouteWrapper{ + Route: &models.Route{ Path: route, Image: image, Memory: c.Int64("memory"), - Type_: c.String("type"), + Type: c.String("type"), Config: extractEnvConfig(c.StringSlice("config")), Format: format, MaxConcurrency: int32(maxC), - Timeout: int32(timeout.Seconds()), + Timeout: &to, }, } - wrapper, _, err := a.AppsAppRoutesPost(appName, body) + resp, err := a.client.Routes.PostAppsAppRoutes(&apiroutes.PostAppsAppRoutesParams{ + Context: context.Background(), + App: appName, + Body: body, + }) + if err != nil { - return fmt.Errorf("error creating route: %v", err) + switch err.(type) { + case *apiroutes.PostAppsAppRoutesBadRequest: + return fmt.Errorf("error: %v", err.(*apiroutes.PostAppsAppRoutesBadRequest).Payload.Error.Message) + case *apiroutes.PostAppsAppRoutesConflict: + return fmt.Errorf("error: %v", err.(*apiroutes.PostAppsAppRoutesConflict).Payload.Error.Message) + case *apiroutes.PostAppsAppRoutesDefault: + return fmt.Errorf("unexpected error: %v", err.(*apiroutes.PostAppsAppRoutesDefault).Payload.Error.Message) + } + return fmt.Errorf("unexpected error: %v", err) } - if msg := wrapper.Error_.Message; msg != "" { - return errors.New(msg) - } - - fmt.Println(wrapper.Route.Path, "created with", wrapper.Route.Image) + fmt.Println(resp.Payload.Route.Path, "created with", resp.Payload.Route.Image) return nil } @@ -365,64 +366,119 @@ func (a *routesCmd) delete(c *cli.Context) error { return errors.New("error: routes listing takes three arguments: an app name and a path") } - if err := resetBasePath(a.Configuration); err != nil { - return fmt.Errorf("error setting endpoint: %v", err) - } - appName := c.Args().Get(0) route := c.Args().Get(1) - resp, err := a.AppsAppRoutesRouteDelete(appName, route) + _, err := a.client.Routes.DeleteAppsAppRoutesRoute(&apiroutes.DeleteAppsAppRoutesRouteParams{ + Context: context.Background(), + App: appName, + Route: route, + }) if err != nil { - return fmt.Errorf("error deleting route: %v", err) - } - - if resp.StatusCode >= http.StatusBadRequest { - return fmt.Errorf("route not found: %s", route) + switch err.(type) { + case *apiroutes.DeleteAppsAppRoutesRouteNotFound: + return fmt.Errorf("error: %v", err.(*apiroutes.DeleteAppsAppRoutesRouteNotFound).Payload.Error.Message) + case *apiroutes.DeleteAppsAppRoutesRouteDefault: + return fmt.Errorf("unexpected error: %v", err.(*apiroutes.DeleteAppsAppRoutesRouteDefault).Payload.Error.Message) + } + return fmt.Errorf("unexpected error: %v", err) } fmt.Println(route, "deleted") return nil } -func (a *routesCmd) update(c *cli.Context) error { - if c.Args().Get(0) == "" { - return errors.New("error: routes creation takes at least one argument: an app name") - } +// _, err = a.client.Routes.PatchAppsAppRoutesRoute(&apiroutes.PatchAppsAppRoutesRouteParams{ +// Context: context.Background(), +// App: appName, +// Route: route, +// Body: resp.Payload, +// }) - if err := resetBasePath(a.Configuration); err != nil { - return fmt.Errorf("error setting endpoint: %v", err) +// if err != nil { +// switch err.(type) { +// case *apiroutes.PatchAppsAppRoutesRouteBadRequest: +// return fmt.Errorf("error: %v", err.(*apiroutes.PatchAppsAppRoutesRouteBadRequest).Payload.Error.Message) +// case *apiroutes.PatchAppsAppRoutesRouteNotFound: +// return fmt.Errorf("error: %v", err.(*apiroutes.PatchAppsAppRoutesRouteNotFound).Payload.Error.Message) +// case *apiroutes.PatchAppsAppRoutesRouteDefault: +// return fmt.Errorf("unexpected error: %v", err.(*apiroutes.PatchAppsAppRoutesRouteDefault).Payload.Error.Message) +// } +// return fmt.Errorf("unexpected error: %v", err) +// } + +func (a *routesCmd) update(c *cli.Context) error { + if c.Args().Get(0) == "" || c.Args().Get(1) == "" { + return errors.New("error: route configuration description takes two arguments: an app name and a route") } appName := c.Args().Get(0) route := c.Args().Get(1) - if route == "" { - return errors.New("error: route path is missing") - } - - headers := map[string][]string{} - for _, header := range c.StringSlice("headers") { - parts := strings.Split(header, "=") - headers[parts[0]] = strings.Split(parts[1], ";") - } - - patchRoute := &functions.Route{ - Image: c.String("image"), - Memory: c.Int64("memory"), - Type_: c.String("type"), - Config: extractEnvConfig(c.StringSlice("config")), - Headers: headers, - Format: c.String("format"), - MaxConcurrency: int32(c.Int64("max-concurrency")), - Timeout: int32(c.Int64("timeout")), - } - - err := a.patchRoute(appName, route, patchRoute) + resp, err := a.client.Routes.GetAppsAppRoutesRoute(&apiroutes.GetAppsAppRoutesRouteParams{ + Context: context.Background(), + App: appName, + Route: route, + }) if err != nil { - return err + switch err.(type) { + case *apiroutes.GetAppsAppRoutesRouteNotFound: + return fmt.Errorf("error: %v", err.(*apiroutes.GetAppsAppRoutesRouteNotFound).Payload.Error.Message) + case *apiroutes.GetAppsAppRoutesRouteDefault: + return fmt.Errorf("unexpected error: %v", err.(*apiroutes.GetAppsAppRoutesRouteDefault).Payload.Error.Message) + } + return fmt.Errorf("unexpected error: %v", err) } + config := resp.Payload.Route.Config + if len(config) == 0 { + return errors.New("this route has no configurations") + } + + if c.Bool("json") { + if err := json.NewEncoder(os.Stdout).Encode(config); err != nil { + fmt.Fprintln(os.Stderr, err) + os.Exit(1) + } + } else if c.Bool("shell") { + for k, v := range config { + fmt.Print("export ", k, "=", v, "\n") + } + } else { + fmt.Println(appName, resp.Payload.Route.Path, "configuration:") + w := tabwriter.NewWriter(os.Stdout, 0, 8, 1, ' ', 0) + for k, v := range config { + fmt.Fprint(w, k, ":\t", v, "\n") + } + w.Flush() + } + + // if route == "" { + // return errors.New("error: route path is missing") + // } + + // headers := map[string][]string{} + // for _, header := range c.StringSlice("headers") { + // parts := strings.Split(header, "=") + // headers[parts[0]] = strings.Split(parts[1], ";") + // } + + // patchRoute := &functions.Route{ + // Image: c.String("image"), + // Memory: c.Int64("memory"), + // Type_: c.String("type"), + // Config: extractEnvConfig(c.StringSlice("config")), + // Headers: headers, + // Format: c.String("format"), + // MaxConcurrency: int32(c.Int64("max-concurrency")), + // Timeout: int32(c.Int64("timeout")), + // } + + // err := a.patchRoute(appName, route, patchRoute) + // if err != nil { + // return err + // } + fmt.Println(appName, route, "updated") return nil } @@ -432,27 +488,69 @@ func (a *routesCmd) configSet(c *cli.Context) error { return errors.New("error: route configuration setting takes four arguments: an app name, a route, a key and a value") } - if err := resetBasePath(a.Configuration); err != nil { - return fmt.Errorf("error setting endpoint: %v", err) - } - appName := c.Args().Get(0) route := c.Args().Get(1) key := c.Args().Get(2) value := c.Args().Get(3) - patchRoute := functions.Route{ - Config: make(map[string]string), - } + resp, err := a.client.Routes.GetAppsAppRoutesRoute(&apiroutes.GetAppsAppRoutesRouteParams{ + Context: context.Background(), + App: appName, + Route: route, + }) - patchRoute.Config[key] = value - - err := a.patchRoute(appName, route, &patchRoute) if err != nil { - return err + switch err.(type) { + case *apiroutes.GetAppsAppRoutesRouteNotFound: + return fmt.Errorf("error: %v", err.(*apiroutes.GetAppsAppRoutesRouteNotFound).Payload.Error.Message) + case *apiroutes.GetAppsAppRoutesRouteDefault: + return fmt.Errorf("unexpected error: %v", err.(*apiroutes.GetAppsAppRoutesRouteDefault).Payload.Error.Message) + } + return fmt.Errorf("unexpected error: %v", err) } - fmt.Println(appName, route, "updated", key, "with", value) + config := resp.Payload.Route.Config + + if config == nil { + config = make(map[string]string) + } + + config[key] = value + resp.Payload.Route.Config = config + + _, err = a.client.Routes.PatchAppsAppRoutesRoute(&apiroutes.PatchAppsAppRoutesRouteParams{ + Context: context.Background(), + App: appName, + Route: route, + Body: resp.Payload, + }) + + if err != nil { + switch err.(type) { + case *apiroutes.PatchAppsAppRoutesRouteBadRequest: + return fmt.Errorf("error: %v", err.(*apiroutes.PatchAppsAppRoutesRouteBadRequest).Payload.Error.Message) + case *apiroutes.PatchAppsAppRoutesRouteNotFound: + return fmt.Errorf("error: %v", err.(*apiroutes.PatchAppsAppRoutesRouteNotFound).Payload.Error.Message) + case *apiroutes.PatchAppsAppRoutesRouteDefault: + return fmt.Errorf("unexpected error: %v", err.(*apiroutes.PatchAppsAppRoutesRouteDefault).Payload.Error.Message) + } + return fmt.Errorf("unexpected error: %v", err) + } + + fmt.Println(appName, resp.Payload.Route.Path, "updated", key, "with", value) + + // patchRoute := functions.Route{ + // Config: make(map[string]string), + // } + + // patchRoute.Config[key] = value + + // err := a.patchRoute(appName, route, &patchRoute) + // if err != nil { + // return err + // } + + // fmt.Println(appName, route, "updated", key, "with", value) return nil } @@ -461,84 +559,40 @@ func (a *routesCmd) configUnset(c *cli.Context) error { return errors.New("error: route configuration setting takes four arguments: an app name, a route and a key") } - if err := resetBasePath(a.Configuration); err != nil { - return fmt.Errorf("error setting endpoint: %v", err) - } - appName := c.Args().Get(0) route := c.Args().Get(1) key := c.Args().Get(2) - patchRoute := functions.Route{ - Config: make(map[string]string), - } + resp, err := a.client.Routes.GetAppsAppRoutesRoute(&apiroutes.GetAppsAppRoutesRouteParams{ + Context: context.Background(), + App: appName, + Route: route, + }) - patchRoute.Config["-"+key] = "" - - err := a.patchRoute(appName, route, &patchRoute) if err != nil { - return err + switch err.(type) { + case *apiroutes.GetAppsAppRoutesRouteNotFound: + return fmt.Errorf("error: %v", err.(*apiroutes.GetAppsAppRoutesRouteNotFound).Payload.Error.Message) + case *apiroutes.GetAppsAppRoutesRouteDefault: + return fmt.Errorf("unexpected error: %v", err.(*apiroutes.GetAppsAppRoutesRouteDefault).Payload.Error.Message) + } + return fmt.Errorf("unexpected error: %v", err) } - fmt.Println(appName, route, "removed", key) - return nil -} + config := resp.Payload.Route.Config -func (a *routesCmd) patchRoute(appName, routePath string, r *functions.Route) error { - wrapper, _, err := a.AppsAppRoutesRouteGet(appName, routePath) - if err != nil { - return fmt.Errorf("error loading route: %v", err) + if config == nil { + config = make(map[string]string) } - if msg := wrapper.Error_.Message; msg != "" { - return errors.New(msg) + if _, ok := config[key]; !ok { + return fmt.Errorf("configuration key %s not found", key) } - wrapper.Route.Path = "" - if r != nil { - if r.Config != nil { - for k, v := range r.Config { - if string(k[0]) == "-" { - delete(r.Config, string(k[1:])) - continue - } - wrapper.Route.Config[k] = v - } - } - if r.Headers != nil { - for k, v := range r.Headers { - if v[0] == "" { - delete(r.Headers, k) - continue - } - wrapper.Route.Headers[k] = v - } - } - if r.Image != "" { - wrapper.Route.Image = r.Image - } - if r.Format != "" { - wrapper.Route.Format = r.Format - } - if r.MaxConcurrency > 0 { - wrapper.Route.MaxConcurrency = r.MaxConcurrency - } - if r.Memory > 0 { - wrapper.Route.Memory = r.Memory - } - if r.Timeout > 0 { - wrapper.Route.Timeout = r.Timeout - } - } - - if wrapper, _, err = a.AppsAppRoutesRoutePatch(appName, routePath, *wrapper); err != nil { - return fmt.Errorf("error updating route: %v", err) - } - - if msg := wrapper.Error_.Message; msg != "" { - return errors.New(msg) - } + delete(config, key) + resp.Payload.Route.Config = config + fmt.Println(appName, resp.Payload.Route.Path, "removed", key) return nil } @@ -547,38 +601,35 @@ func (a *routesCmd) inspect(c *cli.Context) error { return errors.New("error: routes listing takes three arguments: an app name and a path") } - if err := resetBasePath(a.Configuration); err != nil { - return fmt.Errorf("error setting endpoint: %v", err) - } - appName := c.Args().Get(0) route := c.Args().Get(1) prop := c.Args().Get(2) - wrapper, resp, err := a.AppsAppRoutesRouteGet(appName, route) - if err != nil { - return fmt.Errorf("error retrieving route: %v", err) - } + resp, err := a.client.Routes.GetAppsAppRoutesRoute(&apiroutes.GetAppsAppRoutesRouteParams{ + Context: context.Background(), + App: appName, + Route: route, + }) - if msg := wrapper.Error_.Message; msg != "" { - return errors.New(msg) + if err != nil { + switch err.(type) { + case *apiroutes.GetAppsAppRoutesRouteNotFound: + return fmt.Errorf("error: %v", err.(*apiroutes.GetAppsAppRoutesRouteNotFound).Payload.Error.Message) + case *apiroutes.GetAppsAppRoutesRouteDefault: + return fmt.Errorf("unexpected error: %v", err.(*apiroutes.GetAppsAppRoutesRouteDefault).Payload.Error.Message) + } + return fmt.Errorf("unexpected error: %v", err) } enc := json.NewEncoder(os.Stdout) enc.SetIndent("", "\t") if prop == "" { - enc.Encode(wrapper.Route) + enc.Encode(resp.Payload.Route) return nil } - var inspect struct{ Route map[string]interface{} } - err = json.Unmarshal(resp.Payload, &inspect) - if err != nil { - return fmt.Errorf("error inspect route: %v", err) - } - - jq := jsonq.NewQuery(inspect.Route) + jq := jsonq.NewQuery(resp.Payload.Route) field, err := jq.Interface(strings.Split(prop, ".")...) if err != nil { return errors.New("failed to inspect the property")