Skip to content

Commit ea9c5f6

Browse files
authored
Merge pull request #357 from shapeblue/allow-creation-normal-user
Allow cluster creation by a normal ACS user
2 parents d1a6ad9 + 927ca0a commit ea9c5f6

File tree

4 files changed

+35
-15
lines changed

4 files changed

+35
-15
lines changed

docs/book/src/topics/cloudstack-permissions.md

+3-2
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
# CloudStack Permissions for CAPC
22

3-
The account that CAPC runs under must minimally be a Domain Admin type account with a role offering the following permissions
3+
The account that CAPC runs under must minimally be a User type account with a role offering the following permissions
44

55
* assignToLoadBalancerRule
66
* associateIpAddress
@@ -19,7 +19,6 @@ The account that CAPC runs under must minimally be a Domain Admin type account w
1919
* listAccounts
2020
* listAffinityGroups
2121
* listDiskOfferings
22-
* listDomains
2322
* listLoadBalancerRuleInstances
2423
* listLoadBalancerRules
2524
* listNetworkOfferings
@@ -39,4 +38,6 @@ The account that CAPC runs under must minimally be a Domain Admin type account w
3938
* stopVirtualMachine
4039
* updateVMAffinityGroup
4140

41+
> Note: If the user doesn't have permissions to expunge the VM, it will be left in a destroyed state. The user will need to manually expunge the VM.
42+
4243
This permission set has been verified to successfully run the CAPC E2E test suite (Oct 11, 2022).

pkg/cloud/instance.go

+11-4
Original file line numberDiff line numberDiff line change
@@ -452,15 +452,22 @@ func findVirtualMachine(
452452

453453
// DestroyVMInstance Destroys a VM instance. Assumes machine has been fetched prior and has an instance ID.
454454
func (c *client) DestroyVMInstance(csMachine *infrav1.CloudStackMachine) error {
455+
p := c.cs.Configuration.NewListCapabilitiesParams()
456+
capabilities, err := c.cs.Configuration.ListCapabilities(p)
457+
expunge := true
458+
if err == nil {
459+
expunge = capabilities.Capabilities.Allowuserexpungerecovervm
460+
}
461+
455462
// Attempt deletion regardless of machine state.
456-
p := c.csAsync.VirtualMachine.NewDestroyVirtualMachineParams(*csMachine.Spec.InstanceID)
463+
p2 := c.csAsync.VirtualMachine.NewDestroyVirtualMachineParams(*csMachine.Spec.InstanceID)
457464
volIDs, err := c.listVMInstanceDatadiskVolumeIDs(*csMachine.Spec.InstanceID)
458465
if err != nil {
459466
return err
460467
}
461-
p.SetExpunge(true)
462-
setArrayIfNotEmpty(volIDs, p.SetVolumeids)
463-
if _, err := c.csAsync.VirtualMachine.DestroyVirtualMachine(p); err != nil &&
468+
p2.SetExpunge(expunge)
469+
setArrayIfNotEmpty(volIDs, p2.SetVolumeids)
470+
if _, err := c.csAsync.VirtualMachine.DestroyVirtualMachine(p2); err != nil &&
464471
strings.Contains(strings.ToLower(err.Error()), "unable to find uuid for id") {
465472
// VM doesn't exist. Success...
466473
return nil

pkg/cloud/instance_test.go

+19-8
Original file line numberDiff line numberDiff line change
@@ -46,19 +46,21 @@ var _ = Describe("Instance", func() {
4646
unknownError := errors.New(unknownErrorMessage)
4747

4848
var (
49-
mockCtrl *gomock.Controller
50-
mockClient *cloudstack.CloudStackClient
51-
vms *cloudstack.MockVirtualMachineServiceIface
52-
sos *cloudstack.MockServiceOfferingServiceIface
53-
dos *cloudstack.MockDiskOfferingServiceIface
54-
ts *cloudstack.MockTemplateServiceIface
55-
vs *cloudstack.MockVolumeServiceIface
56-
client cloud.Client
49+
mockCtrl *gomock.Controller
50+
mockClient *cloudstack.CloudStackClient
51+
configuration *cloudstack.MockConfigurationServiceIface
52+
vms *cloudstack.MockVirtualMachineServiceIface
53+
sos *cloudstack.MockServiceOfferingServiceIface
54+
dos *cloudstack.MockDiskOfferingServiceIface
55+
ts *cloudstack.MockTemplateServiceIface
56+
vs *cloudstack.MockVolumeServiceIface
57+
client cloud.Client
5758
)
5859

5960
BeforeEach(func() {
6061
mockCtrl = gomock.NewController(GinkgoT())
6162
mockClient = cloudstack.NewMockClient(mockCtrl)
63+
configuration = mockClient.Configuration.(*cloudstack.MockConfigurationServiceIface)
6264
vms = mockClient.VirtualMachine.(*cloudstack.MockVirtualMachineServiceIface)
6365
sos = mockClient.ServiceOffering.(*cloudstack.MockServiceOfferingServiceIface)
6466
dos = mockClient.DiskOffering.(*cloudstack.MockDiskOfferingServiceIface)
@@ -872,8 +874,12 @@ var _ = Describe("Instance", func() {
872874
})
873875

874876
Context("when destroying a VM instance", func() {
877+
listCapabilitiesParams := &cloudstack.ListCapabilitiesParams{}
875878
expungeDestroyParams := &cloudstack.DestroyVirtualMachineParams{}
876879
expungeDestroyParams.SetExpunge(true)
880+
listCapabilitiesResponse := &cloudstack.ListCapabilitiesResponse{
881+
Capabilities: &cloudstack.Capability{Allowuserexpungerecovervm: true},
882+
}
877883
listVolumesParams := &cloudstack.ListVolumesParams{}
878884
listVolumesResponse := &cloudstack.ListVolumesResponse{
879885
Volumes: []*cloudstack.Volume{
@@ -886,6 +892,11 @@ var _ = Describe("Instance", func() {
886892
},
887893
}
888894

895+
BeforeEach(func() {
896+
configuration.EXPECT().NewListCapabilitiesParams().Return(listCapabilitiesParams)
897+
configuration.EXPECT().ListCapabilities(listCapabilitiesParams).Return(listCapabilitiesResponse, nil)
898+
})
899+
889900
It("calls destroy and finds VM doesn't exist, then returns nil", func() {
890901
listVolumesParams.SetVirtualmachineid(*dummies.CSMachine1.Spec.InstanceID)
891902
listVolumesParams.SetType("DATADISK")

pkg/cloud/user_credentials.go

+2-1
Original file line numberDiff line numberDiff line change
@@ -152,7 +152,8 @@ func (c *client) ResolveDomain(domain *Domain) error {
152152
// ResolveAccount resolves an account's information.
153153
func (c *client) ResolveAccount(account *Account) error {
154154
// Resolve domain prior to any account resolution activity.
155-
if err := c.ResolveDomain(&account.Domain); err != nil {
155+
if err := c.ResolveDomain(&account.Domain); err != nil &&
156+
!strings.Contains(err.Error(), "The API [listDomains] does not exist or is not available for the account Account") {
156157
return errors.Wrapf(err, "resolving domain %s details", account.Domain.Name)
157158
}
158159

0 commit comments

Comments
 (0)