Skip to content

Commit aa3354c

Browse files
#878 added revoke tests, updated gosec to not be quiet.
1 parent 64bb5bb commit aa3354c

File tree

13 files changed

+145
-76
lines changed

13 files changed

+145
-76
lines changed

bin/buildAndDeploy.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -94,7 +94,7 @@ def runTests() -> None:
9494
except subprocess.CalledProcessError as e:
9595
print(f"[red]>>> Go Test failed <<<")
9696
sys.exit(e.returncode)
97-
go_sec = ['gosec', '-exclude-dir=fixture', '-exclude-dir=plugin/resources', '-quiet', './...']
97+
go_sec = ['gosec', '-exclude-dir=fixture', '-exclude-dir=plugin/resources', '-exclude-generated', './...']
9898
# Not using the 'real' command because this is more copy/pasteable.
9999
print('[turquoise2]Running: ' + " ".join(go_sec))
100100
try:

plugin/commands/block/access_revoke.go

Lines changed: 78 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,14 @@
11
package block
22

33
import (
4+
"strconv"
45
"github.com/spf13/cobra"
56

67
slErr "github.ibm.com/SoftLayer/softlayer-cli/plugin/errors"
78
. "github.ibm.com/SoftLayer/softlayer-cli/plugin/i18n"
89
"github.ibm.com/SoftLayer/softlayer-cli/plugin/managers"
910
"github.ibm.com/SoftLayer/softlayer-cli/plugin/metadata"
11+
"github.ibm.com/SoftLayer/softlayer-cli/plugin/utils"
1012
)
1113

