github.com/Hashicorp/terraform@v0.11.12-beta1/builtin/providers/terraform/data_source_state.go (about)

     1  package terraform
     2  
     3  import (
     4  	"fmt"
     5  	"log"
     6  	"time"
     7  
     8  	multierror "github.com/hashicorp/go-multierror"
     9  	"github.com/hashicorp/terraform/backend"
    10  	backendInit "github.com/hashicorp/terraform/backend/init"
    11  	"github.com/hashicorp/terraform/config"
    12  	"github.com/hashicorp/terraform/helper/schema"
    13  	"github.com/hashicorp/terraform/terraform"
    14  )
    15  
    16  func dataSourceRemoteState() *schema.Resource {
    17  	return &schema.Resource{
    18  		Read: dataSourceRemoteStateRead,
    19  
    20  		Schema: map[string]*schema.Schema{
    21  			"backend": {
    22  				Type:     schema.TypeString,
    23  				Required: true,
    24  				ValidateFunc: func(v interface{}, k string) (ws []string, errors []error) {
    25  					if vStr, ok := v.(string); ok && vStr == "_local" {
    26  						ws = append(ws, "Use of the %q backend is now officially "+
    27  							"supported as %q. Please update your configuration to ensure "+
    28  							"compatibility with future versions of Terraform.",
    29  							"_local", "local")
    30  					}
    31  
    32  					return
    33  				},
    34  			},
    35  
    36  			// This field now contains all possible attributes that are supported
    37  			// by any of the existing backends. When merging this into 0.12 this
    38  			// should be reverted and instead the new 'cty.DynamicPseudoType' type
    39  			// should be used to make this work with any future backends as well.
    40  			"config": {
    41  				Type:     schema.TypeSet,
    42  				Optional: true,
    43  				MaxItems: 1,
    44  				Elem: &schema.Resource{
    45  					Schema: map[string]*schema.Schema{
    46  						"path": &schema.Schema{
    47  							Type:     schema.TypeString,
    48  							Optional: true,
    49  						},
    50  						"hostname": &schema.Schema{
    51  							Type:     schema.TypeString,
    52  							Optional: true,
    53  						},
    54  						"organization": &schema.Schema{
    55  							Type:     schema.TypeString,
    56  							Optional: true,
    57  						},
    58  						"token": &schema.Schema{
    59  							Type:     schema.TypeString,
    60  							Optional: true,
    61  						},
    62  						"workspaces": &schema.Schema{
    63  							Type:     schema.TypeList,
    64  							Optional: true,
    65  							MaxItems: 1,
    66  							Elem:     &schema.Schema{Type: schema.TypeMap},
    67  						},
    68  						"username": &schema.Schema{
    69  							Type:     schema.TypeString,
    70  							Optional: true,
    71  						},
    72  						"password": &schema.Schema{
    73  							Type:     schema.TypeString,
    74  							Optional: true,
    75  						},
    76  						"url": &schema.Schema{
    77  							Type:     schema.TypeString,
    78  							Optional: true,
    79  						},
    80  						"repo": &schema.Schema{
    81  							Type:     schema.TypeString,
    82  							Optional: true,
    83  						},
    84  						"subpath": &schema.Schema{
    85  							Type:     schema.TypeString,
    86  							Optional: true,
    87  						},
    88  						"storage_account_name": &schema.Schema{
    89  							Type:     schema.TypeString,
    90  							Optional: true,
    91  						},
    92  						"container_name": &schema.Schema{
    93  							Type:     schema.TypeString,
    94  							Optional: true,
    95  						},
    96  						"key": &schema.Schema{
    97  							Type:     schema.TypeString,
    98  							Optional: true,
    99  						},
   100  						"access_key": &schema.Schema{
   101  							Type:     schema.TypeString,
   102  							Optional: true,
   103  						},
   104  						"environment": &schema.Schema{
   105  							Type:     schema.TypeString,
   106  							Optional: true,
   107  						},
   108  						"resource_group_name": &schema.Schema{
   109  							Type:     schema.TypeString,
   110  							Optional: true,
   111  						},
   112  						"arm_subscription_id": &schema.Schema{
   113  							Type:     schema.TypeString,
   114  							Optional: true,
   115  						},
   116  						"arm_client_id": &schema.Schema{
   117  							Type:     schema.TypeString,
   118  							Optional: true,
   119  						},
   120  						"arm_client_secret": &schema.Schema{
   121  							Type:     schema.TypeString,
   122  							Optional: true,
   123  						},
   124  						"arm_tenant_id": &schema.Schema{
   125  							Type:     schema.TypeString,
   126  							Optional: true,
   127  						},
   128  						"access_token": &schema.Schema{
   129  							Type:     schema.TypeString,
   130  							Optional: true,
   131  						},
   132  						"address": &schema.Schema{
   133  							Type:     schema.TypeString,
   134  							Optional: true,
   135  						},
   136  						"scheme": &schema.Schema{
   137  							Type:     schema.TypeString,
   138  							Optional: true,
   139  						},
   140  						"datacenter": &schema.Schema{
   141  							Type:     schema.TypeString,
   142  							Optional: true,
   143  						},
   144  						"http_auth": &schema.Schema{
   145  							Type:     schema.TypeString,
   146  							Optional: true,
   147  						},
   148  						"gzip": &schema.Schema{
   149  							Type:     schema.TypeString,
   150  							Optional: true,
   151  						},
   152  						"lock": &schema.Schema{
   153  							Type:     schema.TypeString,
   154  							Optional: true,
   155  						},
   156  						"ca_file": &schema.Schema{
   157  							Type:     schema.TypeString,
   158  							Optional: true,
   159  						},
   160  						"cert_file": &schema.Schema{
   161  							Type:     schema.TypeString,
   162  							Optional: true,
   163  						},
   164  						"key_file": &schema.Schema{
   165  							Type:     schema.TypeString,
   166  							Optional: true,
   167  						},
   168  						"endpoints": &schema.Schema{
   169  							Type:     schema.TypeString,
   170  							Optional: true,
   171  						},
   172  						"prefix": &schema.Schema{
   173  							Type:     schema.TypeString,
   174  							Optional: true,
   175  						},
   176  						"cacert_path": &schema.Schema{
   177  							Type:     schema.TypeString,
   178  							Optional: true,
   179  						},
   180  						"cert_path": &schema.Schema{
   181  							Type:     schema.TypeString,
   182  							Optional: true,
   183  						},
   184  						"key_path": &schema.Schema{
   185  							Type:     schema.TypeString,
   186  							Optional: true,
   187  						},
   188  						"bucket": &schema.Schema{
   189  							Type:     schema.TypeString,
   190  							Optional: true,
   191  						},
   192  						"credentials": &schema.Schema{
   193  							Type:     schema.TypeString,
   194  							Optional: true,
   195  						},
   196  						"project": &schema.Schema{
   197  							Type:     schema.TypeString,
   198  							Optional: true,
   199  						},
   200  						"region": &schema.Schema{
   201  							Type:     schema.TypeString,
   202  							Optional: true,
   203  						},
   204  						"encryption_key": &schema.Schema{
   205  							Type:     schema.TypeString,
   206  							Optional: true,
   207  						},
   208  						"update_method": &schema.Schema{
   209  							Type:     schema.TypeString,
   210  							Optional: true,
   211  						},
   212  						"lock_address": &schema.Schema{
   213  							Type:     schema.TypeString,
   214  							Optional: true,
   215  						},
   216  						"lock_method": &schema.Schema{
   217  							Type:     schema.TypeString,
   218  							Optional: true,
   219  						},
   220  						"unlock_address": &schema.Schema{
   221  							Type:     schema.TypeString,
   222  							Optional: true,
   223  						},
   224  						"unlock_method": &schema.Schema{
   225  							Type:     schema.TypeString,
   226  							Optional: true,
   227  						},
   228  						"skip_cert_verification": &schema.Schema{
   229  							Type:     schema.TypeString,
   230  							Optional: true,
   231  						},
   232  						"account": &schema.Schema{
   233  							Type:     schema.TypeString,
   234  							Optional: true,
   235  						},
   236  						"user": &schema.Schema{
   237  							Type:     schema.TypeString,
   238  							Optional: true,
   239  						},
   240  						"key_material": &schema.Schema{
   241  							Type:     schema.TypeString,
   242  							Optional: true,
   243  						},
   244  						"key_id": &schema.Schema{
   245  							Type:     schema.TypeString,
   246  							Optional: true,
   247  						},
   248  						"insecure_skip_tls_verify": &schema.Schema{
   249  							Type:     schema.TypeString,
   250  							Optional: true,
   251  						},
   252  						"object_name": &schema.Schema{
   253  							Type:     schema.TypeString,
   254  							Optional: true,
   255  						},
   256  						"endpoint": &schema.Schema{
   257  							Type:     schema.TypeString,
   258  							Optional: true,
   259  						},
   260  						"encrypt": &schema.Schema{
   261  							Type:     schema.TypeString,
   262  							Optional: true,
   263  						},
   264  						"acl": &schema.Schema{
   265  							Type:     schema.TypeString,
   266  							Optional: true,
   267  						},
   268  						"secret_key": &schema.Schema{
   269  							Type:     schema.TypeString,
   270  							Optional: true,
   271  						},
   272  						"kms_key_id": &schema.Schema{
   273  							Type:     schema.TypeString,
   274  							Optional: true,
   275  						},
   276  						"lock_table": &schema.Schema{
   277  							Type:     schema.TypeString,
   278  							Optional: true,
   279  						},
   280  						"dynamodb_table": &schema.Schema{
   281  							Type:     schema.TypeString,
   282  							Optional: true,
   283  						},
   284  						"profile": &schema.Schema{
   285  							Type:     schema.TypeString,
   286  							Optional: true,
   287  						},
   288  						"shared_credentials_file": &schema.Schema{
   289  							Type:     schema.TypeString,
   290  							Optional: true,
   291  						},
   292  						"role_arn": &schema.Schema{
   293  							Type:     schema.TypeString,
   294  							Optional: true,
   295  						},
   296  						"assume_role_policy": &schema.Schema{
   297  							Type:     schema.TypeString,
   298  							Optional: true,
   299  						},
   300  						"external_id": &schema.Schema{
   301  							Type:     schema.TypeString,
   302  							Optional: true,
   303  						},
   304  						"session_name": &schema.Schema{
   305  							Type:     schema.TypeString,
   306  							Optional: true,
   307  						},
   308  						"workspace_key_prefix": &schema.Schema{
   309  							Type:     schema.TypeString,
   310  							Optional: true,
   311  						},
   312  						"skip_credentials_validation": &schema.Schema{
   313  							Type:     schema.TypeString,
   314  							Optional: true,
   315  						},
   316  						"skip_get_ec2_platforms": &schema.Schema{
   317  							Type:     schema.TypeString,
   318  							Optional: true,
   319  						},
   320  						"skip_region_validation": &schema.Schema{
   321  							Type:     schema.TypeString,
   322  							Optional: true,
   323  						},
   324  						"skip_requesting_account_id": &schema.Schema{
   325  							Type:     schema.TypeString,
   326  							Optional: true,
   327  						},
   328  						"skip_metadata_api_check": &schema.Schema{
   329  							Type:     schema.TypeString,
   330  							Optional: true,
   331  						},
   332  						"force_path_style": &schema.Schema{
   333  							Type:     schema.TypeString,
   334  							Optional: true,
   335  						},
   336  						"auth_url": &schema.Schema{
   337  							Type:     schema.TypeString,
   338  							Optional: true,
   339  						},
   340  						"container": &schema.Schema{
   341  							Type:     schema.TypeString,
   342  							Optional: true,
   343  						},
   344  						"user_name": &schema.Schema{
   345  							Type:     schema.TypeString,
   346  							Optional: true,
   347  						},
   348  						"user_id": &schema.Schema{
   349  							Type:     schema.TypeString,
   350  							Optional: true,
   351  						},
   352  						"region_name": &schema.Schema{
   353  							Type:     schema.TypeString,
   354  							Optional: true,
   355  						},
   356  						"tenant_id": &schema.Schema{
   357  							Type:     schema.TypeString,
   358  							Optional: true,
   359  						},
   360  						"tenant_name": &schema.Schema{
   361  							Type:     schema.TypeString,
   362  							Optional: true,
   363  						},
   364  						"domain_id": &schema.Schema{
   365  							Type:     schema.TypeString,
   366  							Optional: true,
   367  						},
   368  						"domain_name": &schema.Schema{
   369  							Type:     schema.TypeString,
   370  							Optional: true,
   371  						},
   372  						"insecure": &schema.Schema{
   373  							Type:     schema.TypeString,
   374  							Optional: true,
   375  						},
   376  						"cacert_file": &schema.Schema{
   377  							Type:     schema.TypeString,
   378  							Optional: true,
   379  						},
   380  						"cert": &schema.Schema{
   381  							Type:     schema.TypeString,
   382  							Optional: true,
   383  						},
   384  						"archive_container": &schema.Schema{
   385  							Type:     schema.TypeString,
   386  							Optional: true,
   387  						},
   388  						"archive_path": &schema.Schema{
   389  							Type:     schema.TypeString,
   390  							Optional: true,
   391  						},
   392  						"expire_after": &schema.Schema{
   393  							Type:     schema.TypeString,
   394  							Optional: true,
   395  						},
   396  						"name": &schema.Schema{
   397  							Type:     schema.TypeString,
   398  							Optional: true,
   399  						},
   400  					},
   401  				},
   402  			},
   403  
   404  			"defaults": {
   405  				Type:     schema.TypeMap,
   406  				Optional: true,
   407  			},
   408  
   409  			"environment": {
   410  				Type:       schema.TypeString,
   411  				Optional:   true,
   412  				Default:    backend.DefaultStateName,
   413  				Deprecated: "Terraform environments are now called workspaces. Please use the workspace key instead.",
   414  			},
   415  
   416  			"workspace": {
   417  				Type:     schema.TypeString,
   418  				Optional: true,
   419  				Default:  backend.DefaultStateName,
   420  			},
   421  
   422  			"__has_dynamic_attributes": {
   423  				Type:     schema.TypeString,
   424  				Optional: true,
   425  			},
   426  		},
   427  	}
   428  }
   429  
   430  func dataSourceRemoteStateRead(d *schema.ResourceData, meta interface{}) error {
   431  	backendType := d.Get("backend").(string)
   432  
   433  	// Get the configuration in a type we want. This is a bit of a hack but makes
   434  	// things work for the 'remote' backend as well. This can simply be deleted or
   435  	// reverted when merging this 0.12.
   436  	raw := make(map[string]interface{})
   437  	if cfg, ok := d.GetOk("config"); ok {
   438  		if raw, ok = cfg.(*schema.Set).List()[0].(map[string]interface{}); ok {
   439  			for k, v := range raw {
   440  				switch v := v.(type) {
   441  				case string:
   442  					if v == "" {
   443  						delete(raw, k)
   444  					}
   445  				case []interface{}:
   446  					if len(v) == 0 {
   447  						delete(raw, k)
   448  					}
   449  				}
   450  			}
   451  		}
   452  	}
   453  
   454  	rawConfig, err := config.NewRawConfig(raw)
   455  	if err != nil {
   456  		return fmt.Errorf("error initializing backend: %s", err)
   457  	}
   458  
   459  	// Don't break people using the old _local syntax - but note warning above
   460  	if backendType == "_local" {
   461  		log.Println(`[INFO] Switching old (unsupported) backend "_local" to "local"`)
   462  		backendType = "local"
   463  	}
   464  
   465  	// Create the client to access our remote state
   466  	log.Printf("[DEBUG] Initializing remote state backend: %s", backendType)
   467  	f := backendInit.Backend(backendType)
   468  	if f == nil {
   469  		return fmt.Errorf("Unknown backend type: %s", backendType)
   470  	}
   471  	b := f()
   472  
   473  	warns, errs := b.Validate(terraform.NewResourceConfig(rawConfig))
   474  	for _, warning := range warns {
   475  		log.Printf("[DEBUG] Warning validating backend config: %s", warning)
   476  	}
   477  	if len(errs) > 0 {
   478  		return fmt.Errorf("error validating backend config: %s", multierror.Append(nil, errs...))
   479  	}
   480  
   481  	// Configure the backend
   482  	if err := b.Configure(terraform.NewResourceConfig(rawConfig)); err != nil {
   483  		return fmt.Errorf("error initializing backend: %s", err)
   484  	}
   485  
   486  	// environment is deprecated in favour of workspace.
   487  	// If both keys are set workspace should win.
   488  	name := d.Get("environment").(string)
   489  	if ws, ok := d.GetOk("workspace"); ok && ws != backend.DefaultStateName {
   490  		name = ws.(string)
   491  	}
   492  
   493  	state, err := b.State(name)
   494  	if err != nil {
   495  		return fmt.Errorf("error loading the remote state: %s", err)
   496  	}
   497  	if err := state.RefreshState(); err != nil {
   498  		return err
   499  	}
   500  	d.SetId(time.Now().UTC().String())
   501  
   502  	outputMap := make(map[string]interface{})
   503  
   504  	defaults := d.Get("defaults").(map[string]interface{})
   505  	for key, val := range defaults {
   506  		outputMap[key] = val
   507  	}
   508  
   509  	remoteState := state.State()
   510  	if remoteState.Empty() {
   511  		log.Println("[DEBUG] empty remote state")
   512  	} else {
   513  		for key, val := range remoteState.RootModule().Outputs {
   514  			if val.Value != nil {
   515  				outputMap[key] = val.Value
   516  			}
   517  		}
   518  	}
   519  
   520  	mappedOutputs := remoteStateFlatten(outputMap)
   521  
   522  	for key, val := range mappedOutputs {
   523  		d.UnsafeSetFieldRaw(key, val)
   524  	}
   525  
   526  	return nil
   527  }