Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

OCM-10615 | Implement 'gcp wif-config update' command #667

Merged
merged 5 commits into from
Sep 27, 2024
Merged
Show file tree
Hide file tree
Changes from 3 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
24 changes: 20 additions & 4 deletions cmd/ocm/create/cluster/cmd.go
Original file line number Diff line number Diff line change
Expand Up @@ -477,16 +477,21 @@ func GetDefaultClusterFlavors(connection *sdk.Connection, flavour string) (dMach
}

func getVersionOptions(connection *sdk.Connection) ([]arguments.Option, error) {
options, _, err := getVersionOptionsWithDefault(connection, "", "")
options, _, err := getVersionOptionsWithDefault(connection, "", "", "")
return options, err
}

func getVersionOptionsWithDefault(connection *sdk.Connection, channelGroup string, gcpMarketplaceEnabled string) (
func getVersionOptionsWithDefault(
connection *sdk.Connection,
channelGroup string,
gcpMarketplaceEnabled string,
additionalFilters string,
) (
options []arguments.Option, defaultVersion string, err error,
) {
// Check and set the cluster version
versionList, defaultVersion, err := c.GetEnabledVersions(
connection.ClustersMgmt().V1(), channelGroup, gcpMarketplaceEnabled)
connection.ClustersMgmt().V1(), channelGroup, gcpMarketplaceEnabled, additionalFilters)
if err != nil {
return
}
Expand Down Expand Up @@ -674,8 +679,9 @@ func preRun(cmd *cobra.Command, argv []string) error {
if isGcpMarketplace {
gcpMarketplaceEnabled = strconv.FormatBool(isGcpMarketplace)
}
additionalFilters := getVersionFilters()
versions, defaultVersion, err := getVersionOptionsWithDefault(connection, args.channelGroup,
gcpMarketplaceEnabled)
gcpMarketplaceEnabled, additionalFilters)
if err != nil {
return err
}
Expand Down Expand Up @@ -1573,3 +1579,13 @@ func promptAutoscaling(fs *pflag.FlagSet) error {
}
return nil
}

