Skip to content

Commit d460c68

Browse files
authored
Merge pull request #149 from DimensionDataResearch/development/v2.0
Merge from dev branch
2 parents 7c79904 + 9bb07b8 commit d460c68

File tree

10 files changed

+292
-29
lines changed

10 files changed

+292
-29
lines changed

.gitmodules

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
11
[submodule "vendor/compute-api"]
22
path = vendor/github.com/DimensionDataResearch/go-dd-cloud-compute
33
url = https://github.com/DimensionDataResearch/go-dd-cloud-compute.git
4+
branch = development/v2.0

.travis.yml

Lines changed: 16 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,32 +1,28 @@
1+
dist: trusty
12
language: go
2-
33
go:
4-
- "1.12.1"
5-
6-
branches:
7-
only:
8-
- /^development\/v.*$/
9-
- /^release\/v.*$/
10-
- /^v.*$/
11-
4+
- 1.12.x
5+
env:
6+
- GOMAXPROCS=4 GO111MODULE=on
127
install:
138
- go get golang.org/x/crypto/pkcs12
149
- go get github.com/pkg/errors
15-
- go get github.com/hashicorp/terraform
16-
- pushd $GOPATH/src/github.com/hashicorp/terraform
17-
- git checkout v0.11.13
18-
- popd
19-
10+
- go get github.com/hashicorp/[email protected]
11+
- go mod tidy
12+
- go mod vendor
13+
- go get github.com/DimensionDataResearch/go-dd-cloud-compute@development/v2.0
2014
script:
2115
- make dist
22-
16+
before_deploy:
17+
- export TRAVIS_TAG="v2.3.6"
18+
- git tag $TRAVIS_TAG
2319
deploy:
2420
provider: releases
25-
file: _bin/terraform-provider-ddcloud.*.zip
21+
api_key:
22+
secure: e8YOmjwTS+Dqp7JtyC0yCGonHmpN0ZmhZUPb5miZKtzlHUqqsiMglOrfkqad4r2olyjLWtyNwWwXvqEPSPKO81FOs7HQ1PkoluvAOdesvaBZ2bm5LbXhpzSzbFZNN4mdx5RNYMmIB6pBz48bC5AtcWD6yWtVWG1v7ZhIlXYlo7TQvV2VxZKN/j45OdfDmkGM+es+MlBTzmJUanoReXdvXjvwb373yHDDNVi5mfWE+AwMK/G8+gUdDb6UTBO59GnbT3VisB1tL31aytWwaubdiuWmnpFxeZ/i+cJvGoywbwSGUv80ZyE97JpO81wLG2f+dlkUCRMzLd9GhPxWVmP+JxXPXYvlewXPijoK3SEfH6+Ojj5CjyoycHEcB0/QIZpQOUyWRMsqkeA4TCluCZe5luq4Xjn3AJo9LAfCYCymHmrVAL0/t1Qyv/cXIwPu9lSEFjHXYKojMLdtYVYS9jUCcWI0a01mQUb1MKPixbxeDe/7iZ1PgSng7hbomnjlX+ETO6y3BB4yzJMDEFmoHgBxNQo8ArvfJ4EijiA4q+NMgU7FosKjLBYcO/GV+0AK/wG0jPaPd8u3kLNJRGctBSMz1HmX0YBtE+d0w74ps9lOPArzfOltN98X3sqRp0zvtVuRM68pIbBIQ0l15PU4r2IDXQT1yNR0QQqI9Mp5OGZlJwE=
2623
file_glob: true
27-
skip_cleanup: true
24+
file: _bin/terraform-provider-ddcloud.*.zip
2825
on:
2926
repo: DimensionDataResearch/dd-cloud-compute-terraform
30-
tags: true
31-
api_key:
32-
secure: LTJjqC/G2arlaXfH+BGaU4dWUdBk9f6nKQwM0B3MtRZm76Lhi/wZFWOqzU3qSXbSGEHuSgfH4MsSM3AqQrLwsYRxkDo2QmwC05WrCa8ErdHPl0MWxEr1ZnRSysZsh2/BoVka1NsH93quPxCi6VjlSXPEjMAOtpMytsax3ac/gSZNOHrByEyxmNPFYlsS8eY+7B8D5c8EbBYZ6uuyN5vBqs46HwiAiXqIKEoUnjUjTrr/oyyH9Dd9RW98Ak6QF8ZnyrW1W6g4jyGPlRKfP6mhNI18jhn26w45sx6B84zKNY6YgmGwtrGJHfWC8qS0WBEDIKlmkRL8/j9mEzvsHMQ8wVYItgSPHl+kRnQjEuqI6vkiyEeFdmUrs1ZFKWbfkfO9Doz6pohQBxrATM480nEumnyRyeo50wxiXwe0BAlG5do/duqPT/p03sb2Zh8JolXqfbHcCXFdFiX9cEUBhaO+ofiWfpq0T2ezxr5fH8m+1TMZLOPhJc1yDXirnoEFtrm4QBYAfMJOeJhKHB12MZjMIirYahNoFT1+wDeTx/GGwfIkm4AG+OnYic2muRqIU+dG3DPpbn2YbkNTnS+nvdE73g8wcQQnjbsPaD7obuKnMrK7EDIgBl8CJwzdRan9kRc6BUuGzdGEJ1ern7yZKzIrmTz76hbPTRB6tTWTQh1uBb0=
27+
branch: development\/v2.0
28+
skip_cleanup: 'true'

