Skip to content

Commit

Permalink
Make TTL of record optional
Browse files Browse the repository at this point in the history
TTL is a optional attribute of a record, and is now optional in this provider as well.

Closes #11
  • Loading branch information
timohirt committed Aug 28, 2020
1 parent 5685f8b commit 5642e7b
Show file tree
Hide file tree
Showing 6 changed files with 96 additions and 20 deletions.
1 change: 1 addition & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,7 @@ github.com/hashicorp/terraform-json v0.4.0 h1:KNh29iNxozP5adfUFBJ4/fWd0Cu3taGgjH
github.com/hashicorp/terraform-json v0.4.0/go.mod h1:eAbqb4w0pSlRmdvl8fOyHAi/+8jnkVYN28gJkSJrLhU=
github.com/hashicorp/terraform-plugin-sdk v1.12.0 h1:HPp65ShSsKUMPf6jD50UQn/xAjyrGVO4FxI63bvu+pc=
github.com/hashicorp/terraform-plugin-sdk v1.12.0/go.mod h1:HiWIPD/T9HixIhQUwaSoDQxo4BLFdmiBi/Qz5gjB8Q0=
github.com/hashicorp/terraform-plugin-sdk v1.15.0 h1:bmYnTT7MqNXlUHDc7pT8E6uKT2g/upjlRLypJFK1OQU=
github.com/hashicorp/terraform-plugin-test v1.3.0 h1:hU5LoxrOn9qvOo+LTKN6mSav2J+dAMprbdxJPEQvp4U=
github.com/hashicorp/terraform-plugin-test v1.3.0/go.mod h1:QIJHYz8j+xJtdtLrFTlzQVC0ocr3rf/OjIpgZLK56Hs=
github.com/hashicorp/terraform-svchost v0.0.0-20191011084731-65d371908596 h1:hjyO2JsNZUKT1ym+FAdlBEkGPevazYsmVgIMw7dVELg=
Expand Down
2 changes: 1 addition & 1 deletion hetznerdns/api/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -329,7 +329,7 @@ type CreateRecordOpts struct {
Type string `json:"type"`
Name string `json:"name"`
Value string `json:"value"`
TTL int `json:"ttl"`
TTL *int `json:"ttl,omitempty"`
}

// CreateRecord create a new DNS records
Expand Down
22 changes: 18 additions & 4 deletions hetznerdns/api/client_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -117,14 +117,26 @@ func TestClientDeleteZone(t *testing.T) {
}

func TestClientGetRecord(t *testing.T) {
aTTL := 3600
responseBody := []byte(`{"record":{"zone_id":"wwwlsksjjenm","id":"12345678","name":"zone1.online","ttl":3600,"type":"A","value":"192.168.1.1"}}`)
config := RequestConfig{responseHTTPStatus: http.StatusOK, responseBodyJSON: responseBody}
client := createTestClient(config)

record, err := client.GetRecord("12345678")

assert.NoError(t, err)
assert.Equal(t, Record{ZoneID: "wwwlsksjjenm", ID: "12345678", Name: "zone1.online", TTL: 3600, Type: "A", Value: "192.168.1.1"}, *record)
assert.Equal(t, Record{ZoneID: "wwwlsksjjenm", ID: "12345678", Name: "zone1.online", TTL: &aTTL, Type: "A", Value: "192.168.1.1"}, *record)
}

func TestClientGetRecordWithUndefinedTTL(t *testing.T) {
responseBody := []byte(`{"record":{"zone_id":"wwwlsksjjenm","id":"12345678","name":"zone1.online","type":"A","value":"192.168.1.1"}}`)
config := RequestConfig{responseHTTPStatus: http.StatusOK, responseBodyJSON: responseBody}
client := createTestClient(config)

record, err := client.GetRecord("12345678")

assert.NoError(t, err)
assert.Equal(t, Record{ZoneID: "wwwlsksjjenm", ID: "12345678", Name: "zone1.online", TTL: nil, Type: "A", Value: "192.168.1.1"}, *record)
}

