Skip to content

Commit cea8e19

Browse files
[CLDGR-748] Adding capacity operations for ns update (#479)
* [CLDGR-749] Use GetNamespace from Cloud API instead * fix * testfix * revert connection.go * refactor] * testfix * unit tests * [CLDGR-748] Adding capacity operations for ns update * test
1 parent d5b7732 commit cea8e19

2 files changed

Lines changed: 198 additions & 0 deletions

File tree

app/namespace.go

Lines changed: 100 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,12 @@ const (
4646
disableFailoverFlagName = "disable-auto-failover"
4747
enableDeleteProtectionFlagName = "enable-delete-protection"
4848
tagFlagName = "tag"
49+
50+
capacityModeFlagName = "capacity-mode"
51+
capacityValueFlagName = "capacity-value"
52+
53+
provisionedCapacityMode = "provisioned"
54+
onDemandCapacityMode = "on_demand"
4955
)
5056

5157
const (
@@ -166,6 +172,28 @@ var (
166172
Aliases: []string{"ids"},
167173
Required: false,
168174
}
175+
176+
capacityModeFlag = &cli.StringFlag{
177+
Name: capacityModeFlagName,
178+
Usage: fmt.Sprintf("The capacity mode to use for the namespace. Valid values are '%s' and '%s'", onDemandCapacityMode, provisionedCapacityMode),
179+
Aliases: []string{"cm"},
180+
Required: false,
181+
Action: func(_ *cli.Context, s string) error {
182+
switch s {
183+
case "", onDemandCapacityMode, provisionedCapacityMode:
184+
return nil
185+
default:
186+
return fmt.Errorf("invalid capacity mode %s, valid values are 'on_demand' and 'provisioned'", s)
187+
}
188+
},
189+
}
190+
191+
capacityValueFlag = &cli.Float64Flag{
192+
Name: capacityValueFlagName,
193+
Usage: "The capacity value to use for the namespace. Required if capacity mode is 'provisioned', ignored otherwise",
194+
Aliases: []string{"cv"},
195+
Required: false,
196+
}
169197
)
170198

171199
type NamespaceClient struct {
@@ -377,6 +405,28 @@ func (c *NamespaceClient) updateNamespace(ctx *cli.Context, n *namespace.Namespa
377405
return PrintProto(res)
378406
}
379407

408+
func (c *NamespaceClient) updateNamespaceCloudApi(ctx *cli.Context, n *cloudNamespace.Namespace) error {
409+
resourceVersion := n.ResourceVersion
410+
if v := ctx.String(ResourceVersionFlagName); v != "" {
411+
resourceVersion = v
412+
}
413+
414+
res, err := c.cloudAPIClient.UpdateNamespace(c.ctx, &cloudservice.UpdateNamespaceRequest{
415+
AsyncOperationId: ctx.String(RequestIDFlagName),
416+
Namespace: n.Namespace,
417+
ResourceVersion: resourceVersion,
418+
Spec: n.Spec,
419+
})
420+
if err != nil {
421+
if isNothingChangedErr(ctx, err) {
422+
return nil
423+
}
424+
return err
425+
}
426+
427+
return PrintProto(res)
428+
}
429+
380430
func (c *NamespaceClient) updateNamespaceTags(ctx *cli.Context, tagsToUpsert map[string]string, tagsToRemove []string) error {
381431
namespace := ctx.String(NamespaceFlagName)
382432
if len(namespace) == 0 {
@@ -1847,6 +1897,56 @@ func NewNamespaceCommand(getNamespaceClientFn GetNamespaceClientFn) (CommandOut,
18471897
return PrintProto(n.GetCapacity())
18481898
},
18491899
},
1900+
{
1901+
Name: "update",
1902+
Usage: "Set the capacity of a given namespace.",
1903+
Aliases: []string{"u"},
1904+
Flags: []cli.Flag{
1905+
NamespaceFlag,
1906+
capacityModeFlag,
1907+
capacityValueFlag,
1908+
RequestIDFlag,
1909+
ResourceVersionFlag,
1910+
},
1911+
Action: func(ctx *cli.Context) error {
1912+
nsID := ctx.String(NamespaceFlagName)
1913+
mode := ctx.String(capacityModeFlagName)
1914+
value := ctx.Float64(capacityValueFlagName)
1915+
if mode == "" {
1916+
return fmt.Errorf("capacity mode must be specified (either '%s' or '%s')", onDemandCapacityMode, provisionedCapacityMode)
1917+
}
1918+
if mode == provisionedCapacityMode && value <= 0 {
1919+
return fmt.Errorf("capacity value must be greater than 0 when capacity mode is '%s'", provisionedCapacityMode)
1920+
}
1921+
var capacitySpec *cloudNamespace.CapacitySpec
1922+
switch mode {
1923+
case onDemandCapacityMode:
1924+
capacitySpec = &cloudNamespace.CapacitySpec{
1925+
Spec: &cloudNamespace.CapacitySpec_OnDemand_{
1926+
OnDemand: &cloudNamespace.CapacitySpec_OnDemand{},
1927+
},
1928+
}
1929+
case provisionedCapacityMode:
1930+
capacitySpec = &cloudNamespace.CapacitySpec{
1931+
Spec: &cloudNamespace.CapacitySpec_Provisioned_{
1932+
Provisioned: &cloudNamespace.CapacitySpec_Provisioned{
1933+
Value: value,
1934+
},
1935+
},
1936+
}
1937+
}
1938+
ns, err := c.getNamespaceCloudApi(nsID)
1939+
if err != nil {
1940+
return err
1941+
}
1942+
1943+
if ns != nil && ns.Spec == nil {
1944+
ns.Spec = &cloudNamespace.NamespaceSpec{}
1945+
}
1946+
ns.Spec.CapacitySpec = capacitySpec
1947+
return c.updateNamespaceCloudApi(ctx, ns)
1948+
},
1949+
},
18501950
},
18511951
},
18521952
}