// getVersionFilters returns a version filter based on the current args
func getVersionFilters() string {
filter := ""
// WIF filter
if args.gcpAuthentication.Type == c.AuthenticationWif {
filter = fmt.Sprintf("%s AND wif_enabled = 'true'", filter)
}
return filter
}
23 changes: 8 additions & 15 deletions cmd/ocm/gcp/delete-wif-config.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ var (
// NewDeleteWorkloadIdentityConfiguration provides the "gcp delete wif-config" subcommand
func NewDeleteWorkloadIdentityConfiguration() *cobra.Command {
deleteWifConfigCmd := &cobra.Command{
Use: "wif-config [ID]",
Use: "wif-config [ID|Name]",
Short: "Delete workload identity configuration",
RunE: deleteWorkloadIdentityConfigurationCmd,
PreRunE: validationForDeleteWorkloadIdentityConfigurationCmd,
Expand All @@ -42,22 +42,15 @@ func NewDeleteWorkloadIdentityConfiguration() *cobra.Command {
}

func validationForDeleteWorkloadIdentityConfigurationCmd(cmd *cobra.Command, argv []string) error {
if len(argv) != 1 {
return fmt.Errorf(
"expected exactly one command line parameters containing the id " +
"of the WIF config",
)
if err := wifKeyArgCheck(argv); err != nil {
return err
}
return nil
}

func deleteWorkloadIdentityConfigurationCmd(cmd *cobra.Command, argv []string) error {
ctx := context.Background()

wifConfigId := argv[0]
if wifConfigId == "" {
return fmt.Errorf("WIF config ID is required")
}
key := argv[0]

// Create the client for the OCM API:
connection, err := ocm.NewConnection().Build()
Expand All @@ -66,11 +59,11 @@ func deleteWorkloadIdentityConfigurationCmd(cmd *cobra.Command, argv []string) e
}
defer connection.Close()

response, err := connection.ClustersMgmt().V1().GCP().WifConfigs().WifConfig(wifConfigId).Get().Send()
// Verify the WIF configuration exists
wifConfig, err := findWifConfig(connection.ClustersMgmt().V1(), key)
if err != nil {
return errors.Wrapf(err, "failed to get wif-config")
}
wifConfig := response.Body()

if DeleteWifConfigOpts.DryRun {
log.Printf("Writing script files to %s", DeleteWifConfigOpts.TargetDir)
Expand All @@ -96,11 +89,11 @@ func deleteWorkloadIdentityConfigurationCmd(cmd *cobra.Command, argv []string) e
}

_, err = connection.ClustersMgmt().V1().GCP().WifConfigs().
WifConfig(wifConfigId).
WifConfig(wifConfig.ID()).
Delete().
Send()
if err != nil {
return errors.Wrapf(err, "failed to delete wif config %q", wifConfigId)
return errors.Wrapf(err, "failed to delete wif config %q", wifConfig.ID())
}
return nil
}
Expand Down
16 changes: 6 additions & 10 deletions cmd/ocm/gcp/describe-wif-config.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,15 +6,14 @@ import (
"text/tabwriter"

"github.com/openshift-online/ocm-cli/pkg/ocm"
"github.com/openshift-online/ocm-cli/pkg/urls"
"github.com/pkg/errors"
"github.com/spf13/cobra"
)

// NewDescribeWorkloadIdentityConfiguration provides the "gcp describe wif-config" subcommand
func NewDescribeWorkloadIdentityConfiguration() *cobra.Command {
describeWorkloadIdentityPoolCmd := &cobra.Command{
Use: "wif-config [ID]",
Use: "wif-config [ID|Name]",
Short: "Show details of a wif-config.",
RunE: describeWorkloadIdentityConfigurationCmd,
PreRunE: validationForDescribeWorkloadIdentityConfigurationCmd,
Expand All @@ -24,10 +23,7 @@ func NewDescribeWorkloadIdentityConfiguration() *cobra.Command {
}

func describeWorkloadIdentityConfigurationCmd(cmd *cobra.Command, argv []string) error {
id, err := urls.Expand(argv)
if err != nil {
return errors.Wrapf(err, "could not create URI")
}
key := argv[0]

// Create the client for the OCM API:
connection, err := ocm.NewConnection().Build()
Expand All @@ -36,11 +32,11 @@ func describeWorkloadIdentityConfigurationCmd(cmd *cobra.Command, argv []string)
}
defer connection.Close()

response, err := connection.ClustersMgmt().V1().GCP().WifConfigs().WifConfig(id).Get().Send()
// Verify the WIF configuration exists
wifConfig, err := findWifConfig(connection.ClustersMgmt().V1(), key)
if err != nil {
return errors.Wrapf(err, "failed to get wif-config")
}
wifConfig := response.Body()

// Print output
w := tabwriter.NewWriter(os.Stdout, 8, 0, 2, ' ', 0)
Expand All @@ -54,8 +50,8 @@ func describeWorkloadIdentityConfigurationCmd(cmd *cobra.Command, argv []string)
}

func validationForDescribeWorkloadIdentityConfigurationCmd(cmd *cobra.Command, argv []string) error {
if len(argv) != 1 {
return fmt.Errorf("Expected exactly one command line parameters containing the id of the WIF config")
if err := wifKeyArgCheck(argv); err != nil {
return err
}
return nil
}
13 changes: 11 additions & 2 deletions cmd/ocm/gcp/gcp-client-shim.go
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,7 @@ func (c *shim) CreateWorkloadIdentityPool(
return errors.Wrapf(err, "failed to check if there is existing workload identity pool %s", poolId)
}
} else {
log.Printf("Workload identity pool %s already exists", poolId)
log.Printf("Workload identity pool %s exists", poolId)
}

return nil
Expand Down Expand Up @@ -137,7 +137,7 @@ func (c *shim) CreateWorkloadIdentityProvider(
providerId, poolId)
}
} else {
return errors.Errorf("workload identity provider %s already exists in pool %s", providerId, poolId)
log.Printf("Workload identity provider %s exists", providerId)
}

return nil
Expand Down Expand Up @@ -545,3 +545,12 @@ func (c *shim) createMemberRoleBindingForProject(
Role: roleName,
})
}