func TestClientGetRecordReturnNilIfNotFound(t *testing.T) {
Expand All @@ -143,11 +155,12 @@ func TestClientCreateRecordSuccess(t *testing.T) {
config := RequestConfig{responseHTTPStatus: http.StatusOK, requestBodyReader: &requestBodyReader, responseBodyJSON: responseBody}
client := createTestClient(config)

opts := CreateRecordOpts{ZoneID: "wwwlsksjjenm", Name: "zone1.online", TTL: 3600, Type: "A", Value: "192.168.1.1"}
aTTL := 3600
opts := CreateRecordOpts{ZoneID: "wwwlsksjjenm", Name: "zone1.online", TTL: &aTTL, Type: "A", Value: "192.168.1.1"}
record, err := client.CreateRecord(opts)

assert.NoError(t, err)
assert.Equal(t, Record{ZoneID: "wwwlsksjjenm", ID: "12345678", Name: "zone1.online", TTL: 3600, Type: "A", Value: "192.168.1.1"}, *record)
assert.Equal(t, Record{ZoneID: "wwwlsksjjenm", ID: "12345678", Name: "zone1.online", TTL: &aTTL, Type: "A", Value: "192.168.1.1"}, *record)
assert.NotNil(t, requestBodyReader, "The request body should not be nil")
jsonRequestBody, _ := ioutil.ReadAll(requestBodyReader)
assert.Equal(t, `{"zone_id":"wwwlsksjjenm","type":"A","name":"zone1.online","value":"192.168.1.1","ttl":3600}`, string(jsonRequestBody))
Expand All @@ -163,7 +176,8 @@ func TestClientRecordZone(t *testing.T) {
}

func TestClientUpdateRecordSuccess(t *testing.T) {
recordWithUpdates := Record{ZoneID: "wwwlsksjjenm", ID: "12345678", Name: "zone2.online", TTL: 3600, Type: "A", Value: "192.168.1.1"}
aTTL := 3600
recordWithUpdates := Record{ZoneID: "wwwlsksjjenm", ID: "12345678", Name: "zone2.online", TTL: &aTTL, Type: "A", Value: "192.168.1.1"}
recordWithUpdatesJSON := `{"zone_id":"wwwlsksjjenm","id":"12345678","type":"A","name":"zone2.online","value":"192.168.1.1","ttl":3600}`
var requestBodyReader io.Reader
responseBody := []byte(`{"record":{"zone_id":"wwwlsksjjenm","id":"12345678","type":"A","name":"zone2.online","value":"192.168.1.1","ttl":3600}}`)
Expand Down
9 changes: 7 additions & 2 deletions hetznerdns/api/record.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,12 @@ type Record struct {
Type string `json:"type"`
Name string `json:"name"`
Value string `json:"value"`
TTL int `json:"ttl"`
TTL *int `json:"ttl,omitempty"`
}

// HasTTL returns true if a Record has a TTL set and false if TTL is undefined
func (r *Record) HasTTL() bool {
return r.TTL != nil
}

// CreateRecordRequest represents all data required to create a new record
Expand All @@ -16,7 +21,7 @@ type CreateRecordRequest struct {
Type string `json:"type"`
Name string `json:"name"`
Value string `json:"value"`
TTL int `json:"ttl"`
TTL *int `json:"ttl,omitempty"`
}

// RecordsResponse represents a response from tha API containing a list of records
Expand Down
25 changes: 16 additions & 9 deletions hetznerdns/resource_record.go
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ func resourceRecord() *schema.Resource {
},
"ttl": {
Type: schema.TypeInt,
Required: true,
Optional: true,
},
},
}
Expand All @@ -64,11 +64,6 @@ func resourceRecordCreate(d *schema.ResourceData, m interface{}) error {
return fmt.Errorf("Type of record not set")
}

tTL, tTLNonEmpty := d.GetOk("ttl")
if !tTLNonEmpty {
return fmt.Errorf("TTL of record not set")
}

value, valueNonEmpty := d.GetOk("value")
if !valueNonEmpty {
return fmt.Errorf("Value of record not set")
Expand All @@ -79,7 +74,12 @@ func resourceRecordCreate(d *schema.ResourceData, m interface{}) error {
Name: name.(string),
Type: recordType.(string),
Value: value.(string),
TTL: tTL.(int),
}

tTL, tTLNonEmpty := d.GetOk("ttl")
if tTLNonEmpty {
nonEmptyTTL := tTL.(int)
opts.TTL = &nonEmptyTTL
}

record, err := client.CreateRecord(opts)
Expand Down Expand Up @@ -112,7 +112,11 @@ func resourceRecordRead(d *schema.ResourceData, m interface{}) error {
d.Set("name", record.Name)
d.Set("zone_id", record.ZoneID)
d.Set("type", record.Type)
d.Set("ttl", record.TTL)

d.Set("ttl", nil)
if record.HasTTL() {
d.Set("ttl", record.TTL)
}
d.Set("value", record.Value)

return nil
Expand All @@ -136,7 +140,10 @@ func resourceRecordUpdate(d *schema.ResourceData, m interface{}) error {

if d.HasChanges("name", "ttl", "type", "value") {
record.Name = d.Get("name").(string)
record.TTL = d.Get("ttl").(int)
ttl, ttlNonEmpty := d.GetOk("ttl")
if ttlNonEmpty {
record.TTL = ttl.(*int)
}
record.Type = d.Get("type").(string)
record.Value = d.Get("value").(string)

Expand Down
57 changes: 53 additions & 4 deletions hetznerdns/resource_record_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,18 +12,19 @@ import (
func TestAccRecordResources(t *testing.T) {
// aZoneName must be a valid DNS domain name with an existing TLD
aZoneName := fmt.Sprintf("%s.online", acctest.RandString(10))
aZoneTTL := 60

aValue := "192.168.1.1"
aName := acctest.RandString(10)
aType := "A"
aTTL := 60
aTTL := aZoneTTL * 2

resource.Test(t, resource.TestCase{
PreCheck: func() { testAccAPITokenPresent(t) },
Providers: testAccProviders,
Steps: []resource.TestStep{
{
Config: testAccRecordResourceConfigCreate(aZoneName, aName, aType, aValue, aTTL),
Config: testAccRecordResourceConfigCreate(aZoneName, aZoneTTL, aName, aType, aValue, aTTL),
PreventDiskCleanup: true,
Check: resource.ComposeTestCheckFunc(
resource.TestCheckResourceAttrSet(
Expand All @@ -42,7 +43,7 @@ func TestAccRecordResources(t *testing.T) {
})
}

func testAccRecordResourceConfigCreate(aZoneName string, aName string, aType string, aValue string, aTTL int) string {
func testAccRecordResourceConfigCreate(aZoneName string, aZoneTTL int, aName string, aType string, aValue string, aTTL int) string {
return fmt.Sprintf(`
resource "hetznerdns_zone" "zone1" {
name = "%s"
Expand All @@ -56,7 +57,55 @@ resource "hetznerdns_record" "record1" {
value = "%s"
ttl = %d
}
`, aZoneName, aTTL, aType, aName, aValue, aTTL)
`, aZoneName, aZoneTTL, aType, aName, aValue, aTTL)
}

func TestAccRecordWithDefaultTTLResources(t *testing.T) {
// aZoneName must be a valid DNS domain name with an existing TLD
aZoneName := fmt.Sprintf("%s.online", acctest.RandString(10))
aZoneTTL := 3600

aValue := "192.168.1.1"
aName := acctest.RandString(10)
aType := "A"

resource.Test(t, resource.TestCase{
PreCheck: func() { testAccAPITokenPresent(t) },
Providers: testAccProviders,
Steps: []resource.TestStep{
{
Config: testAccRecordResourceConfigCreateWithDefaultTTL(aZoneName, aZoneTTL, aName, aType, aValue),
PreventDiskCleanup: true,
Check: resource.ComposeTestCheckFunc(
resource.TestCheckResourceAttrSet(
"hetznerdns_record.record1", "id"),
resource.TestCheckResourceAttr(
"hetznerdns_record.record1", "type", aType),
resource.TestCheckResourceAttr(
"hetznerdns_record.record1", "name", aName),
resource.TestCheckResourceAttr(
"hetznerdns_record.record1", "value", aValue),
resource.TestCheckResourceAttr("hetznerdns_record.record1", "ttl.#", "0"),
),
},
},
})
}

func testAccRecordResourceConfigCreateWithDefaultTTL(aZoneName string, aZoneTTL int, aName string, aType string, aValue string) string {
return fmt.Sprintf(`
resource "hetznerdns_zone" "zone1" {
name = "%s"
ttl = %d
}
resource "hetznerdns_record" "record1" {
zone_id = "${hetznerdns_zone.zone1.id}"
type = "%s"
name = "%s"
value = "%s"
}
`, aZoneName, aZoneTTL, aType, aName, aValue)
}

func TestAccTwoRecordResources(t *testing.T) {
Expand Down

0 comments on commit 5642e7b

Please sign in to comment.