From f2f8cbb38819797e58739fdb355e6f008d122341 Mon Sep 17 00:00:00 2001 From: Qiu Jian Date: Thu, 14 Mar 2019 13:17:32 +0800 Subject: [PATCH 1/3] feature: add cryptool for convenience --- cmd/cryptool/main.go | 89 +++++++++++++++++++++++++++++++++++ cmd/cryptool/shell/decrypt.go | 24 ++++++++++ 2 files changed, 113 insertions(+) create mode 100644 cmd/cryptool/main.go create mode 100644 cmd/cryptool/shell/decrypt.go diff --git a/cmd/cryptool/main.go b/cmd/cryptool/main.go new file mode 100644 index 0000000000..9e6c3fa730 --- /dev/null +++ b/cmd/cryptool/main.go @@ -0,0 +1,89 @@ +package main + +import ( + "fmt" + "os" + + "yunion.io/x/log" + "yunion.io/x/structarg" + + "yunion.io/x/onecloud/pkg/util/shellutils" + + _ "yunion.io/x/onecloud/cmd/cryptool/shell" +) + +type BaseOptions struct { + Debug bool `help:"debug mode"` + Help bool `help:"Show help"` + SUBCOMMAND string `help:"aliyuncli subcommand" subcommand:"true"` +} + +func getSubcommandParser() (*structarg.ArgumentParser, error) { + parse, e := structarg.NewArgumentParser(&BaseOptions{}, + "cryptool", + "Command-line cryptography tools.", + `See "cryptool help COMMAND" for help on a specific command.`) + + if e != nil { + return nil, e + } + + subcmd := parse.GetSubcommand() + if subcmd == nil { + return nil, fmt.Errorf("No subcommand argument.") + } + type HelpOptions struct { + SUBCOMMAND string `help:"sub-command name"` + } + shellutils.R(&HelpOptions{}, "help", "Show help of a subcommand", func(args *HelpOptions) error { + helpstr, e := subcmd.SubHelpString(args.SUBCOMMAND) + if e != nil { + return e + } else { + fmt.Print(helpstr) + return nil + } + }) + for _, v := range shellutils.CommandTable { + _, e := subcmd.AddSubParser(v.Options, v.Command, v.Desc, v.Callback) + if e != nil { + return nil, e + } + } + return parse, nil +} + +func showErrorAndExit(e error) { + log.Errorf("%s", e) + os.Exit(1) +} + +func main() { + parser, e := getSubcommandParser() + if e != nil { + showErrorAndExit(e) + } + e = parser.ParseArgs(os.Args[1:], false) + options := parser.Options().(*BaseOptions) + + if options.Help { + fmt.Print(parser.HelpString()) + } else { + subcmd := parser.GetSubcommand() + subparser := subcmd.GetSubParser() + if e != nil { + if subparser != nil { + fmt.Print(subparser.Usage()) + } else { + fmt.Print(parser.Usage()) + } + showErrorAndExit(e) + } else { + suboptions := subparser.Options() + e = subcmd.Invoke(suboptions) + if e != nil { + showErrorAndExit(e) + } + } + } +} diff --git a/cmd/cryptool/shell/decrypt.go b/cmd/cryptool/shell/decrypt.go new file mode 100644 index 0000000000..65326615b2 --- /dev/null +++ b/cmd/cryptool/shell/decrypt.go @@ -0,0 +1,24 @@ +package shell + +import ( + "fmt" + + "yunion.io/x/pkg/utils" + + "yunion.io/x/onecloud/pkg/util/shellutils" +) + +func init() { + type DecryptSecretOptions struct { + KEY string `help:"secret key"` + SECRET string `help:"secret to descrypt"` + } + shellutils.R(&DecryptSecretOptions{}, "decrypt", "Decrypt", func(args *DecryptSecretOptions) error { + text, err := utils.DescryptAESBase64(args.KEY, args.SECRET) + if err != nil { + return err + } + fmt.Println(text) + return nil + }) +} From b7d57461971cbe6e83fb4581de828c1ed23993df Mon Sep 17 00:00:00 2001 From: Qiu Jian Date: Sat, 16 Mar 2019 20:24:24 +0800 Subject: [PATCH 2/3] feature: cloudaccount add options field to store additional options, such billing_report_bucket for AWS and balance_key for Azure --- cmd/climc/shell/cloudaccounts.go | 134 +++++++++++++++++++++++--- pkg/compute/models/cloudaccounts.go | 23 ++++- pkg/mcclient/options/cloudaccounts.go | 48 +++++++++ 3 files changed, 189 insertions(+), 16 deletions(-) diff --git a/cmd/climc/shell/cloudaccounts.go b/cmd/climc/shell/cloudaccounts.go index 3f87b8028e..812fc76a19 100644 --- a/cmd/climc/shell/cloudaccounts.go +++ b/cmd/climc/shell/cloudaccounts.go @@ -103,8 +103,15 @@ func init() { }) R(&options.SAWSCloudAccountCreateOptions{}, "cloud-account-create-aws", "Create an AWS cloud account", func(s *mcclient.ClientSession, args *options.SAWSCloudAccountCreateOptions) error { - params := jsonutils.Marshal(args) - params.(*jsonutils.JSONDict).Add(jsonutils.NewString("Aws"), "provider") + params := jsonutils.Marshal(args).(*jsonutils.JSONDict) + options := jsonutils.NewDict() + if len(args.OptionsBillingReportBucket) > 0 { + options.Add(jsonutils.NewString(args.OptionsBillingReportBucket), "billing_report_bucket") + } + if options.Size() > 0 { + params.Add(options, "options") + } + params.Add(jsonutils.NewString("Aws"), "provider") result, err := modules.Cloudaccounts.Create(s, params) if err != nil { return err @@ -147,24 +154,121 @@ func init() { Desc string `help:"Description"` } R(&CloudaccountUpdateOptions{}, "cloud-account-update", "Update a cloud account", func(s *mcclient.ClientSession, args *CloudaccountUpdateOptions) error { - params := jsonutils.NewDict() - if len(args.Name) > 0 { - params.Add(jsonutils.NewString(args.Name), "name") + return fmt.Errorf("obsolete, please try cloud-account-update-xxx, where xxx is vmware, aliyun, azure, qcloud, aws, openstack, huawei etc.") + }) + + R(&options.SVMwareCloudAccountUpdateOptions{}, "cloud-account-update-vmware", "update a vmware cloud account", func(s *mcclient.ClientSession, args *options.SVMwareCloudAccountUpdateOptions) error { + params := jsonutils.Marshal(args).(*jsonutils.JSONDict) + if params.Size() == 0 { + return InvalidUpdateError() } - if len(args.AccessUrl) > 0 { - params.Add(jsonutils.NewString(args.AccessUrl), "access_url") + result, err := modules.Cloudaccounts.Update(s, args.ID, params) + if err != nil { + return err } - if len(args.BalanceKey) > 0 { - params.Add(jsonutils.NewString(args.BalanceKey), "balance_key") - } else if args.RemoveBalanceKey { - params.Add(jsonutils.NewString(""), "balance_key") + printObject(result) + return nil + }) + + R(&options.SAliyunCloudAccountUpdateOptions{}, "cloud-account-update-aliyun", "update an Aliyun cloud account", func(s *mcclient.ClientSession, args *options.SAliyunCloudAccountUpdateOptions) error { + params := jsonutils.Marshal(args).(*jsonutils.JSONDict) + if params.Size() == 0 { + return InvalidUpdateError() } - if args.SyncIntervalSeconds > 0 { - params.Add(jsonutils.NewInt(int64(args.SyncIntervalSeconds)), "sync_interval_seconds") + result, err := modules.Cloudaccounts.Update(s, args.ID, params) + if err != nil { + return err } - if len(args.Desc) > 0 { - params.Add(jsonutils.NewString(args.Desc), "description") + printObject(result) + return nil + }) + + R(&options.SAzureCloudAccountUpdateOptions{}, "cloud-account-update-azure", "update an Azure cloud account", func(s *mcclient.ClientSession, args *options.SAzureCloudAccountUpdateOptions) error { + params := jsonutils.Marshal(args).(*jsonutils.JSONDict) + + options := jsonutils.NewDict() + if len(args.OptionsBalanceKey) > 0 { + options.Add(jsonutils.NewString(args.OptionsBalanceKey), "balance_key") } + if options.Size() > 0 { + params.Add(options, "options") + } + removeOptions := make([]string, 0) + if args.RemoveOptionsBalanceKey { + removeOptions = append(removeOptions, "balance_key") + } + if len(removeOptions) > 0 { + params.Add(jsonutils.NewStringArray(removeOptions), "remove_options") + } + + if params.Size() == 0 { + return InvalidUpdateError() + } + result, err := modules.Cloudaccounts.Update(s, args.ID, params) + if err != nil { + return err + } + printObject(result) + return nil + }) + + R(&options.SQcloudCloudAccountUpdateOptions{}, "cloud-account-update-qcloud", "update a Tencent cloud account", func(s *mcclient.ClientSession, args *options.SQcloudCloudAccountUpdateOptions) error { + params := jsonutils.Marshal(args).(*jsonutils.JSONDict) + if params.Size() == 0 { + return InvalidUpdateError() + } + result, err := modules.Cloudaccounts.Update(s, args.ID, params) + if err != nil { + return err + } + printObject(result) + return nil + }) + + R(&options.SAWSCloudAccountUpdateOptions{}, "cloud-account-update-aws", "update an AWS cloud account", func(s *mcclient.ClientSession, args *options.SAWSCloudAccountUpdateOptions) error { + params := jsonutils.Marshal(args).(*jsonutils.JSONDict) + + options := jsonutils.NewDict() + if len(args.OptionsBillingReportBucket) > 0 { + options.Add(jsonutils.NewString(args.OptionsBillingReportBucket), "billing_report_bucket") + } + if options.Size() > 0 { + params.Add(options, "options") + } + removeOptions := make([]string, 0) + if args.RemoveOptionsBillingReportBucket { + removeOptions = append(removeOptions, "billing_report_bucket") + } + if len(removeOptions) > 0 { + params.Add(jsonutils.NewStringArray(removeOptions), "remove_options") + } + + if params.Size() == 0 { + return InvalidUpdateError() + } + result, err := modules.Cloudaccounts.Update(s, args.ID, params) + if err != nil { + return err + } + printObject(result) + return nil + }) + + R(&options.SOpenStackCloudAccountUpdateOptions{}, "cloud-account-update-openstack", "update an AWS cloud account", func(s *mcclient.ClientSession, args *options.SOpenStackCloudAccountUpdateOptions) error { + params := jsonutils.Marshal(args).(*jsonutils.JSONDict) + if params.Size() == 0 { + return InvalidUpdateError() + } + result, err := modules.Cloudaccounts.Update(s, args.ID, params) + if err != nil { + return err + } + printObject(result) + return nil + }) + + R(&options.SHuaweiCloudAccountUpdateOptions{}, "cloud-account-update-huawei", "update a Huawei cloud account", func(s *mcclient.ClientSession, args *options.SHuaweiCloudAccountUpdateOptions) error { + params := jsonutils.Marshal(args).(*jsonutils.JSONDict) if params.Size() == 0 { return InvalidUpdateError() } diff --git a/pkg/compute/models/cloudaccounts.go b/pkg/compute/models/cloudaccounts.go index 7f9090168c..8291d5ed29 100644 --- a/pkg/compute/models/cloudaccounts.go +++ b/pkg/compute/models/cloudaccounts.go @@ -53,7 +53,7 @@ type SCloudaccount struct { Account string `width:"128" charset:"ascii" nullable:"false" list:"admin" create:"admin_required"` // Column(VARCHAR(64, charset='ascii'), nullable=False) Secret string `width:"256" charset:"ascii" nullable:"false" list:"admin" create:"admin_required"` // Column(VARCHAR(256, charset='ascii'), nullable=False) - BalanceKey string `width:"256" charset:"ascii" nullable:"true" list:"admin" update:"admin" create:"admin_optional"` + // BalanceKey string `width:"256" charset:"ascii" nullable:"true" list:"admin" update:"admin" create:"admin_optional"` IsPublicCloud *bool `nullable:"false" get:"user" create:"optional" list:"user" default:"true"` IsOnPremise bool `nullable:"false" get:"user" create:"optional" list:"user" default:"false"` @@ -72,6 +72,8 @@ type SCloudaccount struct { Version string `width:"32" charset:"ascii" nullable:"true" list:"admin"` // Column(VARCHAR(32, charset='ascii'), nullable=True) Sysinfo jsonutils.JSONObject `get:"admin"` // Column(JSONEncodedDict, nullable=True) + + Options *jsonutils.JSONDict `get:"admin" create:"admin_optional" update:"admin"` } func (self *SCloudaccountManager) AllowListItems(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject) bool { @@ -179,6 +181,25 @@ func (self *SCloudaccount) ValidateUpdateData(ctx context.Context, userCred mccl } data.Set("sync_interval_seconds", jsonutils.NewInt(syncIntervalSecs)) } + if data.Contains("options") || data.Contains("remove_options") { + toRemoveKeys, _ := data.GetArray("remove_options") + removes := make([]string, 0) + if len(toRemoveKeys) > 0 { + for i := range toRemoveKeys { + key, _ := toRemoveKeys[i].GetString() + removes = append(removes, key) + } + } + var optionsJson *jsonutils.JSONDict + if self.Options != nil { + optionsJson = self.Options.CopyExcludes(removes...) + } else { + optionsJson = jsonutils.NewDict() + } + toUpdate, _ := data.Get("options") + optionsJson.Update(toUpdate) + data.Set("options", optionsJson) + } return self.SEnabledStatusStandaloneResourceBase.ValidateUpdateData(ctx, userCred, query, data) } diff --git a/pkg/mcclient/options/cloudaccounts.go b/pkg/mcclient/options/cloudaccounts.go index 95d29219e6..1e6c285c8e 100644 --- a/pkg/mcclient/options/cloudaccounts.go +++ b/pkg/mcclient/options/cloudaccounts.go @@ -91,6 +91,8 @@ type SQcloudCloudAccountCreateOptions struct { type SAWSCloudAccountCreateOptions struct { SCloudAccountCreateBaseOptions SAccessKeyCredentialWithEnvironment + + OptionsBillingReportBucket string `help:"bucket that stores billing report" json:"-"` } type SOpenStackCloudAccountCreateOptions struct { @@ -143,3 +145,49 @@ type SHuaweiCloudAccountUpdateCredentialOptions struct { SCloudAccountUpdateCredentialBaseOptions SAccessKeyCredential } + +// update + +type SCloudAccountUpdateBaseOptions struct { + ID string `help:"ID or Name of cloud account" json:"-"` + Name string `help:"New name to update"` + + SyncIntervalSeconds int `help:"auto synchornize interval in seconds"` + AutoCreateProject *bool `help:"automatically create local project for new remote project"` + + Desc string `help:"Description" json:"description" token:"desc"` +} + +type SVMwareCloudAccountUpdateOptions struct { + SCloudAccountUpdateBaseOptions +} + +type SAliyunCloudAccountUpdateOptions struct { + SCloudAccountUpdateBaseOptions +} + +type SAzureCloudAccountUpdateOptions struct { + SCloudAccountUpdateBaseOptions + + OptionsBalanceKey string `help:"update cloud balance account key, such as Azure EA key" json:"-"` + RemoveOptionsBalanceKey bool `help:"remove cloud blance account key" json:"-"` +} + +type SQcloudCloudAccountUpdateOptions struct { + SCloudAccountUpdateBaseOptions +} + +type SAWSCloudAccountUpdateOptions struct { + SCloudAccountUpdateBaseOptions + + OptionsBillingReportBucket string `help:"update AWS S3 bucket that stores account billing report" json:"-"` + RemoveOptionsBillingReportBucket bool `help:"remote AWS S3 bucket that stores account billing report" json:"-"` +} + +type SOpenStackCloudAccountUpdateOptions struct { + SCloudAccountUpdateBaseOptions +} + +type SHuaweiCloudAccountUpdateOptions struct { + SCloudAccountUpdateBaseOptions +} From bd94daec0ca83069d376e6ca1f5e10a4e4ac72b6 Mon Sep 17 00:00:00 2001 From: Qiu Jian Date: Sat, 16 Mar 2019 20:29:04 +0800 Subject: [PATCH 3/3] minor updates --- pkg/compute/models/cloudaccounts.go | 20 +++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) diff --git a/pkg/compute/models/cloudaccounts.go b/pkg/compute/models/cloudaccounts.go index 8291d5ed29..d514765bdc 100644 --- a/pkg/compute/models/cloudaccounts.go +++ b/pkg/compute/models/cloudaccounts.go @@ -182,22 +182,24 @@ func (self *SCloudaccount) ValidateUpdateData(ctx context.Context, userCred mccl data.Set("sync_interval_seconds", jsonutils.NewInt(syncIntervalSecs)) } if data.Contains("options") || data.Contains("remove_options") { - toRemoveKeys, _ := data.GetArray("remove_options") - removes := make([]string, 0) - if len(toRemoveKeys) > 0 { - for i := range toRemoveKeys { - key, _ := toRemoveKeys[i].GetString() - removes = append(removes, key) - } - } var optionsJson *jsonutils.JSONDict if self.Options != nil { + toRemoveKeys, _ := data.GetArray("remove_options") + removes := make([]string, 0) + if len(toRemoveKeys) > 0 { + for i := range toRemoveKeys { + key, _ := toRemoveKeys[i].GetString() + removes = append(removes, key) + } + } optionsJson = self.Options.CopyExcludes(removes...) } else { optionsJson = jsonutils.NewDict() } toUpdate, _ := data.Get("options") - optionsJson.Update(toUpdate) + if toUpdate != nil { + optionsJson.Update(toUpdate) + } data.Set("options", optionsJson) } return self.SEnabledStatusStandaloneResourceBase.ValidateUpdateData(ctx, userCred, query, data)