diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index dd57a7d..c6bb735 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -42,12 +42,11 @@ jobs: - name: Set up Docker run: | brew install docker docker-machine docker-compose - sudo mkdir -p /usr/local/bin sudo curl -L -o /usr/local/bin/colima https://github.com/abiosoft/colima/releases/download/v0.6.7/colima-Darwin-x86_64 && sudo chmod +x /usr/local/bin/colima brew install lima + brew install qemu colima start - sudo ln -sf $HOME/.colima/default/docker.sock /var/run/docker.sock - name: Cache Go modules diff --git a/docs/vcr.md b/docs/vcr.md index 404a7d0..9ccf35a 100644 --- a/docs/vcr.md +++ b/docs/vcr.md @@ -43,4 +43,4 @@ $ vcr init * [vcr secret](vcr_secret.md) - Manage VCR secrets * [vcr upgrade](vcr_upgrade.md) - Show and update VCR CLI version -###### Auto generated by spf13/cobra on 11-Nov-2024 +###### Auto generated by spf13/cobra on 26-Nov-2024 diff --git a/docs/vcr_app.md b/docs/vcr_app.md index f9ba4ce..72b096b 100644 --- a/docs/vcr_app.md +++ b/docs/vcr_app.md @@ -26,4 +26,4 @@ Use app commands to create, list and generate the key pairs of Vonage applicatio * [vcr app generate-keys](vcr_app_generate-keys.md) - Generate Vonage application keys * [vcr app list](vcr_app_list.md) - List Vonage applications -###### Auto generated by spf13/cobra on 11-Nov-2024 +###### Auto generated by spf13/cobra on 26-Nov-2024 diff --git a/docs/vcr_app_create.md b/docs/vcr_app_create.md index 0055933..6aafad9 100644 --- a/docs/vcr_app_create.md +++ b/docs/vcr_app_create.md @@ -42,4 +42,4 @@ $ vcr app create --name App * [vcr app](vcr_app.md) - Use app commands to manage Vonage applications -###### Auto generated by spf13/cobra on 11-Nov-2024 +###### Auto generated by spf13/cobra on 26-Nov-2024 diff --git a/docs/vcr_app_generate-keys.md b/docs/vcr_app_generate-keys.md index 06b031e..22f9ab5 100644 --- a/docs/vcr_app_generate-keys.md +++ b/docs/vcr_app_generate-keys.md @@ -44,4 +44,4 @@ $ vcr app generate-keys --app-id 42066b10-c4ae-48a0-addd-feb2bd615a67 * [vcr app](vcr_app.md) - Use app commands to manage Vonage applications -###### Auto generated by spf13/cobra on 11-Nov-2024 +###### Auto generated by spf13/cobra on 26-Nov-2024 diff --git a/docs/vcr_app_list.md b/docs/vcr_app_list.md index 3b091a2..060cd66 100644 --- a/docs/vcr_app_list.md +++ b/docs/vcr_app_list.md @@ -38,4 +38,4 @@ ID Name * [vcr app](vcr_app.md) - Use app commands to manage Vonage applications -###### Auto generated by spf13/cobra on 11-Nov-2024 +###### Auto generated by spf13/cobra on 26-Nov-2024 diff --git a/docs/vcr_configure.md b/docs/vcr_configure.md index 1c42dc9..230e6da 100644 --- a/docs/vcr_configure.md +++ b/docs/vcr_configure.md @@ -39,4 +39,4 @@ $ vcr configure * [vcr](vcr.md) - Streamline your Vonage Cloud Runtime development and management tasks with VCR -###### Auto generated by spf13/cobra on 11-Nov-2024 +###### Auto generated by spf13/cobra on 26-Nov-2024 diff --git a/docs/vcr_debug.md b/docs/vcr_debug.md index 94ea62a..7dc6eff 100644 --- a/docs/vcr_debug.md +++ b/docs/vcr_debug.md @@ -75,4 +75,4 @@ $ vcr debug --name debugger" * [vcr](vcr.md) - Streamline your Vonage Cloud Runtime development and management tasks with VCR -###### Auto generated by spf13/cobra on 11-Nov-2024 +###### Auto generated by spf13/cobra on 26-Nov-2024 diff --git a/docs/vcr_deploy.md b/docs/vcr_deploy.md index b8191c8..d4de11d 100644 --- a/docs/vcr_deploy.md +++ b/docs/vcr_deploy.md @@ -85,4 +85,4 @@ $ vcr deploy * [vcr](vcr.md) - Streamline your Vonage Cloud Runtime development and management tasks with VCR -###### Auto generated by spf13/cobra on 11-Nov-2024 +###### Auto generated by spf13/cobra on 26-Nov-2024 diff --git a/docs/vcr_init.md b/docs/vcr_init.md index 55401fc..0ae840a 100644 --- a/docs/vcr_init.md +++ b/docs/vcr_init.md @@ -42,4 +42,4 @@ $ vcr init my-app * [vcr](vcr.md) - Streamline your Vonage Cloud Runtime development and management tasks with VCR -###### Auto generated by spf13/cobra on 11-Nov-2024 +###### Auto generated by spf13/cobra on 26-Nov-2024 diff --git a/docs/vcr_instance.md b/docs/vcr_instance.md index 4d22a85..e054ce5 100644 --- a/docs/vcr_instance.md +++ b/docs/vcr_instance.md @@ -24,4 +24,4 @@ Used for instance management * [vcr instance log](vcr_instance_log.md) - This command will output the log of an instance. * [vcr instance remove](vcr_instance_remove.md) - This command will remove an instance. -###### Auto generated by spf13/cobra on 11-Nov-2024 +###### Auto generated by spf13/cobra on 26-Nov-2024 diff --git a/docs/vcr_instance_log.md b/docs/vcr_instance_log.md index f34872f..d8e55e0 100644 --- a/docs/vcr_instance_log.md +++ b/docs/vcr_instance_log.md @@ -44,4 +44,4 @@ $ vcr instance log --project-name --instance-name * [vcr instance](vcr_instance.md) - Used for instance management -###### Auto generated by spf13/cobra on 11-Nov-2024 +###### Auto generated by spf13/cobra on 26-Nov-2024 diff --git a/docs/vcr_instance_remove.md b/docs/vcr_instance_remove.md index 530965b..19f8c0a 100644 --- a/docs/vcr_instance_remove.md +++ b/docs/vcr_instance_remove.md @@ -41,4 +41,4 @@ $ vcr instance rm --id * [vcr instance](vcr_instance.md) - Used for instance management -###### Auto generated by spf13/cobra on 11-Nov-2024 +###### Auto generated by spf13/cobra on 26-Nov-2024 diff --git a/docs/vcr_mongo.md b/docs/vcr_mongo.md index aad6547..fc6b46e 100644 --- a/docs/vcr_mongo.md +++ b/docs/vcr_mongo.md @@ -22,4 +22,4 @@ Used for managing MongoDB databases * [vcr mongo info](vcr_mongo_info.md) - Get database connection info * [vcr mongo list](vcr_mongo_list.md) - List databases -###### Auto generated by spf13/cobra on 11-Nov-2024 +###### Auto generated by spf13/cobra on 26-Nov-2024 diff --git a/docs/vcr_mongo_create.md b/docs/vcr_mongo_create.md index 563b7cf..96c6532 100644 --- a/docs/vcr_mongo_create.md +++ b/docs/vcr_mongo_create.md @@ -34,4 +34,4 @@ $ vcr mongo create * [vcr mongo](vcr_mongo.md) - Used for managing MongoDB databases -###### Auto generated by spf13/cobra on 11-Nov-2024 +###### Auto generated by spf13/cobra on 26-Nov-2024 diff --git a/docs/vcr_mongo_delete.md b/docs/vcr_mongo_delete.md index 43fa302..97c154f 100644 --- a/docs/vcr_mongo_delete.md +++ b/docs/vcr_mongo_delete.md @@ -35,4 +35,4 @@ $ vcr mongo delete --database * [vcr mongo](vcr_mongo.md) - Used for managing MongoDB databases -###### Auto generated by spf13/cobra on 11-Nov-2024 +###### Auto generated by spf13/cobra on 26-Nov-2024 diff --git a/docs/vcr_mongo_info.md b/docs/vcr_mongo_info.md index 43709c4..0d2d18b 100644 --- a/docs/vcr_mongo_info.md +++ b/docs/vcr_mongo_info.md @@ -35,4 +35,4 @@ $ vcr mongo info --database * [vcr mongo](vcr_mongo.md) - Used for managing MongoDB databases -###### Auto generated by spf13/cobra on 11-Nov-2024 +###### Auto generated by spf13/cobra on 26-Nov-2024 diff --git a/docs/vcr_mongo_list.md b/docs/vcr_mongo_list.md index 282cebb..b04f306 100644 --- a/docs/vcr_mongo_list.md +++ b/docs/vcr_mongo_list.md @@ -34,4 +34,4 @@ $ vcr mongo list * [vcr mongo](vcr_mongo.md) - Used for managing MongoDB databases -###### Auto generated by spf13/cobra on 11-Nov-2024 +###### Auto generated by spf13/cobra on 26-Nov-2024 diff --git a/docs/vcr_secret.md b/docs/vcr_secret.md index 59a36e3..d272642 100644 --- a/docs/vcr_secret.md +++ b/docs/vcr_secret.md @@ -29,4 +29,4 @@ $ vcr secret create --name --file * [vcr secret remove](vcr_secret_remove.md) - Remove a secret * [vcr secret update](vcr_secret_update.md) - update a secret -###### Auto generated by spf13/cobra on 11-Nov-2024 +###### Auto generated by spf13/cobra on 26-Nov-2024 diff --git a/docs/vcr_secret_create.md b/docs/vcr_secret_create.md index 86a394a..cbb2aab 100644 --- a/docs/vcr_secret_create.md +++ b/docs/vcr_secret_create.md @@ -46,4 +46,4 @@ $ vcr secret create --name --file * [vcr secret](vcr_secret.md) - Manage VCR secrets -###### Auto generated by spf13/cobra on 11-Nov-2024 +###### Auto generated by spf13/cobra on 26-Nov-2024 diff --git a/docs/vcr_secret_remove.md b/docs/vcr_secret_remove.md index fc59007..1605954 100644 --- a/docs/vcr_secret_remove.md +++ b/docs/vcr_secret_remove.md @@ -35,4 +35,4 @@ $ vcr secret remove -n * [vcr secret](vcr_secret.md) - Manage VCR secrets -###### Auto generated by spf13/cobra on 11-Nov-2024 +###### Auto generated by spf13/cobra on 26-Nov-2024 diff --git a/docs/vcr_secret_update.md b/docs/vcr_secret_update.md index 9542daa..5493c9e 100644 --- a/docs/vcr_secret_update.md +++ b/docs/vcr_secret_update.md @@ -39,4 +39,4 @@ $ vcr secret update --name my-secret --value changed-value * [vcr secret](vcr_secret.md) - Manage VCR secrets -###### Auto generated by spf13/cobra on 11-Nov-2024 +###### Auto generated by spf13/cobra on 26-Nov-2024 diff --git a/docs/vcr_upgrade.md b/docs/vcr_upgrade.md index 01ba6fe..287afc7 100644 --- a/docs/vcr_upgrade.md +++ b/docs/vcr_upgrade.md @@ -16,7 +16,8 @@ vcr upgrade [flags] ### Options ``` - -f, --force Force update and skip prompt if new update exists + -f, --force Force update and skip prompt if new update exists + -p, --path string Path to the VCR CLI installed directory ``` ### Options inherited from parent commands @@ -35,4 +36,4 @@ vcr upgrade [flags] * [vcr](vcr.md) - Streamline your Vonage Cloud Runtime development and management tasks with VCR -###### Auto generated by spf13/cobra on 11-Nov-2024 +###### Auto generated by spf13/cobra on 26-Nov-2024 diff --git a/pkg/cmdutil/factory.go b/pkg/cmdutil/factory.go index 6af2beb..66f3b90 100644 --- a/pkg/cmdutil/factory.go +++ b/pkg/cmdutil/factory.go @@ -74,6 +74,7 @@ type DatastoreInterface interface { // Factory provides clients and parameters for all subcommands. type Factory interface { Init(ctx context.Context, cfg config.CLIConfig, opts *config.GlobalOptions) error + InitUpgrade(opts *config.GlobalOptions) InitDatastore(cfg config.CLIConfig, opts *config.GlobalOptions) InitDeploymentClient(ctx context.Context, regionAlias string) error SetGlobalOptions(opts *config.GlobalOptions) @@ -126,6 +127,7 @@ func NewDefaultFactory(apiVersion string, releaseURL string) *DefaultFactory { } func (f *DefaultFactory) Init(ctx context.Context, cfg config.CLIConfig, opts *config.GlobalOptions) error { + f.cliConfig = cfg f.globalOpts = opts f.websocketConnectionClient = getWebsocketConnectionClient(f.APIKey(), f.APISecret()) @@ -145,6 +147,12 @@ func (f *DefaultFactory) Init(ctx context.Context, cfg config.CLIConfig, opts *c return nil } +func (f *DefaultFactory) InitUpgrade(opts *config.GlobalOptions) { + f.globalOpts = opts + f.httpClient = GetHTTPClient("", "") + f.releaseClient = api.NewReleaseClient(f.releaseURL, f.httpClient) +} + func (f *DefaultFactory) InitDatastore(cfg config.CLIConfig, opts *config.GlobalOptions) { f.globalOpts = opts f.cliConfig = cfg @@ -220,6 +228,9 @@ func (f *DefaultFactory) GraphQLURL() string { if f.globalOpts.GraphqlEndpoint != "" { return f.globalOpts.GraphqlEndpoint } + if f.globalOpts.Region != "" { + return makeGraphqlEndpoint(f.globalOpts.Region) + } return f.cliConfig.GraphqlEndpoint } @@ -268,3 +279,8 @@ func getDatastore(graphQLURL string, httpClient *resty.Client) *api.Datastore { func getWebsocketConnectionClient(apiKey, apiSecret string) *api.WebsocketConnectionClient { return api.NewWebsocketConnectionClient(apiKey, apiSecret) } + +func makeGraphqlEndpoint(region string) string { + region = region[4:] + return fmt.Sprintf("https://graphql.%s.runtime.vonage.cloud/v1/graphql", region) +} diff --git a/script/install.sh b/script/install.sh index b823073..184fce6 100644 --- a/script/install.sh +++ b/script/install.sh @@ -2,7 +2,56 @@ # Based on Deno installer: Copyright 2019 the Deno authors. All rights reserved. MIT license. set -e +version="" +path="" +while test $# -gt 0; do + case "$1" in + -h|--help) + echo "options:" + echo "-h, --help show brief help" + echo "-v, --version=VERSION specify a version to download" + echo "-o, --output-dir=DIR specify a directory to install" + exit 0 + ;; + -v) + shift + if test $# -gt 0; then + version=$1 + else + echo "no version specified" + exit 1 + fi + shift + ;; + --version*) + version=`echo $1 | sed -e 's/^[^=]*=//g'` + echo "version:$version" + shift + ;; + -o) + shift + if test $# -gt 0; then + path=$1 + else + echo "no output dir specified" + exit 1 + fi + shift + ;; + --output-dir*) + path=`echo $1 | sed -e 's/^[^=]*=//g'` + echo "path:$path" + shift + ;; + *) + echo "Error: Invalid argument $1" 1>&2 + exit 1 + ;; + esac +done + main() { + os=$(uname -s | tr '[:upper:]' '[:lower:]') arch=$(uname -m) if [ "$arch" = "x86_64" ]; then @@ -11,7 +60,7 @@ main() { arch="arm64" fi vcr_binary="vcr_${os}_${arch}" - version="${1:+download/$1}" + version="${version:+download/$version}" version="${version:-latest/download}" vcr_uri="https://github.com/Vonage/cloud-runtime-cli/releases/$version/$vcr_binary.tar.gz" @@ -31,6 +80,12 @@ main() { mkdir -p "$bin_dir" mkdir -p "$tmp_dir" + if [ -n "$path" ]; then + echo "Path provided: $path" + mkdir -p $path + + fi + if ! curl -q --fail --location --progress-bar --output "$tmp_dir/${vcr_binary}.tar.gz" "$vcr_uri"; then echo "Error encountered when downloading ${vcr_binary} to ${tmp_dir} , please try to run with sudo" exit 1 @@ -41,20 +96,33 @@ main() { rm "$tmp_dir/${vcr_binary}.tar.gz" cp "$tmp_dir/${vcr_binary}" "$exe" + + if [ -n "$path" ]; then + if mv "$tmp_dir/${vcr_binary}" "$path/vcr"; then + echo "vcr was installed successfully to $path/vcr" + echo "Run '$path/vcr --help' to get started" + case $SHELL in + /bin/zsh) shell_profile=".zshrc" ;; + *) shell_profile=".bash_profile" ;; + esac + echo "Or manually add the directory to your \$HOME/$shell_profile (or similar)" + echo " export VCR_INSTALL=\"$path\"" + echo " export PATH=\"\$VCR_INSTALL:\$PATH\"" + exit 0 + else + exit 1 + fi + + fi + if mv "$tmp_dir/${vcr_binary}" "$sys_exe"; then - echo "vcr was installed successfully to $sys_exe" - echo "Run 'vcr --help' to get started" + echo "vcr was installed successfully to $sys_exe" + echo "Run 'vcr --help' to get started" + exit 0 else - case $SHELL in - /bin/zsh) shell_profile=".zshrc" ;; - *) shell_profile=".bash_profile" ;; - esac echo "Error encountered when moving ${vcr_binary} to $sys_exe , please try to run with sudo" - echo "Or manually add the directory to your \$HOME/$shell_profile (or similar)" - echo " export VCR_INSTALL=\"$vcr_install\"" - echo " export PATH=\"\$VCR_INSTALL/bin:\$PATH\"" - echo "Run '$exe --help' to get started" + echo "Or use the -o flag to specify a directory where you have write permissions, for more information run with -h" + exit 1 fi } - -main "$1" \ No newline at end of file +main "$1" diff --git a/testutil/mocks/factory.go b/testutil/mocks/factory.go index 2714cf7..86c81c2 100644 --- a/testutil/mocks/factory.go +++ b/testutil/mocks/factory.go @@ -932,6 +932,18 @@ func (mr *MockFactoryMockRecorder) InitDeploymentClient(ctx, regionAlias interfa return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "InitDeploymentClient", reflect.TypeOf((*MockFactory)(nil).InitDeploymentClient), ctx, regionAlias) } +// InitUpgrade mocks base method. +func (m *MockFactory) InitUpgrade(opts *config.GlobalOptions) { + m.ctrl.T.Helper() + m.ctrl.Call(m, "InitUpgrade", opts) +} + +// InitUpgrade indicates an expected call of InitUpgrade. +func (mr *MockFactoryMockRecorder) InitUpgrade(opts interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "InitUpgrade", reflect.TypeOf((*MockFactory)(nil).InitUpgrade), opts) +} + // MarketplaceClient mocks base method. func (m *MockFactory) MarketplaceClient() cmdutil.MarketplaceInterface { m.ctrl.T.Helper() diff --git a/vcr/root/root.go b/vcr/root/root.go index eb57bfd..512bf34 100644 --- a/vcr/root/root.go +++ b/vcr/root/root.go @@ -57,6 +57,12 @@ func NewCmdRoot(f cmdutil.Factory, version, buildDate, commit string, updateStre return nil } + if cmd.Name() == "upgrade" { + f.InitUpgrade(&opts) + close(updateStream) + return nil + } + cliConfig, err := config.ReadCLIConfig(opts.ConfigFilePath) if err != nil { if !errors.Is(err, config.ErrNoConfig) { @@ -67,9 +73,9 @@ func NewCmdRoot(f cmdutil.Factory, version, buildDate, commit string, updateStre cliConfig, path, err = config.ReadDefaultCLIConfig() switch { case errors.Is(err, config.ErrNoConfig): - fmt.Fprintf(io.ErrOut, "%s Config file not found at %q, please use 'vcr configure' to create one. Trying to use flags...\n", c.WarningIcon(), opts.ConfigFilePath) + fmt.Fprintf(io.Out, "%s Config file not found at %q, please use 'vcr configure' to create one. Trying to use flags...\n", c.WarningIcon(), opts.ConfigFilePath) case err == nil: - fmt.Fprintf(io.ErrOut, "%s Config file not found at %q, using %q\n", c.WarningIcon(), opts.ConfigFilePath, path) + fmt.Fprintf(io.Out, "%s Config file not found at %q, using %q\n", c.WarningIcon(), opts.ConfigFilePath, path) default: close(updateStream) return fmt.Errorf("failed to read config file %q : %w", path, err) @@ -84,11 +90,6 @@ func NewCmdRoot(f cmdutil.Factory, version, buildDate, commit string, updateStre return fmt.Errorf("failed to initialize cli: %w", err) } - if cmd.Name() == "upgrade" { - close(updateStream) - return nil - } - go func() { ctx, cancel := context.WithDeadline(context.Background(), time.Now().Add(opts.Timeout)) defer cancel() diff --git a/vcr/upgrade/upgrade.go b/vcr/upgrade/upgrade.go index c104611..86e3762 100644 --- a/vcr/upgrade/upgrade.go +++ b/vcr/upgrade/upgrade.go @@ -17,12 +17,14 @@ import ( "vonage-cloud-runtime-cli/pkg/api" "vonage-cloud-runtime-cli/pkg/cmdutil" + "vonage-cloud-runtime-cli/pkg/config" ) type Options struct { cmdutil.Factory forceUpdate bool + path string } func NewCmdUpgrade(f cmdutil.Factory, version string) *cobra.Command { @@ -42,12 +44,20 @@ func NewCmdUpgrade(f cmdutil.Factory, version string) *cobra.Command { ctx, cancel := context.WithDeadline(context.Background(), opts.Deadline()) defer cancel() fmt.Fprint(f.IOStreams().Out, cmd.Root().Annotations["versionInfo"]) + if opts.path != "" { + absPath, err := config.GetAbsDir(opts.path) + if err != nil { + return fmt.Errorf("failed to get absolute path of %q: %w", opts.path, err) + } + opts.path = absPath + } + return runUpgrade(ctx, &opts, version) }, } cmd.Flags().BoolVarP(&opts.forceUpdate, "force", "f", false, "Force update and skip prompt if new update exists") - + cmd.Flags().StringVarP(&opts.path, "path", "p", "", "Path to the VCR CLI installed directory") return cmd } @@ -96,6 +106,15 @@ func runUpgrade(ctx context.Context, opts *Options, version string) error { return fmt.Errorf("failed to get executable path: %w", err) } + if opts.path != "" { + exePath = opts.path + "/vcr" + } + + if !executableExists(exePath) { + return fmt.Errorf("failed to find executable CLI file at %s", exePath) + } + + fmt.Println(exePath) spinner = cmdutil.DisplaySpinnerMessageWithHandle(fmt.Sprintf(" Updating CLI to latest version - v%s...", latestVersion)) err = updateByAsset(ctx, opts, release, exePath) spinner.Stop() @@ -179,3 +198,11 @@ func getDownloadURL(release api.Release) (string, error) { } return "", fmt.Errorf("no asset found for %s %s", runtime.GOOS, runtime.GOARCH) } + +func executableExists(path string) bool { + info, err := os.Stat(path) + if err != nil { + return false + } + return !info.IsDir() && info.Mode()&0111 != 0 +}