From 34a7ab8bf36ff9121f21b838d7c1259edd17cb43 Mon Sep 17 00:00:00 2001 From: Alibaba Cloud SDK Date: Tue, 20 Jul 2021 16:28:36 +0000 Subject: [PATCH 1/8] Release version v3.0.82 --- .appveyor.yml | 2 +- CHANGELOG.md | 4 ++++ Makefile | 2 +- README-CN.md | 8 ++++---- README.md | 8 ++++---- aliyun-openapi-meta | 2 +- 6 files changed, 15 insertions(+), 11 deletions(-) diff --git a/.appveyor.yml b/.appveyor.yml index a7761579f..4fc43fa7b 100644 --- a/.appveyor.yml +++ b/.appveyor.yml @@ -9,7 +9,7 @@ install: # by default, all script lines are interpreted as batch - cmd: git clone -q --branch=master https://github.com/aliyun/aliyun-openapi-meta.git C:\Users\appveyor\go\src\github.com\aliyun\aliyun-openapi-meta - cmd: set path=%path%;C:\Users\appveyor\go\bin - - cmd: set VERSION=3.0.81 + - cmd: set VERSION=3.0.82 - cmd: go get -u github.com/shuLhan/go-bindata/... - cmd: go-bindata -o resource/metas.go -pkg resource -prefix ../aliyun-openapi-meta ../aliyun-openapi-meta/... - cmd: go build -ldflags "-X 'github.com/aliyun/aliyun-cli/cli.Version=%VERSION%'" -o C:\Users\appveyor\go\bin\aliyun.exe main/main.go diff --git a/CHANGELOG.md b/CHANGELOG.md index e02c69919..3c3dfbe1a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,10 @@ ### Master +### 3.0.82 + +- update: meta data + ### 3.0.81 - update: meta data diff --git a/Makefile b/Makefile index 953e95137..7c28ffbb6 100644 --- a/Makefile +++ b/Makefile @@ -1,4 +1,4 @@ -export VERSION=3.0.81 +export VERSION=3.0.82 export RELEASE_PATH="releases/aliyun-cli-${VERSION}" all: build diff --git a/README-CN.md b/README-CN.md index 8a2e263a1..f4423bedd 100644 --- a/README-CN.md +++ b/README-CN.md @@ -43,11 +43,11 @@ CLI 版本更改说明请参考 [CHANGELOG](./CHANGELOG.md) 阿里云CLI工具下载、解压后即可使用,支持Mac, Linux, Windows平台(x64版本)。您可以将解压的`aliyun`可执行文件移至`/usr/local/bin`目录下,或添加到`$PATH`中。 - 下载链接如下 (3.0.81): + 下载链接如下 (3.0.82): - - [Mac](https://aliyuncli.alicdn.com/aliyun-cli-macosx-3.0.81-amd64.tgz) - - [Linux](https://aliyuncli.alicdn.com/aliyun-cli-linux-3.0.81-amd64.tgz) - - [Windows (64 bit)](https://aliyuncli.alicdn.com/aliyun-cli-windows-3.0.81-amd64.zip) + - [Mac](https://aliyuncli.alicdn.com/aliyun-cli-macosx-3.0.82-amd64.tgz) + - [Linux](https://aliyuncli.alicdn.com/aliyun-cli-linux-3.0.82-amd64.tgz) + - [Windows (64 bit)](https://aliyuncli.alicdn.com/aliyun-cli-windows-3.0.82-amd64.zip) - **使用brew** diff --git a/README.md b/README.md index bbcbcfbd1..bf60dc239 100644 --- a/README.md +++ b/README.md @@ -41,11 +41,11 @@ The release notes for the CLI can be found in the [CHANGELOG](./CHANGELOG.md) Download the installer, then extract the installer. You can move the extracted `aliyun` executable file to the `/usr/local/bin` directory or add it to the `$PATH`. - Download link: (3.0.81) + Download link: (3.0.82) - - [Mac](https://aliyuncli.alicdn.com/aliyun-cli-macosx-3.0.81-amd64.tgz) - - [Linux](https://aliyuncli.alicdn.com/aliyun-cli-linux-3.0.81-amd64.tgz) - - [Windows (64 bit)](https://aliyuncli.alicdn.com/aliyun-cli-windows-3.0.81-amd64.zip) + - [Mac](https://aliyuncli.alicdn.com/aliyun-cli-macosx-3.0.82-amd64.tgz) + - [Linux](https://aliyuncli.alicdn.com/aliyun-cli-linux-3.0.82-amd64.tgz) + - [Windows (64 bit)](https://aliyuncli.alicdn.com/aliyun-cli-windows-3.0.82-amd64.zip) - **Use brew** If you have installed `brew` in your computer, you can use it to install Alibaba Cloud CLI as following: diff --git a/aliyun-openapi-meta b/aliyun-openapi-meta index 5cfbc3887..078efd1c8 160000 --- a/aliyun-openapi-meta +++ b/aliyun-openapi-meta @@ -1 +1 @@ -Subproject commit 5cfbc388745706fc683b2402631fcd970edaf980 +Subproject commit 078efd1c838e71a96c8d10a28d99b1eced798cbf From 8ef7b1f249f272e65943ab37594ea92c715ecdb2 Mon Sep 17 00:00:00 2001 From: Jackson Tian Date: Mon, 2 Aug 2021 14:52:25 +0800 Subject: [PATCH 2/8] fix next token mode check --- openapi/pager.go | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/openapi/pager.go b/openapi/pager.go index bc1395d36..a977c7cd2 100644 --- a/openapi/pager.go +++ b/openapi/pager.go @@ -148,20 +148,20 @@ func (a *Pager) FeedResponse(body string) error { return fmt.Errorf("unmarshal %s", err.Error()) } - if a.nextTokenMode { - a.nextToken = "" - } + a.nextToken = "" + if a.NextTokenExpr != "" { + a.nextTokenMode = true // allow to ignore NextToken mode if val, err := jmespath.Search(a.NextTokenExpr, j); err == nil { if nextToken, ok := val.(string); ok { a.nextToken = nextToken - a.nextTokenMode = true } } else { return fmt.Errorf("jmespath: '%s' failed %s", a.NextTokenExpr, err) } } + if !a.nextTokenMode { if total, err := jmespath.Search(a.TotalCountExpr, j); err == nil { var totalCount float64 From dd71ab37bf84e6d1bad906c4541f1fc9b4d0e7f2 Mon Sep 17 00:00:00 2001 From: Alibaba Cloud SDK Date: Mon, 2 Aug 2021 08:51:19 +0000 Subject: [PATCH 3/8] Release version v3.0.83 --- .appveyor.yml | 2 +- CHANGELOG.md | 4 ++++ Makefile | 2 +- README-CN.md | 8 ++++---- README.md | 8 ++++---- aliyun-openapi-meta | 2 +- 6 files changed, 15 insertions(+), 11 deletions(-) diff --git a/.appveyor.yml b/.appveyor.yml index 4fc43fa7b..c1a1d968a 100644 --- a/.appveyor.yml +++ b/.appveyor.yml @@ -9,7 +9,7 @@ install: # by default, all script lines are interpreted as batch - cmd: git clone -q --branch=master https://github.com/aliyun/aliyun-openapi-meta.git C:\Users\appveyor\go\src\github.com\aliyun\aliyun-openapi-meta - cmd: set path=%path%;C:\Users\appveyor\go\bin - - cmd: set VERSION=3.0.82 + - cmd: set VERSION=3.0.83 - cmd: go get -u github.com/shuLhan/go-bindata/... - cmd: go-bindata -o resource/metas.go -pkg resource -prefix ../aliyun-openapi-meta ../aliyun-openapi-meta/... - cmd: go build -ldflags "-X 'github.com/aliyun/aliyun-cli/cli.Version=%VERSION%'" -o C:\Users\appveyor\go\bin\aliyun.exe main/main.go diff --git a/CHANGELOG.md b/CHANGELOG.md index 3c3dfbe1a..44480c0dd 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,10 @@ ### Master +### 3.0.83 + +- update: meta data + ### 3.0.82 - update: meta data diff --git a/Makefile b/Makefile index 7c28ffbb6..f5d6f531e 100644 --- a/Makefile +++ b/Makefile @@ -1,4 +1,4 @@ -export VERSION=3.0.82 +export VERSION=3.0.83 export RELEASE_PATH="releases/aliyun-cli-${VERSION}" all: build diff --git a/README-CN.md b/README-CN.md index f4423bedd..6fdf59a87 100644 --- a/README-CN.md +++ b/README-CN.md @@ -43,11 +43,11 @@ CLI 版本更改说明请参考 [CHANGELOG](./CHANGELOG.md) 阿里云CLI工具下载、解压后即可使用,支持Mac, Linux, Windows平台(x64版本)。您可以将解压的`aliyun`可执行文件移至`/usr/local/bin`目录下,或添加到`$PATH`中。 - 下载链接如下 (3.0.82): + 下载链接如下 (3.0.83): - - [Mac](https://aliyuncli.alicdn.com/aliyun-cli-macosx-3.0.82-amd64.tgz) - - [Linux](https://aliyuncli.alicdn.com/aliyun-cli-linux-3.0.82-amd64.tgz) - - [Windows (64 bit)](https://aliyuncli.alicdn.com/aliyun-cli-windows-3.0.82-amd64.zip) + - [Mac](https://aliyuncli.alicdn.com/aliyun-cli-macosx-3.0.83-amd64.tgz) + - [Linux](https://aliyuncli.alicdn.com/aliyun-cli-linux-3.0.83-amd64.tgz) + - [Windows (64 bit)](https://aliyuncli.alicdn.com/aliyun-cli-windows-3.0.83-amd64.zip) - **使用brew** diff --git a/README.md b/README.md index bf60dc239..85212b973 100644 --- a/README.md +++ b/README.md @@ -41,11 +41,11 @@ The release notes for the CLI can be found in the [CHANGELOG](./CHANGELOG.md) Download the installer, then extract the installer. You can move the extracted `aliyun` executable file to the `/usr/local/bin` directory or add it to the `$PATH`. - Download link: (3.0.82) + Download link: (3.0.83) - - [Mac](https://aliyuncli.alicdn.com/aliyun-cli-macosx-3.0.82-amd64.tgz) - - [Linux](https://aliyuncli.alicdn.com/aliyun-cli-linux-3.0.82-amd64.tgz) - - [Windows (64 bit)](https://aliyuncli.alicdn.com/aliyun-cli-windows-3.0.82-amd64.zip) + - [Mac](https://aliyuncli.alicdn.com/aliyun-cli-macosx-3.0.83-amd64.tgz) + - [Linux](https://aliyuncli.alicdn.com/aliyun-cli-linux-3.0.83-amd64.tgz) + - [Windows (64 bit)](https://aliyuncli.alicdn.com/aliyun-cli-windows-3.0.83-amd64.zip) - **Use brew** If you have installed `brew` in your computer, you can use it to install Alibaba Cloud CLI as following: diff --git a/aliyun-openapi-meta b/aliyun-openapi-meta index 078efd1c8..1b76ed85f 160000 --- a/aliyun-openapi-meta +++ b/aliyun-openapi-meta @@ -1 +1 @@ -Subproject commit 078efd1c838e71a96c8d10a28d99b1eced798cbf +Subproject commit 1b76ed85f2a9923e4ccd7451bd0b498aafe19092 From 905afc1b6c04fd4f7cdaa007ab92a0363553e6c5 Mon Sep 17 00:00:00 2001 From: Alibaba Cloud SDK Date: Wed, 4 Aug 2021 08:36:16 +0000 Subject: [PATCH 4/8] Release version v3.0.84 --- .appveyor.yml | 2 +- CHANGELOG.md | 4 ++++ Makefile | 2 +- README-CN.md | 8 ++++---- README.md | 8 ++++---- aliyun-openapi-meta | 2 +- 6 files changed, 15 insertions(+), 11 deletions(-) diff --git a/.appveyor.yml b/.appveyor.yml index c1a1d968a..ca0094f2d 100644 --- a/.appveyor.yml +++ b/.appveyor.yml @@ -9,7 +9,7 @@ install: # by default, all script lines are interpreted as batch - cmd: git clone -q --branch=master https://github.com/aliyun/aliyun-openapi-meta.git C:\Users\appveyor\go\src\github.com\aliyun\aliyun-openapi-meta - cmd: set path=%path%;C:\Users\appveyor\go\bin - - cmd: set VERSION=3.0.83 + - cmd: set VERSION=3.0.84 - cmd: go get -u github.com/shuLhan/go-bindata/... - cmd: go-bindata -o resource/metas.go -pkg resource -prefix ../aliyun-openapi-meta ../aliyun-openapi-meta/... - cmd: go build -ldflags "-X 'github.com/aliyun/aliyun-cli/cli.Version=%VERSION%'" -o C:\Users\appveyor\go\bin\aliyun.exe main/main.go diff --git a/CHANGELOG.md b/CHANGELOG.md index 44480c0dd..7b52ab019 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,10 @@ ### Master +### 3.0.84 + +- update: meta data + ### 3.0.83 - update: meta data diff --git a/Makefile b/Makefile index f5d6f531e..c03492928 100644 --- a/Makefile +++ b/Makefile @@ -1,4 +1,4 @@ -export VERSION=3.0.83 +export VERSION=3.0.84 export RELEASE_PATH="releases/aliyun-cli-${VERSION}" all: build diff --git a/README-CN.md b/README-CN.md index 6fdf59a87..aaab4637d 100644 --- a/README-CN.md +++ b/README-CN.md @@ -43,11 +43,11 @@ CLI 版本更改说明请参考 [CHANGELOG](./CHANGELOG.md) 阿里云CLI工具下载、解压后即可使用,支持Mac, Linux, Windows平台(x64版本)。您可以将解压的`aliyun`可执行文件移至`/usr/local/bin`目录下,或添加到`$PATH`中。 - 下载链接如下 (3.0.83): + 下载链接如下 (3.0.84): - - [Mac](https://aliyuncli.alicdn.com/aliyun-cli-macosx-3.0.83-amd64.tgz) - - [Linux](https://aliyuncli.alicdn.com/aliyun-cli-linux-3.0.83-amd64.tgz) - - [Windows (64 bit)](https://aliyuncli.alicdn.com/aliyun-cli-windows-3.0.83-amd64.zip) + - [Mac](https://aliyuncli.alicdn.com/aliyun-cli-macosx-3.0.84-amd64.tgz) + - [Linux](https://aliyuncli.alicdn.com/aliyun-cli-linux-3.0.84-amd64.tgz) + - [Windows (64 bit)](https://aliyuncli.alicdn.com/aliyun-cli-windows-3.0.84-amd64.zip) - **使用brew** diff --git a/README.md b/README.md index 85212b973..f72393e75 100644 --- a/README.md +++ b/README.md @@ -41,11 +41,11 @@ The release notes for the CLI can be found in the [CHANGELOG](./CHANGELOG.md) Download the installer, then extract the installer. You can move the extracted `aliyun` executable file to the `/usr/local/bin` directory or add it to the `$PATH`. - Download link: (3.0.83) + Download link: (3.0.84) - - [Mac](https://aliyuncli.alicdn.com/aliyun-cli-macosx-3.0.83-amd64.tgz) - - [Linux](https://aliyuncli.alicdn.com/aliyun-cli-linux-3.0.83-amd64.tgz) - - [Windows (64 bit)](https://aliyuncli.alicdn.com/aliyun-cli-windows-3.0.83-amd64.zip) + - [Mac](https://aliyuncli.alicdn.com/aliyun-cli-macosx-3.0.84-amd64.tgz) + - [Linux](https://aliyuncli.alicdn.com/aliyun-cli-linux-3.0.84-amd64.tgz) + - [Windows (64 bit)](https://aliyuncli.alicdn.com/aliyun-cli-windows-3.0.84-amd64.zip) - **Use brew** If you have installed `brew` in your computer, you can use it to install Alibaba Cloud CLI as following: diff --git a/aliyun-openapi-meta b/aliyun-openapi-meta index 1b76ed85f..dc687bf1e 160000 --- a/aliyun-openapi-meta +++ b/aliyun-openapi-meta @@ -1 +1 @@ -Subproject commit 1b76ed85f2a9923e4ccd7451bd0b498aafe19092 +Subproject commit dc687bf1eeed840adf69e13acdd3e744dd90fcde From 169077676db843dfae1df1bcc2b88d97940db646 Mon Sep 17 00:00:00 2001 From: Jackson Tian Date: Wed, 4 Aug 2021 17:52:01 +0800 Subject: [PATCH 5/8] print error logs to stderr --- cli/command.go | 4 +- cli/command_help.go | 4 +- cli/command_help_test.go | 14 +++++- cli/command_test.go | 19 +++++--- cli/completion_installer.go | 17 ++++---- cli/completion_installer_test.go | 18 +++++--- cli/context.go | 8 +++- cli/context_test.go | 19 +++++--- cli/errors_test.go | 6 ++- cli/output.go | 9 +++- cli/suggestion_test.go | 3 +- cli/version_test.go | 3 +- config/configuration_test.go | 6 ++- config/configure_delete.go | 16 +++---- config/configure_delete_test.go | 30 +++++++++---- config/configure_get.go | 74 ++++++++++++++++++-------------- config/configure_get_test.go | 18 +++++--- config/configure_test.go | 11 +++-- config/hello_test.go | 3 +- config/profile_test.go | 18 +++++--- main/main.go | 5 ++- openapi/commando_test.go | 15 ++++--- openapi/force_rpc_test.go | 6 ++- openapi/invoker_test.go | 3 +- openapi/output_filter_test.go | 6 ++- openapi/restful_test.go | 9 ++-- openapi/rpc_test.go | 3 +- 27 files changed, 221 insertions(+), 126 deletions(-) diff --git a/cli/command.go b/cli/command.go index d953795f6..b5f35d486 100644 --- a/cli/command.go +++ b/cli/command.go @@ -238,14 +238,14 @@ func (c *Command) executeInner(ctx *Context, args []string) error { } func (c *Command) processError(ctx *Context, err error) { - Errorf(ctx.Writer(), "ERROR: %s\n", err.Error()) + Errorf(ctx.Stderr(), "ERROR: %s\n", err.Error()) if e, ok := err.(SuggestibleError); ok { PrintSuggestions(ctx, i18n.GetLanguage(), e.GetSuggestions()) Exit(2) return } if e, ok := err.(ErrorWithTip); ok { - Noticef(ctx.Writer(), "\n%s\n", e.GetTip(i18n.GetLanguage())) + Noticef(ctx.Stderr(), "\n%s\n", e.GetTip(i18n.GetLanguage())) Exit(3) return } diff --git a/cli/command_help.go b/cli/command_help.go index cea3ae4b7..ba59883e6 100644 --- a/cli/command_help.go +++ b/cli/command_help.go @@ -77,8 +77,8 @@ func (c *Command) PrintFlags(ctx *Context) { } func (c *Command) PrintFailed(ctx *Context, err error, suggestion string) { - Errorf(ctx.Writer(), "ERROR: %v\n", err) - Printf(ctx.Writer(), "%s\n", suggestion) + Errorf(ctx.Stderr(), "ERROR: %v\n", err) + Printf(ctx.Stderr(), "%s\n", suggestion) } func (c *Command) PrintTail(ctx *Context) { diff --git a/cli/command_help_test.go b/cli/command_help_test.go index df35db280..f29e0d836 100644 --- a/cli/command_help_test.go +++ b/cli/command_help_test.go @@ -24,7 +24,8 @@ import ( func TestCmdPrint(t *testing.T) { w := new(bytes.Buffer) - ctx := NewCommandContext(w) + stderr := new(bytes.Buffer) + ctx := NewCommandContext(w, stderr) c := &Command{ Name: "aliyun", EnableUnknownFlag: true, @@ -44,19 +45,23 @@ func TestCmdPrint(t *testing.T) { //PrintUsage w.Reset() + stderr.Reset() c.PrintUsage(ctx) assert.Equal(t, "\nUsage:\n aliyun [subcmd]\n", w.String()) w.Reset() + stderr.Reset() c.Usage = "" assert.Empty(t, w.String()) //PrintSample w.Reset() + stderr.Reset() c.PrintSample(ctx) assert.Equal(t, "\nSample:\n aliyun oss\n", w.String()) //PrintSubCommands w.Reset() + stderr.Reset() subcmd := &Command{ Name: "oss", SuggestDistance: 2, @@ -72,24 +77,29 @@ func TestCmdPrint(t *testing.T) { //PrintFlags w.Reset() + stderr.Reset() c.PrintFlags(ctx) assert.Empty(t, w.String()) c.flags.flags = []*Flag{&Flag{Name: "output", Shorthand: 'o'}} w.Reset() + stderr.Reset() c.PrintFlags(ctx) assert.Equal(t, "\nFlags:\n", w.String()) w.Reset() + stderr.Reset() ctx.flags.flags = []*Flag{&Flag{Name: "output", Shorthand: 'o', Short: i18n.T("o test", "")}, &Flag{Name: "filter", Short: i18n.T("", "")}, &Flag{Name: "hidden", Hidden: true}} c.PrintFlags(ctx) assert.Equal(t, "\nFlags:\n --output,-o o test\n --filter \n", w.String()) //PrintFailed w.Reset() + stderr.Reset() c.PrintFailed(ctx, errors.New("you failed"), "come on again") - assert.Equal(t, "\x1b[1;31mERROR: you failed\n\x1b[0mcome on again\n", w.String()) + assert.Equal(t, "\x1b[1;31mERROR: you failed\n\x1b[0mcome on again\n", stderr.String()) //PrintTail w.Reset() + stderr.Reset() c.PrintTail(ctx) assert.Equal(t, "\nUse `aliyun --help` for more information.\n", w.String()) } diff --git a/cli/command_test.go b/cli/command_test.go index bc99d8ddb..2d5197e90 100644 --- a/cli/command_test.go +++ b/cli/command_test.go @@ -82,7 +82,8 @@ func TestCommand(t *testing.T) { //ExecuteComplete w := new(bytes.Buffer) - ctx := NewCommandContext(w) + stderr := new(bytes.Buffer) + ctx := NewCommandContext(w, stderr) ctx.completion = new(Completion) ctx.completion.Current = "--f" ctx.flags.flags = append(ctx.flags.flags, []*Flag{ @@ -192,7 +193,8 @@ func TestGetSubCommand(t *testing.T) { func TestExecute(t *testing.T) { buf := new(bytes.Buffer) - ctx := NewCommandContext(buf) + buf2 := new(bytes.Buffer) + ctx := NewCommandContext(buf, buf2) cmd := newAliyunCmd() subCmd := newTestCmd() @@ -204,7 +206,7 @@ func TestExecute(t *testing.T) { DisableExitCode() defer EnableExitCode() cmd.Execute(ctx, []string{}) - assert.Equal(t, "\x1b[1;31mERROR: 'test' is not a vaild command\n\x1b[0m", buf.String()) + assert.Equal(t, "\x1b[1;31mERROR: 'test' is not a vaild command\n\x1b[0m", buf2.String()) } func TestProcessError(t *testing.T) { @@ -212,17 +214,19 @@ func TestProcessError(t *testing.T) { defer EnableExitCode() cmd := newAliyunCmd() buf := new(bytes.Buffer) - ctx := NewCommandContext(buf) + buf2 := new(bytes.Buffer) + ctx := NewCommandContext(buf, buf2) e := errors.New("test error tip") err := NewErrorWithTip(e, "") cmd.processError(ctx, err) - assert.Equal(t, "\x1b[1;31mERROR: test error tip\n\x1b[0m\x1b[1;33m\n\n\x1b[0m", buf.String()) + assert.Equal(t, "\x1b[1;31mERROR: test error tip\n\x1b[0m\x1b[1;33m\n\n\x1b[0m", buf2.String()) } func TestExecuteHelp(t *testing.T) { cmd := newAliyunCmd() buf := new(bytes.Buffer) - ctx := NewCommandContext(buf) + buf2 := new(bytes.Buffer) + ctx := NewCommandContext(buf, buf2) cmd.Help = func(ctx *Context, args []string) error { fmt.Fprint(ctx.Writer(), "test execute help") return nil @@ -231,11 +235,12 @@ func TestExecuteHelp(t *testing.T) { assert.Equal(t, "test execute help", buf.String()) buf.Reset() + buf2.Reset() DisableExitCode() defer EnableExitCode() cmd.Help = func(ctx *Context, args []string) error { return errors.New("test help error") } cmd.executeHelp(ctx, nil) - assert.Equal(t, "\x1b[1;31mERROR: test help error\n\x1b[0m", buf.String()) + assert.Equal(t, "\x1b[1;31mERROR: test help error\n\x1b[0m", buf2.String()) } diff --git a/cli/completion_installer.go b/cli/completion_installer.go index 0ee7c083d..dc13ef3ff 100644 --- a/cli/completion_installer.go +++ b/cli/completion_installer.go @@ -15,7 +15,6 @@ package cli import ( "fmt" - "io" "github.com/aliyun/aliyun-cli/i18n" ) @@ -44,9 +43,9 @@ func NewAutoCompleteCommand() *Command { // fmt.Printf("zshInstaller: %s\n", f) //} if uninstallFlag.IsAssigned() { - uninstallCompletion(ctx.Writer(), "aliyun") + uninstallCompletion(ctx, "aliyun") } else { - installCompletion(ctx.Writer(), "aliyun") + installCompletion(ctx, "aliyun") } return nil }, @@ -55,32 +54,32 @@ func NewAutoCompleteCommand() *Command { return cmd } -func installCompletion(w io.Writer, cmd string) { +func installCompletion(ctx *Context, cmd string) { bin, err := getBinaryPath() if err != nil { - Errorf(w, "can't get binary path %s", err) + Errorf(ctx.Stderr(), "can't get binary path %s", err) return } for _, i := range completionInstallers() { err := i.Install(cmd, bin) if err != nil { - Errorf(w, "install completion failed for %s %s\n", bin, err) + Errorf(ctx.Stderr(), "install completion failed for %s %s\n", bin, err) } } } -func uninstallCompletion(w io.Writer, cmd string) { +func uninstallCompletion(ctx *Context, cmd string) { bin, err := hookGetBinaryPath(getBinaryPath)() if err != nil { - Errorf(w, "can't get binary path %s", err) + Errorf(ctx.Stderr(), "can't get binary path %s", err) return } for _, i := range completionInstallers() { err := i.Uninstall(cmd, bin) if err != nil { - Errorf(w, "uninstall %s failed\n", err) + Errorf(ctx.Stderr(), "uninstall %s failed\n", err) } } } diff --git a/cli/completion_installer_test.go b/cli/completion_installer_test.go index 00fd77196..16e071eed 100644 --- a/cli/completion_installer_test.go +++ b/cli/completion_installer_test.go @@ -101,7 +101,9 @@ func TestCompletionInstallers(t *testing.T) { } func TestCompletion(t *testing.T) { w := new(bytes.Buffer) - installCompletion(w, "is this a cmd?") + stderr := new(bytes.Buffer) + ctx := NewCommandContext(w, stderr) + installCompletion(ctx, "is this a cmd?") assert.Empty(t, w.String()) } @@ -114,9 +116,9 @@ func TestNewAutoCompleteCommand(t *testing.T) { Usage: "auto-completion [--uninstall]", Run: func(ctx *Context, args []string) error { if uninstallFlag.IsAssigned() { - uninstallCompletion(ctx.Writer(), "aliyun") + uninstallCompletion(ctx, "aliyun") } else { - installCompletion(ctx.Writer(), "aliyun") + installCompletion(ctx, "aliyun") } return nil }, @@ -125,14 +127,14 @@ func TestNewAutoCompleteCommand(t *testing.T) { cmd := NewAutoCompleteCommand() assert.ObjectsAreEqualValues(excmd, cmd) w := new(bytes.Buffer) - ctx := NewCommandContext(w) + stderr := new(bytes.Buffer) + ctx := NewCommandContext(w, stderr) err := cmd.Run(ctx, []string{}) assert.Nil(t, err) assert.Empty(t, w.String()) } func TestUninstallCompletion(t *testing.T) { - orighookGetBinaryPath := hookGetBinaryPath defer func() { hookGetBinaryPath = orighookGetBinaryPath @@ -144,6 +146,8 @@ func TestUninstallCompletion(t *testing.T) { } w := new(bytes.Buffer) - uninstallCompletion(w, "aliyun") - assert.Equal(t, "\x1b[1;31mcan't get binary path path error\x1b[0m", w.String()) + stderr := new(bytes.Buffer) + ctx := NewCommandContext(w, stderr) + uninstallCompletion(ctx, "aliyun") + assert.Equal(t, "\x1b[1;31mcan't get binary path path error\x1b[0m", stderr.String()) } diff --git a/cli/context.go b/cli/context.go index b60058956..26ec0cbc6 100644 --- a/cli/context.go +++ b/cli/context.go @@ -44,13 +44,15 @@ type Context struct { command *Command completion *Completion writer io.Writer + stderr io.Writer } -func NewCommandContext(w io.Writer) *Context { +func NewCommandContext(w io.Writer, stderr io.Writer) *Context { return &Context{ flags: NewFlagSet(), unknownFlags: nil, writer: w, + stderr: stderr, } } @@ -78,6 +80,10 @@ func (ctx *Context) Writer() io.Writer { return ctx.writer } +func (ctx *Context) Stderr() io.Writer { + return ctx.stderr +} + func (ctx *Context) UnknownFlags() *FlagSet { return ctx.unknownFlags } diff --git a/cli/context_test.go b/cli/context_test.go index c915a25b5..368515fa1 100644 --- a/cli/context_test.go +++ b/cli/context_test.go @@ -41,18 +41,21 @@ func TestNewHelpFlag(t *testing.T) { func TestContext_SetUnknownFlags(t *testing.T) { w := new(bytes.Buffer) - ctx := NewCommandContext(w) + stderr := new(bytes.Buffer) + ctx := NewCommandContext(w, stderr) ctx.SetUnknownFlags(NewFlagSet()) assert.NotNil(t, ctx.unknownFlags) } func TestNewCommandContext(t *testing.T) { w := new(bytes.Buffer) - ctx := NewCommandContext(w) + stderr := new(bytes.Buffer) + ctx := NewCommandContext(w, stderr) assert.Equal(t, &Context{ flags: NewFlagSet(), unknownFlags: nil, writer: w, + stderr: stderr, help: false, command: nil, completion: nil, @@ -61,7 +64,8 @@ func TestNewCommandContext(t *testing.T) { func TestCtx(t *testing.T) { w := new(bytes.Buffer) - ctx := NewCommandContext(w) + stderr := new(bytes.Buffer) + ctx := NewCommandContext(w, stderr) assert.False(t, ctx.IsHelp()) assert.Nil(t, ctx.Command()) assert.Nil(t, ctx.Completion()) @@ -80,7 +84,8 @@ func TestCtx(t *testing.T) { func TestCheckFlags(t *testing.T) { w := new(bytes.Buffer) - ctx := NewCommandContext(w) + stderr := new(bytes.Buffer) + ctx := NewCommandContext(w, stderr) ctx.flags.AddByName("MrX") assert.Nil(t, ctx.CheckFlags()) ctx.flags.flags[0].Required = true @@ -96,7 +101,8 @@ func TestCheckFlags(t *testing.T) { func TestDetectFlag(t *testing.T) { w := new(bytes.Buffer) - ctx := NewCommandContext(w) + stderr := new(bytes.Buffer) + ctx := NewCommandContext(w, stderr) ctx.flags.AddByName("MrX") f, err := ctx.detectFlag("mrx") assert.Nil(t, f) @@ -112,7 +118,8 @@ func TestDetectFlag(t *testing.T) { func TestDetectFlagByShorthand(t *testing.T) { w := new(bytes.Buffer) - ctx := NewCommandContext(w) + stderr := new(bytes.Buffer) + ctx := NewCommandContext(w, stderr) ctx.flags.Add(&Flag{Name: "profile", Shorthand: 'p'}) f, err := ctx.detectFlagByShorthand('p') assert.Equal(t, &Flag{Name: "profile", Shorthand: 'p', formation: "-p"}, f) diff --git a/cli/errors_test.go b/cli/errors_test.go index b5f48562e..c9519cd9f 100644 --- a/cli/errors_test.go +++ b/cli/errors_test.go @@ -33,7 +33,8 @@ func TestErrorWithTip(t *testing.T) { func TestInvalidCommandError(t *testing.T) { w := new(bytes.Buffer) - ctx := NewCommandContext(w) + stderr := new(bytes.Buffer) + ctx := NewCommandContext(w, stderr) err := NewInvalidCommandError("MrX", ctx) e, ok := err.(*InvalidCommandError) assert.True(t, ok) @@ -44,7 +45,8 @@ func TestInvalidCommandError(t *testing.T) { func TestInvalidFlagError(t *testing.T) { w := new(bytes.Buffer) - ctx := NewCommandContext(w) + stderr := new(bytes.Buffer) + ctx := NewCommandContext(w, stderr) err := NewInvalidFlagError("MrX", ctx) e, ok := err.(*InvalidFlagError) assert.True(t, ok) diff --git a/cli/output.go b/cli/output.go index 193feccf8..f6babaf38 100644 --- a/cli/output.go +++ b/cli/output.go @@ -20,14 +20,19 @@ import ( ) var ( - defaultOutput = NewOutput() - defaultWriter = os.Stdout + defaultOutput = NewOutput() + defaultWriter = os.Stdout + defaultStderrWriter = os.Stderr ) func DefaultWriter() io.Writer { return defaultWriter } +func DefaultStderrWriter() io.Writer { + return defaultStderrWriter +} + func Print(w io.Writer, a ...interface{}) (n int, err error) { return defaultOutput.Print(w, a...) } diff --git a/cli/suggestion_test.go b/cli/suggestion_test.go index 0257efd9e..999e06525 100644 --- a/cli/suggestion_test.go +++ b/cli/suggestion_test.go @@ -39,7 +39,8 @@ func TestApply(t *testing.T) { func TestPrintSuggestions(t *testing.T) { w := new(bytes.Buffer) - ctx := NewCommandContext(w) + stderr := new(bytes.Buffer) + ctx := NewCommandContext(w, stderr) PrintSuggestions(ctx, "en", []string{"hello", "nihao"}) assert.Equal(t, "\x1b[1;33m\nDid you mean:\n\x1b[0m\x1b[1;33m hello\n\x1b[0m\x1b[1;33m nihao\n\x1b[0m", w.String()) diff --git a/cli/version_test.go b/cli/version_test.go index fc4efaced..4eba04465 100644 --- a/cli/version_test.go +++ b/cli/version_test.go @@ -39,7 +39,8 @@ func TestNewVersionCommand(t *testing.T) { assert.ObjectsAreEqualValues(excmd, cmd) w := new(bytes.Buffer) - ctx := NewCommandContext(w) + stderr := new(bytes.Buffer) + ctx := NewCommandContext(w, stderr) err := cmd.Run(ctx, []string{}) assert.Nil(t, err) assert.Equal(t, Version+"\n", w.String()) diff --git a/config/configuration_test.go b/config/configuration_test.go index ef0b95f2e..fee74d31c 100644 --- a/config/configuration_test.go +++ b/config/configuration_test.go @@ -73,7 +73,8 @@ func TestConfiguration(t *testing.T) { //GetCurrentProfile w := new(bytes.Buffer) - ctx := cli.NewCommandContext(w) + stderr := new(bytes.Buffer) + ctx := cli.NewCommandContext(w, stderr) AddFlags(ctx.Flags()) os.Setenv("ACCESS_KEY_ID", "") @@ -265,7 +266,8 @@ func TestLoadProfileWithContext(t *testing.T) { } } w := new(bytes.Buffer) - ctx := cli.NewCommandContext(w) + stderr := new(bytes.Buffer) + ctx := cli.NewCommandContext(w, stderr) AddFlags(ctx.Flags()) //testcase 1 diff --git a/config/configure_delete.go b/config/configure_delete.go index d30f6f219..bdde5de0c 100644 --- a/config/configure_delete.go +++ b/config/configure_delete.go @@ -14,8 +14,6 @@ package config import ( - "io" - "github.com/aliyun/aliyun-cli/cli" "github.com/aliyun/aliyun-cli/i18n" ) @@ -28,21 +26,21 @@ func NewConfigureDeleteCommand() *cli.Command { Run: func(c *cli.Context, args []string) error { profileName, ok := ProfileFlag(c.Flags()).GetValue() if !ok { - cli.Errorf(c.Writer(), "missing --profile \n") - cli.Noticef(c.Writer(), "\nusage:\n aliyun configure delete --profile \n") + cli.Errorf(c.Stderr(), "missing --profile \n") + cli.Noticef(c.Stderr(), "\nusage:\n aliyun configure delete --profile \n") return nil } - doConfigureDelete(c.Writer(), profileName) + doConfigureDelete(c, profileName) return nil }, } return cmd } -func doConfigureDelete(w io.Writer, profileName string) { +func doConfigureDelete(ctx *cli.Context, profileName string) { conf, err := hookLoadConfiguration(LoadConfiguration)(GetConfigPath() + "/" + configFile) if err != nil { - cli.Errorf(w, "ERROR: load configure failed: %v\n", err) + cli.Errorf(ctx.Stderr(), "ERROR: load configure failed: %v\n", err) } deleted := false r := make([]Profile, 0) @@ -55,7 +53,7 @@ func doConfigureDelete(w io.Writer, profileName string) { } if !deleted { - cli.Errorf(w, "Error: configuration profile `%s` not found\n", profileName) + cli.Errorf(ctx.Stderr(), "Error: configuration profile `%s` not found\n", profileName) return } @@ -70,6 +68,6 @@ func doConfigureDelete(w io.Writer, profileName string) { err = hookSaveConfiguration(SaveConfiguration)(conf) if err != nil { - cli.Errorf(w, "Error: save configuration failed %s\n", err) + cli.Errorf(ctx.Stderr(), "Error: save configuration failed %s\n", err) } } diff --git a/config/configure_delete_test.go b/config/configure_delete_test.go index a1ff15aea..16db1a6d3 100644 --- a/config/configure_delete_test.go +++ b/config/configure_delete_test.go @@ -18,11 +18,15 @@ import ( "errors" "testing" + "github.com/aliyun/aliyun-cli/cli" "github.com/stretchr/testify/assert" ) func TestDoConfigureDelete(t *testing.T) { w := new(bytes.Buffer) + stderr := new(bytes.Buffer) + ctx := cli.NewCommandContext(w, stderr) + originhook := hookLoadConfiguration originhookSave := hookSaveConfiguration defer func() { @@ -33,7 +37,9 @@ func TestDoConfigureDelete(t *testing.T) { //testcase 1 hookLoadConfiguration = func(fn func(path string) (*Configuration, error)) func(path string) (*Configuration, error) { return func(path string) (*Configuration, error) { - return &Configuration{CurrentProfile: "default", Profiles: []Profile{Profile{Name: "default", Mode: AK, AccessKeyId: "default_aliyun_access_key_id", AccessKeySecret: "default_aliyun_access_key_secret", OutputFormat: "json"}, Profile{Name: "bbb", Mode: AK, AccessKeyId: "sdf", AccessKeySecret: "ddf", OutputFormat: "json"}}}, nil + return &Configuration{CurrentProfile: "default", Profiles: []Profile{ + Profile{Name: "default", Mode: AK, AccessKeyId: "default_aliyun_access_key_id", AccessKeySecret: "default_aliyun_access_key_secret", OutputFormat: "json"}, + Profile{Name: "bbb", Mode: AK, AccessKeyId: "sdf", AccessKeySecret: "ddf", OutputFormat: "json"}}}, nil } } hookSaveConfiguration = func(fn func(config *Configuration) error) func(config *Configuration) error { @@ -41,13 +47,15 @@ func TestDoConfigureDelete(t *testing.T) { return nil } } - doConfigureDelete(w, "bbb") + + doConfigureDelete(ctx, "bbb") assert.Empty(t, w.String()) //testcase 2 w.Reset() - doConfigureDelete(w, "aaa") - assert.Equal(t, "\x1b[1;31mError: configuration profile `aaa` not found\n\x1b[0m", w.String()) + stderr.Reset() + doConfigureDelete(ctx, "aaa") + assert.Equal(t, "\x1b[1;31mError: configuration profile `aaa` not found\n\x1b[0m", stderr.String()) //testcase 3 hookLoadConfiguration = func(fn func(path string) (*Configuration, error)) func(path string) (*Configuration, error) { @@ -57,13 +65,16 @@ func TestDoConfigureDelete(t *testing.T) { } w.Reset() - doConfigureDelete(w, "bbb") - assert.Equal(t, "\x1b[1;31mERROR: load configure failed: error\n\x1b[0m\x1b[1;31mError: configuration profile `bbb` not found\n\x1b[0m", w.String()) + stderr.Reset() + doConfigureDelete(ctx, "bbb") + assert.Equal(t, "\x1b[1;31mERROR: load configure failed: error\n\x1b[0m\x1b[1;31mError: configuration profile `bbb` not found\n\x1b[0m", stderr.String()) //testcase 4 hookLoadConfiguration = func(fn func(path string) (*Configuration, error)) func(path string) (*Configuration, error) { return func(path string) (*Configuration, error) { - return &Configuration{CurrentProfile: "default", Profiles: []Profile{Profile{Name: "default", Mode: AK, AccessKeyId: "default_aliyun_access_key_id", AccessKeySecret: "default_aliyun_access_key_secret", OutputFormat: "json"}, Profile{Name: "bbb", Mode: AK, AccessKeyId: "sdf", AccessKeySecret: "ddf", OutputFormat: "json"}}}, nil + return &Configuration{CurrentProfile: "default", Profiles: []Profile{ + Profile{Name: "default", Mode: AK, AccessKeyId: "default_aliyun_access_key_id", AccessKeySecret: "default_aliyun_access_key_secret", OutputFormat: "json"}, + Profile{Name: "bbb", Mode: AK, AccessKeyId: "sdf", AccessKeySecret: "ddf", OutputFormat: "json"}}}, nil } } hookSaveConfiguration = func(fn func(config *Configuration) error) func(config *Configuration) error { @@ -72,6 +83,7 @@ func TestDoConfigureDelete(t *testing.T) { } } w.Reset() - doConfigureDelete(w, "bbb") - assert.Equal(t, "\x1b[1;31mError: save configuration failed save error\n\x1b[0m", w.String()) + stderr.Reset() + doConfigureDelete(ctx, "bbb") + assert.Equal(t, "\x1b[1;31mError: save configuration failed save error\n\x1b[0m", stderr.String()) } diff --git a/config/configure_get.go b/config/configure_get.go index 2fd4f1d7b..0c94afab5 100644 --- a/config/configure_get.go +++ b/config/configure_get.go @@ -50,7 +50,9 @@ func NewConfigureGetCommand() *cli.Command { func doConfigureGet(c *cli.Context, args []string) { config, err := hookLoadConfiguration(LoadConfiguration)(GetConfigPath() + "/" + configFile) if err != nil { - cli.Errorf(c.Writer(), "load configuration failed %s", err) + cli.Errorf(c.Stderr(), "load configuration failed %s", err) + cli.Printf(c.Stderr(), "\n") + return } profile := config.GetCurrentProfile(c) @@ -58,46 +60,52 @@ func doConfigureGet(c *cli.Context, args []string) { if pn, ok := ProfileFlag(c.Flags()).GetValue(); ok { profile, ok = config.GetProfile(pn) if !ok { - cli.Errorf(c.Writer(), "profile %s not found!", pn) + cli.Errorf(c.Stderr(), "profile %s not found!", pn) + cli.Printf(c.Stderr(), "\n") + return } } if len(args) == 0 && !reflect.DeepEqual(profile, Profile{}) { data, err := json.MarshalIndent(profile, "", "\t") if err != nil { - cli.Printf(c.Writer(), "ERROR:"+err.Error()) + cli.Printf(c.Stderr(), "ERROR:"+err.Error()) + cli.Printf(c.Stderr(), "\n") + return } cli.Println(c.Writer(), string(data)) - } else { - for _, arg := range args { - switch arg { - case ProfileFlagName: - cli.Printf(c.Writer(), "profile=%s\n", profile.Name) - case ModeFlagName: - cli.Printf(c.Writer(), "mode=%s\n", profile.Mode) - case AccessKeyIdFlagName: - cli.Printf(c.Writer(), "access-key-id=%s\n", MosaicString(profile.AccessKeyId, 3)) - case AccessKeySecretFlagName: - cli.Printf(c.Writer(), "access-key-secret=%s\n", MosaicString(profile.AccessKeySecret, 3)) - case StsTokenFlagName: - cli.Printf(c.Writer(), "sts-token=%s\n", profile.StsToken) - case StsRegionFlagName: - cli.Printf(c.Writer(), "sts-region=%s\n", profile.StsRegion) - case RamRoleNameFlagName: - cli.Printf(c.Writer(), "ram-role-name=%s\n", profile.RamRoleName) - case RamRoleArnFlagName: - cli.Printf(c.Writer(), "ram-role-arn=%s\n", profile.RamRoleArn) - case RoleSessionNameFlagName: - cli.Printf(c.Writer(), "role-session-name=%s\n", profile.RoleSessionName) - case KeyPairNameFlagName: - cli.Printf(c.Writer(), "key-pair-name=%s\n", profile.KeyPairName) - case PrivateKeyFlagName: - cli.Printf(c.Writer(), "private-key=%s\n", profile.PrivateKey) - case RegionFlagName: - cli.Printf(c.Writer(), profile.RegionId) - case LanguageFlagName: - cli.Printf(c.Writer(), "language=%s\n", profile.Language) - } + cli.Printf(c.Writer(), "\n") + return + } + + for _, arg := range args { + switch arg { + case ProfileFlagName: + cli.Printf(c.Writer(), "profile=%s\n", profile.Name) + case ModeFlagName: + cli.Printf(c.Writer(), "mode=%s\n", profile.Mode) + case AccessKeyIdFlagName: + cli.Printf(c.Writer(), "access-key-id=%s\n", MosaicString(profile.AccessKeyId, 3)) + case AccessKeySecretFlagName: + cli.Printf(c.Writer(), "access-key-secret=%s\n", MosaicString(profile.AccessKeySecret, 3)) + case StsTokenFlagName: + cli.Printf(c.Writer(), "sts-token=%s\n", profile.StsToken) + case StsRegionFlagName: + cli.Printf(c.Writer(), "sts-region=%s\n", profile.StsRegion) + case RamRoleNameFlagName: + cli.Printf(c.Writer(), "ram-role-name=%s\n", profile.RamRoleName) + case RamRoleArnFlagName: + cli.Printf(c.Writer(), "ram-role-arn=%s\n", profile.RamRoleArn) + case RoleSessionNameFlagName: + cli.Printf(c.Writer(), "role-session-name=%s\n", profile.RoleSessionName) + case KeyPairNameFlagName: + cli.Printf(c.Writer(), "key-pair-name=%s\n", profile.KeyPairName) + case PrivateKeyFlagName: + cli.Printf(c.Writer(), "private-key=%s\n", profile.PrivateKey) + case RegionFlagName: + cli.Printf(c.Writer(), profile.RegionId) + case LanguageFlagName: + cli.Printf(c.Writer(), "language=%s\n", profile.Language) } } diff --git a/config/configure_get_test.go b/config/configure_get_test.go index 6549df0a8..a3093b709 100644 --- a/config/configure_get_test.go +++ b/config/configure_get_test.go @@ -26,7 +26,8 @@ import ( func TestDoConfigureGet(t *testing.T) { w := new(bytes.Buffer) - ctx := cli.NewCommandContext(w) + stderr := new(bytes.Buffer) + ctx := cli.NewCommandContext(w, stderr) AddFlags(ctx.Flags()) originhook := hookLoadConfiguration defer func() { @@ -43,27 +44,32 @@ func TestDoConfigureGet(t *testing.T) { os.Setenv("ACCESS_KEY_ID", "") os.Setenv("ACCESS_KEY_SECRET", "") doConfigureGet(ctx, []string{}) - assert.Equal(t, "\x1b[1;31mload configuration failed error\x1b[0m\n", w.String()) + assert.Equal(t, "\x1b[1;31mload configuration failed error\x1b[0m\n", stderr.String()) //testcase 2 hookLoadConfiguration = func(fn func(path string) (*Configuration, error)) func(path string) (*Configuration, error) { return func(path string) (*Configuration, error) { - return &Configuration{CurrentProfile: "default", Profiles: []Profile{Profile{Name: "default", Mode: AK, AccessKeyId: "default_aliyun_access_key_id", AccessKeySecret: "default_aliyun_access_key_secret", OutputFormat: "json"}, Profile{Name: "aaa", Mode: AK, AccessKeyId: "sdf", AccessKeySecret: "ddf", OutputFormat: "json"}}}, nil + return &Configuration{CurrentProfile: "default", Profiles: []Profile{ + Profile{Name: "default", Mode: AK, AccessKeyId: "default_aliyun_access_key_id", AccessKeySecret: "default_aliyun_access_key_secret", OutputFormat: "json"}, Profile{Name: "aaa", Mode: AK, AccessKeyId: "sdf", AccessKeySecret: "ddf", OutputFormat: "json"}}}, nil } } w.Reset() + stderr.Reset() ctx.Flags().Get("profile").SetAssigned(true) ctx.Flags().Get("profile").SetValue("") doConfigureGet(ctx, []string{}) - assert.Equal(t, "\x1b[1;31mprofile not found!\x1b[0m\n", w.String()) + assert.Equal(t, "\x1b[1;31mprofile not found!\x1b[0m\n", stderr.String()) //testcase 3 hookLoadConfiguration = func(fn func(path string) (*Configuration, error)) func(path string) (*Configuration, error) { return func(path string) (*Configuration, error) { - return &Configuration{CurrentProfile: "default", Profiles: []Profile{Profile{Name: "default", Mode: AK, AccessKeyId: "default_aliyun_access_key_id", AccessKeySecret: "default_aliyun_access_key_secret", OutputFormat: "json"}, Profile{Name: "aaa", Mode: AK, AccessKeyId: "sdf", AccessKeySecret: "ddf", OutputFormat: "json"}}}, nil + return &Configuration{CurrentProfile: "default", Profiles: []Profile{ + Profile{Name: "default", Mode: AK, AccessKeyId: "default_aliyun_access_key_id", AccessKeySecret: "default_aliyun_access_key_secret", OutputFormat: "json"}, + Profile{Name: "aaa", Mode: AK, AccessKeyId: "sdf", AccessKeySecret: "ddf", OutputFormat: "json"}}}, nil } } w.Reset() + stderr.Reset() ctx.Flags().Flags()[1].SetAssigned(false) doConfigureGet(ctx, []string{"profile", "mode", "access-key-id", "access-key-secret", "sts-token", "ram-role-name", "ram-role-arn", "role-session-name", "private-key", "key-pair-name", "region", "language"}) assert.Equal(t, "profile=default\nmode=AK\naccess-key-id=*************************_id\naccess-key-secret=*****************************ret\nsts-token=\nram-role-name=\nram-role-arn=\nrole-session-name=\nprivate-key=\nkey-pair-name=\nlanguage=\n\n", w.String()) @@ -75,6 +81,7 @@ func TestDoConfigureGet(t *testing.T) { } } w.Reset() + stderr.Reset() ctx.Flags().Get("profile").SetAssigned(true) ctx.Flags().Get("profile").SetValue("default") doConfigureGet(ctx, []string{}) @@ -87,6 +94,7 @@ func TestDoConfigureGet(t *testing.T) { } } w.Reset() + stderr.Reset() ctx.Flags().Get("profile").SetAssigned(true) ctx.Flags().Get("profile").SetValue("default") doConfigureGet(ctx, []string{"mode", "profile", "access-key-id", "language"}) diff --git a/config/configure_test.go b/config/configure_test.go index 1d01f5d3b..364d2e380 100644 --- a/config/configure_test.go +++ b/config/configure_test.go @@ -62,7 +62,8 @@ func TestNewConfigureCommand(t *testing.T) { //testcase w := new(bytes.Buffer) - ctx := cli.NewCommandContext(w) + stderr := new(bytes.Buffer) + ctx := cli.NewCommandContext(w, stderr) AddFlags(ctx.Flags()) //testcase @@ -84,9 +85,10 @@ func TestNewConfigureCommand(t *testing.T) { //testcase w.Reset() + stderr.Reset() err = configureDelete.Run(ctx, []string{"delete"}) assert.Nil(t, err) - assert.Equal(t, "\x1b[1;31mmissing --profile \n\x1b[0m\x1b[1;33m\nusage:\n aliyun configure delete --profile \n\x1b[0m", w.String()) + assert.Equal(t, "\x1b[1;31mmissing --profile \n\x1b[0m\x1b[1;33m\nusage:\n aliyun configure delete --profile \n\x1b[0m", stderr.String()) //testcase cmd := NewConfigureCommand() @@ -95,12 +97,14 @@ func TestNewConfigureCommand(t *testing.T) { //testcase w.Reset() + stderr.Reset() err = cmd.Run(ctx, []string{"configure"}) assert.Empty(t, w.String()) assert.NotNil(t, err) //testcase w.Reset() + stderr.Reset() err = cmd.Run(ctx, []string{}) assert.Nil(t, err) assert.Equal(t, "Configuring profile 'default' in 'AK' authenticate mode...\nAccess Key Id [*************************_id]: Access Key Secret [*****************************ret]: Default Region Id []: Default Output Format [json]: json (Only support json)\nDefault Language [zh|en] : Saving profile[default] ...Done.\n-----------------------------------------------\n!!! Configure Failed please configure again !!!\n-----------------------------------------------\ndefault RegionId is empty! run `aliyun configure` first\n-----------------------------------------------\n!!! Configure Failed please configure again !!!\n-----------------------------------------------\n", w.String()) @@ -142,7 +146,8 @@ func TestDoConfigure(t *testing.T) { } } w := new(bytes.Buffer) - ctx := cli.NewCommandContext(w) + stderr := new(bytes.Buffer) + ctx := cli.NewCommandContext(w, stderr) AddFlags(ctx.Flags()) err := doConfigure(ctx, "profile", "AK") assert.Nil(t, err) diff --git a/config/hello_test.go b/config/hello_test.go index 6b59b9a75..98c38c81e 100644 --- a/config/hello_test.go +++ b/config/hello_test.go @@ -28,7 +28,8 @@ func TestDoHello(t *testing.T) { os.Setenv("ALIBABA_CLOUD_VENDOR", "cli_test_VendorTest") w := new(bytes.Buffer) - ctx := cli.NewCommandContext(w) + stderr := new(bytes.Buffer) + ctx := cli.NewCommandContext(w, stderr) ctx.Flags().AddByName("skip-secure-verify") profile := NewProfile("default") diff --git a/config/profile_test.go b/config/profile_test.go index 7bc886174..f7af2c4d3 100644 --- a/config/profile_test.go +++ b/config/profile_test.go @@ -152,7 +152,8 @@ func TestGetParent(t *testing.T) { } func TestOverwriteWithFlags(t *testing.T) { buf := new(bytes.Buffer) - ctx := cli.NewCommandContext(buf) + stderr := new(bytes.Buffer) + ctx := cli.NewCommandContext(buf, stderr) AddFlags(ctx.Flags()) resetEnv() actual := newProfile() @@ -216,7 +217,8 @@ func TestOverwriteWithFlags(t *testing.T) { } func TestOverwriteWithFlagsWithRegionIDEnv(t *testing.T) { buf := new(bytes.Buffer) - ctx := cli.NewCommandContext(buf) + stderr := new(bytes.Buffer) + ctx := cli.NewCommandContext(buf, stderr) AddFlags(ctx.Flags()) resetEnv() @@ -246,7 +248,8 @@ func TestOverwriteWithFlagsWithRegionIDEnv(t *testing.T) { func TestOverwriteWithFlagsWithStsTokenEnv(t *testing.T) { resetEnv() buf := new(bytes.Buffer) - ctx := cli.NewCommandContext(buf) + stderr := new(bytes.Buffer) + ctx := cli.NewCommandContext(buf, stderr) AddFlags(ctx.Flags()) actual := newProfile() exp := newProfile() @@ -261,7 +264,8 @@ func TestOverwriteWithFlagsWithStsTokenEnv(t *testing.T) { func TestOverwriteWithFlagsWithAccessKeySecretEnv(t *testing.T) { buf := new(bytes.Buffer) - ctx := cli.NewCommandContext(buf) + buf2 := new(bytes.Buffer) + ctx := cli.NewCommandContext(buf, buf2) AddFlags(ctx.Flags()) resetEnv() @@ -291,7 +295,8 @@ func TestOverwriteWithFlagsWithAccessKeySecretEnv(t *testing.T) { func TestOverwriteWithFlagsWithAccessKeyIDEnv(t *testing.T) { buf := new(bytes.Buffer) - ctx := cli.NewCommandContext(buf) + buf2 := new(bytes.Buffer) + ctx := cli.NewCommandContext(buf, buf2) AddFlags(ctx.Flags()) resetEnv() @@ -334,7 +339,8 @@ func resetEnv() { func TestGetClient(t *testing.T) { actual := newProfile() buf := new(bytes.Buffer) - ctx := cli.NewCommandContext(buf) + buf2 := new(bytes.Buffer) + ctx := cli.NewCommandContext(buf, buf2) AddFlags(ctx.Flags()) actual.RetryCount = 2 diff --git a/main/main.go b/main/main.go index 74ee14047..aa4e109f0 100644 --- a/main/main.go +++ b/main/main.go @@ -26,11 +26,12 @@ import ( func main() { cli.PlatformCompatible() writer := cli.DefaultWriter() + stderr := cli.DefaultStderrWriter() // load current configuration profile, err := config.LoadCurrentProfile() if err != nil { - cli.Errorf(writer, "ERROR: load current configuration failed %s", err) + cli.Errorf(stderr, "ERROR: load current configuration failed %s", err) return } @@ -54,7 +55,7 @@ func main() { commando := openapi.NewCommando(writer, profile) commando.InitWithCommand(rootCmd) - ctx := cli.NewCommandContext(writer) + ctx := cli.NewCommandContext(writer, stderr) ctx.EnterCommand(rootCmd) ctx.SetCompletion(cli.ParseCompletionForShell()) diff --git a/openapi/commando_test.go b/openapi/commando_test.go index d1f5d62e5..c259d5c37 100644 --- a/openapi/commando_test.go +++ b/openapi/commando_test.go @@ -29,7 +29,8 @@ import ( func Test_main(t *testing.T) { w := new(bytes.Buffer) - ctx := cli.NewCommandContext(w) + stderr := new(bytes.Buffer) + ctx := cli.NewCommandContext(w, stderr) profile := config.Profile{ Language: "en", RegionId: "cn-hangzhou", @@ -120,7 +121,8 @@ func Test_main(t *testing.T) { func Test_processInvoke(t *testing.T) { w := new(bytes.Buffer) - ctx := cli.NewCommandContext(w) + stderr := new(bytes.Buffer) + ctx := cli.NewCommandContext(w, stderr) cmd := &cli.Command{} cmd.EnableUnknownFlag = true @@ -216,7 +218,8 @@ func Test_processInvoke(t *testing.T) { func Test_help(t *testing.T) { w := new(bytes.Buffer) - ctx := cli.NewCommandContext(w) + stderr := new(bytes.Buffer) + ctx := cli.NewCommandContext(w, stderr) cmd := &cli.Command{} cmd.EnableUnknownFlag = true @@ -254,7 +257,8 @@ func Test_help(t *testing.T) { func Test_complete(t *testing.T) { w := new(bytes.Buffer) - ctx := cli.NewCommandContext(w) + stderr := new(bytes.Buffer) + ctx := cli.NewCommandContext(w, stderr) cmd := &cli.Command{} cmd.EnableUnknownFlag = true @@ -312,7 +316,8 @@ func TestCreateInvoker(t *testing.T) { commando := NewCommando(w, profile) tempWriter := new(bytes.Buffer) - ctx := cli.NewCommandContext(tempWriter) + tempStderrWriter := new(bytes.Buffer) + ctx := cli.NewCommandContext(tempWriter, tempStderrWriter) config.AddFlags(ctx.Flags()) AddFlags(ctx.Flags()) ctx.Flags().Get("force").SetAssigned(true) diff --git a/openapi/force_rpc_test.go b/openapi/force_rpc_test.go index fa75e012b..31b9508e0 100644 --- a/openapi/force_rpc_test.go +++ b/openapi/force_rpc_test.go @@ -15,12 +15,13 @@ package openapi import ( "bufio" + "testing" + "github.com/aliyun/alibaba-cloud-sdk-go/sdk" "github.com/aliyun/alibaba-cloud-sdk-go/sdk/requests" "github.com/aliyun/aliyun-cli/cli" "github.com/aliyun/aliyun-cli/config" "github.com/stretchr/testify/assert" - "testing" ) func TestForceRpcInvoker_Prepare(t *testing.T) { @@ -32,7 +33,8 @@ func TestForceRpcInvoker_Prepare(t *testing.T) { } a.BasicInvoker.request.QueryParams = make(map[string]string) w := new(bufio.Writer) - ctx := cli.NewCommandContext(w) + stderr := new(bufio.Writer) + ctx := cli.NewCommandContext(w, stderr) cmd := config.NewConfigureCommand() cmd.EnableUnknownFlag = true ctx.EnterCommand(cmd) diff --git a/openapi/invoker_test.go b/openapi/invoker_test.go index 07f547963..6c92ec042 100644 --- a/openapi/invoker_test.go +++ b/openapi/invoker_test.go @@ -35,7 +35,8 @@ func TestBasicInvoker_Init(t *testing.T) { assert.Nil(t, req) w := new(bytes.Buffer) - ctx := cli.NewCommandContext(w) + stderr := new(bytes.Buffer) + ctx := cli.NewCommandContext(w, stderr) regionflag := config.NewRegionFlag() regionflag.SetAssigned(true) diff --git a/openapi/output_filter_test.go b/openapi/output_filter_test.go index a96e8fa1f..993a3d540 100644 --- a/openapi/output_filter_test.go +++ b/openapi/output_filter_test.go @@ -23,7 +23,8 @@ import ( func TestNewTableOutputFilter(t *testing.T) { w := new(bufio.Writer) - ctx := cli.NewCommandContext(w) + stderr := new(bufio.Writer) + ctx := cli.NewCommandContext(w, stderr) outflag := NewOutputFlag() ctx.Flags().Add(outflag) out := GetOutputFilter(ctx) @@ -67,7 +68,8 @@ func TestNewTableOutputFilter(t *testing.T) { func TestTableOutputFilter_FormatTable(t *testing.T) { w := new(bufio.Writer) - ctx := cli.NewCommandContext(w) + stderr := new(bufio.Writer) + ctx := cli.NewCommandContext(w, stderr) ctx.Flags().Add(NewOutputFlag()) out := NewTableOutputFilter(ctx) tableout, ok := out.(*TableOutputFilter) diff --git a/openapi/restful_test.go b/openapi/restful_test.go index 00b03b34c..fda19997e 100644 --- a/openapi/restful_test.go +++ b/openapi/restful_test.go @@ -35,7 +35,8 @@ func TestRestfulInvoker_Prepare(t *testing.T) { a.BasicInvoker.request.RegionId = "cn-hangzhou" a.BasicInvoker.request.Content = []byte("{") w := new(bufio.Writer) - ctx := cli.NewCommandContext(w) + stderr := new(bufio.Writer) + ctx := cli.NewCommandContext(w, stderr) bodyflag := NewBodyFlag() bodyflag.SetAssigned(true) @@ -80,7 +81,8 @@ func TestRestfulInvoker_Prepare(t *testing.T) { api, _ := library.GetApi("cs", "2015-12-15", "DescribeClusterUserKubeconfig") a.api = &api w = new(bufio.Writer) - ctx = cli.NewCommandContext(w) + stderr = new(bufio.Writer) + ctx = cli.NewCommandContext(w, stderr) ctx.SetUnknownFlags(cli.NewFlagSet()) ctx.Flags().Add(NewBodyFlag()) ctx.Flags().Add(NewSecureFlag()) @@ -113,7 +115,8 @@ func TestRestfulInvoker_Call(t *testing.T) { func Test_checkRestfulMethod(t *testing.T) { w := new(bufio.Writer) - ctx := cli.NewCommandContext(w) + stderr := new(bufio.Writer) + ctx := cli.NewCommandContext(w, stderr) methodOrPath := "get" pathPattern := "/user" ok, method, path, err := checkRestfulMethod(ctx, methodOrPath, "") diff --git a/openapi/rpc_test.go b/openapi/rpc_test.go index 583e5c341..29a76b641 100644 --- a/openapi/rpc_test.go +++ b/openapi/rpc_test.go @@ -39,7 +39,8 @@ func TestRpcInvoker_Prepare(t *testing.T) { }, } w := new(bufio.Writer) - ctx := cli.NewCommandContext(w) + stderr := new(bufio.Writer) + ctx := cli.NewCommandContext(w, stderr) secureflag := NewSecureFlag() secureflag.SetAssigned(true) From 8c7cd9e9668b3504bee7641c4880df466b413650 Mon Sep 17 00:00:00 2001 From: Alibaba Cloud SDK Date: Wed, 4 Aug 2021 16:50:59 +0000 Subject: [PATCH 6/8] Release version v3.0.85 --- .appveyor.yml | 2 +- CHANGELOG.md | 4 ++++ Makefile | 2 +- README-CN.md | 8 ++++---- README.md | 8 ++++---- aliyun-openapi-meta | 2 +- 6 files changed, 15 insertions(+), 11 deletions(-) diff --git a/.appveyor.yml b/.appveyor.yml index ca0094f2d..fd78c35cf 100644 --- a/.appveyor.yml +++ b/.appveyor.yml @@ -9,7 +9,7 @@ install: # by default, all script lines are interpreted as batch - cmd: git clone -q --branch=master https://github.com/aliyun/aliyun-openapi-meta.git C:\Users\appveyor\go\src\github.com\aliyun\aliyun-openapi-meta - cmd: set path=%path%;C:\Users\appveyor\go\bin - - cmd: set VERSION=3.0.84 + - cmd: set VERSION=3.0.85 - cmd: go get -u github.com/shuLhan/go-bindata/... - cmd: go-bindata -o resource/metas.go -pkg resource -prefix ../aliyun-openapi-meta ../aliyun-openapi-meta/... - cmd: go build -ldflags "-X 'github.com/aliyun/aliyun-cli/cli.Version=%VERSION%'" -o C:\Users\appveyor\go\bin\aliyun.exe main/main.go diff --git a/CHANGELOG.md b/CHANGELOG.md index 7b52ab019..cabc505b4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,10 @@ ### Master +### 3.0.85 + +- update: meta data + ### 3.0.84 - update: meta data diff --git a/Makefile b/Makefile index c03492928..26c57d644 100644 --- a/Makefile +++ b/Makefile @@ -1,4 +1,4 @@ -export VERSION=3.0.84 +export VERSION=3.0.85 export RELEASE_PATH="releases/aliyun-cli-${VERSION}" all: build diff --git a/README-CN.md b/README-CN.md index aaab4637d..65ee488d9 100644 --- a/README-CN.md +++ b/README-CN.md @@ -43,11 +43,11 @@ CLI 版本更改说明请参考 [CHANGELOG](./CHANGELOG.md) 阿里云CLI工具下载、解压后即可使用,支持Mac, Linux, Windows平台(x64版本)。您可以将解压的`aliyun`可执行文件移至`/usr/local/bin`目录下,或添加到`$PATH`中。 - 下载链接如下 (3.0.84): + 下载链接如下 (3.0.85): - - [Mac](https://aliyuncli.alicdn.com/aliyun-cli-macosx-3.0.84-amd64.tgz) - - [Linux](https://aliyuncli.alicdn.com/aliyun-cli-linux-3.0.84-amd64.tgz) - - [Windows (64 bit)](https://aliyuncli.alicdn.com/aliyun-cli-windows-3.0.84-amd64.zip) + - [Mac](https://aliyuncli.alicdn.com/aliyun-cli-macosx-3.0.85-amd64.tgz) + - [Linux](https://aliyuncli.alicdn.com/aliyun-cli-linux-3.0.85-amd64.tgz) + - [Windows (64 bit)](https://aliyuncli.alicdn.com/aliyun-cli-windows-3.0.85-amd64.zip) - **使用brew** diff --git a/README.md b/README.md index f72393e75..947838bec 100644 --- a/README.md +++ b/README.md @@ -41,11 +41,11 @@ The release notes for the CLI can be found in the [CHANGELOG](./CHANGELOG.md) Download the installer, then extract the installer. You can move the extracted `aliyun` executable file to the `/usr/local/bin` directory or add it to the `$PATH`. - Download link: (3.0.84) + Download link: (3.0.85) - - [Mac](https://aliyuncli.alicdn.com/aliyun-cli-macosx-3.0.84-amd64.tgz) - - [Linux](https://aliyuncli.alicdn.com/aliyun-cli-linux-3.0.84-amd64.tgz) - - [Windows (64 bit)](https://aliyuncli.alicdn.com/aliyun-cli-windows-3.0.84-amd64.zip) + - [Mac](https://aliyuncli.alicdn.com/aliyun-cli-macosx-3.0.85-amd64.tgz) + - [Linux](https://aliyuncli.alicdn.com/aliyun-cli-linux-3.0.85-amd64.tgz) + - [Windows (64 bit)](https://aliyuncli.alicdn.com/aliyun-cli-windows-3.0.85-amd64.zip) - **Use brew** If you have installed `brew` in your computer, you can use it to install Alibaba Cloud CLI as following: diff --git a/aliyun-openapi-meta b/aliyun-openapi-meta index dc687bf1e..8436317eb 160000 --- a/aliyun-openapi-meta +++ b/aliyun-openapi-meta @@ -1 +1 @@ -Subproject commit dc687bf1eeed840adf69e13acdd3e744dd90fcde +Subproject commit 8436317eba9e16043916b54af49638c0c6a5eb18 From 7d4c2a5196a329d80ba05d3dd22d6c2fba31430d Mon Sep 17 00:00:00 2001 From: Jackson Tian Date: Wed, 4 Aug 2021 23:57:02 +0800 Subject: [PATCH 7/8] improve ci for submodule --- .appveyor.yml | 5 ++--- .travis.yml | 1 + 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.appveyor.yml b/.appveyor.yml index fd78c35cf..131d2d806 100644 --- a/.appveyor.yml +++ b/.appveyor.yml @@ -7,11 +7,11 @@ clone_folder: C:\Users\appveyor\go\src\github.com\aliyun\aliyun-cli # scripts that run after cloning repository install: # by default, all script lines are interpreted as batch - - cmd: git clone -q --branch=master https://github.com/aliyun/aliyun-openapi-meta.git C:\Users\appveyor\go\src\github.com\aliyun\aliyun-openapi-meta + - cmd: git submodule update --init --recursive - cmd: set path=%path%;C:\Users\appveyor\go\bin - cmd: set VERSION=3.0.85 - cmd: go get -u github.com/shuLhan/go-bindata/... - - cmd: go-bindata -o resource/metas.go -pkg resource -prefix ../aliyun-openapi-meta ../aliyun-openapi-meta/... + - cmd: go-bindata -o resource/metas.go -pkg resource ./aliyun-openapi-meta/... - cmd: go build -ldflags "-X 'github.com/aliyun/aliyun-cli/cli.Version=%VERSION%'" -o C:\Users\appveyor\go\bin\aliyun.exe main/main.go # build platform, i.e. x86, x64, Any CPU. This setting is optional. @@ -28,4 +28,3 @@ test_script: $client.DownloadFile('https://github.com/stedolan/jq/releases/download/jq-1.6/jq-win64.exe', 'C:/go/bin/jq.exe') if (-not $env:ACCESS_KEY_ID.length -eq 0 -and -not $env:ACCESS_KEY_SECRET.length -eq 0){./integration/ecs_test.PS1} - \ No newline at end of file diff --git a/.travis.yml b/.travis.yml index 5f4b8f514..8ff14b177 100644 --- a/.travis.yml +++ b/.travis.yml @@ -13,6 +13,7 @@ before_install: - sudo apt-get install -y jq install: + - git submodule update --init --recursive - make build - sudo cp out/aliyun /usr/local/bin From e70bc4ccf617168a07bda346a500ed2dfb231351 Mon Sep 17 00:00:00 2001 From: Jackson Tian Date: Thu, 5 Aug 2021 09:26:03 +0800 Subject: [PATCH 8/8] Add env variables support for CI --- .github/workflows/go.yml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/.github/workflows/go.yml b/.github/workflows/go.yml index 064d9b378..f0e2cd1d2 100644 --- a/.github/workflows/go.yml +++ b/.github/workflows/go.yml @@ -10,6 +10,10 @@ jobs: build: runs-on: ubuntu-latest + env: + ACCESS_KEY_ID: ${{ secrets.ACCESS_KEY_ID }} + ACCESS_KEY_SECRET: ${{ secrets.ACCESS_KEY_SECRET }} + REGION_ID: ${{ secrets.REGION_ID }} steps: - uses: actions/checkout@v2 # fetch submodule for aliyun-openapi-meta