Skip to content

Commit

Permalink
feat: OpenSearch as a service
Browse files Browse the repository at this point in the history
  • Loading branch information
Kyrremann committed Feb 26, 2022
1 parent 4f36491 commit 39920e6
Show file tree
Hide file tree
Showing 6 changed files with 97 additions and 17 deletions.
2 changes: 2 additions & 0 deletions cmd/flags.go
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
package cmd

const (
AccessFlag = "access"
CommitInformation = "commit"
ConfigFlag = "config"
ContextFlag = "context"
ExpireFlag = "expire"
HostFlag = "host"
InstanceFlag = "instance"
NamespaceFlag = "namespace"
PoolFlag = "pool"
PortFlag = "port"
Expand Down
6 changes: 6 additions & 0 deletions cmd/root/aiven/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,12 @@ func (a Config) InitCmds(root *cobra.Command) {
a.get.Flags().StringP(cmd.ConfigFlag, "c", "all", "Type of config to generate. Supported values: .env, kcat, java, all (optional)")
viper.BindPFlag(cmd.ConfigFlag, a.get.Flags().Lookup(cmd.ConfigFlag))

a.create.Flags().StringP(cmd.InstanceFlag, "i", "", "Instance to connect to (required for OpenSearch)")
viper.BindPFlag(cmd.InstanceFlag, a.get.Flags().Lookup(cmd.InstanceFlag))

a.create.Flags().StringP(cmd.AccessFlag, "a", "read", "Type of access needed. Supported values: read, write, readwrite, admin (optional)")
viper.BindPFlag(cmd.AccessFlag, a.get.Flags().Lookup(cmd.AccessFlag))

root.AddCommand(a.aiven)
a.aiven.AddCommand(a.create)
a.aiven.AddCommand(a.get)
Expand Down
27 changes: 22 additions & 5 deletions cmd/root/aiven/create_cmd.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,16 +14,17 @@ var createCmd = &cobra.Command{
Use: "create [args] [flags]",
Short: "Creates an protected and time-limited 'AivenApplication'",
Long: `Creates an 'AivenApplication' based on input`,
Example: `nais aiven create kafka username namespace | nais aiven create kafka username namespace -p kafka-pool |
nais aiven create kafka username namespace -e 10 | nais aiven create kafka username namespace -s preferred-secret-name`,
Example: `nais aiven create kafka username namespace | nais aiven kafka create username namespace -p kafka-pool |
nais aiven create opensearch username namespace -i soknad -s preferred-secret-name |
nais aiven opensearch create username namespace -i soknad -a read`,
RunE: func(command *cobra.Command, args []string) error {
if len(args) != 3 {
return fmt.Errorf("missing required arguments: %v, %v, %v", cmd.ServiceFlag, cmd.UsernameFlag, cmd.NamespaceFlag)
}

service, err := aiven.ServiceFromString(strings.TrimSpace(args[0]))
if err != nil {
return err
return fmt.Errorf("%v\nvalid values for %v: %v | %v", err, cmd.ServiceFlag, aiven.Kafka, aiven.OpenSearch)
}
username := strings.TrimSpace(args[1])
namespace := strings.TrimSpace(args[2])
Expand All @@ -33,7 +34,7 @@ nais aiven create kafka username namespace -e 10 | nais aiven create kafka usern
return fmt.Errorf("flag: %v", err)
}
pool, err := aiven.KafkaPoolFromString(poolFlag)
if err != nil {
if err != nil && service == aiven.Kafka {
return fmt.Errorf("valid values for '-%v': %v",
cmd.PoolFlag,
strings.Join(aiven.KafkaPools, " | "))
Expand All @@ -49,10 +50,26 @@ nais aiven create kafka username namespace -e 10 | nais aiven create kafka usern
return fmt.Errorf("flag: %v", err)
}

instance, err := cmd.GetString(command, cmd.InstanceFlag, service == aiven.OpenSearch)
if err != nil {
return fmt.Errorf("flag: %v", err)
}

accessFlag, err := cmd.GetString(command, cmd.AccessFlag, false)
if err != nil {
return fmt.Errorf("flag: %v", err)
}
access, err := aiven.OpenSearchAccessFromString(accessFlag)
if err != nil && service == aiven.OpenSearch {
return fmt.Errorf("valid values for '-%v': %v",
cmd.AccessFlag,
strings.Join(aiven.KafkaPools, " | "))
}

// workaround https://github.com/spf13/cobra/issues/340
command.SilenceUsage = true

aivenConfig := aiven.SetupAiven(client.SetupClient(), service, username, namespace, secretName, expiry, pool)
aivenConfig := aiven.Setup(client.SetupClient(), service, username, namespace, secretName, instance, pool, access, expiry)
aivenApp, err := aivenConfig.GenerateApplication()
if err != nil {
return fmt.Errorf("an error occurred generating 'AivenApplication': %v", err)
Expand Down
39 changes: 29 additions & 10 deletions pkg/aiven/aiven.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,12 +21,15 @@ type Service int64

const (
Kafka Service = iota
OpenSearch
)

func ServiceFromString(service string) (Service, error) {
switch strings.ToLower(service) {
case "kafka":
return Kafka, nil
case "opensearch":
return OpenSearch, nil
default:
return -1, fmt.Errorf("unknown service: %v", service)
}
Expand All @@ -42,6 +45,11 @@ type Aiven struct {
Properties Properties
}

type OpenSearchProperties struct {
Instance string
Access OpenSearchAccess
}

type Properties struct {
Service Service
Username string
Expand All @@ -50,10 +58,11 @@ type Properties struct {
SecretName string
Expiry int
Kafka *KafkaProperties
OpenSearch *OpenSearchProperties
}

func SetupAiven(innClient ctrl.Client, service Service, username, namespace, secretName string, expiry int, pool KafkaPool) *Aiven {
aiven := &Aiven{
func Setup(innClient ctrl.Client, service Service, username, namespace, secretName, instance string, pool KafkaPool, access OpenSearchAccess, expiry int) *Aiven {
aiven := Aiven{
context.Background(),
innClient,
Properties{
Expand All @@ -70,35 +79,41 @@ func SetupAiven(innClient ctrl.Client, service Service, username, namespace, sec
aiven.Properties.Kafka = &KafkaProperties{
Pool: pool,
}

case OpenSearch:
aiven.Properties.OpenSearch = &OpenSearchProperties{
Instance: instance,
Access: access,
}
}

return aiven
return &aiven
}

func (a *Aiven) GenerateApplication() (*aiven_nais_io_v1.AivenApplication, error) {
properties := a.Properties
namespace := v1.Namespace{}
err := common.ValidateNamespace(a.Ctx, a.Client, a.Properties.Namespace, &namespace)

err := common.ValidateNamespace(a.Ctx, a.Client, properties.Namespace, &namespace)
if err != nil {
return nil, err
}
a.Properties.Namespace = namespace.Name
properties.Namespace = namespace.Name

secretName, err := common.SetSecretName(a.Properties.SecretName, a.Properties.Username, a.Properties.Namespace)
secretName, err := common.SetSecretName(properties.SecretName, properties.Username, properties.Namespace)
if err != nil {
return nil, err
}
aivenApp := *a.AivenApplication(secretName)

aivenApp := *a.AivenApplication(secretName)
err = a.CreateOrUpdate(&aivenApp)

if err != nil {
return nil, fmt.Errorf("create/update: %v", err)
}
return &aivenApp, nil
}

func (a Aiven) AivenApplication(secretName string) *aiven_nais_io_v1.AivenApplication {
name := strings.ReplaceAll(a.Properties.Username, ".", "-")
applicationSpec := aiven_nais_io_v1.AivenApplicationSpec{
SecretName: secretName,
Protected: DefaultProtected,
Expand All @@ -110,9 +125,13 @@ func (a Aiven) AivenApplication(secretName string) *aiven_nais_io_v1.AivenApplic
applicationSpec.Kafka = &aiven_nais_io_v1.KafkaSpec{
Pool: a.Properties.Kafka.Pool.String(),
}
case OpenSearch:
applicationSpec.Elastic = &aiven_nais_io_v1.ElasticSpec{
Instance: a.Properties.OpenSearch.Instance,
Access: a.Properties.OpenSearch.Access.String(),
}
}

name := strings.ReplaceAll(a.Properties.Username, ".", "-")
app := aiven_nais_io_v1.NewAivenApplicationBuilder(name, a.Properties.Namespace).WithSpec(applicationSpec).Build()
return &app
}
Expand Down
4 changes: 2 additions & 2 deletions pkg/aiven/aiven_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ func TestAivenGenerateApplicationCreated(t *testing.T) {
}

fakeClient := test.BuildWithScheme(&namespace).Build()
aiven := SetupAiven(fakeClient, Kafka, username, team, secretName, expiry, NavDev)
aiven := Setup(fakeClient, Kafka, username, team, secretName, "", NavDev, Read, expiry)
currentAivenApp, err := aiven.GenerateApplication()
assert.NoError(t, err)

Expand Down Expand Up @@ -66,7 +66,7 @@ func TestAivenGenerateApplicationUpdated(t *testing.T) {
}

fakeClient := test.BuildWithScheme(&namespace, &aivenApp).Build()
aiven := SetupAiven(fakeClient, Kafka, username, team, secretName, expiry, NavDev)
aiven := Setup(fakeClient, Kafka, username, team, secretName, "", NavDev, Read, expiry)
currentAivenApp, err := aiven.GenerateApplication()
assert.NoError(t, err)

Expand Down
36 changes: 36 additions & 0 deletions pkg/aiven/opensearch.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
package aiven

import (
"fmt"
"strings"
)

type OpenSearchAccess int64

const (
Read OpenSearchAccess = iota
Write
ReadWrite
Admin
)

var OpenSearchAccesses = []string{"read", "write", "readwrite", "admin"}

func OpenSearchAccessFromString(access string) (OpenSearchAccess, error) {
switch strings.ToLower(access) {
case OpenSearchAccesses[0]:
return Read, nil
case OpenSearchAccesses[1]:
return Write, nil
case OpenSearchAccesses[2]:
return ReadWrite, nil
case OpenSearchAccesses[3]:
return Admin, nil
default:
return -1, fmt.Errorf("unknown access: %v", access)
}
}

func (p OpenSearchAccess) String() string {
return OpenSearchAccesses[p]
}

0 comments on commit 39920e6

Please sign in to comment.