Makefile

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,11 @@
11
PROVIDER_NAME = ddcloud
22

3-
VERSION = 2.3.3
3+
VERSION = 2.3.6
44
VERSION_INFO_FILE = ./$(PROVIDER_NAME)/version-info.go
55

66
BIN_DIRECTORY = _bin
7-
DEV_BIN_DIRECTORY = /usr/local/bin/
7+
DEV_BIN_DIRECTORY = _bin
8+
LOCAL_BIN_DIRECTORY = /usr/local/bin
89
EXECUTABLE_NAME = terraform-provider-$(PROVIDER_NAME)
910
DIST_ZIP_PREFIX = $(EXECUTABLE_NAME).v$(VERSION)
1011

@@ -20,9 +21,12 @@ fmt:
2021

2122
clean:
2223
rm -rf $(BIN_DIRECTORY) $(VERSION_INFO_FILE)
23-
rm -rf $(DEV_BIN_DIRECTORY) $(VERSION_INFO_FILE)
2424
go clean $(REPO_ROOT)/...
2525

26+
# Peform a LOCAL development (current-platform-only) build.
27+
local: version fmt
28+
go build -o $(LOCAL_BIN_DIRECTORY)/$(EXECUTABLE_NAME)
29+
2630
# Peform a development (current-platform-only) build.
2731
dev: version fmt
2832
go build -o $(DEV_BIN_DIRECTORY)/$(EXECUTABLE_NAME)

