Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
67 changes: 67 additions & 0 deletions cmd/create/cluster/cmd.go
Original file line number Diff line number Diff line change
Expand Up @@ -50,13 +50,15 @@ import (
"github.com/openshift/rosa/pkg/aws/tags"
"github.com/openshift/rosa/pkg/clusterautoscaler"
"github.com/openshift/rosa/pkg/clusterregistryconfig"
"github.com/openshift/rosa/pkg/config"
"github.com/openshift/rosa/pkg/fedramp"
"github.com/openshift/rosa/pkg/helper"
mpHelpers "github.com/openshift/rosa/pkg/helper/machinepools"
"github.com/openshift/rosa/pkg/helper/roles"
urlHelper "github.com/openshift/rosa/pkg/helper/url"
"github.com/openshift/rosa/pkg/helper/versions"
"github.com/openshift/rosa/pkg/ingress"
"github.com/openshift/rosa/pkg/input"
"github.com/openshift/rosa/pkg/interactive"
"github.com/openshift/rosa/pkg/interactive/confirm"
"github.com/openshift/rosa/pkg/interactive/consts"
Expand Down Expand Up @@ -105,6 +107,7 @@ const (
privateLinkFlagName = "private-link"
privateFlagName = "private"
enableDeleteProtectionFlagName = "enable-delete-protection"
notificationContactsFlagName = "notification-contacts"
)

var args struct {
Expand Down Expand Up @@ -139,6 +142,7 @@ var args struct {
flavour string
disableWorkloadMonitoring bool
enableDeleteProtection bool
notificationContacts []string
ec2MetadataHttpTokens string

//Encryption
Expand Down Expand Up @@ -730,6 +734,14 @@ func initFlags(cmd *cobra.Command) {
false,
"Enable cluster delete protection against accidental deletion after the cluster is created.",
)
flags.StringSliceVar(
&args.notificationContacts,
notificationContactsFlagName,
nil,
"Comma-separated list of OCM account usernames or email addresses to receive "+
"cluster notification emails. All contacts must belong to the same Red Hat "+
"organization as the cluster.",
)

flags.BoolVarP(
&args.watch,
Expand Down Expand Up @@ -3142,6 +3154,34 @@ func run(cmd *cobra.Command, _ []string) {
args.enableDeleteProtection = enableDeleteProtection
}

notificationContacts := args.notificationContacts
showNotificationContactsPrompt := false
if interactive.Enabled() && cmd.Flags().Changed("interactive") {
showNotificationContactsPrompt = true
} else if interactive.Enabled() {
cfg, cfgErr := config.Load()
if cfgErr == nil && cfg.ClientID != "" {
showNotificationContactsPrompt = true
}
}
if showNotificationContactsPrompt {
ncInput, err := interactive.GetString(interactive.Input{
Question: "Notification contact usernames or emails (comma-separated, leave empty to skip)",
Help: cmd.Flags().Lookup(notificationContactsFlagName).Usage,
Default: strings.Join(notificationContacts, ","),
})
if err != nil {
r.Reporter.Errorf("Expected a valid notification-contacts value: %v", err)
os.Exit(1)
}
if ncInput != "" {
notificationContacts = helper.HandleEmptyStringOnSlice(strings.Split(ncInput, ","))
} else {
notificationContacts = nil
}
args.notificationContacts = notificationContacts
}

// Cluster-wide proxy configuration
if (subnetsProvided || (useExistingVPC && !enableProxy)) && interactive.Enabled() {
enableProxy, err = interactive.GetBool(interactive.Input{
Expand Down Expand Up @@ -3723,6 +3763,30 @@ func run(cmd *cobra.Command, _ []string) {
}
}

if len(notificationContacts) == 1 &&
(notificationContacts[0] == input.DoubleQuotesToRemove || notificationContacts[0] == "") {
notificationContacts = []string{}
}
if len(notificationContacts) > 0 {
Comment thread
michaelryanmcneill marked this conversation as resolved.
subID := cluster.Subscription().ID()
if subID == "" {
r.Reporter.Errorf(
"Cluster '%s' was created but notification contacts could not be set: "+
"subscription ID is not available",
cluster.ID(),
)
os.Exit(1)
}
if err := r.OCMClient.UpdateSubscriptionNotificationContacts(cmd.Context(), subID, notificationContacts); err != nil {
r.Reporter.Errorf(
"Cluster '%s' was created but notification contacts could not be set: %v",
cluster.ID(),
err,
)
os.Exit(1)
}
}

Comment thread
coderabbitai[bot] marked this conversation as resolved.
if !output.HasFlag() || r.Reporter.IsTerminal() {
r.Reporter.Infof("Cluster '%s' has been created.", clusterName)
r.Reporter.Infof(
Expand Down Expand Up @@ -4344,6 +4408,9 @@ func buildCommand(spec ocm.Spec, operatorRolesPrefix string,
if args.enableDeleteProtection {
command += " --enable-delete-protection"
}
if len(args.notificationContacts) > 0 {
command += fmt.Sprintf(" --notification-contacts %s", strings.Join(args.notificationContacts, ","))
Comment thread
coderabbitai[bot] marked this conversation as resolved.
}
Comment thread
coderabbitai[bot] marked this conversation as resolved.
if userSelectedAvailabilityZones {
command += fmt.Sprintf(" --availability-zones %s", strings.Join(spec.AvailabilityZones, ","))
}
Expand Down
38 changes: 38 additions & 0 deletions cmd/describe/cluster/cmd.go
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,15 @@ func run(cmd *cobra.Command, argv []string) {
}
}

var notificationContactUsernames []string
if subscriptionExists {
contacts, err := r.OCMClient.GetSubscriptionNotificationContacts(cmd.Context(), cluster.Subscription().ID())
if err != nil {
r.Reporter.Debugf("Failed to get notification contacts: %s", err)
}
notificationContactUsernames = contacts
}

Comment thread
coderabbitai[bot] marked this conversation as resolved.
if !isHypershift {
scheduledUpgrade, upgradeState, err = r.OCMClient.GetScheduledUpgrade(cluster.ID())
if err != nil {
Expand All @@ -135,6 +144,11 @@ func run(cmd *cobra.Command, argv []string) {
r.Reporter.Errorf("%s", err)
os.Exit(1)
}
if len(notificationContactUsernames) > 0 {
f["notification_contacts"] = notificationContactUsernames
} else {
f["notification_contacts"] = []string{}
}
err = output.Print(f)
if err != nil {
r.Reporter.Errorf("%s", err)
Expand All @@ -155,6 +169,11 @@ func run(cmd *cobra.Command, argv []string) {
r.Reporter.Errorf("%s", err)
os.Exit(1)
}
if len(notificationContactUsernames) > 0 {
f["notification_contacts"] = notificationContactUsernames
} else {
f["notification_contacts"] = []string{}
}
err = output.Print(f)
if err != nil {
r.Reporter.Errorf("%s", err)
Expand Down Expand Up @@ -447,6 +466,18 @@ func run(cmd *cobra.Command, argv []string) {
deleteProtection = EnabledOutput
}

notificationContactsDisplay := ""
if len(notificationContactUsernames) > 0 {
const maxDisplayContacts = 25
if len(notificationContactUsernames) > maxDisplayContacts {
notificationContactsDisplay = output.PrintStringSlice(notificationContactUsernames[:maxDisplayContacts]) +
fmt.Sprintf(", ... (%d more, use --output json to see all)",
len(notificationContactUsernames)-maxDisplayContacts)
} else {
notificationContactsDisplay = output.PrintStringSlice(notificationContactUsernames)
}
}

str = fmt.Sprintf("%s"+
"State: %s %s\n"+
"Private: %s\n"+
Expand All @@ -458,6 +489,13 @@ func run(cmd *cobra.Command, argv []string) {
deleteProtection,
cluster.CreationTimestamp().Format("Jan _2 2006 15:04:05 MST"))

if notificationContactsDisplay != "" {
str = fmt.Sprintf("%s"+
"Notification Contacts: %s\n",
str,
notificationContactsDisplay)
}

if !isHypershift {
str = fmt.Sprintf("%s"+
"User Workload Monitoring: %s\n",
Expand Down
89 changes: 88 additions & 1 deletion cmd/edit/cluster/cmd.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ import (
"github.com/openshift/rosa/pkg/arguments"
"github.com/openshift/rosa/pkg/aws"
"github.com/openshift/rosa/pkg/clusterregistryconfig"
"github.com/openshift/rosa/pkg/config"
"github.com/openshift/rosa/pkg/fedramp"
"github.com/openshift/rosa/pkg/helper"
"github.com/openshift/rosa/pkg/helper/autonode"
Expand All @@ -42,12 +43,14 @@ import (
)

const enableDeleteProtectionFlagName = "enable-delete-protection"
const notificationContactsFlagName = "notification-contacts"

var args struct {
// Basic options
expirationTime string
expirationDuration time.Duration
enableDeleteProtection bool
notificationContacts []string

// Networking options
private bool
Expand Down Expand Up @@ -135,6 +138,14 @@ func initFlags(cmd *cobra.Command) {
"Enable or disable cluster delete protection against accidental deletion. "+
"Use '--enable-delete-protection=false' to disable.",
)
flags.StringSliceVar(
&args.notificationContacts,
notificationContactsFlagName,
nil,
"Comma-separated list of OCM account usernames or email addresses to receive "+
"cluster notification emails. All contacts must belong to the same Red Hat "+
"organization as the cluster. Pass an empty value to remove all notification contacts.",
)
// Cluster expiration is not supported in production
flags.MarkHidden("expiration-time")
flags.MarkHidden("expiration")
Expand Down Expand Up @@ -292,7 +303,7 @@ func runWithRuntime(r *rosa.Runtime, cmd *cobra.Command) error {
"registry-config-insecure-registries", "allowed-registries-for-import",
"registry-config-platform-allowlist", "registry-config-additional-trusted-ca", "billing-account",
"registry-config-allowed-registries-for-import", "enable-delete-protection", "spot-termination-queue-url",
"channel-group", "network-type", "channel"} {
"channel-group", "network-type", "channel", notificationContactsFlagName} {
if cmd.Flags().Changed(flag) {
changedFlags = true
break
Expand Down Expand Up @@ -853,6 +864,82 @@ func runWithRuntime(r *rosa.Runtime, cmd *cobra.Command) error {
}
}

// Notification Contacts
var notificationContacts []string
updateNotificationContacts := cmd.Flags().Changed(notificationContactsFlagName)
if updateNotificationContacts {
notificationContacts = args.notificationContacts
}
showNotificationContactsPrompt := false
if !updateNotificationContacts && interactive.Enabled() {
if cmd.Flags().Changed("interactive") {
showNotificationContactsPrompt = true
} else {
cfg, cfgErr := config.Load()
if cfgErr == nil && cfg.ClientID != "" {
showNotificationContactsPrompt = true
}
}
}
if showNotificationContactsPrompt {
updateValue, err := interactive.GetBool(interactive.Input{
Question: "Update notification contacts",
Default: false,
})
if err != nil {
r.Reporter.Errorf("Expected a valid value: %v", err)
os.Exit(1)
}
updateNotificationContacts = updateValue
}
if updateNotificationContacts && interactive.Enabled() {
promptDefault := strings.Join(notificationContacts, ",")
if !cmd.Flags().Changed(notificationContactsFlagName) {
currentContacts, err := r.OCMClient.GetSubscriptionNotificationContacts(
cmd.Context(), cluster.Subscription().ID())
if err != nil {
r.Reporter.Errorf("Could not fetch current notification contacts: %v", err)
os.Exit(1)
}
const maxPromptContacts = 5
if len(currentContacts) > maxPromptContacts {
r.Reporter.Infof("Cluster has %d notification contacts configured. "+
"Enter the full desired list below.", len(currentContacts))
promptDefault = ""
} else {
promptDefault = strings.Join(currentContacts, ",")
}
}
ncInput, err := interactive.GetString(interactive.Input{
Question: "Notification contact usernames or emails (comma-separated)",
Help: cmd.Flags().Lookup(notificationContactsFlagName).Usage,
Default: promptDefault,
})
if err != nil {
r.Reporter.Errorf("Expected a valid value for notification contacts: %v", err)
os.Exit(1)
}
notificationContacts = helper.HandleEmptyStringOnSlice(strings.Split(ncInput, ","))
}
if updateNotificationContacts {
subID := cluster.Subscription().ID()
if subID == "" {
r.Reporter.Errorf("Cluster subscription ID is not available. " +
"Notification contacts could not be updated.")
os.Exit(1)
}
contacts := notificationContacts
if len(contacts) == 1 &&
(contacts[0] == input.DoubleQuotesToRemove || contacts[0] == "") {
contacts = []string{}
}
if err := r.OCMClient.UpdateSubscriptionNotificationContacts(cmd.Context(), subID, contacts); err != nil {
r.Reporter.Errorf("Failed to update notification contacts: %v", err)
os.Exit(1)
}
r.Reporter.Infof("Updated notification contacts for cluster '%s'", clusterKey)
}

// SDN -> OVN Migration
var migrateNetworkType bool
// Only prompt user with migrating the cluster's network type when it is not OVN-Kubernetes
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,7 @@
- name: disable-scp-checks
- name: disable-workload-monitoring
- name: enable-delete-protection
- name: notification-contacts
- name: watch
- name: dry-run
- name: fake-cluster
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
- name: expiration-time
- name: expiration
- name: enable-delete-protection
- name: notification-contacts
- name: private
- name: disable-workload-monitoring
- name: http-proxy
Expand Down
Loading