app/namespace_test.go

Lines changed: 98 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3321,3 +3321,101 @@ func (s *NamespaceTestSuite) TestGetNamespaceCapacity() {
33213321
})
33223322
}
33233323
}
3324+
3325+
func (s *NamespaceTestSuite) TestUpdateNamespaceCapacity() {
3326+
tests := []struct {
3327+
name string
3328+
args []string
3329+
mock func()
3330+
expectErr bool
3331+
}{
3332+
{
3333+
name: "update namespace capacity - success",
3334+
args: []string{"namespace", "capacity", "update", "--namespace", "ns1", "--capacity-mode", "provisioned", "--capacity-value", "16"},
3335+
mock: func() {
3336+
s.mockCloudApiClient.EXPECT().
3337+
GetNamespace(gomock.Any(), &cloudservice.GetNamespaceRequest{
3338+
Namespace: "ns1",
3339+
}).Return(&cloudservice.GetNamespaceResponse{
3340+
Namespace: &cloudNamespace.Namespace{
3341+
Namespace: "ns1",
3342+
Capacity: &cloudNamespace.Capacity{
3343+
CurrentMode: &cloudNamespace.Capacity_OnDemand_{
3344+
OnDemand: &cloudNamespace.Capacity_OnDemand{},
3345+
},
3346+
},
3347+
},
3348+
}, nil).Times(1)
3349+
3350+
s.mockCloudApiClient.EXPECT().
3351+
UpdateNamespace(gomock.Any(), &cloudservice.UpdateNamespaceRequest{
3352+
Namespace: "ns1",
3353+
Spec: &cloudNamespace.NamespaceSpec{
3354+
CapacitySpec: &cloudNamespace.CapacitySpec{
3355+
Spec: &cloudNamespace.CapacitySpec_Provisioned_{
3356+
Provisioned: &cloudNamespace.CapacitySpec_Provisioned{
3357+
Value: 16.0,
3358+
},
3359+
},
3360+
},
3361+
},
3362+
}).
3363+
Return(&cloudservice.UpdateNamespaceResponse{
3364+
AsyncOperation: &operation.AsyncOperation{
3365+
Id: "op-123",
3366+
},
3367+
}, nil)
3368+
3369+
},
3370+
},
3371+
{
3372+
name: "update namespace capacity - failure",
3373+
args: []string{"namespace", "capacity", "update", "--namespace", "ns1", "--capacity-mode", "provisioned", "--capacity-value", "16"},
3374+
mock: func() {
3375+
s.mockCloudApiClient.EXPECT().
3376+
GetNamespace(gomock.Any(), &cloudservice.GetNamespaceRequest{
3377+
Namespace: "ns1",
3378+
}).Return(&cloudservice.GetNamespaceResponse{
3379+
Namespace: &cloudNamespace.Namespace{
3380+
Namespace: "ns1",
3381+
Capacity: &cloudNamespace.Capacity{
3382+
CurrentMode: &cloudNamespace.Capacity_OnDemand_{
3383+
OnDemand: &cloudNamespace.Capacity_OnDemand{},
3384+
},
3385+
},
3386+
},
3387+
}, nil).Times(1)
3388+
3389+
s.mockCloudApiClient.EXPECT().
3390+
UpdateNamespace(gomock.Any(), &cloudservice.UpdateNamespaceRequest{
3391+
Namespace: "ns1",
3392+
Spec: &cloudNamespace.NamespaceSpec{
3393+
CapacitySpec: &cloudNamespace.CapacitySpec{
3394+
Spec: &cloudNamespace.CapacitySpec_Provisioned_{
3395+
Provisioned: &cloudNamespace.CapacitySpec_Provisioned{
3396+
Value: 16.0,
3397+
},
3398+
},
3399+
},
3400+
},
3401+
}).
3402+
Return(nil, errors.New("some error"))
3403+
},
3404+
expectErr: true,
3405+
},
3406+
}
3407+
3408+
for _, tc := range tests {
3409+
s.Run(tc.name, func() {
3410+
if tc.mock != nil {
3411+
tc.mock()
3412+
}
3413+
err := s.RunCmd(tc.args...)
3414+
if tc.expectErr {
3415+
s.Error(err)
3416+
} else {
3417+
s.NoError(err)
3418+
}
3419+
})
3420+
}
3421+
}

0 commit comments

Comments
 (0)