ddcloud/provider.go

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -23,14 +23,12 @@ func Provider() terraform.ResourceProvider {
2323
"region": &schema.Schema{
2424
Type: schema.TypeString,
2525
Optional: true,
26-
Default: "",
2726
Description: "The region code that identifies the target end-point for the Dimension Data CloudControl API.",
2827
ConflictsWith: []string{"cloudcontrol_endpoint"},
2928
},
3029
"cloudcontrol_endpoint": &schema.Schema{
3130
Type: schema.TypeString,
3231
Optional: true,
33-
Default: "",
3432
Description: "The base URL of a custom target end-point for the Dimension Data CloudControl API.",
3533
ConflictsWith: []string{"region"},
3634
},
@@ -129,8 +127,11 @@ func Provider() terraform.ResourceProvider {
129127
// A reserved IPv6 or private IPv4 address on a VLAN.
130128
"ddcloud_ip_address_reservation": resourceIPAddressReservation(),
131129

132-
// Enterprise network domain static route
130+
// Enterprise network domain static route.
133131
"ddcloud_static_route": resourceStaticRoute(),
132+
133+
// A IP address block in network domain.
134+
"ddcloud_ip_address_block": resourceIPAddressBlock(),
134135
},
135136

136137
DataSourcesMap: map[string]*schema.Resource{
Lines changed: 199 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,199 @@
1+
package ddcloud
2+
3+
import (
4+
"fmt"
5+
"github.com/DimensionDataResearch/dd-cloud-compute-terraform/retry"
6+
"github.com/DimensionDataResearch/go-dd-cloud-compute/compute"
7+
"github.com/hashicorp/terraform/helper/schema"
8+
"log"
9+
)
10+
11+
const (
12+
resourceKeyIPAddressBlockID = "ipblock_id"
13+
resourceKeyIPAddressBlockDomainID = "domain_id"
14+
resourceKeyIPAddressBlockBaseIp = "base_ip"
15+
resourceKeyIPAddressBlockDescription = "description"
16+
)
17+
18+
func resourceIPAddressBlock() *schema.Resource {
19+
return &schema.Resource{
20+
Create: resourceIPAddressBlockCreate,
21+
Read: resourceIPAddressBlockRead,
22+
Update: resourceIPAddressBlockUpdate,
23+
Delete: resourceIPAddressBlockDelete,
24+
Importer: &schema.ResourceImporter{
25+
State: resourceIPAddressBlockImport,
26+
},
27+
28+
Schema: map[string]*schema.Schema{
29+
resourceKeyIPAddressBlockID: &schema.Schema{
30+
Type: schema.TypeString,
31+
Computed: true,
32+
Description: "The Id of the IP Address block.",
33+
},
34+
resourceKeyIPAddressBlockDomainID: &schema.Schema{
35+
Type: schema.TypeString,
36+
Required: true,
37+
ForceNew: true,
38+
Description: "The network domain where IP address block resides.",
39+
},
40+
resourceKeyIPAddressBlockBaseIp: &schema.Schema{
41+
Type: schema.TypeString,
42+
Computed: true,
43+
ForceNew: false,
44+
Description: "An IPv4 address in dot notation, corresponding to the lowest IPv address in the block.",
45+
},
46+
resourceKeyIPAddressBlockDescription: &schema.Schema{
47+
Type: schema.TypeString,
48+
Optional: true,
49+
Default: "",
50+
Description: "A description for the IP Address Block",
51+
},
52+
resourceKeyTag: schemaTag(),
53+
},
54+
}
55+
}
56+
57+
func resourceIPAddressBlockCreate(data *schema.ResourceData, provider interface{}) (err error) {
58+
domainID := data.Get(resourceKeyIPAddressBlockDomainID).(string)
59+
providerState := provider.(*providerState)
60+
apiClient := providerState.Client()
61+
62+
log.Printf("Creating new IP address block in network domain '%s'",
63+
domainID,
64+
)
65+
66+
ipBlockID, err := apiClient.AddPublicIPBlock(domainID)
67+
data.SetId(ipBlockID)
68+
69+
if err != nil {
70+
return err
71+
}
72+
73+
// Tags
74+
err = applyTags(data, apiClient, compute.AssetTypePublicIPBlock, providerState.Settings())
75+
if err != nil {
76+
return err
77+
}
78+
data.SetPartial(resourceKeyTag)
79+
data.Partial(false)
80+
81+
return nil
82+
}
83+
84+
func resourceIPAddressBlockRead(data *schema.ResourceData, provider interface{}) (err error) {
85+
86+
id := data.Id()
87+
domainID := data.Get(resourceKeyIPAddressBlockDomainID).(string)
88+
ipBlockID := data.Get(resourceKeyIPAddressBlockID).(string)
89+
baseIp := data.Get(resourceKeyIPAddressBlockBaseIp).(string)
90+
91+
log.Printf("Read IP Address Block Id = '%s' in network domain '%s', IP Base Address '%s').", ipBlockID, domainID, baseIp)
92+
93+
apiClient := provider.(*providerState).Client()
94+
95+
ipBlock, err := apiClient.GetPublicIPBlock(id)
96+
if err != nil {
97+
return err
98+
}
99+
100+
if ipBlock != nil {
101+
data.Set(resourceKeyIPAddressBlockDomainID, ipBlock.ID)
102+
data.Set(resourceKeyIPAddressBlockDomainID, ipBlock.NetworkDomainID)
103+
data.Set(resourceKeyIPAddressBlockBaseIp, ipBlock.BaseIP)
104+
105+
err = readTags(data, apiClient, compute.AssetTypePublicIPBlock)
106+
if err != nil {
107+
return err
108+
}
109+
110+
} else {
111+
data.SetId("") // Mark resource as deleted.
112+
}
113+
114+
return nil
115+
}
116+
117+
func resourceIPAddressBlockUpdate(data *schema.ResourceData, provider interface{}) (err error) {
118+
119+
providerState := provider.(*providerState)
120+
apiClient := providerState.Client()
121+
122+
if data.HasChange(resourceKeyTag) {
123+
err := applyTags(data, apiClient, compute.AssetTypePublicIPBlock, providerState.Settings())
124+
if err != nil {
125+
return err
126+
}
127+
128+
data.SetPartial(resourceKeyTag)
129+
}
130+
131+
return
132+
}
133+
134+
func resourceIPAddressBlockDelete(data *schema.ResourceData, provider interface{}) (err error) {
135+
136+
id := data.Id()
137+
networkDomainID := data.Get(resourceKeyIPAddressBlockDomainID).(string)
138+
139+
log.Printf("Delete IP Address Block '%s' in network domain '%s'.", id, networkDomainID)
140+
141+
providerState := provider.(*providerState)
142+
apiClient := providerState.Client()
143+
144+
operationDescription := fmt.Sprintf("Delete IP address block '%s'", id)
145+
err = providerState.Retry().Action(operationDescription, deleteTimeoutVLAN, func(context retry.Context) {
146+
// CloudControl has issues if more than one asynchronous operation is initated at a time (returns UNEXPECTED_ERROR).
147+
asyncLock := providerState.AcquireAsyncOperationLock(operationDescription)
148+
defer asyncLock.Release() // Released once the current attempt is complete.
149+
150+
deleteError := apiClient.RemovePublicIPBlock(id)
151+
if deleteError != nil {
152+
if compute.IsResourceBusyError(deleteError) {
153+
context.Retry()
154+
} else {
155+
context.Fail(deleteError)
156+
}
157+
}
158+
159+
asyncLock.Release()
160+
})
161+
if err != nil {
162+
return err
163+
}
164+
165+
log.Printf("IP Address Block '%s' is being deleted...", id)
166+
167+
return apiClient.WaitForDelete(compute.ResourceTypePublicIPBlock, id, 2)
168+
}
169+
170+
func resourceIPAddressBlockImport(data *schema.ResourceData, provider interface{}) (importedData []*schema.ResourceData, err error) {
171+
providerState := provider.(*providerState)
172+
apiClient := providerState.Client()
173+
174+
ipAddressBlockID := data.Id()
175+
log.Printf("Import IP Address Block by ID '%s'.", ipAddressBlockID)
176+
ipAddressBlock, err := apiClient.GetPublicIPBlock(ipAddressBlockID)
177+
178+
if err != nil {
179+
return
180+
}
181+
182+
if ipAddressBlock == nil {
183+
err = fmt.Errorf("IP Address block '%s' not found", ipAddressBlockID)
184+
185+
return
186+
}
187+
188+
data.SetId(ipAddressBlock.ID)
189+
190+
data.Set(resourceKeyIPAddressBlockID, ipAddressBlock.ID)
191+
data.Set(resourceKeyIPAddressBlockDomainID, ipAddressBlock.NetworkDomainID)
192+
data.Set(resourceKeyIPAddressBlockBaseIp, ipAddressBlock.BaseIP)
193+
194+
err = readTags(data, apiClient, compute.AssetTypePublicIPBlock)
195+
196+
importedData = []*schema.ResourceData{data}
197+
198+
return
199+
}

ddcloud/resource_nat.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -145,7 +145,7 @@ func resourceNATCreate(data *schema.ResourceData, provider interface{}) error {
145145
}
146146

147147
data.Set(resourceKeyNATPublicAddress, natRule.ExternalIPAddress)
148-
148+
data.Set(resourceKeyNATPrivateAddress, natRule.InternalIPAddress)
149149
return nil
150150
}
151151

ddcloud/resource_networkdomain.go

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,7 @@ func resourceNetworkDomain() *schema.Resource {
7373
Description: "The IPv4 subnet for transit outside of the network domain",
7474
},
7575
resourceKeyNetworkDomainFirewallRule: schemaNetworkDomainFirewallRule(),
76+
resourceKeyTag: schemaTag(),
7677
},
7778
}
7879
}
@@ -140,6 +141,12 @@ func resourceNetworkDomainCreate(data *schema.ResourceData, provider interface{}
140141
return err
141142
}
142143

