diff --git a/CHANGELOG.md b/CHANGELOG.md index b32132f..bce31a4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,10 @@ # Change Log +## [v1.2.0] - 2018-05-08 + +- #166 Remove support for Go 1.6 - @iheanyi +- #165 Add support for Let's Encrypt Certificates - @viola + ## [v1.1.3] - 2018-03-07 - #156 Handle non-json errors from the API - @aknuds1 diff --git a/certificates.go b/certificates.go index 2414df4..cbc3e16 100644 --- a/certificates.go +++ b/certificates.go @@ -19,19 +19,24 @@ type CertificatesService interface { // 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"` + ID string `json:"id,omitempty"` + Name string `json:"name,omitempty"` + DNSNames []string `json:"dns_names,omitempty"` + NotAfter string `json:"not_after,omitempty"` + SHA1Fingerprint string `json:"sha1_fingerprint,omitempty"` + Created string `json:"created_at,omitempty"` + State string `json:"state,omitempty"` + Type string `json:"type,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"` + Name string `json:"name,omitempty"` + DNSNames []string `json:"dns_names,omitempty"` + PrivateKey string `json:"private_key,omitempty"` + LeafCertificate string `json:"leaf_certificate,omitempty"` + CertificateChain string `json:"certificate_chain,omitempty"` + Type string `json:"type,omitempty"` } type certificateRoot struct { diff --git a/certificates_test.go b/certificates_test.go index 8ad4af2..e522da5 100644 --- a/certificates_test.go +++ b/certificates_test.go @@ -15,9 +15,15 @@ var certJSONResponse = ` "certificate": { "id": "892071a0-bb95-49bc-8021-3afd67a210bf", "name": "web-cert-01", + "dns_names": [ + "somedomain.com", + "api.somedomain.com" + ], "not_after": "2017-02-22T00:23:00Z", "sha1_fingerprint": "dfcc9f57d86bf58e321c2c6c31c7a971be244ac7", - "created_at": "2017-02-08T16:02:37Z" + "created_at": "2017-02-08T16:02:37Z", + "state": "verified", + "type": "custom" } } ` @@ -27,17 +33,26 @@ var certsJSONResponse = ` "certificates": [ { "id": "892071a0-bb95-49bc-8021-3afd67a210bf", - "name": "web-cert-01", + "name": "web-cert-01", + "dns_names": [ + "somedomain.com", + "api.somedomain.com" + ], "not_after": "2017-02-22T00:23:00Z", "sha1_fingerprint": "dfcc9f57d86bf58e321c2c6c31c7a971be244ac7", - "created_at": "2017-02-08T16:02:37Z" + "created_at": "2017-02-08T16:02:37Z", + "state": "verified", + "type": "custom" }, { "id": "992071a0-bb95-49bc-8021-3afd67a210bf", - "name": "web-cert-02", + "name": "web-cert-02", + "dns_names":["example.com"], "not_after": "2017-02-22T00:23:00Z", "sha1_fingerprint": "cfcc9f57d86bf58e321c2c6c31c7a971be244ac7", - "created_at": "2017-02-08T16:02:37Z" + "created_at": "2017-02-08T16:02:37Z", + "state": "pending", + "type": "lets_encrypt" } ], "links": {}, @@ -67,9 +82,12 @@ func TestCertificates_Get(t *testing.T) { expected := &Certificate{ ID: "892071a0-bb95-49bc-8021-3afd67a210bf", Name: "web-cert-01", + DNSNames: []string{"somedomain.com", "api.somedomain.com"}, NotAfter: "2017-02-22T00:23:00Z", SHA1Fingerprint: "dfcc9f57d86bf58e321c2c6c31c7a971be244ac7", Created: "2017-02-08T16:02:37Z", + State: "verified", + Type: "custom", } assert.Equal(t, expected, certificate) @@ -95,16 +113,22 @@ func TestCertificates_List(t *testing.T) { { ID: "892071a0-bb95-49bc-8021-3afd67a210bf", Name: "web-cert-01", + DNSNames: []string{"somedomain.com", "api.somedomain.com"}, NotAfter: "2017-02-22T00:23:00Z", SHA1Fingerprint: "dfcc9f57d86bf58e321c2c6c31c7a971be244ac7", Created: "2017-02-08T16:02:37Z", + State: "verified", + Type: "custom", }, { ID: "992071a0-bb95-49bc-8021-3afd67a210bf", Name: "web-cert-02", + DNSNames: []string{"example.com"}, NotAfter: "2017-02-22T00:23:00Z", SHA1Fingerprint: "cfcc9f57d86bf58e321c2c6c31c7a971be244ac7", Created: "2017-02-08T16:02:37Z", + State: "pending", + Type: "lets_encrypt", }, } @@ -112,44 +136,102 @@ func TestCertificates_List(t *testing.T) { } 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-----", + tests := []struct { + desc string + createRequest *CertificateRequest + certJSONResponse string + expectedCertificate *Certificate + }{ + { + desc: "creates custom certificate", + createRequest: &CertificateRequest{ + Name: "web-cert-01", + PrivateKey: "-----BEGIN PRIVATE KEY-----", + LeafCertificate: "-----BEGIN CERTIFICATE-----", + CertificateChain: "-----BEGIN CERTIFICATE-----", + }, + certJSONResponse: `{ + "certificate": { + "id": "892071a0-bb95-49bc-8021-3afd67a210bf", + "name": "custom-cert", + "dns_names":[], + "not_after": "2017-02-22T00:23:00Z", + "sha1_fingerprint": "dfcc9f57d86bf58e321c2c6c31c7a971be244ac7", + "created_at": "2017-02-08T16:02:37Z", + "state": "verified", + "type": "custom" + } + }`, + expectedCertificate: &Certificate{ + ID: "892071a0-bb95-49bc-8021-3afd67a210bf", + Name: "custom-cert", + DNSNames: []string{}, + NotAfter: "2017-02-22T00:23:00Z", + SHA1Fingerprint: "dfcc9f57d86bf58e321c2c6c31c7a971be244ac7", + Created: "2017-02-08T16:02:37Z", + State: "verified", + Type: "custom", + }, + }, + { + desc: "creates let's encrypt certificate", + createRequest: &CertificateRequest{ + Name: "lets-encrypt-cert", + DNSNames: []string{"example.com", "api.example.com"}, + Type: "lets_encrypt", + }, + certJSONResponse: `{ + "certificate": { + "id": "91bce928-a983-4c97-a5ee-78c585bf798d", + "name": "lets-encrypt-cert", + "dns_names":["example.com", "api.example.com"], + "not_after": "2022-01-26T15:50:00Z", + "sha1_fingerprint": "2e3c2ba8016faf80f431700ff2865ef6dba30a81", + "created_at": "2017-08-23T20:42:46Z", + "state": "pending", + "type": "lets_encrypt" + } + }`, + expectedCertificate: &Certificate{ + ID: "91bce928-a983-4c97-a5ee-78c585bf798d", + Name: "lets-encrypt-cert", + DNSNames: []string{"example.com", "api.example.com"}, + NotAfter: "2022-01-26T15:50:00Z", + SHA1Fingerprint: "2e3c2ba8016faf80f431700ff2865ef6dba30a81", + Created: "2017-08-23T20:42:46Z", + State: "pending", + Type: "lets_encrypt", + }, + }, } - 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) - } + for _, test := range tests { + t.Run(test.desc, func(t *testing.T) { + setup() + defer teardown() - testMethod(t, r, http.MethodPost) - assert.Equal(t, createRequest, v) + 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) + } - fmt.Fprint(w, certJSONResponse) - }) + testMethod(t, r, http.MethodPost) + assert.Equal(t, test.createRequest, v) - certificate, _, err := client.Certificates.Create(ctx, createRequest) - if err != nil { - t.Errorf("Certificates.Create returned error: %v", err) + fmt.Fprint(w, test.certJSONResponse) + }) + + certificate, _, err := client.Certificates.Create(ctx, test.createRequest) + if err != nil { + t.Errorf("Certificates.Create returned error: %v", err) + } + + assert.Equal(t, test.expectedCertificate, certificate) + }) } - - 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) {