From 9edc623cfbcfd00035ea6861159b653cd17e33a8 Mon Sep 17 00:00:00 2001 From: Andrew Reed Date: Sun, 16 Jul 2017 13:01:28 -0700 Subject: [PATCH] Improve UX for vendor CLI Specify app as either slug or ID Implement channel adoption, counts, and releases with tests. Remove adoption, counts, and releases section from channel inspect. Add release sequence and release version label to channel inspect. Align columns in channel inspect and release inspect. Add CreateLicense method to client using v2 swagger spec. Delete apps in single step to avoid rate limits in integration tests. Remove version from release ls becuase release version is unused and easily confused with channel release version. Sort channels by position and channel releases newest to oldest. Don't show help subcommand in available commands. Pass options structs to create and update methods. --- Makefile | 13 +- README.md | 8 +- cli/cmd/channel_adoption.go | 36 + cli/cmd/channel_counts.go | 36 + cli/cmd/channel_create.go | 7 +- cli/cmd/channel_inspect.go | 24 +- cli/cmd/channel_releases.go | 36 + cli/cmd/release_create.go | 11 +- cli/cmd/release_update.go | 4 +- cli/cmd/root.go | 46 +- cli/print/channel_adoption.go | 11 +- cli/print/channel_attributes.go | 8 +- cli/print/channel_license_counts.go | 7 +- cli/print/release.go | 6 +- cli/print/releases.go | 5 +- cli/test/channel_adoption_test.go | 58 ++ cli/test/channel_counts_test.go | 58 ++ cli/test/channel_create_test.go | 5 +- cli/test/channel_inspect_test.go | 46 +- ...hannel_list_test.go => channel_ls_test.go} | 5 +- cli/test/channel_releases_test.go | 86 ++ cli/test/channel_rm_test.go | 5 +- cli/test/cli_test.go | 2 + cli/test/release_create_test.go | 5 +- cli/test/release_inspect.go | 15 +- cli/test/release_ls_test.go | 9 +- cli/test/release_promote_test.go | 7 +- cli/test/release_update_test.go | 7 +- cli/test/util.go | 111 ++- client/app.go | 14 +- client/channel.go | 41 +- client/client.go | 30 +- client/client_test.go | 4 +- client/license.go | 17 + client/release.go | 12 +- gen/go/apps/app_and_channels.go | 2 +- gen/go/apps/app_channel.go | 4 +- gen/go/apps/docs/AppAndChannels.md | 2 +- gen/go/apps/docs/AppChannel.md | 4 +- gen/go/channels/app_channel.go | 4 +- gen/go/channels/docs/AppChannel.md | 4 +- gen/go/channels/docs/InlineResponse2001.md | 2 +- gen/go/channels/inline_response_200_1.go | 2 +- gen/go/releases/app_channel.go | 4 +- gen/go/releases/docs/AppChannel.md | 4 +- gen/go/v2/body.go | 36 + gen/go/v2/body_1.go | 49 + gen/go/v2/body_2.go | 52 ++ gen/go/v2/docs/Body.md | 20 + gen/go/v2/docs/Body1.md | 22 + gen/go/v2/docs/Body2.md | 23 + gen/go/v2/docs/InlineResponse200.md | 10 + gen/go/v2/docs/InlineResponse2001.md | 12 + gen/go/v2/docs/InlineResponse2002.md | 10 + gen/go/v2/docs/InlineResponse2003.md | 10 + gen/go/v2/docs/InlineResponse201.md | 10 + gen/go/v2/docs/LicenseChannel.md | 13 + gen/go/v2/docs/LicenseChannels.md | 9 + gen/go/v2/docs/LicenseFieldValue.md | 13 + gen/go/v2/docs/LicenseFieldValues.md | 9 + gen/go/v2/docs/LicenseV2.md | 45 + gen/go/v2/docs/LicensesV2.md | 9 + gen/go/v2/inline_response_200.go | 16 + gen/go/v2/inline_response_200_1.go | 20 + gen/go/v2/inline_response_200_2.go | 16 + gen/go/v2/inline_response_200_3.go | 16 + gen/go/v2/inline_response_201.go | 16 + gen/go/v2/license_channel.go | 22 + gen/go/v2/license_channels.go | 14 + gen/go/v2/license_field_value.go | 22 + gen/go/v2/license_field_values.go | 14 + gen/go/v2/license_v2.go | 90 ++ gen/go/v2/licenses_v2.go | 14 + gen/spec/v2.json | 842 ++++++++++++++++++ 74 files changed, 2081 insertions(+), 200 deletions(-) create mode 100644 cli/cmd/channel_adoption.go create mode 100644 cli/cmd/channel_counts.go create mode 100644 cli/cmd/channel_releases.go create mode 100644 cli/test/channel_adoption_test.go create mode 100644 cli/test/channel_counts_test.go rename cli/test/{channel_list_test.go => channel_ls_test.go} (91%) create mode 100644 cli/test/channel_releases_test.go create mode 100644 client/license.go create mode 100644 gen/go/v2/body.go create mode 100644 gen/go/v2/body_1.go create mode 100644 gen/go/v2/body_2.go create mode 100644 gen/go/v2/docs/Body.md create mode 100644 gen/go/v2/docs/Body1.md create mode 100644 gen/go/v2/docs/Body2.md create mode 100644 gen/go/v2/docs/InlineResponse200.md create mode 100644 gen/go/v2/docs/InlineResponse2001.md create mode 100644 gen/go/v2/docs/InlineResponse2002.md create mode 100644 gen/go/v2/docs/InlineResponse2003.md create mode 100644 gen/go/v2/docs/InlineResponse201.md create mode 100644 gen/go/v2/docs/LicenseChannel.md create mode 100644 gen/go/v2/docs/LicenseChannels.md create mode 100644 gen/go/v2/docs/LicenseFieldValue.md create mode 100644 gen/go/v2/docs/LicenseFieldValues.md create mode 100644 gen/go/v2/docs/LicenseV2.md create mode 100644 gen/go/v2/docs/LicensesV2.md create mode 100644 gen/go/v2/inline_response_200.go create mode 100644 gen/go/v2/inline_response_200_1.go create mode 100644 gen/go/v2/inline_response_200_2.go create mode 100644 gen/go/v2/inline_response_200_3.go create mode 100644 gen/go/v2/inline_response_201.go create mode 100644 gen/go/v2/license_channel.go create mode 100644 gen/go/v2/license_channels.go create mode 100644 gen/go/v2/license_field_value.go create mode 100644 gen/go/v2/license_field_values.go create mode 100644 gen/go/v2/license_v2.go create mode 100644 gen/go/v2/licenses_v2.go create mode 100644 gen/spec/v2.json diff --git a/Makefile b/Makefile index 80d658c28..9daea20af 100644 --- a/Makefile +++ b/Makefile @@ -25,6 +25,7 @@ get-spec-prod: curl -o gen/spec/$$PKG.json \ https://api.replicated.com/vendor/v1/spec/$$PKG.json; \ done + curl -o gen/spec/v2.json https://api.replicated.com/vendor/v2/spec/swagger.json; # generate the swagger specs from the local replicatedcom/vendor-api repo get-spec-local: @@ -36,7 +37,10 @@ get-spec-local: swagger generate spec \ -b ../../replicatedcom/vendor-api/handlers/replv1/$$PKG \ -o gen/spec/$$PKG.json; \ - done' + done \ + && swagger generate spec \ + -b ../../replicatedcom/vendor-api/handlers/replv2 \ + -o gen/spec/v2.json' # generate from the specs in gen/spec, which come from either get-spec-prod or get-spec-local gen-models: @@ -49,6 +53,13 @@ gen-models: -l go \ -o /local/gen/go/$$PKG; \ done + docker run --rm \ + --volume `pwd`:/local \ + swaggerapi/swagger-codegen-cli generate \ + -Dmodels -DmodelsDocs=false \ + -i /local/gen/spec/v2.json \ + -l go \ + -o /local/gen/go/v2; build: go build -o replicated cli/main.go diff --git a/README.md b/README.md index 5cb44a07a..7fcd784d2 100644 --- a/README.md +++ b/README.md @@ -22,7 +22,7 @@ replicated channel ls --app my-app-slug --token e8d7ce8e3d3278a8b1255237e6310069 ``` Set the following env vars to avoid passing them as arguments to each command. -* REPLICATED_APP_SLUG +* REPLICATED_APP - either an app slug or app ID * REPLICATED_API_TOKEN Then the above command would be simply @@ -33,7 +33,7 @@ replicated channel ls ### CI Example Creating a new release for every tagged build is a common use of the replicated command. -Assume the app's yaml config is checked in at replicated.yaml and you have configured TravisCI or CircleCI with your REPLICATED_APP_SLUG and REPLICATED_API_TOKEN environment variables. +Assume the app's yaml config is checked in at replicated.yaml and you have configured TravisCI or CircleCI with your REPLICATED_APP and REPLICATED_API_TOKEN environment variables. Then add a release.sh script to your project something like this: @@ -106,11 +106,11 @@ import ( func main() { token := os.Getenv("REPLICATED_API_TOKEN") - appSlug := os.Getenv("REPLICATED_APP_SLUG") + appSlugOrID := os.Getenv("REPLICATED_APP") api := client.New(token) - app, err := api.GetAppBySlug(appSlug) + app, err := api.GetApp(appSlugOrID) if err != nil { log.Fatal(err) } diff --git a/cli/cmd/channel_adoption.go b/cli/cmd/channel_adoption.go new file mode 100644 index 000000000..cf7569b17 --- /dev/null +++ b/cli/cmd/channel_adoption.go @@ -0,0 +1,36 @@ +package cmd + +import ( + "errors" + + "github.com/replicatedhq/replicated/cli/print" + "github.com/spf13/cobra" +) + +var channelAdoptionCmd = &cobra.Command{ + Use: "adoption CHANNEL_ID", + Short: "Print channel adoption statistics by license type", + Long: "Print channel adoption statistics by license type", +} + +func init() { + channelCmd.AddCommand(channelAdoptionCmd) +} + +func (r *runners) channelAdoption(cmd *cobra.Command, args []string) error { + if len(args) != 1 { + return errors.New("channel ID is required") + } + chanID := args[0] + + appChan, _, err := r.api.GetChannel(r.appID, chanID) + if err != nil { + return err + } + + if err = print.ChannelAdoption(r.w, appChan.Adoption); err != nil { + return err + } + + return nil +} diff --git a/cli/cmd/channel_counts.go b/cli/cmd/channel_counts.go new file mode 100644 index 000000000..40d57f0de --- /dev/null +++ b/cli/cmd/channel_counts.go @@ -0,0 +1,36 @@ +package cmd + +import ( + "errors" + + "github.com/replicatedhq/replicated/cli/print" + "github.com/spf13/cobra" +) + +var channelCountsCmd = &cobra.Command{ + Use: "counts CHANNEL_ID", + Short: "Print channel license counts", + Long: "Print channel license counts", +} + +func init() { + channelCmd.AddCommand(channelCountsCmd) +} + +func (r *runners) channelCounts(cmd *cobra.Command, args []string) error { + if len(args) != 1 { + return errors.New("channel ID is required") + } + chanID := args[0] + + appChan, _, err := r.api.GetChannel(r.appID, chanID) + if err != nil { + return err + } + + if err = print.LicenseCounts(r.w, appChan.LicenseCounts); err != nil { + return err + } + + return nil +} diff --git a/cli/cmd/channel_create.go b/cli/cmd/channel_create.go index c340c7e68..886df9dcc 100644 --- a/cli/cmd/channel_create.go +++ b/cli/cmd/channel_create.go @@ -2,6 +2,7 @@ package cmd import ( "github.com/replicatedhq/replicated/cli/print" + "github.com/replicatedhq/replicated/client" "github.com/spf13/cobra" ) @@ -25,7 +26,11 @@ func init() { } func (r *runners) channelCreate(cmd *cobra.Command, args []string) error { - allChannels, err := r.api.CreateChannel(r.appID, channelCreateName, channelCreateDescription) + opts := &client.ChannelOptions{ + Name: channelCreateName, + Description: channelCreateDescription, + } + allChannels, err := r.api.CreateChannel(r.appID, opts) if err != nil { return err } diff --git a/cli/cmd/channel_inspect.go b/cli/cmd/channel_inspect.go index ac3ed9709..011da28ea 100644 --- a/cli/cmd/channel_inspect.go +++ b/cli/cmd/channel_inspect.go @@ -2,7 +2,6 @@ package cmd import ( "errors" - "fmt" "github.com/spf13/cobra" @@ -26,7 +25,7 @@ func (r *runners) channelInspect(cmd *cobra.Command, args []string) error { } chanID := args[0] - appChan, releases, err := r.api.GetChannel(r.appID, chanID) + appChan, _, err := r.api.GetChannel(r.appID, chanID) if err != nil { return err } @@ -35,26 +34,5 @@ func (r *runners) channelInspect(cmd *cobra.Command, args []string) error { return err } - if _, err = fmt.Fprint(r.w, "\nADOPTION\n"); err != nil { - return err - } - if err = print.ChannelAdoption(r.w, &appChan.Adoption); err != nil { - return err - } - - if _, err = fmt.Fprint(r.w, "\nLICENSE_COUNTS\n"); err != nil { - return err - } - if err = print.LicenseCounts(r.w, &appChan.LicenseCounts); err != nil { - return err - } - - if _, err = fmt.Fprint(r.w, "\nRELEASES\n"); err != nil { - return err - } - if err = print.ChannelReleases(r.w, releases); err != nil { - return err - } - return nil } diff --git a/cli/cmd/channel_releases.go b/cli/cmd/channel_releases.go new file mode 100644 index 000000000..25cff96a6 --- /dev/null +++ b/cli/cmd/channel_releases.go @@ -0,0 +1,36 @@ +package cmd + +import ( + "errors" + + "github.com/replicatedhq/replicated/cli/print" + "github.com/spf13/cobra" +) + +var channelReleasesCmd = &cobra.Command{ + Use: "releases CHANNEL_ID", + Short: "Print channel license counts", + Long: "Print channel license counts", +} + +func init() { + channelCmd.AddCommand(channelReleasesCmd) +} + +func (r *runners) channelReleases(cmd *cobra.Command, args []string) error { + if len(args) != 1 { + return errors.New("channel ID is required") + } + chanID := args[0] + + _, releases, err := r.api.GetChannel(r.appID, chanID) + if err != nil { + return err + } + + if err = print.ChannelReleases(r.w, releases); err != nil { + return err + } + + return nil +} diff --git a/cli/cmd/release_create.go b/cli/cmd/release_create.go index 44482df76..edc0ed235 100644 --- a/cli/cmd/release_create.go +++ b/cli/cmd/release_create.go @@ -3,6 +3,7 @@ package cmd import ( "fmt" + "github.com/replicatedhq/replicated/client" "github.com/spf13/cobra" ) @@ -26,8 +27,10 @@ func (r *runners) releaseCreate(cmd *cobra.Command, args []string) error { return fmt.Errorf("yaml is required") } - // API does not accept yaml in create operation, so first create then udpate - release, err := r.api.CreateRelease(r.appID) + opts := &client.ReleaseOptions{ + YAML: createReleaseYaml, + } + release, err := r.api.CreateRelease(r.appID, opts) if err != nil { return err } @@ -37,9 +40,5 @@ func (r *runners) releaseCreate(cmd *cobra.Command, args []string) error { } r.w.Flush() - if err := r.api.UpdateRelease(r.appID, release.Sequence, createReleaseYaml); err != nil { - return fmt.Errorf("Failure setting yaml config for release: %v", err) - } - return nil } diff --git a/cli/cmd/release_update.go b/cli/cmd/release_update.go index a35bbef48..7f3b44a06 100644 --- a/cli/cmd/release_update.go +++ b/cli/cmd/release_update.go @@ -5,6 +5,7 @@ import ( "fmt" "strconv" + "github.com/replicatedhq/replicated/client" "github.com/spf13/cobra" ) @@ -34,7 +35,8 @@ func (r *runners) releaseUpdate(cmd *cobra.Command, args []string) error { return fmt.Errorf("invalid release sequence: %s", args[0]) } - if err := r.api.UpdateRelease(r.appID, seq, updateReleaseYaml); err != nil { + opts := &client.ReleaseOptions{YAML: updateReleaseYaml} + if err := r.api.UpdateRelease(r.appID, seq, opts); err != nil { return fmt.Errorf("Failure setting new yaml config for release: %v", err) } diff --git a/cli/cmd/root.go b/cli/cmd/root.go index 056c4d2ee..75483c1a5 100644 --- a/cli/cmd/root.go +++ b/cli/cmd/root.go @@ -18,12 +18,12 @@ const ( padChar = ' ' ) -var appSlug string +var appSlugOrID string var apiToken string var apiOrigin = "https://api.replicated.com/vendor" func init() { - RootCmd.PersistentFlags().StringVar(&appSlug, "app", "", "The app slug to use in all calls") + RootCmd.PersistentFlags().StringVar(&appSlugOrID, "app", "", "The app slug or app id to use in all calls") RootCmd.PersistentFlags().StringVar(&apiToken, "token", "", "The API token to use to access your app in the Vendor API") originFromEnv := os.Getenv("REPLICATED_API_ORIGIN") @@ -39,6 +39,33 @@ var RootCmd = &cobra.Command{ Long: `The replicated CLI allows vendors to manage their apps' channels and releases.`, } +// Almost the same as the default but don't print help subcommand +var rootCmdUsageTmpl = ` +Usage:{{if .Runnable}} + {{.UseLine}}{{end}}{{if .HasAvailableSubCommands}} + {{.CommandPath}} [command]{{end}}{{if gt (len .Aliases) 0}} + +Aliases: + {{.NameAndAliases}}{{end}}{{if .HasExample}} + + Examples: + {{.Example}}{{end}}{{if .HasAvailableSubCommands}} + +Available Commands:{{range .Commands}}{{if .IsAvailableCommand}} + {{rpad .Name .NamePadding }} {{.Short}}{{end}}{{end}}{{end}}{{if .HasAvailableLocalFlags}} + +Flags: + {{.LocalFlags.FlagUsages | trimTrailingWhitespaces}}{{end}}{{if .HasAvailableInheritedFlags}} + +Global Flags: + {{.InheritedFlags.FlagUsages | trimTrailingWhitespaces}}{{end}}{{if .HasHelpSubCommands}} + +Additional help topics:{{range .Commands}}{{if .IsAdditionalHelpTopicCommand}} + {{rpad .CommandPath .CommandPathPadding}} {{.Short}}{{end}}{{end}}{{end}}{{if .HasAvailableSubCommands}} + +Use "{{.CommandPath}} [command] --help" for more information about a command.{{end}} +` + // Execute adds all child commands to the root command and sets flags appropriately. // This is called by main.main(). It only needs to happen once to the rootCmd. func Execute(w io.Writer) error { @@ -47,6 +74,9 @@ func Execute(w io.Writer) error { channelCreateCmd.RunE = runCmds.channelCreate channelInspectCmd.RunE = runCmds.channelInspect + channelAdoptionCmd.RunE = runCmds.channelAdoption + channelReleasesCmd.RunE = runCmds.channelReleases + channelCountsCmd.RunE = runCmds.channelCounts channelLsCmd.RunE = runCmds.channelList channelRmCmd.RunE = runCmds.channelRemove releaseCreateCmd.RunE = runCmds.releaseCreate @@ -55,6 +85,8 @@ func Execute(w io.Writer) error { releaseUpdateCmd.RunE = runCmds.releaseUpdate releasePromoteCmd.RunE = runCmds.releasePromote + RootCmd.SetUsageTemplate(rootCmdUsageTmpl) + RootCmd.PersistentPreRunE = func(cmd *cobra.Command, args []string) error { if apiToken == "" { apiToken = os.Getenv("REPLICATED_API_TOKEN") @@ -65,15 +97,11 @@ func Execute(w io.Writer) error { api := client.NewHTTPClient(apiOrigin, apiToken) runCmds.api = api - if appSlug == "" { - appSlug = os.Getenv("REPLICATED_APP_SLUG") - if appSlug == "" { - return errors.New("Please provide your app slug") - } + if appSlugOrID == "" { + appSlugOrID = os.Getenv("REPLICATED_APP") } - // resolve app ID from slug - app, err := api.GetAppBySlug(appSlug) + app, err := api.GetApp(appSlugOrID) if err != nil { return err } diff --git a/cli/print/channel_adoption.go b/cli/print/channel_adoption.go index f3c90753b..843dcc8bd 100644 --- a/cli/print/channel_adoption.go +++ b/cli/print/channel_adoption.go @@ -29,14 +29,15 @@ type licenseAdoption struct { } func ChannelAdoption(w *tabwriter.Writer, adoption *channels.ChannelAdoption) error { - countsByLicense := make(map[string]licenseAdoption) + countsByLicense := make(map[string]*licenseAdoption) var getOrSetLicenseAdoption = func(licenseType string) *licenseAdoption { - licenseAdoption, ok := countsByLicense[licenseType] + la, ok := countsByLicense[licenseType] if !ok { - countsByLicense[licenseType] = licenseAdoption + la = &licenseAdoption{} + countsByLicense[licenseType] = la } - return &licenseAdoption + return la } // current @@ -64,7 +65,7 @@ func ChannelAdoption(w *tabwriter.Writer, adoption *channels.ChannelAdoption) er } if len(countsByLicense) == 0 { - if _, err := fmt.Fprintln(w, "No licenses in channel"); err != nil { + if _, err := fmt.Fprintln(w, "No active licenses in channel"); err != nil { return err } return w.Flush() diff --git a/cli/print/channel_attributes.go b/cli/print/channel_attributes.go index b7e8e9db6..269f381c6 100644 --- a/cli/print/channel_attributes.go +++ b/cli/print/channel_attributes.go @@ -7,9 +7,11 @@ import ( channels "github.com/replicatedhq/replicated/gen/go/channels" ) -var channelAttrsTmplSrc = `ID: {{ .Id }} -NAME: {{ .Name }} -DESCRIPTION: {{ .Description }} +var channelAttrsTmplSrc = `ID: {{ .Id }} +NAME: {{ .Name }} +DESCRIPTION: {{ .Description }} +RELEASE: {{ .ReleaseSequence }} +VERSION: {{ .ReleaseLabel }} ` var channelAttrsTmpl = template.Must(template.New("ChannelAttributes").Parse(channelAttrsTmplSrc)) diff --git a/cli/print/channel_license_counts.go b/cli/print/channel_license_counts.go index bbb3addb1..0ac9b8561 100644 --- a/cli/print/channel_license_counts.go +++ b/cli/print/channel_license_counts.go @@ -21,14 +21,15 @@ type licenseTypeCounts struct { } func LicenseCounts(w *tabwriter.Writer, counts *channels.LicenseCounts) error { - countsByLicenseType := make(map[string]licenseTypeCounts) + countsByLicenseType := make(map[string]*licenseTypeCounts) var getOrSetLicenseCounts = func(licenseType string) *licenseTypeCounts { licenseCounts, ok := countsByLicenseType[licenseType] if !ok { + licenseCounts = &licenseTypeCounts{} countsByLicenseType[licenseType] = licenseCounts } - return &licenseCounts + return licenseCounts } for licenseType, count := range counts.Active { @@ -45,7 +46,7 @@ func LicenseCounts(w *tabwriter.Writer, counts *channels.LicenseCounts) error { } if len(countsByLicenseType) == 0 { - if _, err := fmt.Fprintln(w, "No licenses in channel"); err != nil { + if _, err := fmt.Fprintln(w, "No active licenses in channel"); err != nil { return err } return w.Flush() diff --git a/cli/print/release.go b/cli/print/release.go index 4da0dc037..ecb97e98f 100644 --- a/cli/print/release.go +++ b/cli/print/release.go @@ -7,9 +7,9 @@ import ( releases "github.com/replicatedhq/replicated/gen/go/releases" ) -var releaseTmplSrc = `SEQUENCE: {{ .Sequence }} -CREATED: {{ time .CreatedAt }} -EDITED: {{ time .EditedAt }} +var releaseTmplSrc = `SEQUENCE: {{ .Sequence }} +CREATED: {{ time .CreatedAt }} +EDITED: {{ time .EditedAt }} CONFIG: {{ .Config }} ` diff --git a/cli/print/releases.go b/cli/print/releases.go index 71110a4a3..d7f3cca80 100644 --- a/cli/print/releases.go +++ b/cli/print/releases.go @@ -9,9 +9,9 @@ import ( releases "github.com/replicatedhq/replicated/gen/go/releases" ) -var releasesTmplSrc = `SEQUENCE VERSION CREATED EDITED ACTIVE_CHANNELS +var releasesTmplSrc = `SEQUENCE CREATED EDITED ACTIVE_CHANNELS {{ range . -}} -{{ .Sequence }} {{ .Version }} {{ time .CreatedAt }} {{ .EditedAt }} {{ .ActiveChannels }} +{{ .Sequence }} {{ time .CreatedAt }} {{ .EditedAt }} {{ .ActiveChannels }} {{ end }}` var releasesTmpl = template.Must(template.New("Releases").Funcs(funcs).Parse(releasesTmplSrc)) @@ -34,7 +34,6 @@ func Releases(w *tabwriter.Writer, appReleases []releases.AppReleaseInfo) error } rs[i] = map[string]interface{}{ "Sequence": r.Sequence, - "Version": r.Version, "CreatedAt": r.CreatedAt, "EditedAt": edited, "ActiveChannels": activeChansField, diff --git a/cli/test/channel_adoption_test.go b/cli/test/channel_adoption_test.go new file mode 100644 index 000000000..cb6ba4508 --- /dev/null +++ b/cli/test/channel_adoption_test.go @@ -0,0 +1,58 @@ +package test + +import ( + "bufio" + "bytes" + + . "github.com/onsi/ginkgo" + "github.com/replicatedhq/replicated/cli/cmd" + "github.com/replicatedhq/replicated/client" + apps "github.com/replicatedhq/replicated/gen/go/apps" + channels "github.com/replicatedhq/replicated/gen/go/channels" + "github.com/stretchr/testify/assert" +) + +// This only tests with no active licenses since the vendor API does not provide +// a way to update licenses' last_active field. +var _ = Describe("channel adoption", func() { + t := GinkgoT() + var app = &apps.App{Name: mustToken(8)} + var appChan = &channels.AppChannel{} + + BeforeEach(func() { + var err error + app, err = api.CreateApp(&client.AppOptions{Name: app.Name}) + assert.Nil(t, err) + + appChans, err := api.ListChannels(app.Id) + assert.Nil(t, err) + appChan = &appChans[0] + }) + + AfterEach(func() { + deleteApp(app.Id) + }) + + Context("with an existing channel ID", func() { + Context("with no licenses and no releases", func() { + It("should print the full channel details", func() { + var stdout bytes.Buffer + var stderr bytes.Buffer + + cmd.RootCmd.SetArgs([]string{"channel", "adoption", appChan.Id, "--app", app.Slug}) + cmd.RootCmd.SetOutput(&stderr) + + err := cmd.Execute(&stdout) + assert.Nil(t, err) + + assert.Zero(t, stderr, "Expected no stderr output") + assert.NotZero(t, stdout, "Expected stdout output") + + r := bufio.NewScanner(&stdout) + + assert.True(t, r.Scan()) + assert.Equal(t, "No active licenses in channel", r.Text()) + }) + }) + }) +}) diff --git a/cli/test/channel_counts_test.go b/cli/test/channel_counts_test.go new file mode 100644 index 000000000..be9df0fcd --- /dev/null +++ b/cli/test/channel_counts_test.go @@ -0,0 +1,58 @@ +package test + +import ( + "bufio" + "bytes" + + . "github.com/onsi/ginkgo" + "github.com/replicatedhq/replicated/cli/cmd" + "github.com/replicatedhq/replicated/client" + apps "github.com/replicatedhq/replicated/gen/go/apps" + channels "github.com/replicatedhq/replicated/gen/go/channels" + "github.com/stretchr/testify/assert" +) + +// This only tests with no active licenses since the vendor API does not provide +// a way to update licenses' last_active field. +var _ = Describe("channel counts", func() { + t := GinkgoT() + var app = &apps.App{Name: mustToken(8)} + var appChan = &channels.AppChannel{} + + BeforeEach(func() { + var err error + app, err = api.CreateApp(&client.AppOptions{Name: app.Name}) + assert.Nil(t, err) + + appChans, err := api.ListChannels(app.Id) + assert.Nil(t, err) + appChan = &appChans[0] + }) + + AfterEach(func() { + deleteApp(app.Id) + }) + + Context("with an existing channel ID", func() { + Context("with no licenses and no releases", func() { + It("should print the full channel details", func() { + var stdout bytes.Buffer + var stderr bytes.Buffer + + cmd.RootCmd.SetArgs([]string{"channel", "counts", appChan.Id, "--app", app.Slug}) + cmd.RootCmd.SetOutput(&stderr) + + err := cmd.Execute(&stdout) + assert.Nil(t, err) + + assert.Zero(t, stderr, "Expected no stderr output") + assert.NotZero(t, stdout, "Expected stdout output") + + r := bufio.NewScanner(&stdout) + + assert.True(t, r.Scan()) + assert.Equal(t, "No active licenses in channel", r.Text()) + }) + }) + }) +}) diff --git a/cli/test/channel_create_test.go b/cli/test/channel_create_test.go index aaf9ecf8e..caa8bf117 100644 --- a/cli/test/channel_create_test.go +++ b/cli/test/channel_create_test.go @@ -7,6 +7,7 @@ import ( . "github.com/onsi/ginkgo" "github.com/replicatedhq/replicated/cli/cmd" + "github.com/replicatedhq/replicated/client" apps "github.com/replicatedhq/replicated/gen/go/apps" "github.com/stretchr/testify/assert" ) @@ -17,13 +18,13 @@ var _ = Describe("channel create", func() { BeforeEach(func() { var err error - app, err = api.CreateApp(app.Name) + app, err = api.CreateApp(&client.AppOptions{Name: app.Name}) assert.Nil(GinkgoT(), err) }) AfterEach(func() { // ignore error, garbage collection - deleteApp(t, app.Id) + deleteApp(app.Id) }) name := mustToken(8) diff --git a/cli/test/channel_inspect_test.go b/cli/test/channel_inspect_test.go index 7b9571e39..73f7d6922 100644 --- a/cli/test/channel_inspect_test.go +++ b/cli/test/channel_inspect_test.go @@ -6,6 +6,7 @@ import ( . "github.com/onsi/ginkgo" "github.com/replicatedhq/replicated/cli/cmd" + "github.com/replicatedhq/replicated/client" apps "github.com/replicatedhq/replicated/gen/go/apps" channels "github.com/replicatedhq/replicated/gen/go/channels" "github.com/stretchr/testify/assert" @@ -18,7 +19,7 @@ var _ = Describe("channel inspect", func() { BeforeEach(func() { var err error - app, err = api.CreateApp(app.Name) + app, err = api.CreateApp(&client.AppOptions{Name: app.Name}) assert.Nil(t, err) appChans, err := api.ListChannels(app.Id) @@ -27,8 +28,7 @@ var _ = Describe("channel inspect", func() { }) AfterEach(func() { - // ignore error, garbage collection - deleteApp(t, app.Id) + deleteApp(app.Id) }) Context("with an existing channel ID", func() { @@ -49,40 +49,32 @@ var _ = Describe("channel inspect", func() { r := bufio.NewScanner(&stdout) assert.True(t, r.Scan()) - assert.Regexp(t, `^ID: `+appChan.Id+`$`, r.Text()) + assert.Regexp(t, `^ID:\s+`+appChan.Id+`$`, r.Text()) assert.True(t, r.Scan()) - assert.Regexp(t, `^NAME: `+appChan.Name+`$`, r.Text()) + assert.Regexp(t, `^NAME:\s+`+appChan.Name+`$`, r.Text()) assert.True(t, r.Scan()) - assert.Regexp(t, `^DESCRIPTION: `+appChan.Description+`$`, r.Text()) + assert.Regexp(t, `^DESCRIPTION:\s+`+appChan.Description+`$`, r.Text()) assert.True(t, r.Scan()) - assert.Equal(t, "", r.Text()) + assert.Regexp(t, `^RELEASE:\s+`, r.Text()) + /* + assert.True(t, r.Scan()) + assert.Equal(t, "LICENSE_COUNTS", r.Text()) - assert.True(t, r.Scan()) - assert.Equal(t, "ADOPTION", r.Text()) - - assert.True(t, r.Scan()) - assert.Equal(t, "No licenses in channel", r.Text()) - - assert.True(t, r.Scan()) - assert.Equal(t, "", r.Text()) - - assert.True(t, r.Scan()) - assert.Equal(t, "LICENSE_COUNTS", r.Text()) - - assert.True(t, r.Scan()) - assert.Equal(t, "No licenses in channel", r.Text()) + assert.True(t, r.Scan()) + assert.Equal(t, "No licenses in channel", r.Text()) - assert.True(t, r.Scan()) - assert.Equal(t, "", r.Text()) + assert.True(t, r.Scan()) + assert.Equal(t, "", r.Text()) - assert.True(t, r.Scan()) - assert.Equal(t, "RELEASES", r.Text()) + assert.True(t, r.Scan()) + assert.Equal(t, "RELEASES", r.Text()) - assert.True(t, r.Scan()) - assert.Equal(t, "No releases in channel", r.Text()) + assert.True(t, r.Scan()) + assert.Equal(t, "No releases in channel", r.Text()) + */ }) }) }) diff --git a/cli/test/channel_list_test.go b/cli/test/channel_ls_test.go similarity index 91% rename from cli/test/channel_list_test.go rename to cli/test/channel_ls_test.go index 27125a855..b94ed66b5 100644 --- a/cli/test/channel_list_test.go +++ b/cli/test/channel_ls_test.go @@ -6,6 +6,7 @@ import ( . "github.com/onsi/ginkgo" "github.com/replicatedhq/replicated/cli/cmd" + "github.com/replicatedhq/replicated/client" apps "github.com/replicatedhq/replicated/gen/go/apps" channels "github.com/replicatedhq/replicated/gen/go/channels" "github.com/stretchr/testify/assert" @@ -18,7 +19,7 @@ var _ = Describe("channel ls", func() { BeforeEach(func() { var err error - app, err = api.CreateApp(app.Name) + app, err = api.CreateApp(&client.AppOptions{Name: app.Name}) assert.Nil(t, err) appChans, err = api.ListChannels(app.Id) @@ -27,7 +28,7 @@ var _ = Describe("channel ls", func() { }) AfterEach(func() { - deleteApp(t, app.Id) + deleteApp(app.Id) }) Context("when an app has three channels without releases", func() { diff --git a/cli/test/channel_releases_test.go b/cli/test/channel_releases_test.go new file mode 100644 index 000000000..4563b00e3 --- /dev/null +++ b/cli/test/channel_releases_test.go @@ -0,0 +1,86 @@ +package test + +import ( + "bufio" + "bytes" + "strings" + + . "github.com/onsi/ginkgo" + "github.com/replicatedhq/replicated/cli/cmd" + "github.com/replicatedhq/replicated/client" + apps "github.com/replicatedhq/replicated/gen/go/apps" + channels "github.com/replicatedhq/replicated/gen/go/channels" + "github.com/stretchr/testify/assert" +) + +var _ = Describe("channel releases", func() { + t := GinkgoT() + app := &apps.App{Name: mustToken(8)} + var appChan channels.AppChannel + + BeforeEach(func() { + var err error + app, err = api.CreateApp(&client.AppOptions{Name: app.Name}) + assert.Nil(t, err) + + appChans, err := api.ListChannels(app.Id) + assert.Nil(t, err) + appChan = appChans[0] + + release, err := api.CreateRelease(app.Id, nil) + assert.Nil(t, err) + err = api.PromoteRelease(app.Id, release.Sequence, "v1", "Big", true, appChan.Id) + assert.Nil(t, err) + + release, err = api.CreateRelease(app.Id, nil) + assert.Nil(t, err) + err = api.PromoteRelease(app.Id, release.Sequence, "v2", "Small", false, appChan.Id) + assert.Nil(t, err) + }) + + AfterEach(func() { + deleteApp(app.Id) + }) + + Context("when a channel has two releases", func() { + It("should print a table of releases with one row", func() { + var stdout bytes.Buffer + var stderr bytes.Buffer + + cmd.RootCmd.SetArgs([]string{"channel", "releases", appChan.Id, "--app", app.Slug}) + cmd.RootCmd.SetOutput(&stderr) + + err := cmd.Execute(&stdout) + assert.Nil(t, err) + + assert.Empty(t, stderr.String(), "Expected no stderr output") + assert.NotEmpty(t, stdout.String(), "Expected stdout output") + + r := bufio.NewScanner(&stdout) + + assert.True(t, r.Scan()) + assert.Regexp(t, `CHANNEL_SEQUENCE\s+RELEASE_SEQUENCE\s+RELEASED\s+VERSION\s+REQUIRED\s+AIRGAP_STATUS\s+RELEASE_NOTES$`, r.Text()) + + assert.True(t, r.Scan()) + words := strings.Fields(r.Text()) + + // reverse chronological order + assert.Equal(t, "1", words[0], "CHANNEL_SEQUENCE") + assert.Equal(t, "2", words[1], "RELEASE_SEQUENCE") + assert.Equal(t, "v2", words[3], "VERSION") + assert.Equal(t, "false", words[4], "REQURED") + assert.Equal(t, "Small", words[6], "RELEASE_NOTES") + + assert.True(t, r.Scan()) + words = strings.Fields(r.Text()) + + assert.Equal(t, "0", words[0], "CHANNEL_SEQUENCE") + assert.Equal(t, "1", words[1], "RELEASE_SEQUENCE") + assert.Equal(t, "v1", words[3], "VERSION") + assert.Equal(t, "true", words[4], "REQUIRED") + assert.Equal(t, "Big", words[6], "RELEASE_NOTES") + + assert.False(t, r.Scan()) + }) + }) +}) diff --git a/cli/test/channel_rm_test.go b/cli/test/channel_rm_test.go index 586a7fc6b..5c4305f52 100644 --- a/cli/test/channel_rm_test.go +++ b/cli/test/channel_rm_test.go @@ -6,6 +6,7 @@ import ( . "github.com/onsi/ginkgo" "github.com/replicatedhq/replicated/cli/cmd" + "github.com/replicatedhq/replicated/client" apps "github.com/replicatedhq/replicated/gen/go/apps" channels "github.com/replicatedhq/replicated/gen/go/channels" "github.com/stretchr/testify/assert" @@ -18,7 +19,7 @@ var _ = Describe("channel rm", func() { BeforeEach(func() { var err error - app, err = api.CreateApp(app.Name) + app, err = api.CreateApp(&client.AppOptions{Name: app.Name}) assert.Nil(t, err) appChans, err := api.ListChannels(app.Id) @@ -27,7 +28,7 @@ var _ = Describe("channel rm", func() { }) AfterEach(func() { - deleteApp(t, app.Id) + deleteApp(app.Id) }) Context("when the channel ID exists", func() { diff --git a/cli/test/cli_test.go b/cli/test/cli_test.go index 546b4f0ef..ab483fd64 100644 --- a/cli/test/cli_test.go +++ b/cli/test/cli_test.go @@ -9,3 +9,5 @@ import ( func TestCLI(t *testing.T) { RunSpecs(t, "CLI Suite") } + +var _ = AfterSuite(cleanupApps) diff --git a/cli/test/release_create_test.go b/cli/test/release_create_test.go index a66182d69..8abb387af 100644 --- a/cli/test/release_create_test.go +++ b/cli/test/release_create_test.go @@ -6,6 +6,7 @@ import ( . "github.com/onsi/ginkgo" "github.com/replicatedhq/replicated/cli/cmd" + "github.com/replicatedhq/replicated/client" apps "github.com/replicatedhq/replicated/gen/go/apps" "github.com/stretchr/testify/assert" ) @@ -16,12 +17,12 @@ var _ = Describe("release create", func() { BeforeEach(func() { var err error - app, err = api.CreateApp(app.Name) + app, err = api.CreateApp(&client.AppOptions{Name: app.Name}) assert.Nil(t, err) }) AfterEach(func() { - deleteApp(t, app.Id) + deleteApp(app.Id) }) Context("with valid --yaml in an app with no releases", func() { diff --git a/cli/test/release_inspect.go b/cli/test/release_inspect.go index c67c17220..89614c256 100644 --- a/cli/test/release_inspect.go +++ b/cli/test/release_inspect.go @@ -7,6 +7,7 @@ import ( . "github.com/onsi/ginkgo" "github.com/replicatedhq/replicated/cli/cmd" + "github.com/replicatedhq/replicated/client" apps "github.com/replicatedhq/replicated/gen/go/apps" releases "github.com/replicatedhq/replicated/gen/go/releases" "github.com/stretchr/testify/assert" @@ -19,17 +20,15 @@ var _ = Describe("release inspect", func() { BeforeEach(func() { var err error - app, err = api.CreateApp(app.Name) + app, err = api.CreateApp(&client.AppOptions{Name: app.Name}) assert.Nil(t, err) - release, err = api.CreateRelease(app.Id) - assert.Nil(t, err) - err = api.UpdateRelease(app.Id, release.Sequence, yaml) + release, err = api.CreateRelease(app.Id, &client.ReleaseOptions{YAML: yaml}) assert.Nil(t, err) }) AfterEach(func() { - deleteApp(t, app.Id) + deleteApp(app.Id) }) Context("with an existing release sequence", func() { @@ -50,13 +49,13 @@ var _ = Describe("release inspect", func() { r := bufio.NewScanner(&stdout) assert.True(t, r.Scan()) - assert.Equal(t, "SEQUENCE: "+seq, r.Text()) + assert.Regexp(t, `^SEQUENCE:\s+`+seq, r.Text()) assert.True(t, r.Scan()) - assert.Regexp(t, `^CREATED: \d+`, r.Text()) + assert.Regexp(t, `^CREATED:\s+\d+`, r.Text()) assert.True(t, r.Scan()) - assert.Regexp(t, `^EDITED: \d+`, r.Text()) + assert.Regexp(t, `^EDITED:\s+\d+`, r.Text()) assert.True(t, r.Scan()) assert.Equal(t, "CONFIG:", r.Text()) diff --git a/cli/test/release_ls_test.go b/cli/test/release_ls_test.go index d616b47ee..0aec24775 100644 --- a/cli/test/release_ls_test.go +++ b/cli/test/release_ls_test.go @@ -6,6 +6,7 @@ import ( . "github.com/onsi/ginkgo" "github.com/replicatedhq/replicated/cli/cmd" + "github.com/replicatedhq/replicated/client" apps "github.com/replicatedhq/replicated/gen/go/apps" "github.com/stretchr/testify/assert" ) @@ -16,15 +17,15 @@ var _ = Describe("release ls", func() { BeforeEach(func() { var err error - app, err = api.CreateApp(app.Name) + app, err = api.CreateApp(&client.AppOptions{Name: app.Name}) assert.Nil(t, err) - _, err = api.CreateRelease(app.Id) + _, err = api.CreateRelease(app.Id, nil) assert.Nil(t, err) }) AfterEach(func() { - deleteApp(t, app.Id) + deleteApp(app.Id) }) Context("when an app has one release", func() { @@ -44,7 +45,7 @@ var _ = Describe("release ls", func() { r := bufio.NewScanner(&stdout) assert.True(t, r.Scan()) - assert.Regexp(t, `SEQUENCE\s+VERSION\s+CREATED\s+EDITED\s+ACTIVE_CHANNELS`, r.Text()) + assert.Regexp(t, `SEQUENCE\s+CREATED\s+EDITED\s+ACTIVE_CHANNELS`, r.Text()) assert.True(t, r.Scan()) assert.Regexp(t, `\d+\s+`, r.Text()) diff --git a/cli/test/release_promote_test.go b/cli/test/release_promote_test.go index baa7402e8..e26aef0c4 100644 --- a/cli/test/release_promote_test.go +++ b/cli/test/release_promote_test.go @@ -7,6 +7,7 @@ import ( . "github.com/onsi/ginkgo" "github.com/replicatedhq/replicated/cli/cmd" + "github.com/replicatedhq/replicated/client" apps "github.com/replicatedhq/replicated/gen/go/apps" channels "github.com/replicatedhq/replicated/gen/go/channels" releases "github.com/replicatedhq/replicated/gen/go/releases" @@ -21,10 +22,10 @@ var _ = Describe("release promote", func() { BeforeEach(func() { var err error - app, err = api.CreateApp(app.Name) + app, err = api.CreateApp(&client.AppOptions{Name: app.Name}) assert.Nil(t, err) - release, err = api.CreateRelease(app.Id) + release, err = api.CreateRelease(app.Id, nil) assert.Nil(t, err) appChannels, err := api.ListChannels(app.Id) @@ -33,7 +34,7 @@ var _ = Describe("release promote", func() { }) AfterEach(func() { - deleteApp(t, app.Id) + deleteApp(app.Id) }) Context("when a channel with no releases is promoted to release 1", func() { diff --git a/cli/test/release_update_test.go b/cli/test/release_update_test.go index 5300274cb..999de54a7 100644 --- a/cli/test/release_update_test.go +++ b/cli/test/release_update_test.go @@ -7,6 +7,7 @@ import ( . "github.com/onsi/ginkgo" "github.com/replicatedhq/replicated/cli/cmd" + "github.com/replicatedhq/replicated/client" apps "github.com/replicatedhq/replicated/gen/go/apps" releases "github.com/replicatedhq/replicated/gen/go/releases" "github.com/stretchr/testify/assert" @@ -19,15 +20,15 @@ var _ = Describe("release update", func() { BeforeEach(func() { var err error - app, err = api.CreateApp(app.Name) + app, err = api.CreateApp(&client.AppOptions{Name: app.Name}) assert.Nil(t, err) - release, err = api.CreateRelease(app.Id) + release, err = api.CreateRelease(app.Id, nil) assert.Nil(t, err) }) AfterEach(func() { - deleteApp(t, app.Id) + deleteApp(app.Id) }) Context("with an existing release sequence and valid --yaml", func() { diff --git a/cli/test/util.go b/cli/test/util.go index ed738853b..9666d6fae 100644 --- a/cli/test/util.go +++ b/cli/test/util.go @@ -5,12 +5,14 @@ import ( "crypto/rand" "encoding/base64" "encoding/json" + "fmt" "io" "log" "net/http" "os" - "github.com/onsi/ginkgo" + . "github.com/onsi/ginkgo" + "github.com/replicatedhq/replicated/client" ) @@ -68,65 +70,80 @@ func mustToken(n int) string { return base64.RawURLEncoding.EncodeToString(data) } -var sessionToken string +var appsToDelete = make([]string, 0) -// for cleanup -func deleteApp(t ginkgo.GinkgoTInterface, id string) { - origin := os.Getenv("REPLICATED_API_ORIGIN") +// Mark app for deletion. The actual deletion will happen in the AfterSuite when +// all tests are finished since this requires logging in as a user, which is +// rate-limited by the Vendor API. +func deleteApp(id string) { + appsToDelete = append(appsToDelete, id) +} - if sessionToken == "" { - email := os.Getenv("VENDOR_USER_EMAIL") - password := os.Getenv("VENDOR_USER_PASSWORD") +func cleanupApps() { + if len(appsToDelete) == 0 { + return + } + t := GinkgoT() + origin := os.Getenv("REPLICATED_API_ORIGIN") + email := os.Getenv("VENDOR_USER_EMAIL") + password := os.Getenv("VENDOR_USER_PASSWORD") - creds := map[string]interface{}{ - "email": email, - "password": password, - "remember_me": false, - } - buf := bytes.NewBuffer(nil) - err := json.NewEncoder(buf).Encode(creds) - if err != nil { - t.Fatal(err) - } + if email == "" || password == "" { + fmt.Println("VENDOR_USER_EMAIL or VENDOR_USER_PASSWORD not set. Skipping app cleanup") + return + } - req, err := http.NewRequest("POST", origin+"/v1/user/login", buf) - if err != nil { - t.Fatal(err) - } - req.Header.Set("Content-Type", "application/json") - req.Header.Set("Accept", "application/json") - resp, err := http.DefaultClient.Do(req) - if err != nil { - t.Fatal(err) - } - defer resp.Body.Close() - if resp.StatusCode >= 300 { - t.Fatalf("Login response status: %d", resp.StatusCode) - } - respBody := struct { - SessionToken string `json:"token"` - }{} - err = json.NewDecoder(resp.Body).Decode(&respBody) - if err != nil { - t.Fatal(err) - } - if respBody.SessionToken == "" { - t.Fatal("Login failed; cannot delete apps") - } - sessionToken = respBody.SessionToken + creds := map[string]interface{}{ + "email": email, + "password": password, + "remember_me": false, + } + buf := bytes.NewBuffer(nil) + err := json.NewEncoder(buf).Encode(creds) + if err != nil { + t.Fatal(err) } - req, err := http.NewRequest("DELETE", origin+"/v1/app/"+id, nil) + req, err := http.NewRequest("POST", origin+"/v1/user/login", buf) if err != nil { t.Fatal(err) } - req.Header.Set("Authorization", sessionToken) + req.Header.Set("Content-Type", "application/json") + req.Header.Set("Accept", "application/json") resp, err := http.DefaultClient.Do(req) if err != nil { t.Fatal(err) } - resp.Body.Close() + defer resp.Body.Close() + if resp.StatusCode >= 300 { - t.Fatalf("Delete app response status: %d", resp.StatusCode) + t.Fatalf("Login response status: %d", resp.StatusCode) + } + respBody := struct { + SessionToken string `json:"token"` + }{} + err = json.NewDecoder(resp.Body).Decode(&respBody) + if err != nil { + t.Fatal(err) + } + if respBody.SessionToken == "" { + t.Fatal("Login failed; cannot delete apps") + } + sessionToken := respBody.SessionToken + + for _, id := range appsToDelete { + req, err := http.NewRequest("DELETE", origin+"/v1/app/"+id, nil) + if err != nil { + t.Fatal(err) + } + req.Header.Set("Authorization", sessionToken) + resp, err := http.DefaultClient.Do(req) + if err != nil { + t.Fatal(err) + } + resp.Body.Close() + if resp.StatusCode >= 300 { + t.Fatalf("Delete app response status: %d", resp.StatusCode) + } } } diff --git a/client/app.go b/client/app.go index 5b6dd453f..5161064f9 100644 --- a/client/app.go +++ b/client/app.go @@ -17,23 +17,23 @@ func (c *HTTPClient) ListApps() ([]apps.AppAndChannels, error) { return appsAndChannels, nil } -// GetAppBySlug resolves an app by slug. -func (c *HTTPClient) GetAppBySlug(slug string) (*apps.App, error) { +// GetApp resolves an app by either slug or ID. +func (c *HTTPClient) GetApp(slugOrID string) (*apps.App, error) { appsAndChannels, err := c.ListApps() if err != nil { - return nil, fmt.Errorf("GetAppBySlug: %v", err) + return nil, fmt.Errorf("GetApp: %v", err) } for _, ac := range appsAndChannels { - if ac.App.Slug == slug { - return &ac.App, nil + if ac.App.Slug == slugOrID || ac.App.Id == slugOrID { + return ac.App, nil } } return nil, ErrNotFound } // CreateApp creates a new app with the given name and returns it. -func (c *HTTPClient) CreateApp(name string) (*apps.App, error) { - reqBody := &apps.Body{Name: name} +func (c *HTTPClient) CreateApp(opts *AppOptions) (*apps.App, error) { + reqBody := &apps.Body{Name: opts.Name} app := &apps.App{} err := c.doJSON("POST", "/v1/app", http.StatusCreated, reqBody, app) if err != nil { diff --git a/client/channel.go b/client/channel.go index 2d968b294..c01507d09 100644 --- a/client/channel.go +++ b/client/channel.go @@ -3,10 +3,26 @@ package client import ( "fmt" "net/http" + "sort" channels "github.com/replicatedhq/replicated/gen/go/channels" ) +// AppChannels sorts []channels.AppChannel by Channel.Position +type AppChannels []channels.AppChannel + +func (acs AppChannels) Len() int { + return len(acs) +} + +func (acs AppChannels) Swap(i, j int) { + acs[i], acs[j] = acs[j], acs[i] +} + +func (acs AppChannels) Less(i, j int) bool { + return acs[i].Position < acs[j].Position +} + // ListChannels returns all channels for an app. func (c *HTTPClient) ListChannels(appID string) ([]channels.AppChannel, error) { path := fmt.Sprintf("/v1/app/%s/channels", appID) @@ -15,15 +31,16 @@ func (c *HTTPClient) ListChannels(appID string) ([]channels.AppChannel, error) { if err != nil { return nil, fmt.Errorf("ListChannels: %v", err) } + sort.Sort(AppChannels(appChannels)) return appChannels, nil } // CreateChannel adds a channel to an app. -func (c *HTTPClient) CreateChannel(appID, name, desc string) ([]channels.AppChannel, error) { +func (c *HTTPClient) CreateChannel(appID string, opts *ChannelOptions) ([]channels.AppChannel, error) { path := fmt.Sprintf("/v1/app/%s/channel", appID) body := &channels.Body{ - Name: name, - Description: desc, + Name: opts.Name, + Description: opts.Description, } appChannels := make([]channels.AppChannel, 0) err := c.doJSON("POST", path, http.StatusOK, body, &appChannels) @@ -55,6 +72,21 @@ func (c *HTTPClient) ArchiveChannel(appID, channelID string) error { return nil } +// ChannelReleases sorts []channels.ChannelRelease newest to oldest +type ChannelReleases []channels.ChannelRelease + +func (crs ChannelReleases) Len() int { + return len(crs) +} + +func (crs ChannelReleases) Swap(i, j int) { + crs[i], crs[j] = crs[j], crs[i] +} + +func (crs ChannelReleases) Less(i, j int) bool { + return crs[i].ChannelSequence > crs[j].ChannelSequence +} + // GetChannel returns channel details and release history func (c *HTTPClient) GetChannel(appID, channelID string) (*channels.AppChannel, []channels.ChannelRelease, error) { path := fmt.Sprintf("/v1/app/%s/channel/%s/releases", appID, channelID) @@ -63,5 +95,6 @@ func (c *HTTPClient) GetChannel(appID, channelID string) (*channels.AppChannel, if err != nil { return nil, nil, fmt.Errorf("GetChannel: %v", err) } - return &respBody.Channel, respBody.Releases, nil + sort.Sort(ChannelReleases(respBody.Releases)) + return respBody.Channel, respBody.Releases, nil } diff --git a/client/client.go b/client/client.go index dde5272b2..ea16af678 100644 --- a/client/client.go +++ b/client/client.go @@ -5,28 +5,30 @@ import ( "bytes" "encoding/json" "fmt" + "io/ioutil" "net/http" apps "github.com/replicatedhq/replicated/gen/go/apps" channels "github.com/replicatedhq/replicated/gen/go/channels" releases "github.com/replicatedhq/replicated/gen/go/releases" + v2 "github.com/replicatedhq/replicated/gen/go/v2" ) const apiOrigin = "https://api.replicated.com/vendor" // Client provides methods to manage apps, channels, and releases. type Client interface { - GetAppBySlug(slug string) (*apps.App, error) - CreateApp(name string) (*apps.App, error) + GetApp(slugOrID string) (*apps.App, error) + CreateApp(opts *AppOptions) (*apps.App, error) ListChannels(appID string) ([]channels.AppChannel, error) - CreateChannel(appID, name, desc string) ([]channels.AppChannel, error) + CreateChannel(appID string, opts *ChannelOptions) ([]channels.AppChannel, error) ArchiveChannel(appID, channelID string) error GetChannel(appID, channelID string) (*channels.AppChannel, []channels.ChannelRelease, error) ListReleases(appID string) ([]releases.AppReleaseInfo, error) - CreateRelease(appID string) (*releases.AppReleaseInfo, error) - UpdateRelease(appID string, sequence int64, yaml string) error + CreateRelease(appID string, opts *ReleaseOptions) (*releases.AppReleaseInfo, error) + UpdateRelease(appID string, sequence int64, opts *ReleaseOptions) error GetRelease(appID string, sequence int64) (*releases.AppRelease, error) PromoteRelease( appID string, @@ -35,6 +37,21 @@ type Client interface { notes string, required bool, channelIDs ...string) error + + CreateLicense(*v2.LicenseV2) (*v2.LicenseV2, error) +} + +type AppOptions struct { + Name string +} + +type ChannelOptions struct { + Name string + Description string +} + +type ReleaseOptions struct { + YAML string } // An HTTPClient communicates with the Replicated Vendor HTTP API. @@ -86,7 +103,8 @@ func (c *HTTPClient) doJSON(method, path string, successStatus int, reqBody, res return ErrNotFound } if resp.StatusCode != successStatus { - return fmt.Errorf("%s %s: status %d", method, endpoint, resp.StatusCode) + body, _ := ioutil.ReadAll(resp.Body) + return fmt.Errorf("%s %s %d: %s", method, endpoint, resp.StatusCode, body) } if respBody != nil { if err := json.NewDecoder(resp.Body).Decode(respBody); err != nil { diff --git a/client/client_test.go b/client/client_test.go index b675b30d2..2fd0e871d 100644 --- a/client/client_test.go +++ b/client/client_test.go @@ -8,11 +8,11 @@ import ( func ExampleNew() { token := os.Getenv("REPLICATED_API_TOKEN") - appSlug := os.Getenv("REPLICATED_APP_SLUG") + appSlugOrID := os.Getenv("REPLICATED_APP") api := New(token) - app, err := api.GetAppBySlug(appSlug) + app, err := api.GetApp(appSlug) if err != nil { log.Fatal(err) } diff --git a/client/license.go b/client/license.go new file mode 100644 index 000000000..66f9cbc66 --- /dev/null +++ b/client/license.go @@ -0,0 +1,17 @@ +package client + +import ( + "fmt" + "net/http" + + v2 "github.com/replicatedhq/replicated/gen/go/v2" +) + +// CreateLicense creates a new License. +func (c *HTTPClient) CreateLicense(license *v2.LicenseV2) (*v2.LicenseV2, error) { + created := &v2.LicenseV2{} + if err := c.doJSON("POST", "/v2/license", http.StatusCreated, license, created); err != nil { + return nil, fmt.Errorf("CreateLicense: %v", err) + } + return created, nil +} diff --git a/client/release.go b/client/release.go index 530e79fae..a23f72be6 100644 --- a/client/release.go +++ b/client/release.go @@ -19,7 +19,7 @@ func (c *HTTPClient) ListReleases(appID string) ([]releases.AppReleaseInfo, erro } // CreateRelease adds a release to an app. -func (c *HTTPClient) CreateRelease(appID string) (*releases.AppReleaseInfo, error) { +func (c *HTTPClient) CreateRelease(appID string, opts *ReleaseOptions) (*releases.AppReleaseInfo, error) { path := fmt.Sprintf("/v1/app/%s/release", appID) body := &releases.Body{ Source: "latest", @@ -28,13 +28,19 @@ func (c *HTTPClient) CreateRelease(appID string) (*releases.AppReleaseInfo, erro if err := c.doJSON("POST", path, http.StatusCreated, body, release); err != nil { return nil, fmt.Errorf("CreateRelease: %v", err) } + // API does not accept yaml in create operation, so first create then udpate + if opts != nil && opts.YAML != "" { + if err := c.UpdateRelease(appID, release.Sequence, opts); err != nil { + return nil, fmt.Errorf("CreateRelease with YAML: %v", err) + } + } return release, nil } // UpdateRelease updates a release's yaml. -func (c *HTTPClient) UpdateRelease(appID string, sequence int64, yaml string) error { +func (c *HTTPClient) UpdateRelease(appID string, sequence int64, opts *ReleaseOptions) error { endpoint := fmt.Sprintf("%s/v1/app/%s/%d/raw", c.apiOrigin, appID, sequence) - req, err := http.NewRequest("PUT", endpoint, strings.NewReader(yaml)) + req, err := http.NewRequest("PUT", endpoint, strings.NewReader(opts.YAML)) if err != nil { return err } diff --git a/gen/go/apps/app_and_channels.go b/gen/go/apps/app_and_channels.go index 4179f0024..30608f1ee 100644 --- a/gen/go/apps/app_and_channels.go +++ b/gen/go/apps/app_and_channels.go @@ -12,7 +12,7 @@ package swagger type AppAndChannels struct { - App App `json:"App"` + App *App `json:"App"` // Channels of the app Channels []AppChannel `json:"Channels"` diff --git a/gen/go/apps/app_channel.go b/gen/go/apps/app_channel.go index bfcd514f4..8895d5037 100644 --- a/gen/go/apps/app_channel.go +++ b/gen/go/apps/app_channel.go @@ -13,7 +13,7 @@ package swagger // An app channel belongs to an app. It contains references to the top (current) release in the channel. type AppChannel struct { - Adoption ChannelAdoption `json:"Adoption,omitempty"` + Adoption *ChannelAdoption `json:"Adoption,omitempty"` // Description that will be shown during license installation Description string `json:"Description"` @@ -21,7 +21,7 @@ type AppChannel struct { // The ID of the channel Id string `json:"Id"` - LicenseCounts LicenseCounts `json:"LicenseCounts,omitempty"` + LicenseCounts *LicenseCounts `json:"LicenseCounts,omitempty"` // The name of channel Name string `json:"Name"` diff --git a/gen/go/apps/docs/AppAndChannels.md b/gen/go/apps/docs/AppAndChannels.md index 4ef367530..4056cc0a8 100644 --- a/gen/go/apps/docs/AppAndChannels.md +++ b/gen/go/apps/docs/AppAndChannels.md @@ -3,7 +3,7 @@ ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- -**App** | [**App**](App.md) | | [default to null] +**App** | [***App**](App.md) | | [default to null] **Channels** | [**[]AppChannel**](AppChannel.md) | Channels of the app | [default to null] [[Back to Model list]](../README.md#documentation-for-models) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to README]](../README.md) diff --git a/gen/go/apps/docs/AppChannel.md b/gen/go/apps/docs/AppChannel.md index 4543c6982..56457d505 100644 --- a/gen/go/apps/docs/AppChannel.md +++ b/gen/go/apps/docs/AppChannel.md @@ -3,10 +3,10 @@ ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- -**Adoption** | [**ChannelAdoption**](ChannelAdoption.md) | | [optional] [default to null] +**Adoption** | [***ChannelAdoption**](ChannelAdoption.md) | | [optional] [default to null] **Description** | **string** | Description that will be shown during license installation | [default to null] **Id** | **string** | The ID of the channel | [default to null] -**LicenseCounts** | [**LicenseCounts**](LicenseCounts.md) | | [optional] [default to null] +**LicenseCounts** | [***LicenseCounts**](LicenseCounts.md) | | [optional] [default to null] **Name** | **string** | The name of channel | [default to null] **Position** | **int64** | The position for which the channel occurs in a list | [optional] [default to null] **ReleaseLabel** | **string** | The label of the current release sequence | [optional] [default to null] diff --git a/gen/go/channels/app_channel.go b/gen/go/channels/app_channel.go index 5eb7fe246..7b088262d 100644 --- a/gen/go/channels/app_channel.go +++ b/gen/go/channels/app_channel.go @@ -13,7 +13,7 @@ package swagger // An app channel belongs to an app. It contains references to the top (current) release in the channel. type AppChannel struct { - Adoption ChannelAdoption `json:"Adoption,omitempty"` + Adoption *ChannelAdoption `json:"Adoption,omitempty"` // Description that will be shown during license installation Description string `json:"Description"` @@ -21,7 +21,7 @@ type AppChannel struct { // The ID of the channel Id string `json:"Id"` - LicenseCounts LicenseCounts `json:"LicenseCounts,omitempty"` + LicenseCounts *LicenseCounts `json:"LicenseCounts,omitempty"` // The name of channel Name string `json:"Name"` diff --git a/gen/go/channels/docs/AppChannel.md b/gen/go/channels/docs/AppChannel.md index 4543c6982..56457d505 100644 --- a/gen/go/channels/docs/AppChannel.md +++ b/gen/go/channels/docs/AppChannel.md @@ -3,10 +3,10 @@ ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- -**Adoption** | [**ChannelAdoption**](ChannelAdoption.md) | | [optional] [default to null] +**Adoption** | [***ChannelAdoption**](ChannelAdoption.md) | | [optional] [default to null] **Description** | **string** | Description that will be shown during license installation | [default to null] **Id** | **string** | The ID of the channel | [default to null] -**LicenseCounts** | [**LicenseCounts**](LicenseCounts.md) | | [optional] [default to null] +**LicenseCounts** | [***LicenseCounts**](LicenseCounts.md) | | [optional] [default to null] **Name** | **string** | The name of channel | [default to null] **Position** | **int64** | The position for which the channel occurs in a list | [optional] [default to null] **ReleaseLabel** | **string** | The label of the current release sequence | [optional] [default to null] diff --git a/gen/go/channels/docs/InlineResponse2001.md b/gen/go/channels/docs/InlineResponse2001.md index 8de88f635..4d1615329 100644 --- a/gen/go/channels/docs/InlineResponse2001.md +++ b/gen/go/channels/docs/InlineResponse2001.md @@ -3,7 +3,7 @@ ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- -**Channel** | [**AppChannel**](AppChannel.md) | | [default to null] +**Channel** | [***AppChannel**](AppChannel.md) | | [default to null] **Releases** | [**[]ChannelRelease**](ChannelRelease.md) | | [default to null] [[Back to Model list]](../README.md#documentation-for-models) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to README]](../README.md) diff --git a/gen/go/channels/inline_response_200_1.go b/gen/go/channels/inline_response_200_1.go index f1400d884..ec43ffd4e 100644 --- a/gen/go/channels/inline_response_200_1.go +++ b/gen/go/channels/inline_response_200_1.go @@ -12,7 +12,7 @@ package swagger type InlineResponse2001 struct { - Channel AppChannel `json:"channel"` + Channel *AppChannel `json:"channel"` Releases []ChannelRelease `json:"releases"` } diff --git a/gen/go/releases/app_channel.go b/gen/go/releases/app_channel.go index 4ce81071d..3aa50da4e 100644 --- a/gen/go/releases/app_channel.go +++ b/gen/go/releases/app_channel.go @@ -13,7 +13,7 @@ package swagger // An app channel belongs to an app. It contains references to the top (current) release in the channel. type AppChannel struct { - Adoption ChannelAdoption `json:"Adoption,omitempty"` + Adoption *ChannelAdoption `json:"Adoption,omitempty"` // Description that will be shown during license installation Description string `json:"Description"` @@ -21,7 +21,7 @@ type AppChannel struct { // The ID of the channel Id string `json:"Id"` - LicenseCounts LicenseCounts `json:"LicenseCounts,omitempty"` + LicenseCounts *LicenseCounts `json:"LicenseCounts,omitempty"` // The name of channel Name string `json:"Name"` diff --git a/gen/go/releases/docs/AppChannel.md b/gen/go/releases/docs/AppChannel.md index 4543c6982..56457d505 100644 --- a/gen/go/releases/docs/AppChannel.md +++ b/gen/go/releases/docs/AppChannel.md @@ -3,10 +3,10 @@ ## Properties Name | Type | Description | Notes ------------ | ------------- | ------------- | ------------- -**Adoption** | [**ChannelAdoption**](ChannelAdoption.md) | | [optional] [default to null] +**Adoption** | [***ChannelAdoption**](ChannelAdoption.md) | | [optional] [default to null] **Description** | **string** | Description that will be shown during license installation | [default to null] **Id** | **string** | The ID of the channel | [default to null] -**LicenseCounts** | [**LicenseCounts**](LicenseCounts.md) | | [optional] [default to null] +**LicenseCounts** | [***LicenseCounts**](LicenseCounts.md) | | [optional] [default to null] **Name** | **string** | The name of channel | [default to null] **Position** | **int64** | The position for which the channel occurs in a list | [optional] [default to null] **ReleaseLabel** | **string** | The label of the current release sequence | [optional] [default to null] diff --git a/gen/go/v2/body.go b/gen/go/v2/body.go new file mode 100644 index 000000000..3859953e1 --- /dev/null +++ b/gen/go/v2/body.go @@ -0,0 +1,36 @@ +/* + * Vendor API V2 + * + * The Vendor API is available as an alternative to configuring your application via the Vendor website. This API will allow you as the Vendor to manage your apps and app configuration, manage customer licenses, view your private container images. The API can be accessed at the URL https://api.replicated.com/vendor/v2. == Authentication Authentication is achieved via a token that can be generated via the Vendor website. You can create a new token by clicking the New API Token button in the API Tokens table. You must give this token a nickname before saving. After you have generated your token, you will need to send this token in the Authorization header of your requests to the Vendor API. The following Error response codes can be expected: [options=\"header\", cols=\".^1,.^3,.^10\"] |=== |Code|Response|Description |400|Bad Request|We were unable to parse your request. |401|Unauthorized|Confirm that your token or username/password is valid. |403|Forbidden|The server is refusing to alloo you to complete this request. |404|Not found|The requested resource was not found. |409|Conflict|The action would result in a conflict and is being rejected. |500|Internal Server Error|Something unexpected happened. |=== You download JSON schemas for this API in our github repo. Check out our Developer Help Center for sample recipes on using our Vendor API + * + * OpenAPI spec version: 1.0.0 + * Contact: info@replicated.com + * Generated by: https://github.com/swagger-api/swagger-codegen.git + */ + +package swagger + +type Body struct { + + IncludeActive bool `json:"include_active,omitempty"` + + IncludeArchived bool `json:"include_archived,omitempty"` + + IncludeDev bool `json:"include_dev,omitempty"` + + IncludeInactive bool `json:"include_inactive,omitempty"` + + IncludePaid bool `json:"include_paid,omitempty"` + + IncludeTrial bool `json:"include_trial,omitempty"` + + Offset int64 `json:"offset,omitempty"` + + PageSize int64 `json:"page_size,omitempty"` + + Query string `json:"query"` + + SortDirection string `json:"sort_direction,omitempty"` + + SortField string `json:"sort_field,omitempty"` +} diff --git a/gen/go/v2/body_1.go b/gen/go/v2/body_1.go new file mode 100644 index 000000000..d66c11939 --- /dev/null +++ b/gen/go/v2/body_1.go @@ -0,0 +1,49 @@ +/* + * Vendor API V2 + * + * The Vendor API is available as an alternative to configuring your application via the Vendor website. This API will allow you as the Vendor to manage your apps and app configuration, manage customer licenses, view your private container images. The API can be accessed at the URL https://api.replicated.com/vendor/v2. == Authentication Authentication is achieved via a token that can be generated via the Vendor website. You can create a new token by clicking the New API Token button in the API Tokens table. You must give this token a nickname before saving. After you have generated your token, you will need to send this token in the Authorization header of your requests to the Vendor API. The following Error response codes can be expected: [options=\"header\", cols=\".^1,.^3,.^10\"] |=== |Code|Response|Description |400|Bad Request|We were unable to parse your request. |401|Unauthorized|Confirm that your token or username/password is valid. |403|Forbidden|The server is refusing to alloo you to complete this request. |404|Not found|The requested resource was not found. |409|Conflict|The action would result in a conflict and is being rejected. |500|Internal Server Error|Something unexpected happened. |=== You download JSON schemas for this API in our github repo. Check out our Developer Help Center for sample recipes on using our Vendor API + * + * OpenAPI spec version: 1.0.0 + * Contact: info@replicated.com + * Generated by: https://github.com/swagger-api/swagger-codegen.git + */ + +package swagger + +type Body1 struct { + + // If activation is required this is the email the code will be sent to. + ActivationEmail string `json:"activation_email"` + + // App Id that this license will be associated with. + AppId string `json:"app_id"` + + // License Label name, ie name of customer who is using license. + Assignee string `json:"assignee"` + + // Channel id that the license will be associated with (deprecated, use \"channels\"). + ChannelId string `json:"channel_id"` + + Channels *LicenseChannels `json:"channels,omitempty"` + + ConsoleAuthOptions []string `json:"console_auth_options,omitempty"` + + EnabledFeatures map[string]interface{} `json:"enabled_features,omitempty"` + + // Date that the license will expire, can be null for no expiration or formatted by year-month-day ex. 2016-02-02. + ExpirationDate string `json:"expiration_date"` + + // Defines expiration policy for this license. Values: ignore: replicated will take no action on a expired license noupdate-norestart: application updates will not be downloaded, and once the application is stopped, it will not be started again noupdate-stop: application updates will not be downloaded and the application will be stopped + ExpirationPolicy string `json:"expiration_policy"` + + FieldValues *LicenseFieldValues `json:"field_values"` + + // LicenseType can be set to \"dev\", \"trial\", or \"prod\" + LicenseType string `json:"license_type"` + + // If this license requires activation set to true, make sure to set activation email as well. + RequireActivation bool `json:"require_activation"` + + // If set to automatic will auto update remote license installation with every release. If set to manual will update only when on-premise admin clicks the install update button. + UpdatePolicy string `json:"update_policy"` +} diff --git a/gen/go/v2/body_2.go b/gen/go/v2/body_2.go new file mode 100644 index 000000000..12c2816ff --- /dev/null +++ b/gen/go/v2/body_2.go @@ -0,0 +1,52 @@ +/* + * Vendor API V2 + * + * The Vendor API is available as an alternative to configuring your application via the Vendor website. This API will allow you as the Vendor to manage your apps and app configuration, manage customer licenses, view your private container images. The API can be accessed at the URL https://api.replicated.com/vendor/v2. == Authentication Authentication is achieved via a token that can be generated via the Vendor website. You can create a new token by clicking the New API Token button in the API Tokens table. You must give this token a nickname before saving. After you have generated your token, you will need to send this token in the Authorization header of your requests to the Vendor API. The following Error response codes can be expected: [options=\"header\", cols=\".^1,.^3,.^10\"] |=== |Code|Response|Description |400|Bad Request|We were unable to parse your request. |401|Unauthorized|Confirm that your token or username/password is valid. |403|Forbidden|The server is refusing to alloo you to complete this request. |404|Not found|The requested resource was not found. |409|Conflict|The action would result in a conflict and is being rejected. |500|Internal Server Error|Something unexpected happened. |=== You download JSON schemas for this API in our github repo. Check out our Developer Help Center for sample recipes on using our Vendor API + * + * OpenAPI spec version: 1.0.0 + * Contact: info@replicated.com + * Generated by: https://github.com/swagger-api/swagger-codegen.git + */ + +package swagger + +type Body2 struct { + + // If activation is required this is the email the code will be sent to. + ActivationEmail string `json:"activation_email"` + + // License Label name, ie name of customer who is using license. + Assignee string `json:"assignee"` + + // Channel id that the license will be associated with. + ChannelId string `json:"channel_id"` + + Channels *LicenseChannels `json:"channels,omitempty"` + + ConsoleAuthOptions []string `json:"console_auth_options,omitempty"` + + EnabledFeatures map[string]interface{} `json:"enabled_features,omitempty"` + + // Date that the license will expire, can be null for no expiration or formated by year-month-day ex. 2016-02-02. + ExpirationDate string `json:"expiration_date"` + + // Defines expiration policy for this license. Values: ignore: replicated will take no action on a expired license noupdate-norestart: application updates will not be downloaded, and once the application is stopped, it will not be started again noupdate-stop: application updates will not be downloaded and the application will be stopped + ExpirationPolicy string `json:"expiration_policy"` + + FieldValues *LicenseFieldValues `json:"field_values"` + + // A license can be optionally locked to a specific release + IsAppVersionLocked bool `json:"is_app_version_locked,omitempty"` + + // LicenseType can be set to \"dev\", \"trial\", or \"prod\" + LicenseType string `json:"license_type"` + + // If app version is locked, this is the version to lock it to (sequence) + LockedAppVersion int64 `json:"locked_app_version,omitempty"` + + // If this license requires activation set to true, make sure to set activation email as well. + RequireActivation bool `json:"require_activation"` + + // If set to automatic will auto update remote license installation with every release. If set to manual will update only when on-premise admin clicks the install update button. + UpdatePolicy string `json:"update_policy"` +} diff --git a/gen/go/v2/docs/Body.md b/gen/go/v2/docs/Body.md new file mode 100644 index 000000000..96a496512 --- /dev/null +++ b/gen/go/v2/docs/Body.md @@ -0,0 +1,20 @@ +# Body + +## Properties +Name | Type | Description | Notes +------------ | ------------- | ------------- | ------------- +**IncludeActive** | **bool** | | [optional] [default to null] +**IncludeArchived** | **bool** | | [optional] [default to null] +**IncludeDev** | **bool** | | [optional] [default to null] +**IncludeInactive** | **bool** | | [optional] [default to null] +**IncludePaid** | **bool** | | [optional] [default to null] +**IncludeTrial** | **bool** | | [optional] [default to null] +**Offset** | **int64** | | [optional] [default to null] +**PageSize** | **int64** | | [optional] [default to null] +**Query** | **string** | | [default to null] +**SortDirection** | **string** | | [optional] [default to null] +**SortField** | **string** | | [optional] [default to null] + +[[Back to Model list]](../README.md#documentation-for-models) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to README]](../README.md) + + diff --git a/gen/go/v2/docs/Body1.md b/gen/go/v2/docs/Body1.md new file mode 100644 index 000000000..963eebd2f --- /dev/null +++ b/gen/go/v2/docs/Body1.md @@ -0,0 +1,22 @@ +# Body1 + +## Properties +Name | Type | Description | Notes +------------ | ------------- | ------------- | ------------- +**ActivationEmail** | **string** | If activation is required this is the email the code will be sent to. | [default to null] +**AppId** | **string** | App Id that this license will be associated with. | [default to null] +**Assignee** | **string** | License Label name, ie name of customer who is using license. | [default to null] +**ChannelId** | **string** | Channel id that the license will be associated with (deprecated, use \"channels\"). | [default to null] +**Channels** | [***LicenseChannels**](LicenseChannels.md) | | [optional] [default to null] +**ConsoleAuthOptions** | **[]string** | | [optional] [default to null] +**EnabledFeatures** | [**map[string]interface{}**](interface{}.md) | | [optional] [default to null] +**ExpirationDate** | **string** | Date that the license will expire, can be null for no expiration or formatted by year-month-day ex. 2016-02-02. | [default to null] +**ExpirationPolicy** | **string** | Defines expiration policy for this license. Values: ignore: replicated will take no action on a expired license noupdate-norestart: application updates will not be downloaded, and once the application is stopped, it will not be started again noupdate-stop: application updates will not be downloaded and the application will be stopped | [default to null] +**FieldValues** | [***LicenseFieldValues**](LicenseFieldValues.md) | | [default to null] +**LicenseType** | **string** | LicenseType can be set to \"dev\", \"trial\", or \"prod\" | [default to null] +**RequireActivation** | **bool** | If this license requires activation set to true, make sure to set activation email as well. | [default to null] +**UpdatePolicy** | **string** | If set to automatic will auto update remote license installation with every release. If set to manual will update only when on-premise admin clicks the install update button. | [default to null] + +[[Back to Model list]](../README.md#documentation-for-models) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to README]](../README.md) + + diff --git a/gen/go/v2/docs/Body2.md b/gen/go/v2/docs/Body2.md new file mode 100644 index 000000000..bf304d473 --- /dev/null +++ b/gen/go/v2/docs/Body2.md @@ -0,0 +1,23 @@ +# Body2 + +## Properties +Name | Type | Description | Notes +------------ | ------------- | ------------- | ------------- +**ActivationEmail** | **string** | If activation is required this is the email the code will be sent to. | [default to null] +**Assignee** | **string** | License Label name, ie name of customer who is using license. | [default to null] +**ChannelId** | **string** | Channel id that the license will be associated with. | [default to null] +**Channels** | [***LicenseChannels**](LicenseChannels.md) | | [optional] [default to null] +**ConsoleAuthOptions** | **[]string** | | [optional] [default to null] +**EnabledFeatures** | [**map[string]interface{}**](interface{}.md) | | [optional] [default to null] +**ExpirationDate** | **string** | Date that the license will expire, can be null for no expiration or formated by year-month-day ex. 2016-02-02. | [default to null] +**ExpirationPolicy** | **string** | Defines expiration policy for this license. Values: ignore: replicated will take no action on a expired license noupdate-norestart: application updates will not be downloaded, and once the application is stopped, it will not be started again noupdate-stop: application updates will not be downloaded and the application will be stopped | [default to null] +**FieldValues** | [***LicenseFieldValues**](LicenseFieldValues.md) | | [default to null] +**IsAppVersionLocked** | **bool** | A license can be optionally locked to a specific release | [optional] [default to null] +**LicenseType** | **string** | LicenseType can be set to \"dev\", \"trial\", or \"prod\" | [default to null] +**LockedAppVersion** | **int64** | If app version is locked, this is the version to lock it to (sequence) | [optional] [default to null] +**RequireActivation** | **bool** | If this license requires activation set to true, make sure to set activation email as well. | [default to null] +**UpdatePolicy** | **string** | If set to automatic will auto update remote license installation with every release. If set to manual will update only when on-premise admin clicks the install update button. | [default to null] + +[[Back to Model list]](../README.md#documentation-for-models) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to README]](../README.md) + + diff --git a/gen/go/v2/docs/InlineResponse200.md b/gen/go/v2/docs/InlineResponse200.md new file mode 100644 index 000000000..93651df6a --- /dev/null +++ b/gen/go/v2/docs/InlineResponse200.md @@ -0,0 +1,10 @@ +# InlineResponse200 + +## Properties +Name | Type | Description | Notes +------------ | ------------- | ------------- | ------------- +**Licenses** | [***LicensesV2**](LicensesV2.md) | | [optional] [default to null] + +[[Back to Model list]](../README.md#documentation-for-models) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to README]](../README.md) + + diff --git a/gen/go/v2/docs/InlineResponse2001.md b/gen/go/v2/docs/InlineResponse2001.md new file mode 100644 index 000000000..1dc540110 --- /dev/null +++ b/gen/go/v2/docs/InlineResponse2001.md @@ -0,0 +1,12 @@ +# InlineResponse2001 + +## Properties +Name | Type | Description | Notes +------------ | ------------- | ------------- | ------------- +**Licenses** | [***LicensesV2**](LicensesV2.md) | | [optional] [default to null] +**Query** | **string** | | [optional] [default to null] +**TotalHits** | **int64** | | [optional] [default to null] + +[[Back to Model list]](../README.md#documentation-for-models) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to README]](../README.md) + + diff --git a/gen/go/v2/docs/InlineResponse2002.md b/gen/go/v2/docs/InlineResponse2002.md new file mode 100644 index 000000000..b28d62c3d --- /dev/null +++ b/gen/go/v2/docs/InlineResponse2002.md @@ -0,0 +1,10 @@ +# InlineResponse2002 + +## Properties +Name | Type | Description | Notes +------------ | ------------- | ------------- | ------------- +**License** | [***LicenseV2**](LicenseV2.md) | | [default to null] + +[[Back to Model list]](../README.md#documentation-for-models) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to README]](../README.md) + + diff --git a/gen/go/v2/docs/InlineResponse2003.md b/gen/go/v2/docs/InlineResponse2003.md new file mode 100644 index 000000000..19c8fc80b --- /dev/null +++ b/gen/go/v2/docs/InlineResponse2003.md @@ -0,0 +1,10 @@ +# InlineResponse2003 + +## Properties +Name | Type | Description | Notes +------------ | ------------- | ------------- | ------------- +**Licenses** | [**[]LicenseV2**](LicenseV2.md) | | [optional] [default to null] + +[[Back to Model list]](../README.md#documentation-for-models) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to README]](../README.md) + + diff --git a/gen/go/v2/docs/InlineResponse201.md b/gen/go/v2/docs/InlineResponse201.md new file mode 100644 index 000000000..944536066 --- /dev/null +++ b/gen/go/v2/docs/InlineResponse201.md @@ -0,0 +1,10 @@ +# InlineResponse201 + +## Properties +Name | Type | Description | Notes +------------ | ------------- | ------------- | ------------- +**License** | [***LicenseV2**](LicenseV2.md) | | [optional] [default to null] + +[[Back to Model list]](../README.md#documentation-for-models) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to README]](../README.md) + + diff --git a/gen/go/v2/docs/LicenseChannel.md b/gen/go/v2/docs/LicenseChannel.md new file mode 100644 index 000000000..4a030a702 --- /dev/null +++ b/gen/go/v2/docs/LicenseChannel.md @@ -0,0 +1,13 @@ +# LicenseChannel + +## Properties +Name | Type | Description | Notes +------------ | ------------- | ------------- | ------------- +**Description** | **string** | | [optional] [default to null] +**Id** | **string** | | [optional] [default to null] +**IsDefault** | **bool** | | [optional] [default to null] +**Name** | **string** | | [optional] [default to null] + +[[Back to Model list]](../README.md#documentation-for-models) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to README]](../README.md) + + diff --git a/gen/go/v2/docs/LicenseChannels.md b/gen/go/v2/docs/LicenseChannels.md new file mode 100644 index 000000000..164d299fa --- /dev/null +++ b/gen/go/v2/docs/LicenseChannels.md @@ -0,0 +1,9 @@ +# LicenseChannels + +## Properties +Name | Type | Description | Notes +------------ | ------------- | ------------- | ------------- + +[[Back to Model list]](../README.md#documentation-for-models) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to README]](../README.md) + + diff --git a/gen/go/v2/docs/LicenseFieldValue.md b/gen/go/v2/docs/LicenseFieldValue.md new file mode 100644 index 000000000..b3bbc00d2 --- /dev/null +++ b/gen/go/v2/docs/LicenseFieldValue.md @@ -0,0 +1,13 @@ +# LicenseFieldValue + +## Properties +Name | Type | Description | Notes +------------ | ------------- | ------------- | ------------- +**Field** | **string** | | [optional] [default to null] +**Title** | **string** | | [optional] [default to null] +**Type_** | **string** | | [optional] [default to null] +**Value** | **string** | | [optional] [default to null] + +[[Back to Model list]](../README.md#documentation-for-models) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to README]](../README.md) + + diff --git a/gen/go/v2/docs/LicenseFieldValues.md b/gen/go/v2/docs/LicenseFieldValues.md new file mode 100644 index 000000000..8a509e1b9 --- /dev/null +++ b/gen/go/v2/docs/LicenseFieldValues.md @@ -0,0 +1,9 @@ +# LicenseFieldValues + +## Properties +Name | Type | Description | Notes +------------ | ------------- | ------------- | ------------- + +[[Back to Model list]](../README.md#documentation-for-models) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to README]](../README.md) + + diff --git a/gen/go/v2/docs/LicenseV2.md b/gen/go/v2/docs/LicenseV2.md new file mode 100644 index 000000000..b116a6ff5 --- /dev/null +++ b/gen/go/v2/docs/LicenseV2.md @@ -0,0 +1,45 @@ +# LicenseV2 + +## Properties +Name | Type | Description | Notes +------------ | ------------- | ------------- | ------------- +**ActivationEmail** | **string** | | [optional] [default to null] +**ActiveInstanceCount** | **int64** | | [optional] [default to null] +**AppId** | **string** | | [optional] [default to null] +**AppStatus** | **string** | | [optional] [default to null] +**Assignee** | **string** | | [optional] [default to null] +**BillingBeginDate** | [**time.Time**](time.Time.md) | | [optional] [default to null] +**BillingEndDate** | [**time.Time**](time.Time.md) | | [optional] [default to null] +**BillingFrequency** | **string** | | [optional] [default to null] +**BillingRevenue** | **string** | | [optional] [default to null] +**ChannelId** | **string** | | [optional] [default to null] +**ChannelName** | **string** | | [optional] [default to null] +**Channels** | [**[]LicenseChannel**](LicenseChannel.md) | | [optional] [default to null] +**CloudNetworks** | **string** | | [optional] [default to null] +**ConsoleAuthOptions** | **[]string** | | [optional] [default to null] +**EnabledFeatures** | [**map[string]interface{}**](interface{}.md) | | [optional] [default to null] +**ExpirationDate** | [**time.Time**](time.Time.md) | | [optional] [default to null] +**ExpirationPolicy** | **string** | | [optional] [default to null] +**GrantDate** | [**time.Time**](time.Time.md) | | [optional] [default to null] +**Id** | **string** | | [optional] [default to null] +**InactiveInstanceCount** | **int64** | | [optional] [default to null] +**InstalledReleaseSequence** | **int64** | | [optional] [default to null] +**InstalledVersionLabel** | **string** | | [optional] [default to null] +**IsActive** | **bool** | | [optional] [default to null] +**IsAnonymous** | **bool** | | [optional] [default to null] +**IsAppVersionLocked** | **bool** | | [optional] [default to null] +**IsArchived** | **bool** | | [optional] [default to null] +**IsInstanceTracked** | **bool** | | [optional] [default to null] +**LastSyncAt** | [**time.Time**](time.Time.md) | | [optional] [default to null] +**LatestReleaseSequence** | **int64** | | [optional] [default to null] +**LatestVersionLabel** | **string** | | [optional] [default to null] +**LicenseType** | **string** | | [optional] [default to null] +**LockedAppVersion** | **int64** | | [optional] [default to null] +**RequireActivation** | **bool** | | [optional] [default to null] +**RevocationDate** | [**time.Time**](time.Time.md) | | [optional] [default to null] +**UntrackedInstanceCount** | **int64** | | [optional] [default to null] +**UpdatePolicy** | **string** | | [optional] [default to null] + +[[Back to Model list]](../README.md#documentation-for-models) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to README]](../README.md) + + diff --git a/gen/go/v2/docs/LicensesV2.md b/gen/go/v2/docs/LicensesV2.md new file mode 100644 index 000000000..47476f16c --- /dev/null +++ b/gen/go/v2/docs/LicensesV2.md @@ -0,0 +1,9 @@ +# LicensesV2 + +## Properties +Name | Type | Description | Notes +------------ | ------------- | ------------- | ------------- + +[[Back to Model list]](../README.md#documentation-for-models) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to README]](../README.md) + + diff --git a/gen/go/v2/inline_response_200.go b/gen/go/v2/inline_response_200.go new file mode 100644 index 000000000..911b791b9 --- /dev/null +++ b/gen/go/v2/inline_response_200.go @@ -0,0 +1,16 @@ +/* + * Vendor API V2 + * + * The Vendor API is available as an alternative to configuring your application via the Vendor website. This API will allow you as the Vendor to manage your apps and app configuration, manage customer licenses, view your private container images. The API can be accessed at the URL https://api.replicated.com/vendor/v2. == Authentication Authentication is achieved via a token that can be generated via the Vendor website. You can create a new token by clicking the New API Token button in the API Tokens table. You must give this token a nickname before saving. After you have generated your token, you will need to send this token in the Authorization header of your requests to the Vendor API. The following Error response codes can be expected: [options=\"header\", cols=\".^1,.^3,.^10\"] |=== |Code|Response|Description |400|Bad Request|We were unable to parse your request. |401|Unauthorized|Confirm that your token or username/password is valid. |403|Forbidden|The server is refusing to alloo you to complete this request. |404|Not found|The requested resource was not found. |409|Conflict|The action would result in a conflict and is being rejected. |500|Internal Server Error|Something unexpected happened. |=== You download JSON schemas for this API in our github repo. Check out our Developer Help Center for sample recipes on using our Vendor API + * + * OpenAPI spec version: 1.0.0 + * Contact: info@replicated.com + * Generated by: https://github.com/swagger-api/swagger-codegen.git + */ + +package swagger + +type InlineResponse200 struct { + + Licenses *LicensesV2 `json:"Licenses,omitempty"` +} diff --git a/gen/go/v2/inline_response_200_1.go b/gen/go/v2/inline_response_200_1.go new file mode 100644 index 000000000..fbb595fe0 --- /dev/null +++ b/gen/go/v2/inline_response_200_1.go @@ -0,0 +1,20 @@ +/* + * Vendor API V2 + * + * The Vendor API is available as an alternative to configuring your application via the Vendor website. This API will allow you as the Vendor to manage your apps and app configuration, manage customer licenses, view your private container images. The API can be accessed at the URL https://api.replicated.com/vendor/v2. == Authentication Authentication is achieved via a token that can be generated via the Vendor website. You can create a new token by clicking the New API Token button in the API Tokens table. You must give this token a nickname before saving. After you have generated your token, you will need to send this token in the Authorization header of your requests to the Vendor API. The following Error response codes can be expected: [options=\"header\", cols=\".^1,.^3,.^10\"] |=== |Code|Response|Description |400|Bad Request|We were unable to parse your request. |401|Unauthorized|Confirm that your token or username/password is valid. |403|Forbidden|The server is refusing to alloo you to complete this request. |404|Not found|The requested resource was not found. |409|Conflict|The action would result in a conflict and is being rejected. |500|Internal Server Error|Something unexpected happened. |=== You download JSON schemas for this API in our github repo. Check out our Developer Help Center for sample recipes on using our Vendor API + * + * OpenAPI spec version: 1.0.0 + * Contact: info@replicated.com + * Generated by: https://github.com/swagger-api/swagger-codegen.git + */ + +package swagger + +type InlineResponse2001 struct { + + Licenses *LicensesV2 `json:"licenses,omitempty"` + + Query string `json:"query,omitempty"` + + TotalHits int64 `json:"total_hits,omitempty"` +} diff --git a/gen/go/v2/inline_response_200_2.go b/gen/go/v2/inline_response_200_2.go new file mode 100644 index 000000000..5a206dca5 --- /dev/null +++ b/gen/go/v2/inline_response_200_2.go @@ -0,0 +1,16 @@ +/* + * Vendor API V2 + * + * The Vendor API is available as an alternative to configuring your application via the Vendor website. This API will allow you as the Vendor to manage your apps and app configuration, manage customer licenses, view your private container images. The API can be accessed at the URL https://api.replicated.com/vendor/v2. == Authentication Authentication is achieved via a token that can be generated via the Vendor website. You can create a new token by clicking the New API Token button in the API Tokens table. You must give this token a nickname before saving. After you have generated your token, you will need to send this token in the Authorization header of your requests to the Vendor API. The following Error response codes can be expected: [options=\"header\", cols=\".^1,.^3,.^10\"] |=== |Code|Response|Description |400|Bad Request|We were unable to parse your request. |401|Unauthorized|Confirm that your token or username/password is valid. |403|Forbidden|The server is refusing to alloo you to complete this request. |404|Not found|The requested resource was not found. |409|Conflict|The action would result in a conflict and is being rejected. |500|Internal Server Error|Something unexpected happened. |=== You download JSON schemas for this API in our github repo. Check out our Developer Help Center for sample recipes on using our Vendor API + * + * OpenAPI spec version: 1.0.0 + * Contact: info@replicated.com + * Generated by: https://github.com/swagger-api/swagger-codegen.git + */ + +package swagger + +type InlineResponse2002 struct { + + License *LicenseV2 `json:"License"` +} diff --git a/gen/go/v2/inline_response_200_3.go b/gen/go/v2/inline_response_200_3.go new file mode 100644 index 000000000..23f010266 --- /dev/null +++ b/gen/go/v2/inline_response_200_3.go @@ -0,0 +1,16 @@ +/* + * Vendor API V2 + * + * The Vendor API is available as an alternative to configuring your application via the Vendor website. This API will allow you as the Vendor to manage your apps and app configuration, manage customer licenses, view your private container images. The API can be accessed at the URL https://api.replicated.com/vendor/v2. == Authentication Authentication is achieved via a token that can be generated via the Vendor website. You can create a new token by clicking the New API Token button in the API Tokens table. You must give this token a nickname before saving. After you have generated your token, you will need to send this token in the Authorization header of your requests to the Vendor API. The following Error response codes can be expected: [options=\"header\", cols=\".^1,.^3,.^10\"] |=== |Code|Response|Description |400|Bad Request|We were unable to parse your request. |401|Unauthorized|Confirm that your token or username/password is valid. |403|Forbidden|The server is refusing to alloo you to complete this request. |404|Not found|The requested resource was not found. |409|Conflict|The action would result in a conflict and is being rejected. |500|Internal Server Error|Something unexpected happened. |=== You download JSON schemas for this API in our github repo. Check out our Developer Help Center for sample recipes on using our Vendor API + * + * OpenAPI spec version: 1.0.0 + * Contact: info@replicated.com + * Generated by: https://github.com/swagger-api/swagger-codegen.git + */ + +package swagger + +type InlineResponse2003 struct { + + Licenses []LicenseV2 `json:"Licenses,omitempty"` +} diff --git a/gen/go/v2/inline_response_201.go b/gen/go/v2/inline_response_201.go new file mode 100644 index 000000000..59d829d69 --- /dev/null +++ b/gen/go/v2/inline_response_201.go @@ -0,0 +1,16 @@ +/* + * Vendor API V2 + * + * The Vendor API is available as an alternative to configuring your application via the Vendor website. This API will allow you as the Vendor to manage your apps and app configuration, manage customer licenses, view your private container images. The API can be accessed at the URL https://api.replicated.com/vendor/v2. == Authentication Authentication is achieved via a token that can be generated via the Vendor website. You can create a new token by clicking the New API Token button in the API Tokens table. You must give this token a nickname before saving. After you have generated your token, you will need to send this token in the Authorization header of your requests to the Vendor API. The following Error response codes can be expected: [options=\"header\", cols=\".^1,.^3,.^10\"] |=== |Code|Response|Description |400|Bad Request|We were unable to parse your request. |401|Unauthorized|Confirm that your token or username/password is valid. |403|Forbidden|The server is refusing to alloo you to complete this request. |404|Not found|The requested resource was not found. |409|Conflict|The action would result in a conflict and is being rejected. |500|Internal Server Error|Something unexpected happened. |=== You download JSON schemas for this API in our github repo. Check out our Developer Help Center for sample recipes on using our Vendor API + * + * OpenAPI spec version: 1.0.0 + * Contact: info@replicated.com + * Generated by: https://github.com/swagger-api/swagger-codegen.git + */ + +package swagger + +type InlineResponse201 struct { + + License *LicenseV2 `json:"License,omitempty"` +} diff --git a/gen/go/v2/license_channel.go b/gen/go/v2/license_channel.go new file mode 100644 index 000000000..2854b4ca2 --- /dev/null +++ b/gen/go/v2/license_channel.go @@ -0,0 +1,22 @@ +/* + * Vendor API V2 + * + * The Vendor API is available as an alternative to configuring your application via the Vendor website. This API will allow you as the Vendor to manage your apps and app configuration, manage customer licenses, view your private container images. The API can be accessed at the URL https://api.replicated.com/vendor/v2. == Authentication Authentication is achieved via a token that can be generated via the Vendor website. You can create a new token by clicking the New API Token button in the API Tokens table. You must give this token a nickname before saving. After you have generated your token, you will need to send this token in the Authorization header of your requests to the Vendor API. The following Error response codes can be expected: [options=\"header\", cols=\".^1,.^3,.^10\"] |=== |Code|Response|Description |400|Bad Request|We were unable to parse your request. |401|Unauthorized|Confirm that your token or username/password is valid. |403|Forbidden|The server is refusing to alloo you to complete this request. |404|Not found|The requested resource was not found. |409|Conflict|The action would result in a conflict and is being rejected. |500|Internal Server Error|Something unexpected happened. |=== You download JSON schemas for this API in our github repo. Check out our Developer Help Center for sample recipes on using our Vendor API + * + * OpenAPI spec version: 1.0.0 + * Contact: info@replicated.com + * Generated by: https://github.com/swagger-api/swagger-codegen.git + */ + +package swagger + +type LicenseChannel struct { + + Description string `json:"description,omitempty"` + + Id string `json:"id,omitempty"` + + IsDefault bool `json:"is_default,omitempty"` + + Name string `json:"name,omitempty"` +} diff --git a/gen/go/v2/license_channels.go b/gen/go/v2/license_channels.go new file mode 100644 index 000000000..b4ee7d421 --- /dev/null +++ b/gen/go/v2/license_channels.go @@ -0,0 +1,14 @@ +/* + * Vendor API V2 + * + * The Vendor API is available as an alternative to configuring your application via the Vendor website. This API will allow you as the Vendor to manage your apps and app configuration, manage customer licenses, view your private container images. The API can be accessed at the URL https://api.replicated.com/vendor/v2. == Authentication Authentication is achieved via a token that can be generated via the Vendor website. You can create a new token by clicking the New API Token button in the API Tokens table. You must give this token a nickname before saving. After you have generated your token, you will need to send this token in the Authorization header of your requests to the Vendor API. The following Error response codes can be expected: [options=\"header\", cols=\".^1,.^3,.^10\"] |=== |Code|Response|Description |400|Bad Request|We were unable to parse your request. |401|Unauthorized|Confirm that your token or username/password is valid. |403|Forbidden|The server is refusing to alloo you to complete this request. |404|Not found|The requested resource was not found. |409|Conflict|The action would result in a conflict and is being rejected. |500|Internal Server Error|Something unexpected happened. |=== You download JSON schemas for this API in our github repo. Check out our Developer Help Center for sample recipes on using our Vendor API + * + * OpenAPI spec version: 1.0.0 + * Contact: info@replicated.com + * Generated by: https://github.com/swagger-api/swagger-codegen.git + */ + +package swagger + +type LicenseChannels struct { +} diff --git a/gen/go/v2/license_field_value.go b/gen/go/v2/license_field_value.go new file mode 100644 index 000000000..7c61d40c6 --- /dev/null +++ b/gen/go/v2/license_field_value.go @@ -0,0 +1,22 @@ +/* + * Vendor API V2 + * + * The Vendor API is available as an alternative to configuring your application via the Vendor website. This API will allow you as the Vendor to manage your apps and app configuration, manage customer licenses, view your private container images. The API can be accessed at the URL https://api.replicated.com/vendor/v2. == Authentication Authentication is achieved via a token that can be generated via the Vendor website. You can create a new token by clicking the New API Token button in the API Tokens table. You must give this token a nickname before saving. After you have generated your token, you will need to send this token in the Authorization header of your requests to the Vendor API. The following Error response codes can be expected: [options=\"header\", cols=\".^1,.^3,.^10\"] |=== |Code|Response|Description |400|Bad Request|We were unable to parse your request. |401|Unauthorized|Confirm that your token or username/password is valid. |403|Forbidden|The server is refusing to alloo you to complete this request. |404|Not found|The requested resource was not found. |409|Conflict|The action would result in a conflict and is being rejected. |500|Internal Server Error|Something unexpected happened. |=== You download JSON schemas for this API in our github repo. Check out our Developer Help Center for sample recipes on using our Vendor API + * + * OpenAPI spec version: 1.0.0 + * Contact: info@replicated.com + * Generated by: https://github.com/swagger-api/swagger-codegen.git + */ + +package swagger + +type LicenseFieldValue struct { + + Field string `json:"field,omitempty"` + + Title string `json:"title,omitempty"` + + Type_ string `json:"type,omitempty"` + + Value string `json:"value,omitempty"` +} diff --git a/gen/go/v2/license_field_values.go b/gen/go/v2/license_field_values.go new file mode 100644 index 000000000..e85fd35a3 --- /dev/null +++ b/gen/go/v2/license_field_values.go @@ -0,0 +1,14 @@ +/* + * Vendor API V2 + * + * The Vendor API is available as an alternative to configuring your application via the Vendor website. This API will allow you as the Vendor to manage your apps and app configuration, manage customer licenses, view your private container images. The API can be accessed at the URL https://api.replicated.com/vendor/v2. == Authentication Authentication is achieved via a token that can be generated via the Vendor website. You can create a new token by clicking the New API Token button in the API Tokens table. You must give this token a nickname before saving. After you have generated your token, you will need to send this token in the Authorization header of your requests to the Vendor API. The following Error response codes can be expected: [options=\"header\", cols=\".^1,.^3,.^10\"] |=== |Code|Response|Description |400|Bad Request|We were unable to parse your request. |401|Unauthorized|Confirm that your token or username/password is valid. |403|Forbidden|The server is refusing to alloo you to complete this request. |404|Not found|The requested resource was not found. |409|Conflict|The action would result in a conflict and is being rejected. |500|Internal Server Error|Something unexpected happened. |=== You download JSON schemas for this API in our github repo. Check out our Developer Help Center for sample recipes on using our Vendor API + * + * OpenAPI spec version: 1.0.0 + * Contact: info@replicated.com + * Generated by: https://github.com/swagger-api/swagger-codegen.git + */ + +package swagger + +type LicenseFieldValues struct { +} diff --git a/gen/go/v2/license_v2.go b/gen/go/v2/license_v2.go new file mode 100644 index 000000000..428ca99ff --- /dev/null +++ b/gen/go/v2/license_v2.go @@ -0,0 +1,90 @@ +/* + * Vendor API V2 + * + * The Vendor API is available as an alternative to configuring your application via the Vendor website. This API will allow you as the Vendor to manage your apps and app configuration, manage customer licenses, view your private container images. The API can be accessed at the URL https://api.replicated.com/vendor/v2. == Authentication Authentication is achieved via a token that can be generated via the Vendor website. You can create a new token by clicking the New API Token button in the API Tokens table. You must give this token a nickname before saving. After you have generated your token, you will need to send this token in the Authorization header of your requests to the Vendor API. The following Error response codes can be expected: [options=\"header\", cols=\".^1,.^3,.^10\"] |=== |Code|Response|Description |400|Bad Request|We were unable to parse your request. |401|Unauthorized|Confirm that your token or username/password is valid. |403|Forbidden|The server is refusing to alloo you to complete this request. |404|Not found|The requested resource was not found. |409|Conflict|The action would result in a conflict and is being rejected. |500|Internal Server Error|Something unexpected happened. |=== You download JSON schemas for this API in our github repo. Check out our Developer Help Center for sample recipes on using our Vendor API + * + * OpenAPI spec version: 1.0.0 + * Contact: info@replicated.com + * Generated by: https://github.com/swagger-api/swagger-codegen.git + */ + +package swagger + +import ( + "time" +) + +type LicenseV2 struct { + + ActivationEmail string `json:"activation_email,omitempty"` + + ActiveInstanceCount int64 `json:"active_instance_count,omitempty"` + + AppId string `json:"app_id,omitempty"` + + AppStatus string `json:"app_status,omitempty"` + + Assignee string `json:"assignee,omitempty"` + + BillingBeginDate time.Time `json:"billing_begin_date,omitempty"` + + BillingEndDate time.Time `json:"billing_end_date,omitempty"` + + BillingFrequency string `json:"billing_frequency,omitempty"` + + BillingRevenue string `json:"billing_revenue,omitempty"` + + ChannelId string `json:"channel_id,omitempty"` + + ChannelName string `json:"channel_name,omitempty"` + + Channels []LicenseChannel `json:"channels,omitempty"` + + CloudNetworks string `json:"cloud_networks,omitempty"` + + ConsoleAuthOptions []string `json:"console_auth_options,omitempty"` + + EnabledFeatures map[string]interface{} `json:"enabled_features,omitempty"` + + ExpirationDate time.Time `json:"expiration_date,omitempty"` + + ExpirationPolicy string `json:"expiration_policy,omitempty"` + + GrantDate time.Time `json:"grant_date,omitempty"` + + Id string `json:"id,omitempty"` + + InactiveInstanceCount int64 `json:"inactive_instance_count,omitempty"` + + InstalledReleaseSequence int64 `json:"installed_release_sequence,omitempty"` + + InstalledVersionLabel string `json:"installed_version_label,omitempty"` + + IsActive bool `json:"is_active,omitempty"` + + IsAnonymous bool `json:"is_anonymous,omitempty"` + + IsAppVersionLocked bool `json:"is_app_version_locked,omitempty"` + + IsArchived bool `json:"is_archived,omitempty"` + + IsInstanceTracked bool `json:"is_instance_tracked,omitempty"` + + LastSyncAt time.Time `json:"last_sync_at,omitempty"` + + LatestReleaseSequence int64 `json:"latest_release_sequence,omitempty"` + + LatestVersionLabel string `json:"latest_version_label,omitempty"` + + LicenseType string `json:"license_type,omitempty"` + + LockedAppVersion int64 `json:"locked_app_version,omitempty"` + + RequireActivation bool `json:"require_activation,omitempty"` + + RevocationDate time.Time `json:"revocation_date,omitempty"` + + UntrackedInstanceCount int64 `json:"untracked_instance_count,omitempty"` + + UpdatePolicy string `json:"update_policy,omitempty"` +} diff --git a/gen/go/v2/licenses_v2.go b/gen/go/v2/licenses_v2.go new file mode 100644 index 000000000..561d04fce --- /dev/null +++ b/gen/go/v2/licenses_v2.go @@ -0,0 +1,14 @@ +/* + * Vendor API V2 + * + * The Vendor API is available as an alternative to configuring your application via the Vendor website. This API will allow you as the Vendor to manage your apps and app configuration, manage customer licenses, view your private container images. The API can be accessed at the URL https://api.replicated.com/vendor/v2. == Authentication Authentication is achieved via a token that can be generated via the Vendor website. You can create a new token by clicking the New API Token button in the API Tokens table. You must give this token a nickname before saving. After you have generated your token, you will need to send this token in the Authorization header of your requests to the Vendor API. The following Error response codes can be expected: [options=\"header\", cols=\".^1,.^3,.^10\"] |=== |Code|Response|Description |400|Bad Request|We were unable to parse your request. |401|Unauthorized|Confirm that your token or username/password is valid. |403|Forbidden|The server is refusing to alloo you to complete this request. |404|Not found|The requested resource was not found. |409|Conflict|The action would result in a conflict and is being rejected. |500|Internal Server Error|Something unexpected happened. |=== You download JSON schemas for this API in our github repo. Check out our Developer Help Center for sample recipes on using our Vendor API + * + * OpenAPI spec version: 1.0.0 + * Contact: info@replicated.com + * Generated by: https://github.com/swagger-api/swagger-codegen.git + */ + +package swagger + +type LicensesV2 struct { +} diff --git a/gen/spec/v2.json b/gen/spec/v2.json new file mode 100644 index 000000000..8dcdec888 --- /dev/null +++ b/gen/spec/v2.json @@ -0,0 +1,842 @@ +{ + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "schemes": [ + "https" + ], + "swagger": "2.0", + "info": { + "description": "The Vendor API is available as an alternative to configuring your application via the Vendor website.\nThis API will allow you as the Vendor to manage your apps and app configuration, manage customer\nlicenses, view your private container images.\n\nThe API can be accessed at the URL https://api.replicated.com/vendor/v2.\n\n== Authentication\n\nAuthentication is achieved via a token that can be generated via the Vendor website. You can create a new token by clicking the New API Token button in the API Tokens table. You must give this token a nickname before saving.\n\nAfter you have generated your token, you will need to send this token in the Authorization header of your requests to the Vendor API.\n\nThe following Error response codes can be expected:\n\n[options=\"header\", cols=\".^1,.^3,.^10\"]\n|===\n|Code|Response|Description\n|400|Bad Request|We were unable to parse your request.\n|401|Unauthorized|Confirm that your token or username/password is valid.\n|403|Forbidden|The server is refusing to alloo you to complete this request.\n|404|Not found|The requested resource was not found.\n|409|Conflict|The action would result in a conflict and is being rejected.\n|500|Internal Server Error|Something unexpected happened.\n|===\n\nYou download JSON schemas for this API in our github repo.\n\nCheck out our Developer Help Center for sample recipes on using our Vendor API", + "title": "Vendor API V2", + "contact": { + "name": "Replicated, Inc.", + "url": "http://www.replicated.com/", + "email": "info@replicated.com" + }, + "version": "1.0.0" + }, + "host": "api.replicated.com", + "basePath": "/vendor/v2", + "paths": { + "/app/{app_id}/licenses": { + "get": { + "produces": [ + "application/json" + ], + "schemes": [ + "https" + ], + "tags": [ + "app", + "licenses" + ], + "summary": "List all licenses for a given appId.", + "operationId": "listAppLicenses", + "security": [ + { + "api_key": [] + } + ], + "parameters": [ + { + "type": "string", + "x-go-name": "AppID", + "description": "App identifier", + "name": "app_id", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "$ref": "#/responses/listAppLicensesResponse" + }, + "400": { + "$ref": "#/responses/responseErrBadRequest" + } + } + } + }, + "/app/{app_id}/licenses/search": { + "post": { + "produces": [ + "application/json" + ], + "schemes": [ + "https" + ], + "tags": [ + "app", + "licenses" + ], + "summary": "Search all licenses for a given appId.", + "operationId": "searchAppLicenses", + "security": [ + { + "api_key": [] + } + ], + "parameters": [ + { + "type": "string", + "x-go-name": "AppID", + "description": "App identifier", + "name": "app_id", + "in": "path", + "required": true + }, + { + "description": "Search licenses parameters.", + "name": "Body", + "in": "body", + "required": true, + "schema": { + "type": "object", + "required": [ + "query" + ], + "properties": { + "include_active": { + "type": "boolean", + "x-go-name": "IncludeActive" + }, + "include_archived": { + "type": "boolean", + "x-go-name": "IncludeArchived" + }, + "include_dev": { + "type": "boolean", + "x-go-name": "IncludeDev" + }, + "include_inactive": { + "type": "boolean", + "x-go-name": "IncludeInactive" + }, + "include_paid": { + "type": "boolean", + "x-go-name": "IncludePaid" + }, + "include_trial": { + "type": "boolean", + "x-go-name": "IncludeTrial" + }, + "offset": { + "type": "integer", + "format": "int64", + "x-go-name": "Offset" + }, + "page_size": { + "type": "integer", + "format": "int64", + "x-go-name": "PageSize" + }, + "query": { + "type": "string", + "x-go-name": "Query" + }, + "sort_direction": { + "type": "string", + "x-go-name": "SortDirection" + }, + "sort_field": { + "type": "string", + "x-go-name": "SortField" + } + } + } + } + ], + "responses": { + "200": { + "$ref": "#/responses/searchAppLicensesResponse" + }, + "400": { + "$ref": "#/responses/responseErrBadRequest" + } + } + } + }, + "/license": { + "post": { + "produces": [ + "application/json" + ], + "schemes": [ + "https" + ], + "tags": [ + "license" + ], + "summary": "Create a license.", + "operationId": "createLicense", + "security": [ + { + "api_key": [] + } + ], + "parameters": [ + { + "name": "Body", + "in": "body", + "required": true, + "schema": { + "type": "object", + "required": [ + "license_type", + "assignee", + "app_id", + "channel_id", + "field_values", + "require_activation", + "activation_email", + "update_policy", + "expiration_date", + "expiration_policy" + ], + "properties": { + "activation_email": { + "description": "If activation is required this is the email the code will be sent to.", + "type": "string", + "x-go-name": "ActivationEmail" + }, + "app_id": { + "description": "App Id that this license will be associated with.", + "type": "string", + "x-go-name": "AppID" + }, + "assignee": { + "description": "License Label name, ie name of customer who is using license.", + "type": "string", + "x-go-name": "Assignee" + }, + "channel_id": { + "description": "Channel id that the license will be associated with (deprecated, use \"channels\").", + "type": "string", + "x-go-name": "ChannelID" + }, + "channels": { + "$ref": "#/definitions/LicenseChannels" + }, + "console_auth_options": { + "type": "array", + "items": { + "type": "string" + }, + "x-go-name": "ConsoleAuthOptions" + }, + "enabled_features": { + "type": "object", + "additionalProperties": { + "type": "object" + }, + "x-go-name": "EnabledFeatures" + }, + "expiration_date": { + "description": "Date that the license will expire, can be null for no expiration or formatted by year-month-day ex. 2016-02-02.", + "type": "string", + "x-go-name": "ExpirationDate" + }, + "expiration_policy": { + "description": "Defines expiration policy for this license.\n\nValues:\nignore: replicated will take no action on a expired license\nnoupdate-norestart: application updates will not be downloaded, and once the application is stopped, it will not be started again\nnoupdate-stop: application updates will not be downloaded and the application will be stopped", + "type": "string", + "x-go-name": "ExpirationPolicy" + }, + "field_values": { + "$ref": "#/definitions/LicenseFieldValues" + }, + "license_type": { + "description": "LicenseType can be set to \"dev\", \"trial\", or \"prod\"", + "type": "string", + "x-go-name": "LicenseType" + }, + "require_activation": { + "description": "If this license requires activation set to true, make sure to set activation email as well.", + "type": "boolean", + "x-go-name": "RequireActivation" + }, + "update_policy": { + "description": "If set to automatic will auto update remote license installation with every release. If set to manual will update only when on-premise admin clicks the install update button.", + "type": "string", + "x-go-name": "UpdatePolicy" + } + } + } + } + ], + "responses": { + "201": { + "$ref": "#/responses/createLicenseResponse" + }, + "400": { + "$ref": "#/responses/responseErrBadRequest" + }, + "403": { + "$ref": "#/responses/responseErrForbidden" + }, + "404": { + "$ref": "#/responses/responseErrNotFound" + } + } + } + }, + "/license/{license_id}": { + "get": { + "produces": [ + "application/json" + ], + "schemes": [ + "https" + ], + "tags": [ + "license" + ], + "summary": "Get app license for a given licenseId.", + "operationId": "getLicense", + "security": [ + { + "api_key": [] + } + ], + "parameters": [ + { + "type": "string", + "x-go-name": "LicenseID", + "description": "License identifier", + "name": "license_id", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "$ref": "#/responses/getLicenseResponse" + }, + "400": { + "$ref": "#/responses/responseErrBadRequest" + }, + "401": { + "$ref": "#/responses/responseErrUnauthorized" + }, + "403": { + "$ref": "#/responses/responseErrForbidden" + }, + "404": { + "$ref": "#/responses/responseErrNotFound" + } + } + }, + "put": { + "description": "Note: that all fields are required to be passed or they will be overwritten to blank or default values.", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "schemes": [ + "https" + ], + "summary": "Update app license for a given licenseId.", + "operationId": "updateLicense", + "security": [ + { + "api_key": [] + } + ], + "parameters": [ + { + "type": "string", + "x-go-name": "LicenseID", + "description": "License identifier", + "name": "license_id", + "in": "path", + "required": true + }, + { + "name": "Body", + "in": "body", + "required": true, + "schema": { + "type": "object", + "required": [ + "license_type", + "assignee", + "channel_id", + "field_values", + "require_activation", + "activation_email", + "update_policy", + "expiration_date", + "expiration_policy" + ], + "properties": { + "activation_email": { + "description": "If activation is required this is the email the code will be sent to.", + "type": "string", + "x-go-name": "ActivationEmail" + }, + "assignee": { + "description": "License Label name, ie name of customer who is using license.", + "type": "string", + "x-go-name": "Assignee" + }, + "channel_id": { + "description": "Channel id that the license will be associated with.", + "type": "string", + "x-go-name": "ChannelID" + }, + "channels": { + "$ref": "#/definitions/LicenseChannels" + }, + "console_auth_options": { + "type": "array", + "items": { + "type": "string" + }, + "x-go-name": "ConsoleAuthOptions" + }, + "enabled_features": { + "type": "object", + "additionalProperties": { + "type": "object" + }, + "x-go-name": "EnabledFeatures" + }, + "expiration_date": { + "description": "Date that the license will expire, can be null for no expiration or formated by year-month-day ex. 2016-02-02.", + "type": "string", + "x-go-name": "ExpirationDate" + }, + "expiration_policy": { + "description": "Defines expiration policy for this license.\n\nValues:\nignore: replicated will take no action on a expired license\nnoupdate-norestart: application updates will not be downloaded, and once the application is stopped, it will not be started again\nnoupdate-stop: application updates will not be downloaded and the application will be stopped", + "type": "string", + "x-go-name": "ExpirationPolicy" + }, + "field_values": { + "$ref": "#/definitions/LicenseFieldValues" + }, + "is_app_version_locked": { + "description": "A license can be optionally locked to a specific release", + "type": "boolean", + "x-go-name": "IsAppVersionLocked" + }, + "license_type": { + "description": "LicenseType can be set to \"dev\", \"trial\", or \"prod\"", + "type": "string", + "x-go-name": "LicenseType" + }, + "locked_app_version": { + "description": "If app version is locked, this is the version to lock it to (sequence)", + "type": "integer", + "format": "int64", + "x-go-name": "LockedAppVersion" + }, + "require_activation": { + "description": "If this license requires activation set to true, make sure to set activation email as well.", + "type": "boolean", + "x-go-name": "RequireActivation" + }, + "update_policy": { + "description": "If set to automatic will auto update remote license installation with every release. If set to manual will update only when on-premise admin clicks the install update button.", + "type": "string", + "x-go-name": "UpdatePolicy" + } + } + } + } + ], + "responses": { + "200": { + "$ref": "#/responses/updateLicenseResponse" + }, + "400": { + "$ref": "#/responses/responseErrBadRequest" + }, + "401": { + "$ref": "#/responses/responseErrUnauthorized" + }, + "403": { + "$ref": "#/responses/responseErrForbidden" + }, + "404": { + "$ref": "#/responses/responseErrNotFound" + } + } + } + }, + "/licenses": { + "get": { + "produces": [ + "application/json" + ], + "schemes": [ + "https" + ], + "tags": [ + "licenses" + ], + "summary": "Lists all licenses.", + "operationId": "licenses", + "security": [ + { + "api_key": [] + } + ], + "responses": { + "200": { + "$ref": "#/responses/listLicensesResponse" + } + } + } + } + }, + "definitions": { + "LicenseChannel": { + "type": "object", + "properties": { + "description": { + "type": "string", + "x-go-name": "Description" + }, + "id": { + "type": "string", + "x-go-name": "ID" + }, + "is_default": { + "type": "boolean", + "x-go-name": "IsDefault" + }, + "name": { + "type": "string", + "x-go-name": "Name" + } + }, + "x-go-package": "github.com/replicatedcom/vendor-api/handlers/replv2" + }, + "LicenseChannels": { + "type": "array", + "items": { + "$ref": "#/definitions/LicenseChannel" + }, + "x-go-package": "github.com/replicatedcom/vendor-api/handlers/replv2" + }, + "LicenseFieldValue": { + "type": "object", + "properties": { + "field": { + "type": "string", + "x-go-name": "FieldName" + }, + "title": { + "type": "string", + "x-go-name": "FieldTitle" + }, + "type": { + "type": "string", + "x-go-name": "FieldType" + }, + "value": { + "type": "string", + "x-go-name": "Value" + } + }, + "x-go-package": "github.com/replicatedcom/vendor-api/handlers/replv2" + }, + "LicenseFieldValues": { + "type": "array", + "items": { + "$ref": "#/definitions/LicenseFieldValue" + }, + "x-go-package": "github.com/replicatedcom/vendor-api/handlers/replv2" + }, + "LicenseV2": { + "type": "object", + "properties": { + "activation_email": { + "type": "string", + "x-go-name": "ActivationEmail" + }, + "active_instance_count": { + "type": "integer", + "format": "int64", + "x-go-name": "ActiveInstanceCount" + }, + "app_id": { + "type": "string", + "x-go-name": "AppID" + }, + "app_status": { + "type": "string", + "x-go-name": "AppStatus" + }, + "assignee": { + "type": "string", + "x-go-name": "Assignee" + }, + "billing_begin_date": { + "type": "string", + "format": "date-time", + "x-go-name": "BillingBeginDate" + }, + "billing_end_date": { + "type": "string", + "format": "date-time", + "x-go-name": "BillingEndDate" + }, + "billing_frequency": { + "type": "string", + "x-go-name": "BillingFrequency" + }, + "billing_revenue": { + "type": "string", + "x-go-name": "BillingRevenue" + }, + "channel_id": { + "type": "string", + "x-go-name": "ChannelID" + }, + "channel_name": { + "type": "string", + "x-go-name": "ChannelName" + }, + "channels": { + "type": "array", + "items": { + "$ref": "#/definitions/LicenseChannel" + }, + "x-go-name": "Channels" + }, + "cloud_networks": { + "type": "string", + "x-go-name": "CloudNetworks" + }, + "console_auth_options": { + "type": "array", + "items": { + "type": "string" + }, + "x-go-name": "ConsoleAuthOptions" + }, + "enabled_features": { + "type": "object", + "additionalProperties": { + "type": "object" + }, + "x-go-name": "EnabledFeatures" + }, + "expiration_date": { + "type": "string", + "format": "date-time", + "x-go-name": "ExpirationDate" + }, + "expiration_policy": { + "type": "string", + "x-go-name": "ExpirationPolicy" + }, + "grant_date": { + "type": "string", + "format": "date-time", + "x-go-name": "GrantDate" + }, + "id": { + "type": "string", + "x-go-name": "ID" + }, + "inactive_instance_count": { + "type": "integer", + "format": "int64", + "x-go-name": "InactiveInstanceCount" + }, + "installed_release_sequence": { + "type": "integer", + "format": "int64", + "x-go-name": "InstalledReleaseSequence" + }, + "installed_version_label": { + "type": "string", + "x-go-name": "InstalledVersionLabel" + }, + "is_active": { + "type": "boolean", + "x-go-name": "IsActive" + }, + "is_anonymous": { + "type": "boolean", + "x-go-name": "IsAnonymous" + }, + "is_app_version_locked": { + "type": "boolean", + "x-go-name": "IsAppVersionLocked" + }, + "is_archived": { + "type": "boolean", + "x-go-name": "IsArchived" + }, + "is_instance_tracked": { + "type": "boolean", + "x-go-name": "IsInstanceTracked" + }, + "last_sync_at": { + "type": "string", + "format": "date-time", + "x-go-name": "LastSyncAt" + }, + "latest_release_sequence": { + "type": "integer", + "format": "int64", + "x-go-name": "LatestReleaseSequence" + }, + "latest_version_label": { + "type": "string", + "x-go-name": "LatestVersionLabel" + }, + "license_type": { + "type": "string", + "x-go-name": "LicenseType" + }, + "locked_app_version": { + "type": "integer", + "format": "int64", + "x-go-name": "LockedAppVersion" + }, + "require_activation": { + "type": "boolean", + "x-go-name": "RequireActivation" + }, + "revocation_date": { + "type": "string", + "format": "date-time", + "x-go-name": "RevocationDate" + }, + "untracked_instance_count": { + "type": "integer", + "format": "int64", + "x-go-name": "UntrackedInstanceCount" + }, + "update_policy": { + "type": "string", + "x-go-name": "UpdatePolicy" + } + }, + "x-go-package": "github.com/replicatedcom/vendor-api/handlers/replv2" + }, + "LicensesV2": { + "type": "array", + "items": { + "$ref": "#/definitions/LicenseV2" + }, + "x-go-package": "github.com/replicatedcom/vendor-api/handlers/replv2" + } + }, + "responses": { + "createLicenseResponse": { + "description": "CreateLicenseResponse contains the created license", + "schema": { + "type": "object", + "properties": { + "License": { + "$ref": "#/definitions/LicenseV2" + } + } + } + }, + "getLicenseResponse": { + "description": "GetLicenseResponse contains the returned license", + "schema": { + "type": "object", + "required": [ + "License" + ], + "properties": { + "License": { + "$ref": "#/definitions/LicenseV2" + } + } + } + }, + "listAppLicensesResponse": { + "description": "ListAppLicensesResponse contains the list of licenses", + "schema": { + "type": "object", + "properties": { + "Licenses": { + "$ref": "#/definitions/LicensesV2" + } + } + } + }, + "listLicensesResponse": { + "description": "ListLicensesResponse contains the parameters needed to call list licenses", + "schema": { + "type": "object", + "properties": { + "Licenses": { + "type": "array", + "items": { + "$ref": "#/definitions/LicenseV2" + } + } + } + } + }, + "responseErrBadRequest": { + "description": "Returned on bad input" + }, + "responseErrConflict": { + "description": "Returned on a conflict" + }, + "responseErrForbidden": { + "description": "Returned if the caller does not have the needed permission" + }, + "responseErrNotFound": { + "description": "Returned on resource not found" + }, + "responseErrUnauthorized": { + "description": "Return if the caller is not authorized" + }, + "responseNoContent": { + "description": "On success, no payload returned" + }, + "responseOk": { + "description": "On success" + }, + "searchAppLicensesResponse": { + "description": "SearchAppLicensesResponse contains the list of licenses", + "schema": { + "type": "object", + "properties": { + "licenses": { + "$ref": "#/definitions/LicensesV2" + }, + "query": { + "type": "string", + "x-go-name": "Query" + }, + "total_hits": { + "type": "integer", + "format": "int64", + "x-go-name": "TotalHits" + } + } + } + }, + "updateLicenseResponse": { + "description": "UpdateLicenseResponse contains the license", + "schema": { + "type": "object", + "required": [ + "License" + ], + "properties": { + "License": { + "$ref": "#/definitions/LicenseV2" + } + } + } + } + } +} \ No newline at end of file