Skip to content

Commit 53f7dc7

Browse files
Romain Dartiguesjpalermo
authored andcommitted
1 parent f2509fd commit 53f7dc7

36 files changed

+1904
-24
lines changed

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@ $ brew install bbl
4242
- [Getting Started: AWS](docs/getting-started-aws.md)
4343
- [Getting Started: vSphere](docs/getting-started-vsphere.md)
4444
- [Getting Started: OpenStack](docs/getting-started-openstack.md)
45+
- [Getting Started: CloudStack](docs/getting-started-cloudstack.md)
4546

4647
### Managing state
4748

acceptance-tests/actors/cloudstack.go

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
package actors
2+
3+
func NewCloudStackLBHelper() vSphereLBHelper {
4+
return vSphereLBHelper{}
5+
}

acceptance-tests/actors/iaas_helper.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,8 @@ func NewIAASLBHelper(iaas string, configuration acceptance.Config) IAASLBHelper
2727
return NewVSphereLBHelper()
2828
case "openstack":
2929
return NewOpenStackLBHelper()
30+
case "cloudstack":
31+
return NewCloudStackLBHelper()
3032
default:
3133
panic(fmt.Sprintf("%s is not a supported iaas", iaas))
3234
}

acceptance-tests/no-iaas/flags_error_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ var _ = Describe("bbl", func() {
1616
Expect(err).NotTo(HaveOccurred())
1717
Eventually(session).Should(gexec.Exit(1))
1818

19-
Expect(string(session.Err.Contents())).To(ContainSubstring("--iaas [gcp, aws, azure, vsphere, openstack] must be provided or BBL_IAAS must be set"))
19+
Expect(string(session.Err.Contents())).To(ContainSubstring("--iaas [gcp, aws, azure, vsphere, openstack, cloudstack] must be provided or BBL_IAAS must be set"))
2020
Expect(string(session.Err.Contents())).NotTo(ContainSubstring("panic"))
2121
})
2222
})

bbl/main.go

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,12 +28,14 @@ import (
2828

2929
awscloudconfig "github.com/cloudfoundry/bosh-bootloader/cloudconfig/aws"
3030
azurecloudconfig "github.com/cloudfoundry/bosh-bootloader/cloudconfig/azure"
31+
cloudstackcloudconfig "github.com/cloudfoundry/bosh-bootloader/cloudconfig/cloudstack"
3132
gcpcloudconfig "github.com/cloudfoundry/bosh-bootloader/cloudconfig/gcp"
3233
openstackcloudconfig "github.com/cloudfoundry/bosh-bootloader/cloudconfig/openstack"
3334
vspherecloudconfig "github.com/cloudfoundry/bosh-bootloader/cloudconfig/vsphere"
3435

3536
awsterraform "github.com/cloudfoundry/bosh-bootloader/terraform/aws"
3637
azureterraform "github.com/cloudfoundry/bosh-bootloader/terraform/azure"
38+
cloudstackterraform "github.com/cloudfoundry/bosh-bootloader/terraform/cloudstack"
3739
gcpterraform "github.com/cloudfoundry/bosh-bootloader/terraform/gcp"
3840
openstackterraform "github.com/cloudfoundry/bosh-bootloader/terraform/openstack"
3941
vsphereterraform "github.com/cloudfoundry/bosh-bootloader/terraform/vsphere"
@@ -244,6 +246,13 @@ func main() {
244246
terraformManager = terraform.NewManager(terraformExecutor, templateGenerator, inputGenerator, terraformOutputBuffer, logger)
245247

246248
cloudConfigOpsGenerator = openstackcloudconfig.NewOpsGenerator(terraformManager)
249+
case "cloudstack":
250+
templateGenerator = cloudstackterraform.NewTemplateGenerator()
251+
inputGenerator = cloudstackterraform.NewInputGenerator()
252+
253+
terraformManager = terraform.NewManager(terraformExecutor, templateGenerator, inputGenerator, terraformOutputBuffer, logger)
254+
255+
cloudConfigOpsGenerator = cloudstackcloudconfig.NewOpsGenerator(terraformManager)
247256
}
248257

249258
cloudConfigManager := cloudconfig.NewManager(logger, configUpdater, stateStore, cloudConfigOpsGenerator, terraformManager, afs)

bosh/executor.go

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -161,6 +161,11 @@ func (e Executor) PlanJumpbox(input DirInput, deploymentDir, iaas string) error
161161
"-v", `openstack_username="${BBL_OPENSTACK_USERNAME}"`,
162162
"-v", `openstack_password="${BBL_OPENSTACK_PASSWORD}"`,
163163
)
164+
case "cloudstack":
165+
boshArgs = append(boshArgs,
166+
"-v", `cloudstack_api_key="${BBL_CLOUDSTACK_API_KEY}"`,
167+
"-v", `cloudstack_secret_access_key="${BBL_CLOUDSTACK_SECRET_ACCESS_KEY}"`,
168+
)
164169
}
165170

