github.com/serbaut/terraform@v0.6.12-0.20160607213102-ac2d195cc560/helper/resource/map.go (about)

     1  package resource
     2  
     3  import (
     4  	"fmt"
     5  	"sort"
     6  
     7  	"github.com/hashicorp/terraform/terraform"
     8  )
     9  
    10  // Map is a map of resources that are supported, and provides helpers for
    11  // more easily implementing a ResourceProvider.
    12  type Map struct {
    13  	Mapping map[string]Resource
    14  }
    15  
    16  func (m *Map) Validate(
    17  	t string, c *terraform.ResourceConfig) ([]string, []error) {
    18  	r, ok := m.Mapping[t]
    19  	if !ok {
    20  		return nil, []error{fmt.Errorf("Unknown resource type: %s", t)}
    21  	}
    22  
    23  	// If there is no validator set, then it is valid
    24  	if r.ConfigValidator == nil {
    25  		return nil, nil
    26  	}
    27  
    28  	return r.ConfigValidator.Validate(c)
    29  }
    30  
    31  // Apply performs a create or update depending on the diff, and calls
    32  // the proper function on the matching Resource.
    33  func (m *Map) Apply(
    34  	info *terraform.InstanceInfo,
    35  	s *terraform.InstanceState,
    36  	d *terraform.InstanceDiff,
    37  	meta interface{}) (*terraform.InstanceState, error) {
    38  	r, ok := m.Mapping[info.Type]
    39  	if !ok {
    40  		return nil, fmt.Errorf("Unknown resource type: %s", info.Type)
    41  	}
    42  
    43  	if d.Destroy || d.RequiresNew() {
    44  		if s.ID != "" {
    45  			// Destroy the resource if it is created
    46  			err := r.Destroy(s, meta)
    47  			if err != nil {
    48  				return s, err
    49  			}
    50  
    51  			s.ID = ""
    52  		}
    53  
    54  		// If we're only destroying, and not creating, then return now.
    55  		// Otherwise, we continue so that we can create a new resource.
    56  		if !d.RequiresNew() {
    57  			return nil, nil
    58  		}
    59  	}
    60  
    61  	var result *terraform.InstanceState
    62  	var err error
    63  	if s.ID == "" {
    64  		result, err = r.Create(s, d, meta)
    65  	} else {
    66  		if r.Update == nil {
    67  			return s, fmt.Errorf(
    68  				"Resource type '%s' doesn't support update",
    69  				info.Type)
    70  		}
    71  
    72  		result, err = r.Update(s, d, meta)
    73  	}
    74  	if result != nil {
    75  		if result.Attributes == nil {
    76  			result.Attributes = make(map[string]string)
    77  		}
    78  
    79  		result.Attributes["id"] = result.ID
    80  	}
    81  
    82  	return result, err
    83  }
    84  
    85  // Diff performs a diff on the proper resource type.
    86  func (m *Map) Diff(
    87  	info *terraform.InstanceInfo,
    88  	s *terraform.InstanceState,
    89  	c *terraform.ResourceConfig,
    90  	meta interface{}) (*terraform.InstanceDiff, error) {
    91  	r, ok := m.Mapping[info.Type]
    92  	if !ok {
    93  		return nil, fmt.Errorf("Unknown resource type: %s", info.Type)
    94  	}
    95  
    96  	return r.Diff(s, c, meta)
    97  }
    98  
    99  // Refresh performs a Refresh on the proper resource type.
   100  //
   101  // Refresh on the Resource won't be called if the state represents a
   102  // non-created resource (ID is blank).
   103  //
   104  // An error is returned if the resource isn't registered.
   105  func (m *Map) Refresh(
   106  	info *terraform.InstanceInfo,
   107  	s *terraform.InstanceState,
   108  	meta interface{}) (*terraform.InstanceState, error) {
   109  	// If the resource isn't created, don't refresh.
   110  	if s.ID == "" {
   111  		return s, nil
   112  	}
   113  
   114  	r, ok := m.Mapping[info.Type]
   115  	if !ok {
   116  		return nil, fmt.Errorf("Unknown resource type: %s", info.Type)
   117  	}
   118  
   119  	return r.Refresh(s, meta)
   120  }
   121  
   122  // Resources returns all the resources that are supported by this
   123  // resource map and can be used to satisfy the Resources method of
   124  // a ResourceProvider.
   125  func (m *Map) Resources() []terraform.ResourceType {
   126  	ks := make([]string, 0, len(m.Mapping))
   127  	for k, _ := range m.Mapping {
   128  		ks = append(ks, k)
   129  	}
   130  	sort.Strings(ks)
   131  
   132  	rs := make([]terraform.ResourceType, 0, len(m.Mapping))
   133  	for _, k := range ks {
   134  		rs = append(rs, terraform.ResourceType{
   135  			Name: k,
   136  		})
   137  	}
   138  
   139  	return rs
   140  }