chef_data_bag_item resource.
This commit is contained in:
parent
d583b936b2
commit
406aba4a62
|
@ -1,6 +1,7 @@
|
|||
package chef
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"time"
|
||||
|
@ -44,7 +45,7 @@ func Provider() terraform.ResourceProvider {
|
|||
//"chef_client": resourceChefClient(),
|
||||
//"chef_cookbook": resourceChefCookbook(),
|
||||
"chef_data_bag": resourceChefDataBag(),
|
||||
//"chef_data_bag_item": resourceChefDataBagItem(),
|
||||
"chef_data_bag_item": resourceChefDataBagItem(),
|
||||
//"chef_environment": resourceChefEnvironment(),
|
||||
//"chef_node": resourceChefNode(),
|
||||
//"chef_role": resourceChefRole(),
|
||||
|
@ -77,3 +78,20 @@ func providerPrivateKeyEnvDefault() (interface{}, error) {
|
|||
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
func jsonStateFunc(value interface{}) string {
|
||||
// Parse and re-stringify the JSON to make sure it's always kept
|
||||
// in a normalized form.
|
||||
in, ok := value.(string)
|
||||
if !ok {
|
||||
return "null"
|
||||
}
|
||||
var tmp map[string]interface{}
|
||||
|
||||
// Assuming the value must be valid JSON since it passed okay through
|
||||
// our prepareDataBagItemContent function earlier.
|
||||
json.Unmarshal([]byte(in), &tmp)
|
||||
|
||||
jsonValue, _ := json.Marshal(&tmp)
|
||||
return string(jsonValue)
|
||||
}
|
||||
|
|
|
@ -0,0 +1,120 @@
|
|||
package chef
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
|
||||
"github.com/hashicorp/terraform/helper/schema"
|
||||
|
||||
chefc "github.com/go-chef/chef"
|
||||
)
|
||||
|
||||
func resourceChefDataBagItem() *schema.Resource {
|
||||
return &schema.Resource{
|
||||
Create: CreateDataBagItem,
|
||||
Read: ReadDataBagItem,
|
||||
Delete: DeleteDataBagItem,
|
||||
|
||||
Schema: map[string]*schema.Schema{
|
||||
"data_bag_name": &schema.Schema{
|
||||
Type: schema.TypeString,
|
||||
Required: true,
|
||||
ForceNew: true,
|
||||
},
|
||||
"content_json": &schema.Schema{
|
||||
Type: schema.TypeString,
|
||||
Required: true,
|
||||
ForceNew: true,
|
||||
StateFunc: jsonStateFunc,
|
||||
},
|
||||
"id": &schema.Schema{
|
||||
Type: schema.TypeString,
|
||||
Computed: true,
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func CreateDataBagItem(d *schema.ResourceData, meta interface{}) error {
|
||||
client := meta.(*chefc.Client)
|
||||
|
||||
dataBagName := d.Get("data_bag_name").(string)
|
||||
itemId, itemContent, err := prepareDataBagItemContent(d.Get("content_json").(string))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
err = client.DataBags.CreateItem(dataBagName, itemContent)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
d.SetId(itemId)
|
||||
d.Set("id", itemId)
|
||||
return nil
|
||||
}
|
||||
|
||||
func ReadDataBagItem(d *schema.ResourceData, meta interface{}) error {
|
||||
client := meta.(*chefc.Client)
|
||||
|
||||
// The Chef API provides no API to read a data bag's metadata,
|
||||
// but we can try to read its items and use that as a proxy for
|
||||
// whether it still exists.
|
||||
|
||||
itemId := d.Id()
|
||||
dataBagName := d.Get("data_bag_name").(string)
|
||||
|
||||
value, err := client.DataBags.GetItem(dataBagName, itemId)
|
||||
if err != nil {
|
||||
if errRes, ok := err.(*chefc.ErrorResponse); ok {
|
||||
if errRes.Response.StatusCode == 404 {
|
||||
d.SetId("")
|
||||
return nil
|
||||
}
|
||||
} else {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
jsonContent, err := json.Marshal(value)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
d.Set("content_json", string(jsonContent))
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func DeleteDataBagItem(d *schema.ResourceData, meta interface{}) error {
|
||||
client := meta.(*chefc.Client)
|
||||
|
||||
itemId := d.Id()
|
||||
dataBagName := d.Get("data_bag_name").(string)
|
||||
|
||||
err := client.DataBags.DeleteItem(dataBagName, itemId)
|
||||
if err == nil {
|
||||
d.SetId("")
|
||||
d.Set("id", "")
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
func prepareDataBagItemContent(contentJson string) (string, interface{}, error) {
|
||||
var value map[string]interface{}
|
||||
err := json.Unmarshal([]byte(contentJson), &value)
|
||||
if err != nil {
|
||||
return "", nil, err
|
||||
}
|
||||
|
||||
var itemId string
|
||||
if itemIdI, ok := value["id"]; ok {
|
||||
itemId, _ = itemIdI.(string)
|
||||
}
|
||||
|
||||
if itemId == "" {
|
||||
return "", nil, fmt.Errorf("content_json must have id attribute, set to a string")
|
||||
}
|
||||
|
||||
return itemId, value, nil
|
||||
}
|
|
@ -0,0 +1,95 @@
|
|||
package chef
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"reflect"
|
||||
"testing"
|
||||
|
||||
chefc "github.com/go-chef/chef"
|
||||
|
||||
"github.com/hashicorp/terraform/helper/resource"
|
||||
"github.com/hashicorp/terraform/terraform"
|
||||
)
|
||||
|
||||
func TestAccDataBagItem_basic(t *testing.T) {
|
||||
var dataBagItemName string
|
||||
resource.Test(t, resource.TestCase{
|
||||
PreCheck: func() { testAccPreCheck(t) },
|
||||
Providers: testAccProviders,
|
||||
CheckDestroy: testAccDataBagItemCheckDestroy(dataBagItemName),
|
||||
Steps: []resource.TestStep{
|
||||
resource.TestStep{
|
||||
Config: testAccDataBagItemConfig_basic,
|
||||
Check: testAccDataBagItemCheck(
|
||||
"chef_data_bag_item.test", &dataBagItemName,
|
||||
),
|
||||
},
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
func testAccDataBagItemCheck(rn string, name *string) resource.TestCheckFunc {
|
||||
return func(s *terraform.State) error {
|
||||
rs, ok := s.RootModule().Resources[rn]
|
||||
if !ok {
|
||||
return fmt.Errorf("resource not found: %s", rn)
|
||||
}
|
||||
|
||||
if rs.Primary.ID == "" {
|
||||
return fmt.Errorf("data bag item id not set")
|
||||
}
|
||||
|
||||
client := testAccProvider.Meta().(*chefc.Client)
|
||||
content, err := client.DataBags.GetItem("terraform-acc-test-bag-item-basic", rs.Primary.ID)
|
||||
if err != nil {
|
||||
return fmt.Errorf("error getting data bag item: %s", err)
|
||||
}
|
||||
|
||||
expectedContent := map[string]interface{}{
|
||||
"id": "terraform_acc_test",
|
||||
"something_else": true,
|
||||
}
|
||||
if !reflect.DeepEqual(content, expectedContent) {
|
||||
return fmt.Errorf("wrong content: expected %#v, got %#v", expectedContent, content)
|
||||
}
|
||||
|
||||
if expected := "terraform_acc_test"; rs.Primary.Attributes["id"] != expected {
|
||||
return fmt.Errorf("wrong id; expected %#v, got %#v", expected, rs.Primary.Attributes["id"])
|
||||
}
|
||||
|
||||
*name = rs.Primary.ID
|
||||
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
func testAccDataBagItemCheckDestroy(name string) resource.TestCheckFunc {
|
||||
return func(s *terraform.State) error {
|
||||
client := testAccProvider.Meta().(*chefc.Client)
|
||||
_, err := client.DataBags.GetItem("terraform-acc-test-bag-item-basic", name)
|
||||
if err == nil {
|
||||
return fmt.Errorf("data bag item still exists")
|
||||
}
|
||||
if _, ok := err.(*chefc.ErrorResponse); err != nil && !ok {
|
||||
return fmt.Errorf("got something other than an HTTP error (%v) when getting data bag item", err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
const testAccDataBagItemConfig_basic = `
|
||||
resource "chef_data_bag" "test" {
|
||||
name = "terraform-acc-test-bag-item-basic"
|
||||
}
|
||||
resource "chef_data_bag_item" "test" {
|
||||
data_bag_name = "terraform-acc-test-bag-item-basic"
|
||||
depends_on = ["chef_data_bag.test"]
|
||||
content_json = <<EOT
|
||||
{
|
||||
"id": "terraform_acc_test",
|
||||
"something_else": true
|
||||
}
|
||||
EOT
|
||||
}
|
||||
`
|
Loading…
Reference in New Issue