github.com/vtorhonen/terraform@v0.9.0-beta2.0.20170307220345-5d894e4ffda7/builtin/providers/openstack/data_source_openstack_images_image_v2.go (about)

     1  package openstack
     2  
     3  import (
     4  	"fmt"
     5  	"log"
     6  	"sort"
     7  
     8  	"github.com/gophercloud/gophercloud/openstack/imageservice/v2/images"
     9  	"github.com/gophercloud/gophercloud/pagination"
    10  
    11  	"github.com/hashicorp/terraform/helper/schema"
    12  )
    13  
    14  func dataSourceImagesImageV2() *schema.Resource {
    15  	return &schema.Resource{
    16  		Read: dataSourceImagesImageV2Read,
    17  
    18  		Schema: map[string]*schema.Schema{
    19  			"region": &schema.Schema{
    20  				Type:        schema.TypeString,
    21  				Required:    true,
    22  				ForceNew:    true,
    23  				DefaultFunc: schema.EnvDefaultFunc("OS_REGION_NAME", ""),
    24  			},
    25  
    26  			"name": {
    27  				Type:     schema.TypeString,
    28  				Optional: true,
    29  				ForceNew: true,
    30  			},
    31  
    32  			"visibility": {
    33  				Type:     schema.TypeString,
    34  				Optional: true,
    35  				ForceNew: true,
    36  			},
    37  
    38  			"owner": {
    39  				Type:     schema.TypeString,
    40  				Optional: true,
    41  				ForceNew: true,
    42  			},
    43  
    44  			"size_min": {
    45  				Type:     schema.TypeInt,
    46  				Optional: true,
    47  				ForceNew: true,
    48  			},
    49  
    50  			"size_max": {
    51  				Type:     schema.TypeInt,
    52  				Optional: true,
    53  				ForceNew: true,
    54  			},
    55  
    56  			"sort_key": {
    57  				Type:     schema.TypeString,
    58  				Optional: true,
    59  				ForceNew: true,
    60  				Default:  "name",
    61  			},
    62  
    63  			"sort_direction": {
    64  				Type:         schema.TypeString,
    65  				Optional:     true,
    66  				ForceNew:     true,
    67  				Default:      "asc",
    68  				ValidateFunc: dataSourceImagesImageV2SortDirection,
    69  			},
    70  
    71  			"tag": {
    72  				Type:     schema.TypeString,
    73  				Optional: true,
    74  				ForceNew: true,
    75  			},
    76  
    77  			"most_recent": {
    78  				Type:     schema.TypeBool,
    79  				Optional: true,
    80  				Default:  false,
    81  				ForceNew: true,
    82  			},
    83  
    84  			// Computed values
    85  			"container_format": {
    86  				Type:     schema.TypeString,
    87  				Computed: true,
    88  			},
    89  
    90  			"disk_format": {
    91  				Type:     schema.TypeString,
    92  				Computed: true,
    93  			},
    94  
    95  			"min_disk_gb": {
    96  				Type:     schema.TypeInt,
    97  				Computed: true,
    98  			},
    99  
   100  			"min_ram_mb": {
   101  				Type:     schema.TypeInt,
   102  				Computed: true,
   103  			},
   104  
   105  			"protected": {
   106  				Type:     schema.TypeBool,
   107  				Computed: true,
   108  			},
   109  
   110  			"checksum": {
   111  				Type:     schema.TypeString,
   112  				Computed: true,
   113  			},
   114  
   115  			"size_bytes": {
   116  				Type:     schema.TypeInt,
   117  				Computed: true,
   118  			},
   119  
   120  			"metadata": {
   121  				Type:     schema.TypeMap,
   122  				Computed: true,
   123  			},
   124  
   125  			"updated_at": {
   126  				Type:     schema.TypeString,
   127  				Computed: true,
   128  			},
   129  
   130  			"file": {
   131  				Type:     schema.TypeString,
   132  				Computed: true,
   133  			},
   134  
   135  			"schema": {
   136  				Type:     schema.TypeString,
   137  				Computed: true,
   138  			},
   139  		},
   140  	}
   141  }
   142  
   143  // dataSourceImagesImageV2Read performs the image lookup.
   144  func dataSourceImagesImageV2Read(d *schema.ResourceData, meta interface{}) error {
   145  	config := meta.(*Config)
   146  	imageClient, err := config.imageV2Client(GetRegion(d))
   147  	if err != nil {
   148  		return fmt.Errorf("Error creating OpenStack image client: %s", err)
   149  	}
   150  
   151  	visibility := resourceImagesImageV2VisibilityFromString(d.Get("visibility").(string))
   152  
   153  	listOpts := images.ListOpts{
   154  		Name:       d.Get("name").(string),
   155  		Visibility: visibility,
   156  		Owner:      d.Get("owner").(string),
   157  		Status:     images.ImageStatusActive,
   158  		SizeMin:    int64(d.Get("size_min").(int)),
   159  		SizeMax:    int64(d.Get("size_max").(int)),
   160  		SortKey:    d.Get("sort_key").(string),
   161  		SortDir:    d.Get("sort_direction").(string),
   162  		Tag:        d.Get("tag").(string),
   163  	}
   164  
   165  	var allImages []images.Image
   166  	pager := images.List(imageClient, listOpts)
   167  	err = pager.EachPage(func(page pagination.Page) (bool, error) {
   168  		images, err := images.ExtractImages(page)
   169  		if err != nil {
   170  			return false, err
   171  		}
   172  
   173  		for _, i := range images {
   174  			allImages = append(allImages, i)
   175  		}
   176  
   177  		return true, nil
   178  	})
   179  
   180  	if err != nil {
   181  		return fmt.Errorf("Unable to retrieve images: %s", err)
   182  	}
   183  
   184  	var image images.Image
   185  	if len(allImages) < 1 {
   186  		return fmt.Errorf("Your query returned no results. Please change your search criteria and try again.")
   187  	}
   188  
   189  	if len(allImages) > 1 {
   190  		recent := d.Get("most_recent").(bool)
   191  		log.Printf("[DEBUG] openstack_images_image: multiple results found and `most_recent` is set to: %t", recent)
   192  		if recent {
   193  			image = mostRecentImage(allImages)
   194  		} else {
   195  			return fmt.Errorf("Your query returned more than one result. Please try a more " +
   196  				"specific search criteria, or set `most_recent` attribute to true.")
   197  		}
   198  	} else {
   199  		image = allImages[0]
   200  	}
   201  
   202  	log.Printf("[DEBUG] openstack_images_image: Single Image found: %s", image.ID)
   203  	return dataSourceImagesImageV2Attributes(d, &image)
   204  }
   205  
   206  // dataSourceImagesImageV2Attributes populates the fields of an Image resource.
   207  func dataSourceImagesImageV2Attributes(d *schema.ResourceData, image *images.Image) error {
   208  	log.Printf("[DEBUG] openstack_images_image details: %#v", image)
   209  
   210  	d.SetId(image.ID)
   211  	d.Set("name", image.Name)
   212  	d.Set("tags", image.Tags)
   213  	d.Set("container_format", image.ContainerFormat)
   214  	d.Set("disk_format", image.DiskFormat)
   215  	d.Set("min_disk_gb", image.MinDiskGigabytes)
   216  	d.Set("min_ram_mb", image.MinRAMMegabytes)
   217  	d.Set("owner", image.Owner)
   218  	d.Set("protected", image.Protected)
   219  	d.Set("visibility", image.Visibility)
   220  	d.Set("checksum", image.Checksum)
   221  	d.Set("size_bytes", image.SizeBytes)
   222  	d.Set("metadata", image.Metadata)
   223  	d.Set("created_at", image.CreatedAt)
   224  	d.Set("updated_at", image.UpdatedAt)
   225  	d.Set("file", image.File)
   226  	d.Set("schema", image.Schema)
   227  
   228  	return nil
   229  }
   230  
   231  type imageSort []images.Image
   232  
   233  func (a imageSort) Len() int      { return len(a) }
   234  func (a imageSort) Swap(i, j int) { a[i], a[j] = a[j], a[i] }
   235  func (a imageSort) Less(i, j int) bool {
   236  	itime := a[i].UpdatedAt
   237  	jtime := a[j].UpdatedAt
   238  	return itime.Unix() < jtime.Unix()
   239  }
   240  
   241  // Returns the most recent Image out of a slice of images.
   242  func mostRecentImage(images []images.Image) images.Image {
   243  	sortedImages := images
   244  	sort.Sort(imageSort(sortedImages))
   245  	return sortedImages[len(sortedImages)-1]
   246  }
   247  
   248  func dataSourceImagesImageV2SortDirection(v interface{}, k string) (ws []string, errors []error) {
   249  	value := v.(string)
   250  	if value != "asc" && value != "desc" {
   251  		err := fmt.Errorf("%s must be either asc or desc", k)
   252  		errors = append(errors, err)
   253  	}
   254  	return
   255  }