diff --git a/.gitignore b/.gitignore index 9f48329..0ad7583 100644 --- a/.gitignore +++ b/.gitignore @@ -7,3 +7,4 @@ BUILDROOT RPMS SOURCES SRPMS +.idea diff --git a/connect_cmd.go b/connect_cmd.go index ee65cec..0e7515e 100644 --- a/connect_cmd.go +++ b/connect_cmd.go @@ -56,6 +56,7 @@ func beforeConnectAction(ctx *cli.Context) error { password := ctx.String("password") organization := ctx.String("organization") activationKeys := ctx.StringSlice("activation-key") + contentTemplates := ctx.StringSlice("content-template") if len(activationKeys) > 0 { if username != "" { @@ -66,6 +67,11 @@ func beforeConnectAction(ctx *cli.Context) error { } } + if len(contentTemplates) > 0 && organization == "" { + err := fmt.Errorf("--organization is required, when --content-template is used") + return cli.Exit(err, 1) + } + // When machine-readable format is used, then additional requirements have to be met if uiSettings.isMachineReadable { if username == "" || password == "" { diff --git a/main.go b/main.go index 18fd2e2..25e45c5 100644 --- a/main.go +++ b/main.go @@ -157,6 +157,11 @@ func main() { Usage: "register with `KEY`", Aliases: []string{"a"}, }, + &cli.StringSliceFlag{ + Name: "content-template", + Usage: "register with `CONTENT_TEMPLATE", + Aliases: []string{"c"}, + }, &cli.StringFlag{ Name: "server", Hidden: true, diff --git a/rhsm.go b/rhsm.go index b0024e2..239615c 100644 --- a/rhsm.go +++ b/rhsm.go @@ -85,7 +85,7 @@ func unpackOrgs(s string) ([]string, error) { // registerUsernamePassword tries to register system against candlepin server (Red Hat Management Service) // username and password are mandatory. When organization is not obtained, then this method // returns list of available organization and user can select one organization from the list. -func registerUsernamePassword(username, password, organization, serverURL string) ([]string, error) { +func registerUsernamePassword(username, password, organization string, environments []string, serverURL string) ([]string, error) { var orgs []string if serverURL != "" { if err := configureRHSM(serverURL); err != nil { @@ -132,6 +132,23 @@ func registerUsernamePassword(username, password, organization, serverURL string return orgs, err } + var options = make(map[string]string) + options["enable_content"] = "true" + + if len(environments) > 0 && organization != "" { + envList, err := getEnvironmentsList(privConn, username, password, organization) + if err != nil { + return orgs, err + } + + envIDs, err := mapEnvironmentNamesToIDs(environments, envList, true) + if err != nil { + return orgs, err + } + + options["environments"] = strings.Join(envIDs, ",") + } + if err := privConn.Object( "com.redhat.RHSM1", "/com/redhat/RHSM1/Register").Call( @@ -140,7 +157,7 @@ func registerUsernamePassword(username, password, organization, serverURL string organization, username, password, - map[string]string{"enable_content": "true"}, + options, map[string]string{}, locale).Err; err != nil { @@ -407,6 +424,7 @@ func registerRHSM(ctx *cli.Context) (string, error) { password := ctx.String("password") organization := ctx.String("organization") activationKeys := ctx.StringSlice("activation-key") + contentTemplates := ctx.StringSlice("content-template") if len(activationKeys) == 0 { if username == "" { @@ -444,9 +462,9 @@ func registerRHSM(ctx *cli.Context) (string, error) { } else { var orgs []string if organization != "" { - _, err = registerUsernamePassword(username, password, organization, ctx.String("server")) + _, err = registerUsernamePassword(username, password, organization, contentTemplates, ctx.String("server")) } else { - orgs, err = registerUsernamePassword(username, password, "", ctx.String("server")) + orgs, err = registerUsernamePassword(username, password, "", contentTemplates, ctx.String("server")) /* When organization was not specified using CLI option --organization, and it is required, because user is member of more than one organization, then ask for the organization. */ @@ -481,7 +499,7 @@ func registerRHSM(ctx *cli.Context) (string, error) { } // Try to register once again with given organization - _, err = registerUsernamePassword(username, password, organization, ctx.String("server")) + _, err = registerUsernamePassword(username, password, organization, contentTemplates, ctx.String("server")) } } } @@ -494,3 +512,76 @@ func registerRHSM(ctx *cli.Context) (string, error) { } return successMsg, nil } + +type Environment struct { + ID string `json:"id"` + Name string `json:"name"` + Description string `json:"description"` + Type string `json:"type"` +} + +func (e *Environment) isContentTemplate() bool { + return e.Type == "content-template" +} + +func unpackEnvironments(s string) ([]Environment, error) { + var environments []Environment + err := json.Unmarshal([]byte(s), &environments) + if err != nil { + return nil, err + } + return environments, nil +} + +func getEnvironmentsList(conn *dbus.Conn, username, password, organization string) ([]Environment, error) { + var err error + locale := getLocale() + obj := conn.Object("com.redhat.RHSM1.Register", "/com/redhat/RHSM1/Register") + var envString string + if err := obj.Call( + "com.redhat.RHSM1.Register.GetEnvironments", + dbus.Flags(0), + username, + password, + organization, + map[string]string{}, + locale).Store(&envString); err != nil { + return nil, unpackRHSMError(err) + } + + var environments []Environment + if environments, err = unpackEnvironments(envString); err != nil { + return nil, err + } + + return environments, nil +} + +func mapEnvironmentNamesToIDs(names []string, environmentList []Environment, contentTemplates bool) ([]string, error) { + var ids []string + + for _, name := range names { + found := false + for _, environment := range environmentList { + if environment.Name == name { + ids = append(ids, environment.ID) + found = true + } + if found { + if contentTemplates && !environment.isContentTemplate() { + return nil, fmt.Errorf("environment \"%s\" is not a content template", environment.Name) + } + break + } + } + if !found { + typeString := "environment" + if contentTemplates { + typeString = "content template" + } + return nil, fmt.Errorf(typeString+" named \"%s\" was not found", name) + } + } + + return ids, nil +}