166171
boshPath := e.CLI.GetBOSHPath()
@@ -278,6 +283,11 @@ func (e Executor) PlanDirector(input DirInput, deploymentDir, iaas string) error
278283
"-v", `openstack_username="${BBL_OPENSTACK_USERNAME}"`,
279284
"-v", `openstack_password="${BBL_OPENSTACK_PASSWORD}"`,
280285
)
286+
case "cloudstack":
287+
boshArgs = append(boshArgs,
288+
"-v", `cloudstack_api_key="${BBL_CLOUDSTACK_API_KEY}"`,
289+
"-v", `cloudstack_secret_access_key="${BBL_CLOUDSTACK_SECRET_ACCESS_KEY}"`,
290+
)
281291
}
282292

283293
boshPath := e.CLI.GetBOSHPath()
@@ -347,6 +357,9 @@ func (e Executor) CreateEnv(input DirInput, state storage.State) (string, error)
347357
case "openstack":
348358
os.Setenv("BBL_OPENSTACK_USERNAME", state.OpenStack.Username)
349359
os.Setenv("BBL_OPENSTACK_PASSWORD", state.OpenStack.Password)
360+
case "cloudstack":
361+
os.Setenv("BBL_CLOUDSTACK_API_KEY", state.CloudStack.ApiKey)
362+
os.Setenv("BBL_CLOUDSTACK_SECRET_ACCESS_KEY", state.CloudStack.SecretAccessKey)
350363
}
351364

352365
cmd := exec.Command(createEnvScript)
@@ -397,6 +410,9 @@ func (e Executor) DeleteEnv(input DirInput, state storage.State) error {
397410
case "vsphere":
398411
os.Setenv("BBL_VSPHERE_VCENTER_USER", state.VSphere.VCenterUser)
399412
os.Setenv("BBL_VSPHERE_VCENTER_PASSWORD", state.VSphere.VCenterPassword)
413+
case "cloudstack":
414+
os.Setenv("BBL_CLOUDSTACK_API_KEY", state.CloudStack.ApiKey)
415+
os.Setenv("BBL_CLOUDSTACK_SECRET_ACCESS_KEY", state.CloudStack.SecretAccessKey)
400416
}
401417

402418
cmd := exec.Command(deleteEnvScript)

bosh/executor_test.go

Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -278,6 +278,39 @@ var _ = Describe("Executor", func() {
278278
})
279279
})
280280
})
281+
282+
Context("cloudstack", func() {
283+
It("generates create-env args for jumpbox", func() {
284+
err := executor.PlanJumpbox(dirInput, deploymentDir, "cloudstack")
285+
Expect(err).NotTo(HaveOccurred())
286+
287+
expectedArgs := []string{
288+
fmt.Sprintf("%s/jumpbox.yml", relativeDeploymentDir),
289+
"--state", fmt.Sprintf("%s/jumpbox-state.json", relativeVarsDir),
290+
"--vars-store", fmt.Sprintf("%s/jumpbox-vars-store.yml", relativeVarsDir),
291+
"--vars-file", fmt.Sprintf("%s/jumpbox-vars-file.yml", relativeVarsDir),
292+
"-o", fmt.Sprintf("%s/cloudstack/cpi.yml", relativeDeploymentDir),
293+
"-v", `cloudstack_api_key="${BBL_CLOUDSTACK_API_KEY}"`,
294+
"-v", `cloudstack_secret_access_key="${BBL_CLOUDSTACK_SECRET_ACCESS_KEY}"`,
295+
}
296+
297+
By("writing the create-env args to a shell script", func() {
298+
expectedScript := formatScript("create-env", stateDir, expectedArgs)
299+
shellScript, err := fs.ReadFile(fmt.Sprintf("%s/create-jumpbox.sh", stateDir))
300+
Expect(err).NotTo(HaveOccurred())
301+
302+
Expect(string(shellScript)).To(Equal(expectedScript))
303+
})
304+
305+
By("writing the delete-env args to a shell script", func() {
306+
expectedScript := formatScript("delete-env", stateDir, expectedArgs)
307+
shellScript, err := fs.ReadFile(fmt.Sprintf("%s/delete-jumpbox.sh", stateDir))
308+
Expect(err).NotTo(HaveOccurred())
309+
310+
Expect(string(shellScript)).To(Equal(expectedScript))
311+
})
312+
})
313+
})
281314
})
282315

