Skip to content

Commit eba0b2a

Browse files
Ciprian Tibulcablvafmenezes
authored
CLOUDP-196796: bcp policy commands (#2484)
Co-authored-by: Bianca Lisle <[email protected]> Co-authored-by: Filipe Constantinov Menezes <[email protected]> Co-authored-by: Bianca <[email protected]>
1 parent 1b8e2bf commit eba0b2a

34 files changed

+1450
-94
lines changed

internal/cli/atlas/backup/compliancepolicy/describe.go

Lines changed: 1 addition & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -32,21 +32,6 @@ type DescribeOpts struct {
3232
store store.CompliancePolicyDescriber
3333
}
3434

35-
var dataProtectionSettingsTemplate = `Project: {{.ProjectId}}
36-
Authorized e-mail: {{.AuthorizedEmail}}
37-
Copy protection enabled: {{.CopyProtectionEnabled}}
38-
Encryption at rest enabled: {{.EncryptionAtRestEnabled}}
39-
Point-in-Time restores enabled: {{.PitEnabled}}
40-
Restore window days: {{.RestoreWindowDays}}
41-
42-
POLICIES
43-
ID FREQUENCY INTERVAL FREQUENCY TYPE RETENTION
44-
{{- range .ScheduledPolicyItems}}
45-
{{.Id}} {{if eq .FrequencyType "hourly"}}{{.FrequencyInterval}}{{else}}-{{end}} {{.FrequencyType}} {{.RetentionValue}} {{.RetentionUnit}}
46-
{{- end}}
47-
{{if .OnDemandPolicyItem}}{{.OnDemandPolicyItem.Id}} - {{.OnDemandPolicyItem.FrequencyType}} {{.OnDemandPolicyItem.RetentionValue}} {{.OnDemandPolicyItem.RetentionUnit}}{{end}}
48-
`
49-
5035
func (opts *DescribeOpts) initStore(ctx context.Context) func() error {
5136
return func() error {
5237
var err error
@@ -74,7 +59,7 @@ func DescribeBuilder() *cobra.Command {
7459
return opts.PreRunE(
7560
opts.ValidateProjectID,
7661
opts.initStore(cmd.Context()),
77-
opts.InitOutput(cmd.OutOrStdout(), dataProtectionSettingsTemplate),
62+
opts.InitOutput(cmd.OutOrStdout(), bcpTemplate),
7863
)
7964
},
8065
RunE: func(cmd *cobra.Command, args []string) error {

internal/cli/atlas/backup/compliancepolicy/describe_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -55,5 +55,5 @@ func TestDescribeOpts_Run(t *testing.T) {
5555
t.Fatalf("Run() unexpected error: %v", err)
5656
}
5757

58-
test.VerifyOutputTemplate(t, dataProtectionSettingsTemplate, expected)
58+
test.VerifyOutputTemplate(t, bcpTemplate, expected)
5959
}

internal/cli/atlas/backup/compliancepolicy/enable.go

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -34,10 +34,12 @@ import (
3434
type EnableOpts struct {
3535
cli.GlobalOpts
3636
cli.WatchOpts
37-
policy *atlasv2.DataProtectionSettings20231001
38-
store store.CompliancePolicyEnabler
39-
authorizedEmail string
40-
confirm bool
37+
policy *atlasv2.DataProtectionSettings20231001
38+
store store.CompliancePolicyEnabler
39+
authorizedUserFirstName string
40+
authorizedUserLastName string
41+
authorizedEmail string
42+
confirm bool
4143
}
4244

4345
var enableConfirmationMessage = `Backup compliance policy can not be disabled without MongoDB Support. Please confirm that you want to continue.
@@ -90,7 +92,7 @@ func (opts *EnableOpts) Run() error {
9092
return errors.New("did not receive confirmation to enable backup compliance policy")
9193
}
9294
}
93-
compliancePolicy, err := opts.store.EnableCompliancePolicy(opts.ConfigProjectID(), opts.authorizedEmail, "", "") // TODO fix when addressing CLOUDP-198381
95+
compliancePolicy, err := opts.store.EnableCompliancePolicy(opts.ConfigProjectID(), opts.authorizedEmail, opts.authorizedUserFirstName, opts.authorizedUserLastName)
9496
opts.policy = compliancePolicy
9597
if err != nil {
9698
return fmt.Errorf("couldn't enable compliance policy: %w", err)
@@ -123,6 +125,10 @@ func EnableBuilder() *cobra.Command {
123125
}
124126

125127
cmd.Flags().StringVar(&opts.ProjectID, flag.ProjectID, "", usage.ProjectID)
128+
cmd.Flags().StringVar(&opts.authorizedUserFirstName, flag.AuthorizedUserFirstName, "", usage.AuthorizedUserFirstName)
129+
_ = cmd.MarkFlagRequired(flag.AuthorizedUserFirstName)
130+
cmd.Flags().StringVar(&opts.authorizedUserLastName, flag.AuthorizedUserLastName, "", usage.AuthorizedUserLastName)
131+
_ = cmd.MarkFlagRequired(flag.AuthorizedUserLastName)
126132
cmd.Flags().StringVar(&opts.authorizedEmail, flag.AuthorizedEmail, "", usage.AuthorizedEmail)
127133
_ = cmd.MarkFlagRequired(flag.AuthorizedEmail)
128134
cmd.Flags().BoolVarP(&opts.EnableWatch, flag.EnableWatch, flag.EnableWatchShort, false, usage.EnableWatchDefault)

internal/cli/atlas/backup/compliancepolicy/enable_test.go

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,9 @@ import (
2727
)
2828

2929
const (
30-
authorizedEmail = "[email protected]"
30+
authorizedUserFirstName = "firstname"
31+
authorizedUserLastName = "lastname"
32+
authorizedEmail = "[email protected]"
3133
)
3234

3335
func TestEnableBuilder(t *testing.T) {
@@ -37,6 +39,8 @@ func TestEnableBuilder(t *testing.T) {
3739
0,
3840
[]string{
3941
flag.ProjectID,
42+
flag.AuthorizedUserFirstName,
43+
flag.AuthorizedUserLastName,
4044
flag.AuthorizedEmail,
4145
flag.Output,
4246
flag.EnableWatch,
@@ -74,21 +78,22 @@ func TestEnableOpts_Run(t *testing.T) {
7478
ctrl := gomock.NewController(t)
7579
mockStore := mocks.NewMockCompliancePolicyEnabler(ctrl)
7680
state := active
77-
email := authorizedEmail
7881

7982
expected := &atlasv2.DataProtectionSettings20231001{
8083
State: &state,
8184
}
8285

8386
opts := &EnableOpts{
84-
store: mockStore,
85-
authorizedEmail: email,
86-
confirm: true,
87+
store: mockStore,
88+
authorizedUserFirstName: authorizedUserFirstName,
89+
authorizedUserLastName: authorizedUserLastName,
90+
authorizedEmail: authorizedEmail,
91+
confirm: true,
8792
}
8893

8994
mockStore.
9095
EXPECT().
91-
EnableCompliancePolicy(opts.ProjectID, email, "", "").
96+
EnableCompliancePolicy(opts.ProjectID, authorizedEmail, authorizedUserFirstName, authorizedUserLastName).
9297
Return(expected, nil).
9398
Times(1)
9499

Lines changed: 115 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,115 @@
1+
// Copyright 2023 MongoDB Inc
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// http://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
15+
package ondemand
16+
17+
import (
18+
"context"
19+
"fmt"
20+
21+
"github.com/mongodb/mongodb-atlas-cli/internal/cli"
22+
"github.com/mongodb/mongodb-atlas-cli/internal/config"
23+
"github.com/mongodb/mongodb-atlas-cli/internal/flag"
24+
store "github.com/mongodb/mongodb-atlas-cli/internal/store/atlas"
25+
"github.com/mongodb/mongodb-atlas-cli/internal/usage"
26+
"github.com/spf13/cobra"
27+
atlasv2 "go.mongodb.org/atlas-sdk/v20231115002/admin"
28+
)
29+
30+
type CreateOpts struct {
31+
cli.GlobalOpts
32+
cli.WatchOpts
33+
store store.CompliancePolicyOnDemandPolicyCreator
34+
policy *atlasv2.DataProtectionSettings20231001
35+
retentionUnit string
36+
retentionValue int
37+
}
38+
39+
const (
40+
active = "ACTIVE"
41+
onDemandFrequencyType = "ondemand"
42+
)
43+
44+
const updateTemplate = `Your backup compliance policy is being updated
45+
`
46+
const updateWatchTemplate = `Your backup compliance policy has been updated
47+
`
48+
49+
func (opts *CreateOpts) initStore(ctx context.Context) func() error {
50+
return func() (err error) {
51+
opts.store, err = store.New(store.AuthenticatedPreset(config.Default()), store.WithContext(ctx))
52+
return
53+
}
54+
}
55+
56+
func (opts *CreateOpts) watcher() (bool, error) {
57+
res, err := opts.store.DescribeCompliancePolicy(opts.ConfigProjectID())
58+
if err != nil {
59+
return false, err
60+
}
61+
opts.policy = res
62+
return res.GetState() == active, nil
63+
}
64+
65+
func (opts *CreateOpts) Run() (err error) {
66+
policyItem := &atlasv2.BackupComplianceOnDemandPolicyItem{
67+
FrequencyType: onDemandFrequencyType,
68+
RetentionUnit: opts.retentionUnit,
69+
RetentionValue: opts.retentionValue,
70+
}
71+
72+
if opts.policy, err = opts.store.CreateOnDemandPolicy(opts.ProjectID, policyItem); err != nil {
73+
return err
74+
}
75+
76+
if opts.EnableWatch {
77+
if errW := opts.Watch(opts.watcher); errW != nil {
78+
return fmt.Errorf("received an error while watching for completion: %w", errW)
79+
}
80+
opts.Template = updateWatchTemplate
81+
}
82+
return opts.Print(opts.policy)
83+
}
84+
85+
func CreateBuilder() *cobra.Command {
86+
opts := &CreateOpts{}
87+
cmd := &cobra.Command{
88+
Use: "create",
89+
Short: "Create the on-demand policy item of the backup compliance policy for your project.",
90+
Example: ` # Create a backup compliance on-demand policy with a retention of two weeks:
91+
atlas backups compliancepolicy policies ondemand create --retentionUnit weeks --retentionValue 2`,
92+
PreRunE: func(cmd *cobra.Command, args []string) error {
93+
return opts.PreRunE(
94+
opts.ValidateProjectID,
95+
opts.initStore(cmd.Context()),
96+
opts.InitOutput(cmd.OutOrStdout(), updateTemplate),
97+
)
98+
},
99+
RunE: func(cmd *cobra.Command, args []string) error {
100+
return opts.Run()
101+
},
102+
}
103+
104+
cmd.Flags().StringVar(&opts.retentionUnit, flag.RetentionUnit, "", usage.RetentionUnit)
105+
cmd.Flags().IntVar(&opts.retentionValue, flag.RetentionValue, 0, usage.RetentionValue)
106+
_ = cmd.MarkFlagRequired(flag.RetentionUnit)
107+
_ = cmd.MarkFlagRequired(flag.RetentionValue)
108+
109+
cmd.Flags().BoolVarP(&opts.EnableWatch, flag.EnableWatch, flag.EnableWatchShort, false, usage.EnableWatchDefault)
110+
cmd.Flags().StringVar(&opts.ProjectID, flag.ProjectID, "", usage.ProjectID)
111+
cmd.Flags().StringVarP(&opts.Output, flag.Output, flag.OutputShort, "", usage.FormatOut)
112+
_ = cmd.RegisterFlagCompletionFunc(flag.Output, opts.AutoCompleteOutputFlag())
113+
114+
return cmd
115+
}
Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
// Copyright 2023 MongoDB Inc
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// http://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
15+
package ondemand
16+
17+
import (
18+
"testing"
19+
20+
"github.com/golang/mock/gomock"
21+
"github.com/mongodb/mongodb-atlas-cli/internal/flag"
22+
"github.com/mongodb/mongodb-atlas-cli/internal/mocks/atlas"
23+
"github.com/mongodb/mongodb-atlas-cli/internal/test"
24+
atlasv2 "go.mongodb.org/atlas-sdk/v20231115002/admin"
25+
)
26+
27+
func TestCreateOpts_Run(t *testing.T) {
28+
ctrl := gomock.NewController(t)
29+
mockStore := atlas.NewMockCompliancePolicyOnDemandPolicyCreator(ctrl)
30+
31+
createOpts := &CreateOpts{
32+
store: mockStore,
33+
retentionUnit: "days",
34+
retentionValue: 30,
35+
}
36+
37+
policyItem := &atlasv2.BackupComplianceOnDemandPolicyItem{
38+
FrequencyType: onDemandFrequencyType,
39+
RetentionUnit: createOpts.retentionUnit,
40+
RetentionValue: createOpts.retentionValue,
41+
}
42+
43+
expected := &atlasv2.DataProtectionSettings20231001{}
44+
45+
mockStore.
46+
EXPECT().
47+
CreateOnDemandPolicy("", policyItem).Return(expected, nil).
48+
Times(1)
49+
50+
if err := createOpts.Run(); err != nil {
51+
t.Fatalf("Run() unexpected error: %v", err)
52+
}
53+
}
54+
55+
func TestCreateBuilder(t *testing.T) {
56+
test.CmdValidator(
57+
t,
58+
CreateBuilder(),
59+
0,
60+
[]string{flag.RetentionUnit, flag.RetentionValue, flag.EnableWatch, flag.ProjectID, flag.Output},
61+
)
62+
}
63+
func TestCreateTemplate(t *testing.T) {
64+
test.VerifyOutputTemplate(t, updateTemplate, &atlasv2.DataProtectionSettings20231001{})
65+
}
Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
// Copyright 2023 MongoDB Inc
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// http://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
15+
package ondemand
16+
17+
import (
18+
"context"
19+
20+
"github.com/mongodb/mongodb-atlas-cli/internal/cli"
21+
"github.com/mongodb/mongodb-atlas-cli/internal/config"
22+
"github.com/mongodb/mongodb-atlas-cli/internal/flag"
23+
store "github.com/mongodb/mongodb-atlas-cli/internal/store/atlas"
24+
"github.com/mongodb/mongodb-atlas-cli/internal/usage"
25+
"github.com/spf13/cobra"
26+
)
27+
28+
type DescribeOpts struct {
29+
cli.GlobalOpts
30+
cli.OutputOpts
31+
store store.CompliancePolicyDescriber
32+
}
33+
34+
const describeTemplate = `ID RETENTION
35+
{{if .}}{{.Id}} {{.RetentionValue}} {{.RetentionUnit}}{{end}}
36+
`
37+
38+
func (opts *DescribeOpts) initStore(ctx context.Context) func() error {
39+
return func() error {
40+
var err error
41+
opts.store, err = store.New(store.AuthenticatedPreset(config.Default()), store.WithContext(ctx))
42+
return err
43+
}
44+
}
45+
46+
func (opts *DescribeOpts) Run() error {
47+
raw, err := opts.store.DescribeCompliancePolicy(opts.ConfigProjectID())
48+
if err != nil {
49+
return err
50+
}
51+
52+
return opts.Print(raw.OnDemandPolicyItem)
53+
}
54+
55+
func DescribeBuilder() *cobra.Command {
56+
opts := new(DescribeOpts)
57+
cmd := &cobra.Command{
58+
Use: "describe",
59+
Aliases: []string{"get"},
60+
Short: "Return the on-demand policy item of the backup compliance policy for your project.",
61+
PreRunE: func(cmd *cobra.Command, args []string) error {
62+
return opts.PreRunE(
63+
opts.ValidateProjectID,
64+
opts.initStore(cmd.Context()),
65+
opts.InitOutput(cmd.OutOrStdout(), describeTemplate),
66+
)
67+
},
68+
RunE: func(cmd *cobra.Command, args []string) error {
69+
return opts.Run()
70+
},
71+
}
72+
73+
cmd.Flags().StringVar(&opts.ProjectID, flag.ProjectID, "", usage.ProjectID)
74+
cmd.Flags().StringVarP(&opts.Output, flag.Output, flag.OutputShort, "", usage.FormatOut)
75+
_ = cmd.RegisterFlagCompletionFunc(flag.Output, opts.AutoCompleteOutputFlag())
76+
77+
return cmd
78+
}

0 commit comments

Comments
 (0)