144+
// Tags
145+
err = applyTags(data, apiClient, compute.AssetTypeNetworkDomain, providerState.Settings())
146+
if err != nil {
147+
return err
148+
}
149+
data.SetPartial(resourceKeyTag)
143150
data.Partial(false)
144151

145152
return nil
@@ -183,6 +190,11 @@ func resourceNetworkDomainRead(data *schema.ResourceData, provider interface{})
183190
networkDomain.OutsideTransitVLANIPv4Subnet.PrefixSize,
184191
))
185192
data.SetPartial(resourceKeyNetworkDomainOutsideTransitIPv4Subnet)
193+
194+
err = readTags(data, apiClient, compute.AssetTypeNetworkDomain)
195+
if err != nil {
196+
return err
197+
}
186198
} else {
187199
data.SetId("") // Mark resource as deleted.
188200
}
@@ -227,6 +239,16 @@ func resourceNetworkDomainUpdate(data *schema.ResourceData, provider interface{}
227239
apiClient := providerState.Client()
228240

229241
var err error
242+
243+
if data.HasChange(resourceKeyTag) {
244+
err := applyTags(data, apiClient, compute.AssetTypeNetworkDomain, providerState.Settings())
245+
if err != nil {
246+
return err
247+
}
248+
249+
data.SetPartial(resourceKeyTag)
250+
}
251+
230252
if newName != nil || newPlan != nil || newDescription != nil {
231253
err = apiClient.EditNetworkDomain(id, newName, newDescription, newPlan)
232254
if err != nil {
@@ -339,6 +361,8 @@ func resourceNetworkDomainImport(data *schema.ResourceData, provider interface{}
339361
data.Set(resourceKeyNetworkDomainPlan, networkDomain.Type)
340362
data.Set(resourceKeyNetworkDomainDataCenter, networkDomain.DatacenterID)
341363

364+
err = readTags(data, apiClient, compute.AssetTypeNetworkDomain)
365+
342366
importedData = []*schema.ResourceData{data}
343367

344368
return

0 commit comments

Comments
 (0)