283316
Describe("PlanDirector", func() {
@@ -428,6 +461,24 @@ var _ = Describe("Executor", func() {
428461
behavesLikePlan(expectedArgs, cli, fs, executor, dirInput, deploymentDir, "openstack", stateDir)
429462
})
430463
})
464+
Context("cloudstack", func() {
465+
It("writes create-director.sh and delete-director.sh", func() {
466+
expectedArgs := []string{
467+
filepath.Join(relativeDeploymentDir, "bosh.yml"),
468+
"--state", filepath.Join(relativeVarsDir, "bosh-state.json"),
469+
"--vars-store", filepath.Join(relativeVarsDir, "director-vars-store.yml"),
470+
"--vars-file", filepath.Join(relativeVarsDir, "director-vars-file.yml"),
471+
"-o", filepath.Join(relativeDeploymentDir, "cloudstack", "cpi.yml"),
472+
"-o", filepath.Join(relativeDeploymentDir, "jumpbox-user.yml"),
473+
"-o", filepath.Join(relativeDeploymentDir, "uaa.yml"),
474+
"-o", filepath.Join(relativeDeploymentDir, "credhub.yml"),
475+
"-v", `cloudstack_api_key="${BBL_CLOUDSTACK_API_KEY}"`,
476+
"-v", `cloudstack_secret_access_key="${BBL_CLOUDSTACK_SECRET_ACCESS_KEY}"`,
477+
}
478+
479+
behavesLikePlan(expectedArgs, cli, fs, executor, dirInput, deploymentDir, "cloudstack", stateDir)
480+
})
481+
})
431482
})
432483

433484
Describe("WriteDeploymentVars", func() {
@@ -637,6 +688,21 @@ var _ = Describe("Executor", func() {
637688
Expect(os.Getenv("BBL_OPENSTACK_PASSWORD")).To(Equal("some-password"))
638689
})
639690
})
691+
Context("on cloudstack", func() {
692+
It("sets credentials in environment variables", func() {
693+
_, err := executor.CreateEnv(dirInput, storage.State{
694+
IAAS: "cloudstack",
695+
CloudStack: storage.CloudStack{
696+
ApiKey: "some-api-key",
697+
SecretAccessKey: "some-secret",
698+
},
699+
})
700+
Expect(err).NotTo(HaveOccurred())
701+
702+
Expect(os.Getenv("BBL_CLOUDSTACK_API_KEY")).To(Equal("some-api-key"))
703+
Expect(os.Getenv("BBL_CLOUDSTACK_SECRET_ACCESS_KEY")).To(Equal("some-secret"))
704+
})
705+
})
640706
})
641707

642708
Context("when the create-env script returns an error", func() {
@@ -859,6 +925,23 @@ var _ = Describe("Executor", func() {
859925
Expect(os.Getenv("BBL_VSPHERE_VCENTER_PASSWORD")).To(Equal("some-password"))
860926
})
861927
})
928+
Context("on cloudstack", func() {
929+
BeforeEach(func() {
930+
state.IAAS = "cloudstack"
931+
state.CloudStack = storage.CloudStack{
932+
ApiKey: "some-api-key",
933+
SecretAccessKey: "some-secret",
934+
}
935+
})
936+
937+
It("sets credentials in environment variables", func() {
938+
err := executor.DeleteEnv(dirInput, state)
939+
Expect(err).NotTo(HaveOccurred())
940+
941+
Expect(os.Getenv("BBL_CLOUDSTACK_API_KEY")).To(Equal("some-api-key"))
942+
Expect(os.Getenv("BBL_CLOUDSTACK_SECRET_ACCESS_KEY")).To(Equal("some-secret"))
943+
})
944+
})
862945
})
863946

