Skip to content

Commit

Permalink
feat(redis): ipam config for private endpoints (#3492)
Browse files Browse the repository at this point in the history
  • Loading branch information
Mia-Cross authored Nov 23, 2023
1 parent d7c1b9d commit e8cc6da
Show file tree
Hide file tree
Showing 24 changed files with 4,387 additions and 0 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ ARGS:
[cluster-size] Number of nodes in the Redis™ cluster
[acl-rules.{index}.ip-cidr] IPv4 network address of the rule
[acl-rules.{index}.description] Description of the rule
[endpoints.{index}.private-network.enable-ipam=false] Will configure your Private Network endpoint with Scaleway IPAM service if true
[endpoints.{index}.private-network.id] UUID of the Private Network to connect to the Database Instance
[endpoints.{index}.private-network.service-ips.{index}] Endpoint IPv4 address with a CIDR notation. You must provide at least one IPv4 per node.
[tls-enabled] Defines whether or not TLS is enabled
Expand All @@ -25,6 +26,7 @@ ARGS:

FLAGS:
-h, --help help for create
-w, --wait wait until the cluster is ready

GLOBAL FLAGS:
-c, --config string The path to the config file
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ ARGS:

FLAGS:
-h, --help help for delete
-w, --wait wait until the cluster is ready

GLOBAL FLAGS:
-c, --config string The path to the config file
Expand Down
1 change: 1 addition & 0 deletions cmd/scw/testdata/test-all-usage-redis-cluster-usage.golden
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ AVAILABLE COMMANDS:
migrate Scale up a Redis™ Database Instance
renew-certificate Renew the TLS certificate of a cluster
update Update a Redis™ Database Instance
wait Wait for a Redis cluster to reach a stable state

FLAGS:
-h, --help help for cluster
Expand Down
24 changes: 24 additions & 0 deletions cmd/scw/testdata/test-all-usage-redis-cluster-wait-usage.golden
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
🎲🎲🎲 EXIT CODE: 0 🎲🎲🎲
🟥🟥🟥 STDERR️️ 🟥🟥🟥️
Wait for a Redis cluster to reach a stable state. This is similar to using --wait flag.

USAGE:
scw redis cluster wait <cluster-id ...> [arg=value ...]

EXAMPLES:
Wait for a Redis cluster to reach a stable state
scw redis cluster wait

ARGS:
cluster-id ID of the cluster you want to wait for
[zone=fr-par-1] Zone to target. If none is passed will use default zone from the config (fr-par-1 | fr-par-2 | nl-ams-1 | nl-ams-2 | pl-waw-1 | pl-waw-2)
[timeout=15m0s] Timeout of the wait

FLAGS:
-h, --help help for wait

GLOBAL FLAGS:
-c, --config string The path to the config file
-D, --debug Enable debug mode
-o, --output string Output format: json or human, see 'scw help output' for more info (default "human")
-p, --profile string The config profile to use
33 changes: 33 additions & 0 deletions docs/commands/redis.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ Managed Database for Redis™ API
- [Scale up a Redis™ Database Instance](#scale-up-a-redis™-database-instance)
- [Renew the TLS certificate of a cluster](#renew-the-tls-certificate-of-a-cluster)
- [Update a Redis™ Database Instance](#update-a-redis™-database-instance)
- [Wait for a Redis cluster to reach a stable state](#wait-for-a-redis-cluster-to-reach-a-stable-state)
- [Endpoints management commands](#endpoints-management-commands)
- [Add endpoints for a cluster](#add-endpoints-for-a-cluster)
- [Delete an endpoint for a cluster](#delete-an-endpoint-for-a-cluster)
Expand Down Expand Up @@ -152,6 +153,7 @@ scw redis cluster create [arg=value ...]
| cluster-size | | Number of nodes in the Redis™ cluster |
| acl-rules.{index}.ip-cidr | | IPv4 network address of the rule |
| acl-rules.{index}.description | | Description of the rule |
| endpoints.{index}.private-network.enable-ipam | Default: `false` | Will configure your Private Network endpoint with Scaleway IPAM service if true |
| endpoints.{index}.private-network.id | | UUID of the Private Network to connect to the Database Instance |
| endpoints.{index}.private-network.service-ips.{index} | | Endpoint IPv4 address with a CIDR notation. You must provide at least one IPv4 per node. |
| tls-enabled | | Defines whether or not TLS is enabled |
Expand Down Expand Up @@ -336,6 +338,37 @@ scw redis cluster update <cluster-id ...> [arg=value ...]



### Wait for a Redis cluster to reach a stable state

Wait for a Redis cluster to reach a stable state. This is similar to using --wait flag.

**Usage:**

```
scw redis cluster wait <cluster-id ...> [arg=value ...]
```


**Args:**

| Name | | Description |
|------|---|-------------|
| cluster-id | Required | ID of the cluster you want to wait for |
| zone | Default: `fr-par-1`<br />One of: `fr-par-1`, `fr-par-2`, `nl-ams-1`, `nl-ams-2`, `pl-waw-1`, `pl-waw-2` | Zone to target. If none is passed will use default zone from the config |
| timeout | Default: `15m0s` | Timeout of the wait |


**Examples:**


Wait for a Redis cluster to reach a stable state
```
scw redis cluster wait
```




## Endpoints management commands

Manage endpoint access to your Redis™ Database Instance through Public or Private Networks.
Expand Down
4 changes: 4 additions & 0 deletions internal/namespaces/redis/v1/custom.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,5 +7,9 @@ import (
func GetCommands() *core.Commands {
cmds := GetGeneratedCommands()

cmds.Merge(core.NewCommands(clusterWaitCommand()))
cmds.MustFind("redis", "cluster", "create").Override(clusterCreateBuilder)
cmds.MustFind("redis", "cluster", "delete").Override(clusterDeleteBuilder)

return cmds
}
146 changes: 146 additions & 0 deletions internal/namespaces/redis/v1/custom_cluster.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,146 @@
package redis

import (
"context"
"errors"
"net/http"
"reflect"
"time"

"github.com/scaleway/scaleway-cli/v2/internal/core"
"github.com/scaleway/scaleway-sdk-go/api/redis/v1"
"github.com/scaleway/scaleway-sdk-go/scw"
)

const redisActionTimeout = 15 * time.Minute

func clusterCreateBuilder(c *core.Command) *core.Command {
type redisEndpointSpecPrivateNetworkSpecCustom struct {
*redis.EndpointSpecPrivateNetworkSpec
EnableIpam bool `json:"enable-ipam"`
}

type redisEndpointSpecCustom struct {
PrivateNetwork *redisEndpointSpecPrivateNetworkSpecCustom `json:"private-network"`
}

type redisCreateClusterRequestCustom struct {
*redis.CreateClusterRequest
Endpoints []*redisEndpointSpecCustom `json:"endpoints"`
}

c.ArgSpecs.AddBefore("endpoints.{index}.private-network.id", &core.ArgSpec{
Name: "endpoints.{index}.private-network.enable-ipam",
Short: "Will configure your Private Network endpoint with Scaleway IPAM service if true",
Required: false,
Default: core.DefaultValueSetter("false"),
})

c.ArgsType = reflect.TypeOf(redisCreateClusterRequestCustom{})

c.WaitFunc = func(ctx context.Context, argsI, respI interface{}) (interface{}, error) {
api := redis.NewAPI(core.ExtractClient(ctx))
cluster, err := api.WaitForCluster(&redis.WaitForClusterRequest{
ClusterID: respI.(*redis.Cluster).ID,
Zone: respI.(*redis.Cluster).Zone,
Timeout: scw.TimeDurationPtr(redisActionTimeout),
RetryInterval: core.DefaultRetryInterval,
})
if err != nil {
return nil, err
}
return cluster, nil
}

c.Run = func(ctx context.Context, argsI interface{}) (interface{}, error) {
client := core.ExtractClient(ctx)
api := redis.NewAPI(client)

customRequest := argsI.(*redisCreateClusterRequestCustom)
createClusterRequest := customRequest.CreateClusterRequest

for _, customEndpoint := range customRequest.Endpoints {
if customEndpoint.PrivateNetwork == nil {
continue
}
ipamConfig := &redis.EndpointSpecPrivateNetworkSpecIpamConfig{}
if !customEndpoint.PrivateNetwork.EnableIpam {
ipamConfig = nil
}
createClusterRequest.Endpoints = append(createClusterRequest.Endpoints, &redis.EndpointSpec{
PrivateNetwork: &redis.EndpointSpecPrivateNetworkSpec{
ID: customEndpoint.PrivateNetwork.ID,
ServiceIPs: customEndpoint.PrivateNetwork.ServiceIPs,
IpamConfig: ipamConfig,
},
})
}

cluster, err := api.CreateCluster(createClusterRequest)
if err != nil {
return nil, err
}
return cluster, nil
}

return c
}

func clusterDeleteBuilder(c *core.Command) *core.Command {
c.WaitFunc = func(ctx context.Context, argsI, respI interface{}) (interface{}, error) {
api := redis.NewAPI(core.ExtractClient(ctx))
cluster, err := api.WaitForCluster(&redis.WaitForClusterRequest{
ClusterID: respI.(*redis.Cluster).ID,
Zone: respI.(*redis.Cluster).Zone,
Timeout: scw.TimeDurationPtr(redisActionTimeout),
RetryInterval: core.DefaultRetryInterval,
})
if err != nil {
// if we get a 404 here, it means the resource was successfully deleted
notFoundError := &scw.ResourceNotFoundError{}
responseError := &scw.ResponseError{}
if errors.As(err, &responseError) && responseError.StatusCode == http.StatusNotFound || errors.As(err, &notFoundError) {
return cluster, nil
}
return nil, err
}
return cluster, nil
}
return c
}

func clusterWaitCommand() *core.Command {
return &core.Command{
Short: "Wait for a Redis cluster to reach a stable state",
Long: "Wait for a Redis cluster to reach a stable state. This is similar to using --wait flag.",
Namespace: "redis",
Resource: "cluster",
Verb: "wait",
ArgsType: reflect.TypeOf(redis.WaitForClusterRequest{}),
Run: func(ctx context.Context, argsI interface{}) (i interface{}, err error) {
api := redis.NewAPI(core.ExtractClient(ctx))
return api.WaitForCluster(&redis.WaitForClusterRequest{
Zone: argsI.(*redis.WaitForClusterRequest).Zone,
ClusterID: argsI.(*redis.WaitForClusterRequest).ClusterID,
Timeout: argsI.(*redis.WaitForClusterRequest).Timeout,
RetryInterval: core.DefaultRetryInterval,
})
},
ArgSpecs: core.ArgSpecs{
{
Name: "cluster-id",
Short: "ID of the cluster you want to wait for",
Required: true,
Positional: true,
},
core.ZoneArgSpec(scw.ZoneFrPar1, scw.ZoneFrPar2, scw.ZoneNlAms1, scw.ZoneNlAms2, scw.ZonePlWaw1, scw.ZonePlWaw2),
core.WaitTimeoutArgSpec(redisActionTimeout),
},
Examples: []*core.Example{
{
Short: "Wait for a Redis cluster to reach a stable state",
ArgsJSON: `{"cluster-id": "11111111-1111-1111-1111-111111111111"}`,
},
},
}
}
Loading

0 comments on commit e8cc6da

Please sign in to comment.