diff --git a/cmd/climc/shell/compute/secgroups.go b/cmd/climc/shell/compute/secgroups.go index 6f2e8ad229..1fdc219b05 100644 --- a/cmd/climc/shell/compute/secgroups.go +++ b/cmd/climc/shell/compute/secgroups.go @@ -35,4 +35,5 @@ func init() { cmd.Perform("uncache-secgroup", &options.SecurityGroupUncacheSecurityGroup{}) cmd.Perform("purge", &options.SecgroupIdOptions{}) cmd.Perform("change-owner", &options.SecgroupChangeOwnerOptions{}) + cmd.Perform("import-rules", &options.SecgroupImportRulesOptions{}) } diff --git a/cmd/climc/shell/helper.go b/cmd/climc/shell/helper.go index cd9c225532..fcd5994daf 100644 --- a/cmd/climc/shell/helper.go +++ b/cmd/climc/shell/helper.go @@ -288,7 +288,10 @@ type IPerformOpt interface { func (cmd ResourceCmd) PerformWithKeyword(keyword, action string, args IPerformOpt) { man := cmd.manager callback := func(s *mcclient.ClientSession, args IPerformOpt) error { - params := jsonutils.Marshal(args) // .Params() + params, err := args.Params() + if err != nil { + return err + } ret, err := man.(modulebase.Manager).PerformAction(s, args.GetId(), action, params) if err != nil { return err diff --git a/pkg/apis/compute/secgroup.go b/pkg/apis/compute/secgroup.go index 7eacd47248..4c08d9643d 100644 --- a/pkg/apis/compute/secgroup.go +++ b/pkg/apis/compute/secgroup.go @@ -287,3 +287,7 @@ type SecurityGroupCloneInput struct { Name string Description string } + +type SecgroupImportRulesInput struct { + Rules []SSecgroupRuleCreateInput `json:"rules"` +} diff --git a/pkg/compute/models/secgroups.go b/pkg/compute/models/secgroups.go index e0834b531d..384a78c0c3 100644 --- a/pkg/compute/models/secgroups.go +++ b/pkg/compute/models/secgroups.go @@ -477,8 +477,8 @@ func (manager *SSecurityGroupManager) ValidateCreateData( input.Status = api.SECGROUP_STATUS_READY - for i, rule := range input.Rules { - err = rule.Check() + for i := range input.Rules { + err = input.Rules[i].Check() if err != nil { return input, httperrors.NewInputParameterError("rule %d is invalid: %s", i, err) } @@ -1216,3 +1216,34 @@ func (sg *SSecurityGroup) GetUsages() []db.IUsage { &usage, } } + +func (self *SSecurityGroup) AllowPerformImportRules(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, data jsonutils.JSONObject) bool { + return self.IsOwner(userCred) || db.IsAdminAllowPerform(userCred, self, "import-rules") +} + +func (self *SSecurityGroup) PerformImportRules(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, input api.SecgroupImportRulesInput) (jsonutils.JSONObject, error) { + for i := range input.Rules { + err := input.Rules[i].Check() + if err != nil { + return nil, httperrors.NewInputParameterError("rule %d is invalid: %s", i, err) + } + } + for _, r := range input.Rules { + rule := &SSecurityGroupRule{ + Priority: int64(r.Priority), + Protocol: r.Protocol, + Ports: r.Ports, + Direction: r.Direction, + CIDR: r.CIDR, + Action: r.Action, + Description: r.Description, + } + rule.SecgroupId = self.Id + + err := SecurityGroupRuleManager.TableSpec().Insert(ctx, rule) + if err != nil { + return nil, httperrors.NewGeneralError(errors.Wrapf(err, "Insert rule")) + } + } + return nil, nil +} diff --git a/pkg/mcclient/options/secgroup.go b/pkg/mcclient/options/secgroup.go index 80ff156b25..6cb411ec9a 100644 --- a/pkg/mcclient/options/secgroup.go +++ b/pkg/mcclient/options/secgroup.go @@ -15,6 +15,10 @@ package options import ( + "fmt" + "strconv" + "strings" + "yunion.io/x/jsonutils" "yunion.io/x/pkg/errors" "yunion.io/x/pkg/util/secrules" @@ -125,3 +129,36 @@ type SecgroupChangeOwnerOptions struct { SecgroupIdOptions apis.ProjectizedResourceInput } + +type SecgroupImportRulesOptions struct { + SecgroupIdOptions + + RULE []string `help:"rule pattern: rule|priority eg: in:allow any 1"` +} + +func (opts *SecgroupImportRulesOptions) Params() (jsonutils.JSONObject, error) { + rules := jsonutils.NewArray() + for _, rule := range opts.RULE { + priority := 1 + var r *secrules.SecurityRule = nil + var err error + info := strings.Split(rule, "|") + switch len(info) { + case 1: + case 2: + priority, err = strconv.Atoi(info[1]) + if err != nil { + return nil, errors.Wrapf(err, "Parse rule %s priority %s", rule, info[1]) + } + default: + return nil, fmt.Errorf("invalid rule %s", rule) + } + r, err = secrules.ParseSecurityRule(info[0]) + if err != nil { + return nil, errors.Wrapf(err, "ParseSecurityRule(%s)", rule) + } + r.Priority = priority + rules.Add(jsonutils.Marshal(r)) + } + return jsonutils.Marshal(map[string]*jsonutils.JSONArray{"rules": rules}), nil +}