-
Notifications
You must be signed in to change notification settings - Fork 20
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
adding the
create
sub-command tree logic.
- Loading branch information
Showing
3 changed files
with
175 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1 +1,95 @@ | ||
package cmd | ||
|
||
import ( | ||
"context" | ||
"fmt" | ||
"github.com/exoscale/cli/pkg/globalstate" | ||
v3 "github.com/exoscale/egoscale/v3" | ||
"github.com/spf13/cobra" | ||
) | ||
|
||
type dbaasAclCreateCmd struct { | ||
cliCommandSettings `cli-cmd:"-"` | ||
|
||
_ bool `cli-cmd:"create"` | ||
Name string `cli-flag:"name" cli-usage:"Name of the DBaaS service"` | ||
Username string `cli-flag:"username" cli-usage:"Username for the ACL entry"` | ||
ServiceType string `cli-flag:"type" cli-short:"t" cli-usage:"Type of the DBaaS service (e.g., kafka opensearch)"` | ||
Pattern string `cli-flag:"pattern" cli-usage:"The pattern for the ACL rule (index* for OpenSearch or topic for Kafka, max 249 characters)"` | ||
Permission string `cli-flag:"permission" cli-usage:"Permission to apply (should be one of admin, read, readwrite, write, or deny (only for OpenSearch))"` | ||
} | ||
|
||
// Command aliases (none in this case) | ||
func (c *dbaasAclCreateCmd) cmdAliases() []string { return nil } | ||
|
||
// Short description for the command | ||
func (c *dbaasAclCreateCmd) cmdShort() string { | ||
return "Create an ACL entry for a DBaaS service" | ||
} | ||
|
||
// Long description for the command | ||
func (c *dbaasAclCreateCmd) cmdLong() string { | ||
return `This command creates an ACL entry for a specified DBaaS service, automatically searching for the service across all available zones.` | ||
} | ||
|
||
func (c *dbaasAclCreateCmd) cmdPreRun(cmd *cobra.Command, args []string) error { | ||
return cliCommandDefaultPreRun(c, cmd, args) | ||
} | ||
|
||
// Main run logic for showing ACL details | ||
func (c *dbaasAclCreateCmd) cmdRun(cmd *cobra.Command, args []string) error { | ||
ctx := context.Background() | ||
|
||
// Validate required inputs | ||
if c.Name == "" || c.Username == "" || c.ServiceType == "" || c.Permission == "" || c.Pattern == "" { | ||
return fmt.Errorf("all --name, --username, --type, --permission and --pattern flags must be specified") | ||
} | ||
|
||
// Fetch all available zones | ||
zones, err := globalstate.EgoscaleV3Client.ListZones(ctx) | ||
if err != nil { | ||
return fmt.Errorf("error fetching zones: %w", err) | ||
} | ||
|
||
// Iterate through zones to find the service | ||
var serviceZone string | ||
var dbType v3.DBAASDatabaseName | ||
var client *v3.Client | ||
found := false | ||
|
||
for _, zone := range zones.Zones { | ||
db, err := dbaasGetV3(ctx, c.Name, string(zone.Name)) | ||
if err == nil { | ||
dbType = v3.DBAASDatabaseName(db.Type) | ||
serviceZone = string(zone.Name) | ||
client, err = switchClientZoneV3(ctx, globalstate.EgoscaleV3Client, v3.ZoneName(serviceZone)) | ||
if err != nil { | ||
return fmt.Errorf("error initializing client for zone %s: %w", serviceZone, err) | ||
} | ||
found = true | ||
break | ||
} | ||
} | ||
|
||
if !found { | ||
return fmt.Errorf("service %q not found in any zone", c.Name) | ||
} | ||
// Validate the service type | ||
if string(dbType) != c.ServiceType { | ||
return fmt.Errorf("service type mismatch: expected %q but got %q for service %q", c.ServiceType, dbType, c.Name) | ||
} | ||
|
||
switch dbType { | ||
case "kafka": | ||
return c.createKafka(ctx, client, c.Name) | ||
case "opensearch": | ||
return c.createOpensearch(ctx, client, c.Name) | ||
default: | ||
return fmt.Errorf("create ACL unsupported for service type %q", dbType) | ||
} | ||
} | ||
func init() { | ||
cobra.CheckErr(registerCLICommand(dbaasAclCmd, &dbaasAclCreateCmd{ | ||
cliCommandSettings: defaultCLICmdSettings(), | ||
})) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,35 @@ | ||
package cmd | ||
|
||
import ( | ||
"context" | ||
"fmt" | ||
|
||
v3 "github.com/exoscale/egoscale/v3" | ||
) | ||
|
||
func (c *dbaasAclCreateCmd) createKafka(ctx context.Context, client *v3.Client, serviceName string) error { | ||
// Define the new Kafka ACL entry | ||
newAcl := v3.DBAASKafkaTopicAclEntry{ | ||
Username: c.Username, | ||
Topic: c.Pattern, | ||
Permission: v3.DBAASKafkaTopicAclEntryPermission(c.Permission), | ||
} | ||
|
||
// Trigger the creation of the ACL entry | ||
op, err := client.CreateDBAASKafkaTopicAclConfig(ctx, serviceName, newAcl) | ||
if err != nil { | ||
return fmt.Errorf("error creating ACL entry for service %q: %w", serviceName, err) | ||
} | ||
|
||
// Use decorateAsyncOperation to handle the operation and provide user feedback | ||
decorateAsyncOperation(fmt.Sprintf("Creating Kafka ACL entry for user %q", c.Username), func() { | ||
op, err = client.Wait(ctx, op, v3.OperationStateSuccess) | ||
}) | ||
|
||
if err != nil { | ||
return fmt.Errorf("error completing ACL creation: %w", err) | ||
} | ||
|
||
fmt.Printf("Kafka ACL entry for user %q successfully created in service %q\n", c.Username, serviceName) | ||
return nil | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,46 @@ | ||
package cmd | ||
|
||
import ( | ||
"context" | ||
"fmt" | ||
v3 "github.com/exoscale/egoscale/v3" | ||
) | ||
|
||
func (c *dbaasAclCreateCmd) createOpensearch(ctx context.Context, client *v3.Client, serviceName string) error { | ||
aclsConfig, err := client.GetDBAASOpensearchAclConfig(ctx, serviceName) | ||
if err != nil { | ||
return fmt.Errorf("error fetching ACL configuration for service %q: %w", serviceName, err) | ||
} | ||
|
||
// Check if an entry with the same username already exists | ||
for _, acl := range aclsConfig.Acls { | ||
if string(acl.Username) == c.Username { | ||
return fmt.Errorf("ACL entry for username %q already exists in service %q", c.Username, serviceName) | ||
} | ||
} | ||
|
||
// Create a new ACL entry | ||
newAcl := v3.DBAASOpensearchAclConfigAcls{ | ||
Username: v3.DBAASUserUsername(c.Username), | ||
Rules: []v3.DBAASOpensearchAclConfigAclsRules{ | ||
{Index: c.Pattern, Permission: v3.EnumOpensearchRulePermission(c.Permission)}, | ||
}, | ||
} | ||
|
||
// Append the new entry to the existing ACLs | ||
aclsConfig.Acls = append(aclsConfig.Acls, newAcl) | ||
|
||
// Update the configuration with the new entry | ||
op, err := client.UpdateDBAASOpensearchAclConfig(ctx, serviceName, *aclsConfig) | ||
if err != nil { | ||
return fmt.Errorf("error updating ACL configuration for service %q: %w", serviceName, err) | ||
} | ||
|
||
// Use decorateAsyncOperation to wait for the operation and provide user feedback | ||
decorateAsyncOperation(fmt.Sprintf("Creating ACL entry for user %q", c.Username), func() { | ||
op, err = client.Wait(ctx, op, v3.OperationStateSuccess) | ||
}) | ||
|
||
fmt.Printf("ACL entry for username %q created successfully in service %q\n", c.Username, serviceName) | ||
return nil | ||
} |