// Checks for WIF config name or id in input
func wifKeyArgCheck(args []string) error {
JakobGray marked this conversation as resolved.
Show resolved Hide resolved
JakobGray marked this conversation as resolved.
Show resolved Hide resolved
if len(args) != 1 || args[0] == "" {
return fmt.Errorf("expected exactly one command line parameters containing the name " +
"or ID of the WIF config")
}
return nil
}
27 changes: 10 additions & 17 deletions cmd/ocm/gcp/generate-wif-script.go
JakobGray marked this conversation as resolved.
Show resolved Hide resolved
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ package gcp

import (
"context"
"fmt"
"log"

"github.com/openshift-online/ocm-cli/pkg/gcp"
Expand All @@ -20,7 +19,7 @@ var (

func NewGenerateCommand() *cobra.Command {
generateScriptCmd := &cobra.Command{
Use: "generate [wif-config ID]",
Use: "generate [wif-config ID|Name]",
Short: "Generate script based on a wif-config",
Args: cobra.ExactArgs(1),
RunE: generateCreateScriptCmd,
Expand All @@ -34,39 +33,33 @@ func NewGenerateCommand() *cobra.Command {
}

func validationForGenerateCreateScriptCmd(cmd *cobra.Command, argv []string) error {
if len(argv) != 1 {
return fmt.Errorf(
"Expected exactly one command line parameters containing the id " +
"of the WIF config.",
)
if err := wifKeyArgCheck(argv); err != nil {
return err
}
return nil
}

func generateCreateScriptCmd(cmd *cobra.Command, argv []string) error {
ctx := context.Background()
key := argv[0]

gcpClient, err := gcp.NewGcpClient(ctx)
if err != nil {
errors.Wrapf(err, "failed to initiate GCP client")
}

// Create the client for the OCM API:
connection, err := ocm.NewConnection().Build()
if err != nil {
return errors.Wrapf(err, "Failed to create OCM connection")
}
defer connection.Close()

wifConfigId := argv[0]
if wifConfigId == "" {
return fmt.Errorf("WIF config ID is required")
gcpClient, err := gcp.NewGcpClient(ctx)
if err != nil {
errors.Wrapf(err, "failed to initiate GCP client")
}

response, err := connection.ClustersMgmt().V1().GCP().WifConfigs().WifConfig(wifConfigId).Get().Send()
// Verify the WIF configuration exists
wifConfig, err := findWifConfig(connection.ClustersMgmt().V1(), key)
if err != nil {
return errors.Wrapf(err, "failed to get wif-config")
}
wifConfig := response.Body()

projectNum, err := gcpClient.ProjectNumberFromId(ctx, wifConfig.Gcp().ProjectId())
if err != nil {
Expand Down
91 changes: 79 additions & 12 deletions cmd/ocm/gcp/update-wif-config.go
Original file line number Diff line number Diff line change
@@ -1,39 +1,106 @@
package gcp

import (
"context"
"fmt"
"log"

"github.com/openshift-online/ocm-cli/pkg/gcp"
"github.com/openshift-online/ocm-cli/pkg/ocm"
cmv1 "github.com/openshift-online/ocm-sdk-go/clustersmgmt/v1"
"github.com/pkg/errors"
"github.com/spf13/cobra"
)

var UpdateWifConfigOpts struct {
wifId string
templateId string
}

// NewUpdateWorkloadIdentityConfiguration provides the "gcp update wif-config" subcommand
func NewUpdateWorkloadIdentityConfiguration() *cobra.Command {
updateWifConfigCmd := &cobra.Command{
Use: "wif-config",
Use: "wif-config [ID|Name]",
Short: "Update wif-config.",
RunE: updateWorkloadIdentityConfigurationCmd,
PreRunE: validationForUpdateWorkloadIdentityConfigurationCmd,
}

updateWifConfigCmd.PersistentFlags().StringVar(&UpdateWifConfigOpts.wifId, "wif-id", "",
"Workload Identity Federation ID")
updateWifConfigCmd.MarkPersistentFlagRequired("wif-id")
updateWifConfigCmd.PersistentFlags().StringVar(&UpdateWifConfigOpts.templateId, "template-id", "",
"Template ID")
updateWifConfigCmd.MarkPersistentFlagRequired("template-id")

return updateWifConfigCmd
}

func validationForUpdateWorkloadIdentityConfigurationCmd(cmd *cobra.Command, argv []string) error {
// No validation needed
if err := wifKeyArgCheck(argv); err != nil {
return err
}
return nil
}

func updateWorkloadIdentityConfigurationCmd(cmd *cobra.Command, argv []string) error {
// No implementation yet
ctx := context.Background()
log := log.Default()
key := argv[0]
JakobGray marked this conversation as resolved.
Show resolved Hide resolved

// Create the client for the OCM API:
connection, err := ocm.NewConnection().Build()
if err != nil {
return errors.Wrapf(err, "Failed to create OCM connection")
}
defer connection.Close()

// Verify the WIF configuration exists
wifConfig, err := findWifConfig(connection.ClustersMgmt().V1(), key)
if err != nil {
return errors.Wrapf(err, "failed to get wif-config")
}

gcpClient, err := gcp.NewGcpClient(ctx)
if err != nil {
return errors.Wrapf(err, "failed to initiate GCP client")
}

// Re-apply WIF resources
gcpClientWifConfigShim := NewGcpClientWifConfigShim(GcpClientWifConfigShimSpec{
GcpClient: gcpClient,
WifConfig: wifConfig,
})

if err := gcpClientWifConfigShim.GrantSupportAccess(ctx, log); err != nil {
return fmt.Errorf("Failed to grant support access to project: %s", err)
}

if err := gcpClientWifConfigShim.CreateWorkloadIdentityPool(ctx, log); err != nil {
return fmt.Errorf("Failed to update workload identity pool: %s", err)
}

if err = gcpClientWifConfigShim.CreateWorkloadIdentityProvider(ctx, log); err != nil {
return fmt.Errorf("Failed to update workload identity provider: %s", err)
}

if err = gcpClientWifConfigShim.CreateServiceAccounts(ctx, log); err != nil {
return fmt.Errorf("Failed to update IAM service accounts: %s", err)
}

return nil
}

// findWifConfig finds the WIF configuration by ID or name
func findWifConfig(client *cmv1.Client, key string) (*cmv1.WifConfig, error) {
JakobGray marked this conversation as resolved.
Show resolved Hide resolved
collection := client.GCP().WifConfigs()
page := 1
size := 1
query := fmt.Sprintf(
"id = '%s' or display_name = '%s'",
key, key,
)

response, err := collection.List().Search(query).Page(page).Size(size).Send()
if err != nil {
return nil, err
}
if response.Total() == 0 {
return nil, fmt.Errorf("WIF configuration with identifier or name '%s' not found", key)
}
if response.Total() > 1 {
return nil, fmt.Errorf("there are %d WIF configurations found with identifier or name '%s'", response.Total(), key)
}
return response.Items().Slice()[0], nil
}
2 changes: 1 addition & 1 deletion cmd/ocm/list/version/cmd.go
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ func run(cmd *cobra.Command, argv []string) error {
defer connection.Close()

client := connection.ClustersMgmt().V1()
versions, defaultVersion, err := cluster.GetEnabledVersions(client, args.channelGroup, args.marketplaceGcp)
versions, defaultVersion, err := cluster.GetEnabledVersions(client, args.channelGroup, args.marketplaceGcp, "")
if err != nil {
return fmt.Errorf("Can't retrieve versions: %v", err)
}
Expand Down
Loading
Loading