diff --git a/builtin/providers/scaleway/data_source_scaleway_bootscript.go b/builtin/providers/scaleway/data_source_scaleway_bootscript.go new file mode 100644 index 000000000..3c2a6a275 --- /dev/null +++ b/builtin/providers/scaleway/data_source_scaleway_bootscript.go @@ -0,0 +1,119 @@ +package scaleway + +import ( + "fmt" + "regexp" + + "github.com/hashicorp/terraform/helper/schema" + "github.com/scaleway/scaleway-cli/pkg/api" +) + +func dataSourceScalewayBootscript() *schema.Resource { + return &schema.Resource{ + Read: dataSourceScalewayBootscriptRead, + + Schema: map[string]*schema.Schema{ + "name": &schema.Schema{ + Type: schema.TypeString, + Optional: true, + ForceNew: true, + }, + "name_filter": &schema.Schema{ + Type: schema.TypeString, + Optional: true, + ForceNew: true, + }, + "architecture": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + Optional: true, + }, + // Computed values. + "organization": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + }, + "public": &schema.Schema{ + Type: schema.TypeBool, + Computed: true, + }, + "boot_cmd_args": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + }, + "dtb": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + }, + "initrd": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + }, + "kernel": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + }, + }, + } +} + +func bootscriptDescriptionAttributes(d *schema.ResourceData, script api.ScalewayBootscript) error { + d.Set("architecture", script.Arch) + d.Set("organization", script.Organization) + d.Set("public", script.Public) + d.Set("boot_cmd_args", script.Bootcmdargs) + d.Set("dtb", script.Dtb) + d.Set("initrd", script.Initrd) + d.Set("kernel", script.Kernel) + d.SetId(script.Identifier) + + return nil +} + +func dataSourceScalewayBootscriptRead(d *schema.ResourceData, meta interface{}) error { + scaleway := meta.(*Client).scaleway + + scripts, err := scaleway.GetBootscripts() + if err != nil { + return err + } + + var isMatch func(api.ScalewayBootscript) bool + + if name, ok := d.GetOk("name"); ok { + isMatch = func(s api.ScalewayBootscript) bool { + return s.Title == name.(string) + } + } else if nameFilter, ok := d.GetOk("name_filter"); ok { + architecture := d.Get("architecture") + exp, err := regexp.Compile(nameFilter.(string)) + if err != nil { + return err + } + + isMatch = func(s api.ScalewayBootscript) bool { + nameMatch := exp.MatchString(s.Title) + architectureMatch := true + if architecture != "" { + architectureMatch = architecture == s.Arch + } + return nameMatch && architectureMatch + } + } + + var matches []api.ScalewayBootscript + for _, script := range *scripts { + if isMatch(script) { + matches = append(matches, script) + } + } + + if len(matches) > 1 { + return fmt.Errorf("The query returned more than one result. Please refine your query.") + } + if len(matches) == 0 { + return fmt.Errorf("The query returned no result. Please refine your query.") + } + + return bootscriptDescriptionAttributes(d, matches[0]) +} diff --git a/builtin/providers/scaleway/data_source_scaleway_bootscript_test.go b/builtin/providers/scaleway/data_source_scaleway_bootscript_test.go new file mode 100644 index 000000000..f873d8eec --- /dev/null +++ b/builtin/providers/scaleway/data_source_scaleway_bootscript_test.go @@ -0,0 +1,72 @@ +package scaleway + +import ( + "fmt" + "regexp" + "testing" + + "github.com/hashicorp/terraform/helper/resource" + "github.com/hashicorp/terraform/terraform" +) + +func TestAccScalewayDataSourceBootscript_Basic(t *testing.T) { + resource.Test(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + Steps: []resource.TestStep{ + resource.TestStep{ + Config: testAccCheckScalewayBootscriptConfig, + Check: resource.ComposeTestCheckFunc( + testAccCheckBootscriptID("data.scaleway_bootscript.debug"), + resource.TestCheckResourceAttr("data.scaleway_bootscript.debug", "architecture", "x86_64"), + resource.TestCheckResourceAttr("data.scaleway_bootscript.debug", "public", "true"), + resource.TestMatchResourceAttr("data.scaleway_bootscript.debug", "kernel", regexp.MustCompile("4.5.7")), + ), + }, + }, + }) +} + +func TestAccScalewayDataSourceBootscript_Filtered(t *testing.T) { + resource.Test(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + Steps: []resource.TestStep{ + resource.TestStep{ + Config: testAccCheckScalewayBootscriptFilterConfig, + Check: resource.ComposeTestCheckFunc( + testAccCheckBootscriptID("data.scaleway_bootscript.debug"), + resource.TestCheckResourceAttr("data.scaleway_bootscript.debug", "architecture", "arm"), + resource.TestCheckResourceAttr("data.scaleway_bootscript.debug", "public", "true"), + ), + }, + }, + }) +} + +func testAccCheckBootscriptID(n string) resource.TestCheckFunc { + return func(s *terraform.State) error { + rs, ok := s.RootModule().Resources[n] + if !ok { + return fmt.Errorf("Can't find bootscript data source: %s", n) + } + + if rs.Primary.ID == "" { + return fmt.Errorf("bootscript data source ID not set") + } + return nil + } +} + +const testAccCheckScalewayBootscriptConfig = ` +data "scaleway_bootscript" "debug" { + name = "x86_64 4.5.7 debug #3" +} +` + +const testAccCheckScalewayBootscriptFilterConfig = ` +data "scaleway_bootscript" "debug" { + architecture = "arm" + name_filter = "Rescue" +} +` diff --git a/builtin/providers/scaleway/data_source_scaleway_image.go b/builtin/providers/scaleway/data_source_scaleway_image.go new file mode 100644 index 000000000..5d9cb7fce --- /dev/null +++ b/builtin/providers/scaleway/data_source_scaleway_image.go @@ -0,0 +1,133 @@ +package scaleway + +import ( + "fmt" + "log" + "regexp" + + "github.com/hashicorp/terraform/helper/schema" + "github.com/scaleway/scaleway-cli/pkg/api" +) + +func dataSourceScalewayImage() *schema.Resource { + return &schema.Resource{ + Read: dataSourceScalewayImageRead, + + Schema: map[string]*schema.Schema{ + "name": &schema.Schema{ + Type: schema.TypeString, + Optional: true, + ForceNew: true, + Computed: true, + }, + "name_filter": &schema.Schema{ + Type: schema.TypeString, + Optional: true, + ForceNew: true, + }, + "architecture": &schema.Schema{ + Type: schema.TypeString, + Required: true, + ForceNew: true, + }, + // Computed values. + "organization": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + }, + "public": &schema.Schema{ + Type: schema.TypeBool, + Computed: true, + }, + "creation_date": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + }, + }, + } +} + +func scalewayImageAttributes(d *schema.ResourceData, img imageMatch) error { + d.Set("architecture", img.imageDefinition.Arch) + d.Set("organization", img.marketImage.Organization) + d.Set("public", img.marketImage.Public) + d.Set("creation_date", img.marketImage.CreationDate) + d.Set("name", img.marketImage.Name) + d.SetId(img.imageDefinition.ID) + + return nil +} + +type imageMatch struct { + marketImage api.MarketImage + imageDefinition api.MarketLocalImageDefinition +} + +func dataSourceScalewayImageRead(d *schema.ResourceData, meta interface{}) error { + scaleway := meta.(*Client).scaleway + + images, err := scaleway.GetImages() + log.Printf("[DEBUG] %#v", images) + if err != nil { + return err + } + + var isNameMatch = func(api.MarketImage) bool { return true } + var isArchMatch = func(api.MarketLocalImageDefinition) bool { return true } + + if name, ok := d.GetOk("name"); ok { + isNameMatch = func(img api.MarketImage) bool { + return img.Name == name.(string) + } + } else if nameFilter, ok := d.GetOk("name_filter"); ok { + exp, err := regexp.Compile(nameFilter.(string)) + if err != nil { + return err + } + + isNameMatch = func(img api.MarketImage) bool { + return exp.MatchString(img.Name) + } + } + + var architecture = d.Get("architecture").(string) + if architecture != "" { + isArchMatch = func(img api.MarketLocalImageDefinition) bool { + return img.Arch == architecture + } + } + + var matches []imageMatch + for _, img := range *images { + if !isNameMatch(img) { + continue + } + + var imageDefinition *api.MarketLocalImageDefinition + for _, version := range img.Versions { + for _, def := range version.LocalImages { + if isArchMatch(def) { + imageDefinition = &def + break + } + } + } + + if imageDefinition == nil { + continue + } + matches = append(matches, imageMatch{ + marketImage: img, + imageDefinition: *imageDefinition, + }) + } + + if len(matches) > 1 { + return fmt.Errorf("The query returned more than one result. Please refine your query.") + } + if len(matches) == 0 { + return fmt.Errorf("The query returned no result. Please refine your query.") + } + + return scalewayImageAttributes(d, matches[0]) +} diff --git a/builtin/providers/scaleway/data_source_scaleway_image_test.go b/builtin/providers/scaleway/data_source_scaleway_image_test.go new file mode 100644 index 000000000..3c11b9e22 --- /dev/null +++ b/builtin/providers/scaleway/data_source_scaleway_image_test.go @@ -0,0 +1,72 @@ +package scaleway + +import ( + "fmt" + "testing" + + "github.com/hashicorp/terraform/helper/resource" + "github.com/hashicorp/terraform/terraform" +) + +func TestAccScalewayDataSourceImage_Basic(t *testing.T) { + resource.Test(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + Steps: []resource.TestStep{ + resource.TestStep{ + Config: testAccCheckScalewayImageConfig, + Check: resource.ComposeTestCheckFunc( + testAccCheckImageID("data.scaleway_image.ubuntu"), + resource.TestCheckResourceAttr("data.scaleway_image.ubuntu", "architecture", "arm"), + resource.TestCheckResourceAttr("data.scaleway_image.ubuntu", "public", "true"), + ), + }, + }, + }) +} + +func TestAccScalewayDataSourceImage_Filtered(t *testing.T) { + resource.Test(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + Steps: []resource.TestStep{ + resource.TestStep{ + Config: testAccCheckScalewayImageFilterConfig, + Check: resource.ComposeTestCheckFunc( + testAccCheckImageID("data.scaleway_image.ubuntu"), + resource.TestCheckResourceAttr("data.scaleway_image.ubuntu", "name", "Ubuntu Precise"), + resource.TestCheckResourceAttr("data.scaleway_image.ubuntu", "architecture", "arm"), + resource.TestCheckResourceAttr("data.scaleway_image.ubuntu", "public", "true"), + ), + }, + }, + }) +} + +func testAccCheckImageID(n string) resource.TestCheckFunc { + return func(s *terraform.State) error { + rs, ok := s.RootModule().Resources[n] + if !ok { + return fmt.Errorf("Can't find image data source: %s", n) + } + + if rs.Primary.ID == "" { + return fmt.Errorf("image data source ID not set") + } + return nil + } +} + +const testAccCheckScalewayImageConfig = ` +data "scaleway_image" "ubuntu" { + name = "Ubuntu Precise" + architecture = "arm" +} +` + +const testAccCheckScalewayImageFilterConfig = ` +data "scaleway_image" "ubuntu" { + name_filter = "Precise" + architecture = "arm" +} +` diff --git a/builtin/providers/scaleway/provider.go b/builtin/providers/scaleway/provider.go index 2beea9606..259d83182 100644 --- a/builtin/providers/scaleway/provider.go +++ b/builtin/providers/scaleway/provider.go @@ -38,6 +38,11 @@ func Provider() terraform.ResourceProvider { "scaleway_volume_attachment": resourceScalewayVolumeAttachment(), }, + DataSourcesMap: map[string]*schema.Resource{ + "scaleway_bootscript": dataSourceScalewayBootscript(), + "scaleway_image": dataSourceScalewayImage(), + }, + ConfigureFunc: providerConfigure, } } diff --git a/website/source/docs/providers/scaleway/d/bootscript.html.markdown b/website/source/docs/providers/scaleway/d/bootscript.html.markdown new file mode 100644 index 000000000..d1d50f1f2 --- /dev/null +++ b/website/source/docs/providers/scaleway/d/bootscript.html.markdown @@ -0,0 +1,49 @@ +--- +layout: "scaleway" +page_title: "Scaleway: scaleway_bootscript" +sidebar_current: "docs-scaleway-datasource-bootscript" +description: |- + Get information on a Scaleway bootscript. +--- + +# scaleway\_bootscript + +Use this data source to get the ID of a registered Bootscript for use with the +`scaleway_server` resource. + +## Example Usage + +``` +data "scaleway_bootscript" "debug" { + architecture = "arm" + name_filter = "Rescue" +} +``` + +## Argument Reference + +* `architecture` - (Optional) any supported Scaleway architecture, e.g. `x86_64`, `arm` + +* `name_filter` - (Optional) Regexp to match Bootscript name by + +* `name` - (Optional) Exact name of desired Bootscript + +## Attributes Reference + +`id` is set to the ID of the found Bootscript. In addition, the following attributes +are exported: + +* `architecture` - architecture of the Bootscript, e.g. `arm` or `x86_64` + +* `organization` - uuid of the organization owning this Bootscript + +* `public` - is this a public bootscript + +* `boot_cmd_args` - command line arguments used for booting + +* `dtb` - path to Device Tree Blob detailing hardware information + +* `initrd` - URL to initial ramdisk content + +* `kernel` - URL to used kernel + diff --git a/website/source/docs/providers/scaleway/d/image.html.markdown b/website/source/docs/providers/scaleway/d/image.html.markdown new file mode 100644 index 000000000..101da8f9b --- /dev/null +++ b/website/source/docs/providers/scaleway/d/image.html.markdown @@ -0,0 +1,49 @@ +--- +layout: "scaleway" +page_title: "Scaleway: scaleway_image" +sidebar_current: "docs-scaleway-datasource-image" +description: |- + Get information on a Scaleway image. +--- + +# scaleway\_image + +Use this data source to get the ID of a registered Image for use with the +`scaleway_server` resource. + +## Example Usage + +``` +data "scaleway_image" "ubuntu" { + architecture = "arm" + name = "Ubuntu Precise" +} + +resource "scaleway_server" "base" { + name = "test" + image = "${data.scaleway_image.ubuntu.id}" + type = "C1" +} +``` + +## Argument Reference + +* `architecture` - (Required) any supported Scaleway architecture, e.g. `x86_64`, `arm` + +* `name_filter` - (Optional) Regexp to match Image name by + +* `name` - (Optional) Exact name of desired Image + +## Attributes Reference + +`id` is set to the ID of the found Image. In addition, the following attributes +are exported: + +* `architecture` - architecture of the Image, e.g. `arm` or `x86_64` + +* `organization` - uuid of the organization owning this Image + +* `public` - is this a public bootscript + +* `creation_date` - date when image was created +