-
Notifications
You must be signed in to change notification settings - Fork 303
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add CertificatesService for managing certificates with the DigitalOce…
…an API. (#126) * Add CertificatesService. * Code review changes.
- Loading branch information
Showing
3 changed files
with
290 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,117 @@ | ||
package godo | ||
|
||
import "path" | ||
|
||
const certificatesBasePath = "/v2/certificates" | ||
|
||
// CertificatesService is an interface for managing certificates with the DigitalOcean API. | ||
// See: https://developers.digitalocean.com/documentation/v2/#certificates | ||
type CertificatesService interface { | ||
Get(cID string) (*Certificate, *Response, error) | ||
List(opt *ListOptions) ([]Certificate, *Response, error) | ||
Create(cr *CertificateRequest) (*Certificate, *Response, error) | ||
Delete(cID string) (*Response, error) | ||
} | ||
|
||
// Certificate represents a DigitalOcean certificate configuration. | ||
type Certificate struct { | ||
ID string `json:"id,omitempty"` | ||
Name string `json:"name,omitempty"` | ||
NotAfter string `json:"not_after,omitempty"` | ||
SHA1Fingerprint string `json:"sha1_fingerprint,omitempty"` | ||
Created string `json:"created_at,omitempty"` | ||
} | ||
|
||
// CertificateRequest represents configuration for a new certificate. | ||
type CertificateRequest struct { | ||
Name string `json:"name,omitempty"` | ||
PrivateKey string `json:"private_key,omitempty"` | ||
LeafCertificate string `json:"leaf_certificate,omitempty"` | ||
CertificateChain string `json:"certificate_chain,omitempty"` | ||
} | ||
|
||
type certificateRoot struct { | ||
Certificate *Certificate `json:"certificate"` | ||
} | ||
|
||
type certificatesRoot struct { | ||
Certificates []Certificate `json:"certificates"` | ||
Links *Links `json:"links"` | ||
} | ||
|
||
// CertificatesServiceOp handles communication with certificates methods of the DigitalOcean API. | ||
type CertificatesServiceOp struct { | ||
client *Client | ||
} | ||
|
||
var _ CertificatesService = &CertificatesServiceOp{} | ||
|
||
// Get an existing certificate by its identifier. | ||
func (c *CertificatesServiceOp) Get(cID string) (*Certificate, *Response, error) { | ||
urlStr := path.Join(certificatesBasePath, cID) | ||
|
||
req, err := c.client.NewRequest("GET", urlStr, nil) | ||
if err != nil { | ||
return nil, nil, err | ||
} | ||
|
||
root := new(certificateRoot) | ||
resp, err := c.client.Do(req, root) | ||
if err != nil { | ||
return nil, resp, err | ||
} | ||
|
||
return root.Certificate, resp, nil | ||
} | ||
|
||
// List all certificates. | ||
func (c *CertificatesServiceOp) List(opt *ListOptions) ([]Certificate, *Response, error) { | ||
urlStr, err := addOptions(certificatesBasePath, opt) | ||
if err != nil { | ||
return nil, nil, err | ||
} | ||
|
||
req, err := c.client.NewRequest("GET", urlStr, nil) | ||
if err != nil { | ||
return nil, nil, err | ||
} | ||
|
||
root := new(certificatesRoot) | ||
resp, err := c.client.Do(req, root) | ||
if err != nil { | ||
return nil, resp, err | ||
} | ||
if l := root.Links; l != nil { | ||
resp.Links = l | ||
} | ||
|
||
return root.Certificates, resp, nil | ||
} | ||
|
||
// Create a new certificate with provided configuration. | ||
func (c *CertificatesServiceOp) Create(cr *CertificateRequest) (*Certificate, *Response, error) { | ||
req, err := c.client.NewRequest("POST", certificatesBasePath, cr) | ||
if err != nil { | ||
return nil, nil, err | ||
} | ||
|
||
root := new(certificateRoot) | ||
resp, err := c.client.Do(req, root) | ||
if err != nil { | ||
return nil, resp, err | ||
} | ||
|
||
return root.Certificate, resp, nil | ||
} | ||
|
||
// Delete a certificate by its identifier. | ||
func (c *CertificatesServiceOp) Delete(cID string) (*Response, error) { | ||
urlStr := path.Join(certificatesBasePath, cID) | ||
|
||
req, err := c.client.NewRequest("DELETE", urlStr, nil) | ||
if err != nil { | ||
return nil, err | ||
} | ||
|
||
return c.client.Do(req, nil) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,171 @@ | ||
package godo | ||
|
||
import ( | ||
"encoding/json" | ||
"fmt" | ||
"net/http" | ||
"path" | ||
"testing" | ||
|
||
"github.com/stretchr/testify/assert" | ||
) | ||
|
||
var certJSONResponse = ` | ||
{ | ||
"certificate": { | ||
"id": "892071a0-bb95-49bc-8021-3afd67a210bf", | ||
"name": "web-cert-01", | ||
"not_after": "2017-02-22T00:23:00Z", | ||
"sha1_fingerprint": "dfcc9f57d86bf58e321c2c6c31c7a971be244ac7", | ||
"created_at": "2017-02-08T16:02:37Z" | ||
} | ||
} | ||
` | ||
|
||
var certsJSONResponse = ` | ||
{ | ||
"certificates": [ | ||
{ | ||
"id": "892071a0-bb95-49bc-8021-3afd67a210bf", | ||
"name": "web-cert-01", | ||
"not_after": "2017-02-22T00:23:00Z", | ||
"sha1_fingerprint": "dfcc9f57d86bf58e321c2c6c31c7a971be244ac7", | ||
"created_at": "2017-02-08T16:02:37Z" | ||
}, | ||
{ | ||
"id": "992071a0-bb95-49bc-8021-3afd67a210bf", | ||
"name": "web-cert-02", | ||
"not_after": "2017-02-22T00:23:00Z", | ||
"sha1_fingerprint": "cfcc9f57d86bf58e321c2c6c31c7a971be244ac7", | ||
"created_at": "2017-02-08T16:02:37Z" | ||
} | ||
], | ||
"links": {}, | ||
"meta": { | ||
"total": 1 | ||
} | ||
} | ||
` | ||
|
||
func TestCertificates_Get(t *testing.T) { | ||
setup() | ||
defer teardown() | ||
|
||
urlStr := "/v2/certificates" | ||
cID := "892071a0-bb95-49bc-8021-3afd67a210bf" | ||
urlStr = path.Join(urlStr, cID) | ||
mux.HandleFunc(urlStr, func(w http.ResponseWriter, r *http.Request) { | ||
testMethod(t, r, "GET") | ||
fmt.Fprint(w, certJSONResponse) | ||
}) | ||
|
||
certificate, _, err := client.Certificates.Get(cID) | ||
if err != nil { | ||
t.Errorf("Certificates.Get returned error: %v", err) | ||
} | ||
|
||
expected := &Certificate{ | ||
ID: "892071a0-bb95-49bc-8021-3afd67a210bf", | ||
Name: "web-cert-01", | ||
NotAfter: "2017-02-22T00:23:00Z", | ||
SHA1Fingerprint: "dfcc9f57d86bf58e321c2c6c31c7a971be244ac7", | ||
Created: "2017-02-08T16:02:37Z", | ||
} | ||
|
||
assert.Equal(t, expected, certificate) | ||
} | ||
|
||
func TestCertificates_List(t *testing.T) { | ||
setup() | ||
defer teardown() | ||
|
||
urlStr := "/v2/certificates" | ||
mux.HandleFunc(urlStr, func(w http.ResponseWriter, r *http.Request) { | ||
testMethod(t, r, "GET") | ||
fmt.Fprint(w, certsJSONResponse) | ||
}) | ||
|
||
certificates, _, err := client.Certificates.List(nil) | ||
|
||
if err != nil { | ||
t.Errorf("Certificates.List returned error: %v", err) | ||
} | ||
|
||
expected := []Certificate{ | ||
{ | ||
ID: "892071a0-bb95-49bc-8021-3afd67a210bf", | ||
Name: "web-cert-01", | ||
NotAfter: "2017-02-22T00:23:00Z", | ||
SHA1Fingerprint: "dfcc9f57d86bf58e321c2c6c31c7a971be244ac7", | ||
Created: "2017-02-08T16:02:37Z", | ||
}, | ||
{ | ||
ID: "992071a0-bb95-49bc-8021-3afd67a210bf", | ||
Name: "web-cert-02", | ||
NotAfter: "2017-02-22T00:23:00Z", | ||
SHA1Fingerprint: "cfcc9f57d86bf58e321c2c6c31c7a971be244ac7", | ||
Created: "2017-02-08T16:02:37Z", | ||
}, | ||
} | ||
|
||
assert.Equal(t, expected, certificates) | ||
} | ||
|
||
func TestCertificates_Create(t *testing.T) { | ||
setup() | ||
defer teardown() | ||
|
||
createRequest := &CertificateRequest{ | ||
Name: "web-cert-01", | ||
PrivateKey: "-----BEGIN PRIVATE KEY-----", | ||
LeafCertificate: "-----BEGIN CERTIFICATE-----", | ||
CertificateChain: "-----BEGIN CERTIFICATE-----", | ||
} | ||
|
||
urlStr := "/v2/certificates" | ||
mux.HandleFunc(urlStr, func(w http.ResponseWriter, r *http.Request) { | ||
v := new(CertificateRequest) | ||
err := json.NewDecoder(r.Body).Decode(v) | ||
if err != nil { | ||
t.Fatal(err) | ||
} | ||
|
||
testMethod(t, r, "POST") | ||
assert.Equal(t, createRequest, v) | ||
|
||
fmt.Fprint(w, certJSONResponse) | ||
}) | ||
|
||
certificate, _, err := client.Certificates.Create(createRequest) | ||
if err != nil { | ||
t.Errorf("Certificates.Create returned error: %v", err) | ||
} | ||
|
||
expected := &Certificate{ | ||
ID: "892071a0-bb95-49bc-8021-3afd67a210bf", | ||
Name: "web-cert-01", | ||
NotAfter: "2017-02-22T00:23:00Z", | ||
SHA1Fingerprint: "dfcc9f57d86bf58e321c2c6c31c7a971be244ac7", | ||
Created: "2017-02-08T16:02:37Z", | ||
} | ||
|
||
assert.Equal(t, expected, certificate) | ||
} | ||
|
||
func TestCertificates_Delete(t *testing.T) { | ||
setup() | ||
defer teardown() | ||
|
||
cID := "892071a0-bb95-49bc-8021-3afd67a210bf" | ||
urlStr := "/v2/certificates" | ||
urlStr = path.Join(urlStr, cID) | ||
mux.HandleFunc(urlStr, func(w http.ResponseWriter, r *http.Request) { | ||
testMethod(t, r, "DELETE") | ||
}) | ||
|
||
_, err := client.Certificates.Delete(cID) | ||
|
||
if err != nil { | ||
t.Errorf("Certificates.Delete returned error: %v", err) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters