Skip to content

Commit 3212168

Browse files
committed
Add support for SSL domain certificates and certificate chains.
DimensionDataResearch/terraform-provider-ddcloud#104
1 parent caf022d commit 3212168

File tree

6 files changed

+652
-80
lines changed

6 files changed

+652
-80
lines changed

compute/client.go

Lines changed: 14 additions & 79 deletions
Original file line numberDiff line numberDiff line change
@@ -289,97 +289,32 @@ func (client *Client) newRequestV1(relativeURI string, method string, body inter
289289

290290
// Create a basic request for the compute API (V2.2, JSON).
291291
func (client *Client) newRequestV22(relativeURI string, method string, body interface{}) (*http.Request, error) {
292-
requestURI := fmt.Sprintf("%s/caas/2.2/%s", client.baseAddress, relativeURI)
293-
294-
var (
295-
request *http.Request
296-
bodyReader io.Reader
297-
err error
298-
)
299-
300-
bodyReader, err = newReaderFromJSON(body)
301-
if err != nil {
302-
return nil, err
303-
}
304-
305-
request, err = http.NewRequest(method, requestURI, bodyReader)
306-
if err != nil {
307-
return nil, err
308-
}
309-
310-
request.SetBasicAuth(client.username, client.password)
311-
request.Header.Add("Accept", "application/json")
312-
313-
if bodyReader != nil {
314-
request.Header.Set("Content-Type", "application/json")
315-
}
316-
317-
return request, nil
292+
return client.newRequestV2x(2, relativeURI, method, body)
318293
}
319294

320295
// Create a basic request for the compute API (V2.3, JSON).
321296
func (client *Client) newRequestV23(relativeURI string, method string, body interface{}) (*http.Request, error) {
322-
requestURI := fmt.Sprintf("%s/caas/2.3/%s", client.baseAddress, relativeURI)
323-
324-
var (
325-
request *http.Request
326-
bodyReader io.Reader
327-
err error
328-
)
329-
330-
bodyReader, err = newReaderFromJSON(body)
331-
if err != nil {
332-
return nil, err
333-
}
334-
335-
request, err = http.NewRequest(method, requestURI, bodyReader)
336-
if err != nil {
337-
return nil, err
338-
}
339-
340-
request.SetBasicAuth(client.username, client.password)
341-
request.Header.Add("Accept", "application/json")
342-
343-
if bodyReader != nil {
344-
request.Header.Set("Content-Type", "application/json")
345-
}
346-
347-
return request, nil
297+
return client.newRequestV2x(3, relativeURI, method, body)
348298
}
349299

350300
// Create a basic request for the compute API (V2.4, JSON).
351301
func (client *Client) newRequestV24(relativeURI string, method string, body interface{}) (*http.Request, error) {
352-
requestURI := fmt.Sprintf("%s/caas/2.4/%s", client.baseAddress, relativeURI)
353-
354-
var (
355-
request *http.Request
356-
bodyReader io.Reader
357-
err error
358-
)
359-
360-
bodyReader, err = newReaderFromJSON(body)
361-
if err != nil {
362-
return nil, err
363-
}
364-
365-
request, err = http.NewRequest(method, requestURI, bodyReader)
366-
if err != nil {
367-
return nil, err
368-
}
369-
370-
request.SetBasicAuth(client.username, client.password)
371-
request.Header.Add("Accept", "application/json")
372-
373-
if bodyReader != nil {
374-
request.Header.Set("Content-Type", "application/json")
375-
}
376-
377-
return request, nil
302+
return client.newRequestV2x(4, relativeURI, method, body)
378303
}
379304

380305
// Create a basic request for the compute API (V2.5, JSON).
381306
func (client *Client) newRequestV25(relativeURI string, method string, body interface{}) (*http.Request, error) {
382-
requestURI := fmt.Sprintf("%s/caas/2.5/%s", client.baseAddress, relativeURI)
307+
return client.newRequestV2x(5, relativeURI, method, body)
308+
}
309+
310+
// Create a basic request for the compute API (V2.5, JSON).
311+
func (client *Client) newRequestV26(relativeURI string, method string, body interface{}) (*http.Request, error) {
312+
return client.newRequestV2x(6, relativeURI, method, body)
313+
}
314+
315+
// Create a basic request for the compute API (V2.x, JSON).
316+
func (client *Client) newRequestV2x(minorVersion int, relativeURI string, method string, body interface{}) (*http.Request, error) {
317+
requestURI := fmt.Sprintf("%s/caas/2.%d/%s", client.baseAddress, minorVersion, relativeURI)
383318

384319
var (
385320
request *http.Request

compute/resources.go

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,12 @@ const (
4747

4848
// ResourceTypeCustomerImage represents a customer image.
4949
ResourceTypeCustomerImage
50+
51+
// ResourceTypeSSLDomainCertificate represents an SSL certificate for a domain name.
52+
ResourceTypeSSLDomainCertificate
53+
54+
// ResourceTypeSSLCertificateChain represents an SSL certificate chain
55+
ResourceTypeSSLCertificateChain
5056
)
5157

5258
// Resource represents a compute resource.
@@ -102,6 +108,12 @@ func GetResourceDescription(resourceType ResourceType) (string, error) {
102108
case ResourceTypeCustomerImage:
103109
return "customer image", nil
104110

111+
case ResourceTypeSSLDomainCertificate:
112+
return "SSL domain certificate", nil
113+
114+
case ResourceTypeSSLCertificateChain:
115+
return "SSL certificate chain", nil
116+
105117
default:
106118
return "", fmt.Errorf("unrecognised resource type (value = %d)", resourceType)
107119
}
@@ -147,6 +159,12 @@ func (client *Client) GetResource(id string, resourceType ResourceType) (Resourc
147159

148160
case ResourceTypeCustomerImage:
149161
return client.GetCustomerImage(id)
162+
163+
case ResourceTypeSSLDomainCertificate:
164+
return client.GetSSLDomainCertificate(id)
165+
166+
case ResourceTypeSSLCertificateChain:
167+
return client.GetSSLCertificateChain(id)
150168
}
151169

152170
return nil, fmt.Errorf("unrecognised resource type (value = %d)", resourceType)

compute/ssl_certificate_chains.go

Lines changed: 232 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,232 @@
1+
package compute
2+
3+
import (
4+
"encoding/json"
5+
"fmt"
6+
"net/http"
7+
"net/url"
8+
)
9+
10+
// SSLCertificateChain represents an SSL certificate applicable to a domain name.
11+
type SSLCertificateChain struct {
12+
ID string `json:"id"`
13+
Name string `json:"name"`
14+
Description string `json:"description"`
15+
State string `json:"state"`
16+
DatacenterID string `json:"datacenterId"`
17+
NetworkDomainID string `json:"networkDomainId"`
18+
}
19+
20+
// GetID returns the certificate chain's Id.
21+
func (certificateChain *SSLCertificateChain) GetID() string {
22+
return certificateChain.ID
23+
}
24+
25+
// GetResourceType returns the certificate chain's resource type.
26+
func (certificateChain *SSLCertificateChain) GetResourceType() ResourceType {
27+
return ResourceTypeSSLCertificateChain
28+
}
29+
30+
// GetName returns the certificate chain's name.
31+
func (certificateChain *SSLCertificateChain) GetName() string {
32+
return certificateChain.Name
33+
}
34+
35+
// GetState returns the certificate chain's current state.
36+
func (certificateChain *SSLCertificateChain) GetState() string {
37+
return certificateChain.State
38+
}
39+
40+
// IsDeleted determines whether the certificate chain has been deleted (is nil).
41+
func (certificateChain *SSLCertificateChain) IsDeleted() bool {
42+
return certificateChain == nil
43+
}
44+
45+
var _ Resource = &SSLCertificateChain{}
46+
47+
// ToEntityReference creates an EntityReference representing the certificate chain.
48+
func (certificateChain *SSLCertificateChain) ToEntityReference() EntityReference {
49+
return EntityReference{
50+
ID: certificateChain.ID,
51+
Name: certificateChain.Name,
52+
}
53+
}
54+
55+
var _ NamedEntity = &SSLCertificateChain{}
56+
57+
// SSLCertificateChains represents a page of SSLCertificateChain results.
58+
type SSLCertificateChains struct {
59+
Items []SSLCertificateChain `json:"sslCertificateChain"`
60+
61+
PagedResult
62+
}
63+
64+
// Request body when importing an SSL certificate chain.
65+
type importSSLCertificateChain struct {
66+
Name string `json:"name"`
67+
Description string `json:"description"`
68+
CertificateChain string `json:"certificateChain"`
69+
NetworkDomainID string `json:"networkDomainId"`
70+
}
71+
72+
// Request body when deleting an SSL certificate chain.
73+
type deleteSSLCertificateChain struct {
74+
// The SSL certificate Id.
75+
ID string `json:"id"`
76+
}
77+
78+
// ListSSLCertificateChainsInNetworkDomain retrieves a list of all SSL certificate chains in the specified network domain.
79+
func (client *Client) ListSSLCertificateChainsInNetworkDomain(networkDomainID string, paging *Paging) (pools *SSLCertificateChains, err error) {
80+
organizationID, err := client.getOrganizationID()
81+
if err != nil {
82+
return nil, err
83+
}
84+
85+
requestURI := fmt.Sprintf("%s/networkDomainVip/sslCertificateChain?networkDomainId=%s&%s",
86+
url.QueryEscape(organizationID),
87+
url.QueryEscape(networkDomainID),
88+
paging.EnsurePaging().toQueryParameters(),
89+
)
90+
request, err := client.newRequestV26(requestURI, http.MethodGet, nil)
91+
if err != nil {
92+
return nil, err
93+
}
94+
95+
responseBody, statusCode, err := client.executeRequest(request)
96+
if err != nil {
97+
return nil, err
98+
}
99+
100+
if statusCode != http.StatusOK {
101+
var apiResponse *APIResponseV2
102+
103+
apiResponse, err = readAPIResponseAsJSON(responseBody, statusCode)
104+
if err != nil {
105+
return nil, err
106+
}
107+
108+
return nil, apiResponse.ToError("Request to list SSL certificate chains in network domain '%s' failed with status code %d (%s): %s", networkDomainID, statusCode, apiResponse.ResponseCode, apiResponse.Message)
109+
}
110+
111+
pools = &SSLCertificateChains{}
112+
err = json.Unmarshal(responseBody, pools)
113+
if err != nil {
114+
return nil, err
115+
}
116+
117+
return pools, nil
118+
}
119+
120+
// GetSSLCertificateChain retrieves the SSL certificate chain with the specified Id.
121+
// Returns nil if no SSL certificate chain is found with the specified Id.
122+
func (client *Client) GetSSLCertificateChain(id string) (pool *SSLCertificateChain, err error) {
123+
organizationID, err := client.getOrganizationID()
124+
if err != nil {
125+
return nil, err
126+
}
127+
128+
requestURI := fmt.Sprintf("%s/networkDomainVip/sslCertificateChain/%s",
129+
url.QueryEscape(organizationID),
130+
url.QueryEscape(id),
131+
)
132+
request, err := client.newRequestV26(requestURI, http.MethodGet, nil)
133+
if err != nil {
134+
return nil, err
135+
}
136+
responseBody, statusCode, err := client.executeRequest(request)
137+
if err != nil {
138+
return nil, err
139+
}
140+
141+
if statusCode != http.StatusOK {
142+
var apiResponse *APIResponseV2
143+
144+
apiResponse, err = readAPIResponseAsJSON(responseBody, statusCode)
145+
if err != nil {
146+
return nil, err
147+
}
148+
149+
if apiResponse.ResponseCode == ResponseCodeResourceNotFound {
150+
return nil, nil // Not an error, but was not found.
151+
}
152+
153+
return nil, apiResponse.ToError("Request to retrieve SSL certificate chain with Id '%s' failed with status code %d (%s): %s", id, statusCode, apiResponse.ResponseCode, apiResponse.Message)
154+
}
155+
156+
pool = &SSLCertificateChain{}
157+
err = json.Unmarshal(responseBody, pool)
158+
if err != nil {
159+
return nil, err
160+
}
161+
162+
return pool, nil
163+
}
164+
165+
// ImportSSLCertificateChain imports an SSL certificate chain into a network domain.
166+
func (client *Client) ImportSSLCertificateChain(networkDomainID string, name string, description string, certificateChain string) (certificateID string, err error) {
167+
organizationID, err := client.getOrganizationID()
168+
if err != nil {
169+
return "", err
170+
}
171+
172+
requestURI := fmt.Sprintf("%s/networkDomainVip/importSslCertificateChain",
173+
url.QueryEscape(organizationID),
174+
)
175+
request, err := client.newRequestV26(requestURI, http.MethodPost, &importSSLCertificateChain{
176+
Name: name,
177+
Description: description,
178+
CertificateChain: certificateChain,
179+
NetworkDomainID: networkDomainID,
180+
})
181+
responseBody, statusCode, err := client.executeRequest(request)
182+
if err != nil {
183+
return "", err
184+
}
185+
186+
apiResponse, err := readAPIResponseAsJSON(responseBody, statusCode)
187+
if err != nil {
188+
return "", err
189+
}
190+
191+
if apiResponse.ResponseCode != ResponseCodeOK {
192+
return "", apiResponse.ToError("Request to import SSL certificate chain '%s' failed with status code %d (%s): %s", name, statusCode, apiResponse.ResponseCode, apiResponse.Message)
193+
}
194+
195+
// Expected: "info" { "name": "sslCertificateChainId", "value": "the-Id-of-the-imported-certificate" }
196+
sslCertificateChainIDMessage := apiResponse.GetFieldMessage("sslCertificateChainId")
197+
if sslCertificateChainIDMessage == nil {
198+
return "", apiResponse.ToError("Received an unexpected response (missing 'sslCertificateChainId') with status code %d (%s): %s", statusCode, apiResponse.ResponseCode, apiResponse.Message)
199+
}
200+
201+
return *sslCertificateChainIDMessage, nil
202+
}
203+
204+
// DeleteSSLCertificateChain deletes an existing SSL certificate chain.
205+
//
206+
// Returns an error if the operation was not successful.
207+
func (client *Client) DeleteSSLCertificateChain(id string) (err error) {
208+
organizationID, err := client.getOrganizationID()
209+
if err != nil {
210+
return err
211+
}
212+
213+
requestURI := fmt.Sprintf("%s/networkDomainVip/deleteSslCertificateChain",
214+
url.QueryEscape(organizationID),
215+
)
216+
request, err := client.newRequestV26(requestURI, http.MethodPost, &deleteSSLCertificateChain{id})
217+
responseBody, statusCode, err := client.executeRequest(request)
218+
if err != nil {
219+
return err
220+
}
221+
222+
apiResponse, err := readAPIResponseAsJSON(responseBody, statusCode)
223+
if err != nil {
224+
return err
225+
}
226+
227+
if apiResponse.ResponseCode != ResponseCodeOK {
228+
return apiResponse.ToError("Request to delete SSL certificate chain '%s' failed with unexpected status code %d (%s): %s", id, statusCode, apiResponse.ResponseCode, apiResponse.Message)
229+
}
230+
231+
return nil
232+
}

0 commit comments

Comments
 (0)