aboutsummaryrefslogtreecommitdiffhomepage
path: root/statuscake
diff options
context:
space:
mode:
Diffstat (limited to 'statuscake')
-rw-r--r--statuscake/provider.go1
-rw-r--r--statuscake/provider_test.go3
-rw-r--r--statuscake/resource_statuscakessl.go290
-rw-r--r--statuscake/resource_statuscakessl_test.go224
4 files changed, 518 insertions, 0 deletions
diff --git a/statuscake/provider.go b/statuscake/provider.go
index 93c691f..7f38d7f 100644
--- a/statuscake/provider.go
+++ b/statuscake/provider.go
@@ -25,6 +25,7 @@ func Provider() terraform.ResourceProvider {
25 25
26 ResourcesMap: map[string]*schema.Resource{ 26 ResourcesMap: map[string]*schema.Resource{
27 "statuscake_test": resourceStatusCakeTest(), 27 "statuscake_test": resourceStatusCakeTest(),
28 "statuscake_ssl": resourceStatusCakeSsl(),
28 }, 29 },
29 30
30 ConfigureFunc: providerConfigure, 31 ConfigureFunc: providerConfigure,
diff --git a/statuscake/provider_test.go b/statuscake/provider_test.go
index b1da050..4537960 100644
--- a/statuscake/provider_test.go
+++ b/statuscake/provider_test.go
@@ -38,4 +38,7 @@ func testAccPreCheck(t *testing.T) {
38 if v := os.Getenv("STATUSCAKE_TEST_CONTACT_GROUP_ID"); v == "" { 38 if v := os.Getenv("STATUSCAKE_TEST_CONTACT_GROUP_ID"); v == "" {
39 t.Fatal("STATUSCAKE_TEST_CONTACT_GROUP_ID must be set for acceptance tests") 39 t.Fatal("STATUSCAKE_TEST_CONTACT_GROUP_ID must be set for acceptance tests")
40 } 40 }
41 if v := os.Getenv("STATUSCAKE_SSL_CONTACT_GROUP_ID"); v == "" {
42 t.Fatal("STATUSCAKE_SSL_CONTACT_GROUP_ID must be set for acceptance tests")
43 }
41} 44}
diff --git a/statuscake/resource_statuscakessl.go b/statuscake/resource_statuscakessl.go
new file mode 100644
index 0000000..2ee50e6
--- /dev/null
+++ b/statuscake/resource_statuscakessl.go
@@ -0,0 +1,290 @@
1package statuscake
2
3import (
4 "fmt"
5 "strconv"
6
7 "github.com/DreamItGetIT/statuscake"
8 "github.com/hashicorp/terraform/helper/schema"
9 "log"
10 "strings"
11)
12
13func resourceStatusCakeSsl() *schema.Resource {
14 return &schema.Resource{
15 Create: CreateSsl,
16 Update: UpdateSsl,
17 Delete: DeleteSsl,
18 Read: ReadSsl,
19 Importer: &schema.ResourceImporter{
20 State: schema.ImportStatePassthrough,
21 },
22
23 Schema: map[string]*schema.Schema{
24 "ssl_id": {
25 Type: schema.TypeString,
26 Computed: true,
27 },
28
29 "domain": {
30 Type: schema.TypeString,
31 Required: true,
32 },
33
34 "contact_groups": {
35 Type: schema.TypeSet,
36 Elem: &schema.Schema{Type: schema.TypeString},
37 Optional: true,
38 Computed: true,
39 ConflictsWith: []string{"contact_groups_c"},
40 },
41
42 "contact_groups_c": {
43 Type: schema.TypeString,
44 Optional: true,
45 Computed: true,
46 ConflictsWith: []string{"contact_groups"},
47 },
48
49 "checkrate": {
50 Type: schema.TypeInt,
51 Required: true,
52 },
53
54 "alert_at": {
55 Type: schema.TypeString,
56 Required: true,
57 },
58
59 "alert_reminder": {
60 Type: schema.TypeBool,
61 Required: true,
62 },
63
64 "alert_expiry": {
65 Type: schema.TypeBool,
66 Required: true,
67 },
68
69 "alert_broken": {
70 Type: schema.TypeBool,
71 Required: true,
72 },
73
74 "alert_mixed": {
75 Type: schema.TypeBool,
76 Required: true,
77 },
78
79 "paused": {
80 Type: schema.TypeBool,
81 Computed: true,
82 },
83
84 "issuer_cn": {
85 Type: schema.TypeString,
86 Computed: true,
87 },
88
89 "cert_score": {
90 Type: schema.TypeString,
91 Computed: true,
92 },
93
94 "cipher_score": {
95 Type: schema.TypeString,
96 Computed: true,
97 },
98
99 "cert_status": {
100 Type: schema.TypeString,
101 Computed: true,
102 },
103
104 "cipher": {
105 Type: schema.TypeString,
106 Computed: true,
107 },
108
109 "valid_from_utc": {
110 Type: schema.TypeString,
111 Computed: true,
112 },
113
114 "valid_until_utc": {
115 Type: schema.TypeString,
116 Computed: true,
117 },
118
119 "mixed_content": {
120 Type: schema.TypeList,
121 Elem: &schema.Schema{
122 Type: schema.TypeMap,
123 Elem: &schema.Schema{Type: schema.TypeString},
124 },
125 Computed: true,
126 },
127
128 "flags": {
129 Type: schema.TypeMap,
130 Elem: &schema.Schema{Type: schema.TypeBool},
131 Computed: true,
132 },
133
134 "last_reminder": {
135 Type: schema.TypeInt,
136 Computed: true,
137 },
138
139 "last_updated_utc": {
140 Type: schema.TypeString,
141 Computed: true,
142 },
143 },
144 }
145}
146
147func CreateSsl(d *schema.ResourceData, meta interface{}) error {
148 client := meta.(*statuscake.Client)
149
150 if v, ok := d.GetOk("contact_groups"); ok {
151 d.Set("contact_groups_c", strings.Join(castSetToSliceStrings(v.(*schema.Set).List()), ","))
152 }
153
154 newSsl := &statuscake.PartialSsl{
155 Domain: d.Get("domain").(string),
156 Checkrate: strconv.Itoa(d.Get("checkrate").(int)),
157 ContactGroupsC: d.Get("contact_groups_c").(string),
158 AlertReminder: d.Get("alert_reminder").(bool),
159 AlertExpiry: d.Get("alert_expiry").(bool),
160 AlertBroken: d.Get("alert_broken").(bool),
161 AlertMixed: d.Get("alert_mixed").(bool),
162 AlertAt: d.Get("alert_at").(string),
163 }
164
165 log.Printf("[DEBUG] Creating new StatusCake Ssl: %s", d.Get("domain").(string))
166
167 response, err := statuscake.NewSsls(client).Create(newSsl)
168 if err != nil {
169 return fmt.Errorf("Error creating StatusCake Ssl: %s", err.Error())
170 }
171
172 d.Set("ssl_id", response.ID)
173 d.Set("paused", response.Paused)
174 d.Set("issuer_cn", response.IssuerCn)
175 d.Set("cert_score", response.CertScore)
176 d.Set("cipher_score", response.CipherScore)
177 d.Set("cert_status", response.CertStatus)
178 d.Set("cipher", response.Cipher)
179 d.Set("valid_from_utc", response.ValidFromUtc)
180 d.Set("valid_until_utc", response.ValidUntilUtc)
181 d.Set("mixed_content", response.MixedContent)
182 d.Set("flags", response.Flags)
183 d.Set("last_reminder", response.LastReminder)
184 d.Set("last_updated_utc", response.LastUpdatedUtc)
185 d.SetId(response.ID)
186
187 return ReadSsl(d, meta)
188}
189
190func UpdateSsl(d *schema.ResourceData, meta interface{}) error {
191 client := meta.(*statuscake.Client)
192
193 params := getStatusCakeSslInput(d)
194
195 log.Printf("[DEBUG] StatusCake Ssl Update for %s", d.Id())
196 _, err := statuscake.NewSsls(client).Update(params)
197 if err != nil {
198 return fmt.Errorf("Error Updating StatusCake Ssl: %s", err.Error())
199 }
200 return nil
201}
202
203func DeleteSsl(d *schema.ResourceData, meta interface{}) error {
204 client := meta.(*statuscake.Client)
205
206 log.Printf("[DEBUG] Deleting StatusCake Ssl: %s", d.Id())
207 err := statuscake.NewSsls(client).Delete(d.Id())
208
209 return err
210}
211
212func ReadSsl(d *schema.ResourceData, meta interface{}) error {
213 client := meta.(*statuscake.Client)
214
215 response, err := statuscake.NewSsls(client).Detail(d.Id())
216 if err != nil {
217 return fmt.Errorf("Error Getting StatusCake Ssl Details for %s: Error: %s", d.Id(), err)
218 }
219 d.Set("domain", response.Domain)
220 d.Set("checkrate", response.Checkrate)
221 d.Set("contact_groups_c", response.ContactGroupsC)
222 d.Set("alert_reminder", response.AlertReminder)
223 d.Set("alert_expiry", response.AlertExpiry)
224 d.Set("alert_broken", response.AlertBroken)
225 d.Set("alert_mixed", response.AlertMixed)
226 d.Set("alert_at", response.AlertAt)
227 d.Set("ssl_id", response.ID)
228 d.Set("contact_groups", response.ContactGroups)
229 d.Set("paused", response.Paused)
230 d.Set("issuer_cn", response.IssuerCn)
231 d.Set("cert_score", response.CertScore)
232 d.Set("cipher_score", response.CipherScore)
233 d.Set("cert_status", response.CertStatus)
234 d.Set("cipher", response.Cipher)
235 d.Set("valid_from_utc", response.ValidFromUtc)
236 d.Set("valid_until_utc", response.ValidUntilUtc)
237 d.Set("mixed_content", response.MixedContent)
238 d.Set("flags", response.Flags)
239 d.Set("last_reminder", response.LastReminder)
240 d.Set("last_updated_utc", response.LastUpdatedUtc)
241 d.SetId(response.ID)
242
243 return nil
244}
245
246func getStatusCakeSslInput(d *schema.ResourceData) *statuscake.PartialSsl {
247 sslId, parseErr := strconv.Atoi(d.Id())
248 if parseErr != nil {
249 log.Printf("[DEBUG] Error Parsing StatusCake Id: %s", d.Id())
250 }
251 ssl := &statuscake.PartialSsl{
252 ID: sslId,
253 }
254
255 if v, ok := d.GetOk("domain"); ok {
256 ssl.Domain = v.(string)
257 }
258
259 if v, ok := d.GetOk("checkrate"); ok {
260 ssl.Checkrate = strconv.Itoa(v.(int))
261 }
262
263 if v, ok := d.GetOk("contact_groups"); ok {
264 ssl.ContactGroupsC = strings.Join(castSetToSliceStrings(v.(*schema.Set).List()), ",")
265 } else if v, ok := d.GetOk("contact_groups_c"); ok {
266 ssl.ContactGroupsC = v.(string)
267 }
268
269 if v, ok := d.GetOk("alert_reminder"); ok {
270 ssl.AlertReminder = v.(bool)
271 }
272
273 if v, ok := d.GetOk("alert_expiry"); ok {
274 ssl.AlertExpiry = v.(bool)
275 }
276
277 if v, ok := d.GetOk("alert_broken"); ok {
278 ssl.AlertBroken = v.(bool)
279 }
280
281 if v, ok := d.GetOk("alert_mixed"); ok {
282 ssl.AlertMixed = v.(bool)
283 }
284
285 if v, ok := d.GetOk("alert_at"); ok {
286 ssl.AlertAt = v.(string)
287 }
288
289 return ssl
290}
diff --git a/statuscake/resource_statuscakessl_test.go b/statuscake/resource_statuscakessl_test.go
new file mode 100644
index 0000000..fa48bad
--- /dev/null
+++ b/statuscake/resource_statuscakessl_test.go
@@ -0,0 +1,224 @@
1package statuscake
2
3import (
4 "fmt"
5 "github.com/DreamItGetIT/statuscake"
6 "github.com/hashicorp/terraform/helper/resource"
7 "github.com/hashicorp/terraform/terraform"
8 "os"
9 "strconv"
10 "testing"
11)
12
13func TestAccStatusCakeSsl_basic(t *testing.T) {
14 var ssl statuscake.Ssl
15
16 resource.Test(t, resource.TestCase{
17 PreCheck: func() { testAccPreCheck(t) },
18 Providers: testAccProviders,
19 CheckDestroy: testAccSslCheckDestroy(&ssl),
20 Steps: []resource.TestStep{
21 {
22 Config: interpolateTerraformTemplateSsl(testAccSslConfig_basic),
23 Check: resource.ComposeTestCheckFunc(
24 testAccSslCheckExists("statuscake_ssl.exemple", &ssl),
25 testAccSslCheckAttributes("statuscake_ssl.exemple", &ssl),
26 ),
27 },
28 },
29 })
30}
31
32func TestAccStatusCakeSsl_withUpdate(t *testing.T) {
33 var ssl statuscake.Ssl
34
35 resource.Test(t, resource.TestCase{
36 PreCheck: func() { testAccPreCheck(t) },
37 Providers: testAccProviders,
38 CheckDestroy: testAccSslCheckDestroy(&ssl),
39 Steps: []resource.TestStep{
40 {
41 Config: interpolateTerraformTemplateSsl(testAccSslConfig_basic),
42 Check: resource.ComposeTestCheckFunc(
43 testAccSslCheckExists("statuscake_ssl.exemple", &ssl),
44 testAccSslCheckAttributes("statuscake_ssl.exemple", &ssl),
45 ),
46 },
47
48 {
49 Config: testAccSslConfig_update,
50 Check: resource.ComposeTestCheckFunc(
51 testAccSslCheckExists("statuscake_ssl.exemple", &ssl),
52 testAccSslCheckAttributes("statuscake_ssl.exemple", &ssl),
53 resource.TestCheckResourceAttr("statuscake_ssl.exemple", "checkrate", "86400"),
54 resource.TestCheckResourceAttr("statuscake_ssl.exemple", "domain", "https://www.exemple.com"),
55 resource.TestCheckResourceAttr("statuscake_ssl.exemple", "contact_groups_c", ""),
56 resource.TestCheckResourceAttr("statuscake_ssl.exemple", "alert_at", "18,81,2019"),
57 resource.TestCheckResourceAttr("statuscake_ssl.exemple", "alert_reminder", "false"),
58 resource.TestCheckResourceAttr("statuscake_ssl.exemple", "alert_expiry", "false"),
59 resource.TestCheckResourceAttr("statuscake_ssl.exemple", "alert_broken", "true"),
60 resource.TestCheckResourceAttr("statuscake_ssl.exemple", "alert_mixed", "false"),
61 ),
62 },
63 },
64 })
65}
66
67func testAccSslCheckExists(rn string, ssl *statuscake.Ssl) resource.TestCheckFunc {
68 return func(s *terraform.State) error {
69 rs, ok := s.RootModule().Resources[rn]
70 if !ok {
71 return fmt.Errorf("resource not found: %s", rn)
72 }
73
74 if rs.Primary.ID == "" {
75 return fmt.Errorf("SslID not set")
76 }
77
78 client := testAccProvider.Meta().(*statuscake.Client)
79 sslId := rs.Primary.ID
80
81 gotSsl, err := statuscake.NewSsls(client).Detail(sslId)
82 if err != nil {
83 return fmt.Errorf("error getting ssl: %s", err)
84 }
85 gotSsl.LastUpdatedUtc = "0000-00-00 00:00:00" // quick fix to avoid issue with it because the state is updated before the value change but it is changed when gotSsl is created
86 *ssl = *gotSsl
87
88 return nil
89 }
90}
91
92func testAccSslCheckAttributes(rn string, ssl *statuscake.Ssl) resource.TestCheckFunc {
93 return func(s *terraform.State) error {
94 attrs := s.RootModule().Resources[rn].Primary.Attributes
95
96 check := func(key, stateValue, sslValue string) error {
97 if sslValue != stateValue {
98 return fmt.Errorf("different values for %s in state (%s) and in statuscake (%s)",
99 key, stateValue, sslValue)
100 }
101 return nil
102 }
103
104 for key, value := range attrs {
105 var err error
106
107 switch key {
108 case "domain":
109 err = check(key, value, ssl.Domain)
110 case "contact_groups_c":
111 err = check(key, value, ssl.ContactGroupsC)
112 case "checkrate":
113 err = check(key, value, strconv.Itoa(ssl.Checkrate))
114 case "alert_at":
115 err = check(key, value, ssl.AlertAt)
116 case "alert_reminder":
117 err = check(key, value, strconv.FormatBool(ssl.AlertReminder))
118 case "alert_expiry":
119 err = check(key, value, strconv.FormatBool(ssl.AlertExpiry))
120 case "alert_broken":
121 err = check(key, value, strconv.FormatBool(ssl.AlertBroken))
122 case "alert_mixed":
123 err = check(key, value, strconv.FormatBool(ssl.AlertMixed))
124 case "last_updated_utc":
125 err = check(key, value, ssl.LastUpdatedUtc)
126 case "paused":
127 err = check(key, value, strconv.FormatBool(ssl.Paused))
128 case "issuer_cn":
129 err = check(key, value, ssl.IssuerCn)
130 case "contact_groups":
131 for _, tv := range ssl.ContactGroups {
132 err = check(key, value, tv)
133 if err != nil {
134 return err
135 }
136 }
137 case "cert_score":
138 err = check(key, value, ssl.CertScore)
139 case "cert_status":
140 err = check(key, value, ssl.CertStatus)
141 case "cipher":
142 err = check(key, value, ssl.Cipher)
143 case "valid_from_utc":
144 err = check(key, value, ssl.ValidFromUtc)
145 case "valid_until_utc":
146 err = check(key, value, ssl.ValidUntilUtc)
147 case "last_reminder":
148 err = check(key, value, strconv.Itoa(ssl.LastReminder))
149 case "flags":
150 for _, tv := range ssl.Flags {
151 err = check(key, value, strconv.FormatBool(tv))
152 if err != nil {
153 return err
154 }
155 }
156
157 case "mixed_content":
158 for _, tv := range ssl.MixedContent {
159 for _, tv2 := range tv {
160 err = check(key, value, tv2)
161 if err != nil {
162 return err
163 }
164 }
165 }
166 }
167 if err != nil {
168 return err
169 }
170 }
171 return nil
172 }
173}
174
175func testAccSslCheckDestroy(ssl *statuscake.Ssl) resource.TestCheckFunc {
176 return func(s *terraform.State) error {
177 client := testAccProvider.Meta().(*statuscake.Client)
178 _, err := statuscake.NewSsls(client).Detail(ssl.ID)
179 if err == nil {
180 return fmt.Errorf("ssl still exists")
181 }
182
183 return nil
184 }
185}
186
187func interpolateTerraformTemplateSsl(template string) string {
188 sslContactGroupId := "43402"
189
190 if v := os.Getenv("STATUSCAKE_SSL_CONTACT_GROUP_ID"); v != "" {
191 sslContactGroupId = v
192 }
193 if sslContactGroupId == "-1" {
194 sslContactGroupId = ""
195 }
196
197 return fmt.Sprintf(template, sslContactGroupId)
198}
199
200const testAccSslConfig_basic = `
201resource "statuscake_ssl" "exemple" {
202 domain = "https://www.exemple.com"
203 contact_groups_c = "%s"
204 checkrate = 3600
205 alert_at = "18,71,2019"
206 alert_reminder = true
207 alert_expiry = true
208 alert_broken = false
209 alert_mixed = true
210}
211`
212
213const testAccSslConfig_update = `
214resource "statuscake_ssl" "exemple" {
215 domain = "https://www.exemple.com"
216 contact_groups_c = ""
217 checkrate = 86400
218 alert_at = "18,81,2019"
219 alert_reminder = false
220 alert_expiry = false
221 alert_broken = true
222 alert_mixed = false
223}
224`