1214
type AccessRevokeCommand struct {
@@ -18,6 +20,7 @@ type AccessRevokeCommand struct {
1820
Virtual_id []int
1921
Ip_address_id []int
2022
Ip_address []string
23+
Subnet_id int
2124
}
2225

2326
func NewAccessRevokeCommand(sl *metadata.SoftlayerStorageCommand) *AccessRevokeCommand {
@@ -29,27 +32,44 @@ func NewAccessRevokeCommand(sl *metadata.SoftlayerStorageCommand) *AccessRevokeC
2932
cobraCmd := &cobra.Command{
3033
Use: "access-revoke " + T("IDENTIFIER"),
3134
Short: T("Revoke authorization for hosts that are accessing a specific volume."),
32-
Long: T(`${COMMAND_NAME} sl {{.storageType}} access-revoke VOLUME_ID [OPTIONS]
33-
34-
EXAMPLE:
35+
Long: T(`EXAMPLE:
3536
${COMMAND_NAME} sl {{.storageType}} access-revoke 12345678 --virtual-id 87654321
36-
This command revokes access of virtual server with ID 87654321 to volume with ID 12345678.`, sl.StorageI18n),
37+
This command revokes access of virtual server with ID 87654321 to volume with ID 12345678.`, sl.StorageI18n) + "\n" +
38+
T(`
39+
${COMMAND_NAME} sl {{.storageType}} access-revoke 5555 --subnet-id 1111
40+
This command removes subnet with id 1111 from the Allowed Host with id 5555. Use 'access-list' to find this id.`, sl.StorageI18n),
3741
Args: metadata.OneArgs,
3842
RunE: func(cmd *cobra.Command, args []string) error {
3943
return thisCmd.Run(args)
4044
},
4145
}
4246

43-
cobraCmd.Flags().IntSliceVarP(&thisCmd.Hardware_id, "hardware-id", "d", []int{}, T("The ID of one hardware server to revoke"))
44-
cobraCmd.Flags().IntSliceVarP(&thisCmd.Virtual_id, "virtual-id", "v", []int{}, T("The ID of one virtual server to revoke"))
45-
cobraCmd.Flags().IntSliceVarP(&thisCmd.Ip_address_id, "ip-address-id", "i", []int{}, T("The ID of one IP address to revoke"))
46-
cobraCmd.Flags().StringSliceVarP(&thisCmd.Ip_address, "ip-address", "p", []string{}, T("An IP address to revoke"))
47+
cobraCmd.Flags().IntSliceVarP(&thisCmd.Hardware_id, "hardware-id", "d", []int{},
48+
T("The ID of one hardware server to revoke"))
49+
cobraCmd.Flags().IntSliceVarP(&thisCmd.Virtual_id, "virtual-id", "v", []int{},
50+
T("The ID of one virtual server to revoke"))
51+
cobraCmd.Flags().IntSliceVarP(&thisCmd.Ip_address_id, "ip-address-id", "i", []int{},
52+
T("The ID of one IP address to revoke"))
53+
cobraCmd.Flags().StringSliceVarP(&thisCmd.Ip_address, "ip-address", "p", []string{},
54+
T("An IP address to revoke"))
55+
cobraCmd.Flags().IntVarP(&thisCmd.Subnet_id, "subnet-id", "s", 0,
56+
T("A Subnet Id. With this option IDENTIFIER should be an 'allowed_host_id' from the access-list command."))
4757
thisCmd.Command = cobraCmd
4858

4959
return thisCmd
5060
}
5161

5262
func (cmd *AccessRevokeCommand) Run(args []string) error {
63+
64+
// Subnets have to get added to an existing authorized host.
65+
if cmd.Subnet_id > 0 {
66+
hostId, err := strconv.Atoi(args[0])
67+
if err != nil {
68+
return slErr.NewInvalidSoftlayerIdInputError("Allowed Host IDENTIFIER")
69+
}
70+
return cmd.RemoveSubnetFromHost(hostId)
71+
}
72+
5373
volumeID, err := cmd.StorageManager.GetVolumeId(args[0], cmd.StorageType)
5474
if err != nil {
5575
return err
@@ -76,17 +96,60 @@ func (cmd *AccessRevokeCommand) Run(args []string) error {
7696
}
7797
_, err = cmd.StorageManager.DeauthorizeHostToVolume(volumeID, cmd.Hardware_id, cmd.Virtual_id, IPIds, nil)
7898
if err != nil {
79-
return slErr.NewAPIError(T("Failed to revoke access to volume {{.VolumeID}}.\n", map[string]interface{}{"VolumeID": volumeID}), err.Error(), 2)
99+
subs := map[string]interface{}{"VolumeID": volumeID}
100+
return slErr.NewAPIError(T("Failed to revoke access to volume {{.VolumeID}}.\n", subs), err.Error(), 2)
80101
}
81102
cmd.UI.Ok()
82-
for _, vsID := range cmd.Virtual_id {
83-
cmd.UI.Print(T("Access to {{.VolumeId}} was revoked for virtual server {{.VsID}}.", map[string]interface{}{"VolumeId": volumeID, "VsID": vsID}))
103+
subs := map[string]interface{}{
104+
"VolumeId": volumeID,
105+
"SL_ID": 0,
106+
"SL_Object": "",
84107
}
85-
for _, hwID := range cmd.Hardware_id {
86-
cmd.UI.Print(T("Access to {{.VolumeId}} was revoked for hardware server {{.HwID}}.", map[string]interface{}{"VolumeId": volumeID, "HwID": hwID}))
108+
for _, sl_id := range cmd.Virtual_id {
109+
subs["SL_Object"] = T("Virtual Server")
110+
subs["SL_ID"] = sl_id
111+
cmd.UI.Print(T("Access to {{.VolumeId}} was revoked for {{.SL_Object}} {{.SL_ID}}.", subs))
87112
}
88-
for _, ip := range IPIds {
89-
cmd.UI.Print(T("Access to {{.VolumeId}} was revoked for IP address {{.IP}}.", map[string]interface{}{"VolumeId": volumeID, "IP": ip}))
113+
for _, sl_id := range cmd.Hardware_id {
114+
subs["SL_Object"] = T("Hardware Server")
115+
subs["SL_ID"] = sl_id
116+
cmd.UI.Print(T("Access to {{.VolumeId}} was revoked for {{.SL_Object}} {{.SL_ID}}.", subs))
117+
}
118+
for _, sl_id := range IPIds {
119+
subs["SL_Object"] = T("IP Address")
120+
subs["SL_ID"] = sl_id
121+
cmd.UI.Print(T("Access to {{.VolumeId}} was revoked for {{.SL_Object}} {{.SL_ID}}.", subs))
90122
}
91123
return nil
92124
}
125+
126+
func (cmd *AccessRevokeCommand) RemoveSubnetFromHost(host_id int) error {
127+
128+
outputFormat := cmd.GetOutputFlag()
129+
subnet_ids := []int{cmd.Subnet_id}
130+
resp, err := cmd.StorageManager.RemoveSubnetsFromAcl(host_id, subnet_ids)
131+
if err != nil {
132+
return err
133+
}
134+
// If the API returns an empty array, that means it didn't add the subnet we asked for.
135+
// Likely because ISCSI Isolation is disabled on the account.
136+
// ibmcloud sl call-api SoftLayer_Account getObject --mask="mask[id,iscsiIsolationDisabled]"
137+
if len(resp) == 0 || utils.IntInSlice(cmd.Subnet_id, resp) == -1 {
138+
subs := map[string]interface{}{"subnetID": cmd.Subnet_id, "accessID": host_id}
139+
return slErr.NewAPIError(
140+
T("Failed to remove subnet id: {{.subnetID}} from allowed host id: {{.accessID}}", subs), "", 2,
141+
)
142+
}
143+
if outputFormat == "JSON" {
144+
return utils.PrintPrettyJSON(cmd.UI, resp)
145+
}
146+
147+
cmd.UI.Ok()
148+
subs := map[string]interface{}{
149+
"VolumeId": host_id,
150+
"SL_ID": cmd.Subnet_id,
151+
"SL_Object": T("Subnet"),
152+
}
153+
cmd.UI.Print(T("Access to {{.VolumeId}} was revoked for {{.SL_Object}} {{.SL_ID}}.", subs))
154+
return nil
155+
}

plugin/commands/block/access_revoke_test.go

Lines changed: 36 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -38,85 +38,79 @@ var _ = Describe("Access Revoke", func() {
3838
})
3939

4040
Describe("Access Revoke", func() {
41-
Context("Access revoke without volume id", func() {
42-
It("return error", func() {
41+
Context("Syntax Errors", func() {
42+
It("Require One Argument", func() {
4343
err := testhelpers.RunCobraCommand(cliCommand.Command)
4444
Expect(err).To(HaveOccurred())
4545
Expect(err.Error()).To(ContainSubstring("Incorrect Usage: This command requires one argument"))
4646
})
4747
})
4848

49-
Context("Access revoke with correct volume id and virtual server id", func() {
49+
Context("Successful Revokations", func() {
5050
BeforeEach(func() {
5151
FakeStorageManager.DeauthorizeHostToVolumeReturns([]datatypes.Network_Storage_Allowed_Host{}, nil)
5252
})
53-
It("return no error", func() {
53+
It("Virtual Server", func() {
5454
err := testhelpers.RunCobraCommand(cliCommand.Command, "1234", "--virtual-id", "5678")
5555
Expect(err).NotTo(HaveOccurred())
56-
Expect(fakeUI.Outputs()).To(ContainSubstring("Access to 1234 was revoked for virtual server 5678"))
56+
Expect(fakeUI.Outputs()).To(ContainSubstring("Access to 1234 was revoked for Virtual Server 5678"))
5757
})
58-
})
59-
60-
Context("Access revoke with correct volume id and hardware server id", func() {
61-
BeforeEach(func() {
62-
FakeStorageManager.DeauthorizeHostToVolumeReturns([]datatypes.Network_Storage_Allowed_Host{}, nil)
63-
})
64-
It("return no error", func() {
58+
It("Hardware Server", func() {
6559
err := testhelpers.RunCobraCommand(cliCommand.Command, "1234", "--hardware-id", "5678")
6660
Expect(err).NotTo(HaveOccurred())
67-
Expect(fakeUI.Outputs()).To(ContainSubstring("Access to 1234 was revoked for hardware server 5678."))
68-
})
69-
})
70-
71-
Context("Access revoke with correct volume id and ip address id", func() {
72-
BeforeEach(func() {
73-
FakeStorageManager.DeauthorizeHostToVolumeReturns([]datatypes.Network_Storage_Allowed_Host{}, nil)
61+
Expect(fakeUI.Outputs()).To(ContainSubstring("Access to 1234 was revoked for Hardware Server 5678."))
7462
})
75-
It("return no error", func() {
63+
It("Single IP Address ID", func() {
7664
err := testhelpers.RunCobraCommand(cliCommand.Command, "1234", "--ip-address-id", "5678")
7765
Expect(err).NotTo(HaveOccurred())
78-
Expect(fakeUI.Outputs()).To(ContainSubstring("Access to 1234 was revoked for IP address 5678."))
66+
Expect(fakeUI.Outputs()).To(ContainSubstring("Access to 1234 was revoked for IP Address 5678."))
7967
})
80-
})
81-
82-
Context("Access revoke with correct volume id and ip address", func() {
83-
BeforeEach(func() {
84-
FakeStorageManager.DeauthorizeHostToVolumeReturns([]datatypes.Network_Storage_Allowed_Host{}, nil)
68+
It("Single IP address", func() {
8569
fakeNetworkManager.IPLookupReturns(datatypes.Network_Subnet_IpAddress{Id: sl.Int(5678)}, nil)
86-
})
87-
It("return no error", func() {
8870
err := testhelpers.RunCobraCommand(cliCommand.Command, "1234", "--ip-address", "1.2.3.4")
8971
Expect(err).NotTo(HaveOccurred())
90-
Expect(fakeUI.Outputs()).To(ContainSubstring("Access to 1234 was revoked for IP address 5678."))
72+
Expect(fakeUI.Outputs()).To(ContainSubstring("Access to 1234 was revoked for IP Address 5678."))
9173
})
9274
})
9375

94-
Context("Access revoke with correct volume id and wrong ip address", func() {
76+
Context("Error Handling", func() {
9577
BeforeEach(func() {
96-
FakeStorageManager.DeauthorizeHostToVolumeReturns([]datatypes.Network_Storage_Allowed_Host{}, nil)
97-
fakeNetworkManager.IPLookupReturns(datatypes.Network_Subnet_IpAddress{}, errors.New("Not Found"))
78+
FakeStorageManager.DeauthorizeHostToVolumeReturns([]datatypes.Network_Storage_Allowed_Host{}, nil)
9879
})
99-
It("return error", func() {
80+
It("IP Not Found", func() {
81+
fakeNetworkManager.IPLookupReturns(datatypes.Network_Subnet_IpAddress{}, errors.New("Not Found"))
10082
err := testhelpers.RunCobraCommand(cliCommand.Command, "1234", "--ip-address", "1.2.3.4")
10183
Expect(err).To(HaveOccurred())
102-
Expect(err.Error()).To(ContainSubstring("IP address 1.2.3.4 is not found on your account.Please confirm IP and try again."))
84+
Expect(err.Error()).To(ContainSubstring("IP address 1.2.3.4 is not found on your account."))
10385
Expect(err.Error()).To(ContainSubstring("Not Found"))
10486
})
105-
})
106-
107-
Context("Access Authorize with correct volume id but server API call fails", func() {
108-
BeforeEach(func() {
87+
It("API error", func() {
10988
FakeStorageManager.DeauthorizeHostToVolumeReturns(
110-
[]datatypes.Network_Storage_Allowed_Host{},
111-
errors.New("Internal Server Error"),
89+
[]datatypes.Network_Storage_Allowed_Host{}, errors.New("Internal Server Error"),
11290
)
113-
})
114-
It("return error", func() {
11591
err := testhelpers.RunCobraCommand(cliCommand.Command, "1234", "--virtual-id", "5678")
11692
Expect(err).To(HaveOccurred())
11793
Expect(err.Error()).To(ContainSubstring("Failed to revoke access to volume 1234."))
11894
Expect(err.Error()).To(ContainSubstring("Internal Server Error"))
11995
})
96+
It("Subnet not removed because isci isolation", func() {
97+
FakeStorageManager.RemoveSubnetsFromAclReturns([]int{}, nil)
98+
err := testhelpers.RunCobraCommand(cliCommand.Command, "1234", "--subnet-id", "5678")
99+
Expect(err).To(HaveOccurred())
100+
Expect(err.Error()).To(ContainSubstring("Failed to remove subnet id: 5678"))
101+
})
102+
It("Subnet not removed because wrong subnet returned", func() {
103+
FakeStorageManager.RemoveSubnetsFromAclReturns([]int{999}, nil)
104+
err := testhelpers.RunCobraCommand(cliCommand.Command, "1234", "--subnet-id", "5678")
105+
Expect(err).To(HaveOccurred())
106+
Expect(err.Error()).To(ContainSubstring("Failed to remove subnet id: 5678"))
107+
})
108+
It("Subnet not removed because API error", func() {
109+
FakeStorageManager.RemoveSubnetsFromAclReturns([]int{}, errors.New("API ERROR"))
110+
err := testhelpers.RunCobraCommand(cliCommand.Command, "1234", "--subnet-id", "5678")
111+
Expect(err).To(HaveOccurred())
112+
Expect(err.Error()).To(ContainSubstring("API ERROR"))
113+
})
120114
})
121115
})
122116
})

plugin/i18n/v2Resources/active.de_DE.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -353,8 +353,8 @@
353353
"${COMMAND_NAME} sl {{.storageType}} access-password ACCESS_ID --password PASSWORD\n\t\n\tACCESS_ID is the allowed_host_id from '${COMMAND_NAME} sl {{.storageType}} access-list'": {
354354
"other": "${COMMAND_NAME} sl {{.storageType}} access-password ACCESS_ID--password PASSWORD\n \n ACCESS_ID ist die zulässige Host-ID (allowed_host_id) aus '${COMMAND_NAME} sl {{.storageType}} access-list'"
355355
},
356-
"${COMMAND_NAME} sl {{.storageType}} access-revoke VOLUME_ID [OPTIONS]\n\t\t\nEXAMPLE:\n ${COMMAND_NAME} sl {{.storageType}} access-revoke 12345678 --virtual-id 87654321\n This command revokes access of virtual server with ID 87654321 to volume with ID 12345678.": {
357-
"other": "${COMMAND_NAME} sl {{.storageType}} access-revoke DATENTRÄGER_ID [OPTIONEN]\n \nBEISPIEL:\n ${COMMAND_NAME} sl {{.storageType}} access-revoke 12345678 --virtual-id 87654321\n Dieser Befehl widerruft den Zugriff des virtuellen Servers mit der ID 87654321 auf den Datenträger mit der ID 12345678."
356+
"EXAMPLE:\n ${COMMAND_NAME} sl {{.storageType}} access-revoke 12345678 --virtual-id 87654321\n This command revokes access of virtual server with ID 87654321 to volume with ID 12345678.": {
357+
"other": "BEISPIEL:\n ${COMMAND_NAME} sl {{.storageType}} access-revoke 12345678 --virtual-id 87654321\n Dieser Befehl widerruft den Zugriff des virtuellen Servers mit der ID 87654321 auf den Datenträger mit der ID 12345678."
358358
},
359359
"${COMMAND_NAME} sl {{.storageType}} replica-failback VOLUME_ID\n\t\t\nEXAMPLE:\n ${COMMAND_NAME} sl {{.storageType}} replica-failback 12345678\n This command performs failback operation for volume with ID 12345678.": {
360360
"other": "${COMMAND_NAME} sl {{.storageType}} replica-failback DATENTRÄGER_ID\n \nBEISPIEL:\n ${COMMAND_NAME} sl {{.storageType}} replica-failback 12345678\n Dieser Befehl führt eine Failback-Operation für einen Datenträger mit der ID 12345678 durch."

plugin/i18n/v2Resources/active.en-US.json

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,9 @@
22
"\n ${COMMAND_NAME} sl {{.storageType}} access-authorize 5555 --subnet-id 1111\n This command adds subnet with id 1111 to the Allowed Host with id 5555. Use 'access-list' to find this id.\n SoftLayer_Account::iscsiIsolationDisabled must be False for this command to do anything.": {
33
"other": "\n ${COMMAND_NAME} sl {{.storageType}} access-authorize 5555 --subnet-id 1111\n This command adds subnet with id 1111 to the Allowed Host with id 5555. Use 'access-list' to find this id.\n SoftLayer_Account::iscsiIsolationDisabled must be False for this command to do anything."
44
},
5+
"\n ${COMMAND_NAME} sl {{.storageType}} access-revoke 5555 --subnet-id 1111\n This command removes subnet with id 1111 from the Allowed Host with id 5555. Use 'access-list' to find this id.": {
6+
"other": "\n ${COMMAND_NAME} sl {{.storageType}} access-revoke 5555 --subnet-id 1111\n This command removes subnet with id 1111 from the Allowed Host with id 5555. Use 'access-list' to find this id."
7+
},
58
"\nEXAMPLE:\n ${COMMAND_NAME} sl {{.storageType}} replica-locations 12345678\n This command lists suitable replication data centers for block volume with ID 12345678.": {
69
"other": "\nEXAMPLE:\n ${COMMAND_NAME} sl {{.storageType}} replica-locations 12345678\n This command lists suitable replication data centers for block volume with ID 12345678."
710
},
@@ -680,6 +683,9 @@
680683
"Access to {{.VolumeId}} was revoked for virtual server {{.VsID}}.": {
681684
"other": "Access to {{.VolumeId}} was revoked for virtual server {{.VsID}}."
682685
},
686+
"Access to {{.VolumeId}} was revoked for {{.SL_Object}} {{.SL_ID}}.": {
687+
"other": "Access to {{.VolumeId}} was revoked for {{.SL_Object}} {{.SL_ID}}."
688+
},
683689
"Account": {
684690
"other": "Account"
685691
},
@@ -1886,6 +1892,9 @@
18861892
"EXAMPLE:\n ${COMMAND_NAME} sl {{.storageType}} access-list 12345678 --sortby id \n This command lists all hosts that are authorized to access volume with ID 12345678 and sorts them by ID.": {
18871893
"other": "EXAMPLE:\n ${COMMAND_NAME} sl {{.storageType}} access-list 12345678 --sortby id \n This command lists all hosts that are authorized to access volume with ID 12345678 and sorts them by ID."
18881894
},
1895+
"EXAMPLE:\n ${COMMAND_NAME} sl {{.storageType}} access-revoke 12345678 --virtual-id 87654321\n This command revokes access of virtual server with ID 87654321 to volume with ID 12345678.": {
1896+
"other": "EXAMPLE:\n ${COMMAND_NAME} sl {{.storageType}} access-revoke 12345678 --virtual-id 87654321\n This command revokes access of virtual server with ID 87654321 to volume with ID 12345678."
1897+
},
18891898
"EXAMPLE:\n ${COMMAND_NAME} sl {{.storageType}} replica-failover 12345678 87654321\n This command performs failover operation for volume with ID 12345678 to replica volume with ID 87654321.": {
18901899
"other": "EXAMPLE:\n ${COMMAND_NAME} sl {{.storageType}} replica-failover 12345678 87654321\n This command performs failover operation for volume with ID 12345678 to replica volume with ID 87654321."
18911900
},
@@ -3122,6 +3131,9 @@
31223131
"Failed to remove rule {{.RuleId}} in security group {{.GroupID}}.\n": {
31233132
"other": "Failed to remove rule {{.RuleId}} in security group {{.GroupID}}.\n"
31243133
},
3134+
"Failed to remove subnet id: {{.subnetID}} from allowed host id: {{.accessID}}": {
3135+
"other": "Failed to remove subnet id: {{.subnetID}} from allowed host id: {{.accessID}}"
3136+
},
31253137
"Failed to remove subnet id: {{.subnetID}} to allowed host id: {{.accessID}}": {
31263138
"other": "Failed to remove subnet id: {{.subnetID}} to allowed host id: {{.accessID}}"
31273139
},

plugin/i18n/v2Resources/active.es_ES.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -353,8 +353,8 @@
353353
"${COMMAND_NAME} sl {{.storageType}} access-password ACCESS_ID --password PASSWORD\n\t\n\tACCESS_ID is the allowed_host_id from '${COMMAND_NAME} sl {{.storageType}} access-list'": {
354354
"other": "${COMMAND_NAME} sl {{.storageType}} access-password ACCESS_ID--password PASSWORD\n\nACCESS_ID es el allowed_host_id de '${COMMAND_NAME} sl {{.storageType}} access-list'"
355355
},
356-
"${COMMAND_NAME} sl {{.storageType}} access-revoke VOLUME_ID [OPTIONS]\n\t\t\nEXAMPLE:\n ${COMMAND_NAME} sl {{.storageType}} access-revoke 12345678 --virtual-id 87654321\n This command revokes access of virtual server with ID 87654321 to volume with ID 12345678.": {
357-
"other": "${COMMAND_NAME} sl {{.storageType}} access-revoke VOLUME_ID [OPTIONS]\n\nEJEMPLO:\n ${COMMAND_NAME} sl {{.storageType}} access-revoke 12345678 --virtual-id 87654321\n Este mandato revoca el acceso del servidor virtual con ID 87654321 al volumen con ID 12345678."
356+
"EXAMPLE:\n ${COMMAND_NAME} sl {{.storageType}} access-revoke 12345678 --virtual-id 87654321\n This command revokes access of virtual server with ID 87654321 to volume with ID 12345678.": {
357+
"other": "EJEMPLO:\n ${COMMAND_NAME} sl {{.storageType}} access-revoke 12345678 --virtual-id 87654321\n Este mandato revoca el acceso del servidor virtual con ID 87654321 al volumen con ID 12345678."
358358
},
359359
"${COMMAND_NAME} sl {{.storageType}} replica-failback VOLUME_ID\n\t\t\nEXAMPLE:\n ${COMMAND_NAME} sl {{.storageType}} replica-failback 12345678\n This command performs failback operation for volume with ID 12345678.": {
360360
"other": "${COMMAND_NAME} sl {{.storageType}} replica-failback ID_VOLUMEN\n\nEJEMPLO:\n ${COMMAND_NAME} sl {{.storageType}} replica-failback 12345678\n Este mandato realiza una operación de restablecimiento para el volumen con ID 12345678."

0 commit comments

Comments
 (0)