864947
Context("when the create-env script returns an error", func() {
Lines changed: 175 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,175 @@
1+
package cloudstack
2+
3+
const (
4+
BaseOps = `
5+
- type: replace
6+
path: /azs
7+
value:
8+
- name: z1
9+
cloud_properties: {}
10+
- name: z2
11+
cloud_properties: {}
12+
- name: z3
13+
cloud_properties: {}
14+
15+
- type: replace
16+
path: /compilation
17+
value:
18+
workers: 5
19+
reuse_compilation_vms: true
20+
vm_type: default
21+
az: z1
22+
network: compilation
23+
24+
- type: replace
25+
path: /disk_types/name=default?
26+
value:
27+
name: default
28+
cloud_properties:
29+
disk_offering: shared.custom
30+
disk_size: 1024
31+
32+
- type: replace
33+
path: /disk_types/name=1GB?
34+
value:
35+
name: 1GB
36+
cloud_properties:
37+
disk_offering: shared.custom
38+
disk_size: 1024
39+
40+
- type: replace
41+
path: /disk_types/name=5GB?
42+
value:
43+
name: 5GB
44+
cloud_properties:
45+
disk_offering: shared.custom
46+
disk_size: 5120
47+
48+
- type: replace
49+
path: /disk_types/name=10GB?
50+
value:
51+
name: 10GB
52+
cloud_properties:
53+
disk_offering: shared.small
54+
disk_size: 10240
55+
56+
- type: replace
57+
path: /disk_types/name=50GB?
58+
value:
59+
name: 50GB
60+
cloud_properties:
61+
disk_offering: shared.medium
62+
disk_size: 51200
63+
64+
- type: replace
65+
path: /disk_types/name=100GB?
66+
value:
67+
name: 100GB
68+
cloud_properties:
69+
disk_offering: shared.large
70+
disk_size: 102400
71+
72+
- type: replace
73+
path: /disk_types/name=500GB?
74+
value:
75+
name: 500GB
76+
cloud_properties:
77+
disk_offering: shared.xxlarge
78+
disk_size: 512000
79+
80+
- type: replace
81+
path: /disk_types/name=1TB?
82+
value:
83+
name: 1TB
84+
cloud_properties:
85+
disk_offering: shared.custom
86+
disk_size: 1048576
87+
88+
- type: replace
89+
path: /vm_types/name=default/cloud_properties?
90+
value:
91+
compute_offering: shared.medium
92+
93+
- type: replace
94+
path: /vm_types/name=minimal/cloud_properties?
95+
value:
96+
compute_offering: shared.small
97+
98+
- type: replace
99+
path: /vm_types/name=small/cloud_properties?
100+
value:
101+
compute_offering: shared.medium
102+
103+
- type: replace
104+
path: /vm_types/name=small-highmem/cloud_properties?
105+
value:
106+
compute_offering: shared.xlarge
107+
108+
- type: replace
109+
path: /vm_types/name=medium/cloud_properties?
110+
value:
111+
compute_offering: shared.xmedium
112+
113+
- type: replace
114+
path: /vm_types/name=large/cloud_properties?
115+
value:
116+
compute_offering: shared.xlarge
117+
118+
- type: replace
119+
path: /vm_types/name=extra-large/cloud_properties?
120+
value:
121+
compute_offering: shared.xlarge
122+
123+
- type: replace
124+
path: /vm_extensions/name=1GB_ephemeral_disk/cloud_properties?
125+
value:
126+
ephemeral_disk_offering: shared.custom
127+
disk: 1024
128+
129+
- type: replace
130+
path: /vm_extensions/name=5GB_ephemeral_disk/cloud_properties?
131+
value:
132+
ephemeral_disk_offering: shared.custom
133+
disk: 5120
134+
135+
- type: replace
136+
path: /vm_extensions/name=10GB_ephemeral_disk/cloud_properties?
137+
value:
138+
ephemeral_disk_offering: shared.small
139+
140+
- type: replace
141+
path: /vm_extensions/name=50GB_ephemeral_disk/cloud_properties?
142+
value:
143+
ephemeral_disk_offering: shared.medium
144+
145+
- type: replace
146+
path: /vm_extensions/name=100GB_ephemeral_disk/cloud_properties?
147+
value:
148+
ephemeral_disk_offering: shared.large
149+
150+
- type: replace
151+
path: /vm_extensions/name=500GB_ephemeral_disk/cloud_properties?
152+
value:
153+
ephemeral_disk_offering: shared.xxlarge
154+
155+
- type: replace
156+
path: /vm_extensions/name=1TB_ephemeral_disk/cloud_properties?
157+
value:
158+
ephemeral_disk_offering: shared.custom
159+
disk: 1048576
160+
161+
- type: replace
162+
path: /vm_extensions/-
163+
value:
164+
name: cf-router-network-properties
165+
166+
- type: replace
167+
path: /vm_extensions/-
168+
value:
169+
name: cf-tcp-router-network-properties
170+
171+
- type: replace
172+
path: /vm_extensions/-
173+
value:
174+
name: diego-ssh-proxy-network-properties`
175+
)

0 commit comments

Comments
 (0)