Merge branch 'master' of github.com:hashicorp/terraform
This commit is contained in:
commit
e3e4b6c2ac
|
@ -15,8 +15,10 @@ FEATURES:
|
|||
* **New Resource:** `cloudstack_affinity_group` [GH-8360]
|
||||
* **New Resource:** `librato_alert` [GH-8170]
|
||||
* **New Resource:** `librato_service` [GH-8170]
|
||||
* **New Remote State Backend:** `local` [GH-8647]
|
||||
* Data source blocks can now have a count associated with them [GH-8635]
|
||||
* The count of a resource can now be referenced for interpolations: `self.count` and `type.name.count` work [GH-8581]
|
||||
* Provisioners now support connection using IPv6 in addition to IPv4 [GH-6616]
|
||||
|
||||
IMPROVEMENTS:
|
||||
* core: Add wildcard (match all) support to `ignore_changes` [GH-8599]
|
||||
|
@ -36,6 +38,7 @@ IMPROVEMENTS:
|
|||
|
||||
BUG FIXES:
|
||||
* core: Changing a module source from file to VCS no longer errors [GH-8398]
|
||||
* core: Configuration is now validated prior to input, fixing an obscure parse error when attempting to interpolate a count [GH-8591]
|
||||
* core: JSON configuration with resources with a single key parse properly [GH-8485]
|
||||
* core: States with duplicate modules are detected and an error is shown [GH-8463]
|
||||
* core: Validate uniqueness of variables/outputs in a module [GH-8482]
|
||||
|
|
|
@ -0,0 +1,66 @@
|
|||
package aws
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/hashicorp/terraform/helper/acctest"
|
||||
"github.com/hashicorp/terraform/helper/resource"
|
||||
)
|
||||
|
||||
func TestAccAWSS3BucketNotification_importBasic(t *testing.T) {
|
||||
resourceName := "aws_s3_bucket_notification.notification"
|
||||
|
||||
resource.Test(t, resource.TestCase{
|
||||
PreCheck: func() { testAccPreCheck(t) },
|
||||
Providers: testAccProviders,
|
||||
CheckDestroy: testAccCheckAWSS3BucketNotificationDestroy,
|
||||
Steps: []resource.TestStep{
|
||||
resource.TestStep{
|
||||
Config: testAccAWSS3BucketConfigWithTopicNotification(acctest.RandInt()),
|
||||
},
|
||||
|
||||
resource.TestStep{
|
||||
ResourceName: resourceName,
|
||||
ImportState: true,
|
||||
ImportStateVerify: true,
|
||||
ImportStateVerifyIgnore: []string{"bucket"},
|
||||
},
|
||||
},
|
||||
})
|
||||
|
||||
resource.Test(t, resource.TestCase{
|
||||
PreCheck: func() { testAccPreCheck(t) },
|
||||
Providers: testAccProviders,
|
||||
CheckDestroy: testAccCheckAWSS3BucketNotificationDestroy,
|
||||
Steps: []resource.TestStep{
|
||||
resource.TestStep{
|
||||
Config: testAccAWSS3BucketConfigWithQueueNotification(acctest.RandInt()),
|
||||
},
|
||||
|
||||
resource.TestStep{
|
||||
ResourceName: resourceName,
|
||||
ImportState: true,
|
||||
ImportStateVerify: true,
|
||||
ImportStateVerifyIgnore: []string{"bucket"},
|
||||
},
|
||||
},
|
||||
})
|
||||
|
||||
resource.Test(t, resource.TestCase{
|
||||
PreCheck: func() { testAccPreCheck(t) },
|
||||
Providers: testAccProviders,
|
||||
CheckDestroy: testAccCheckAWSS3BucketNotificationDestroy,
|
||||
Steps: []resource.TestStep{
|
||||
resource.TestStep{
|
||||
Config: testAccAWSS3BucketConfigWithLambdaNotification(acctest.RandInt()),
|
||||
},
|
||||
|
||||
resource.TestStep{
|
||||
ResourceName: resourceName,
|
||||
ImportState: true,
|
||||
ImportStateVerify: true,
|
||||
ImportStateVerifyIgnore: []string{"bucket"},
|
||||
},
|
||||
},
|
||||
})
|
||||
}
|
|
@ -20,6 +20,9 @@ func resourceAwsS3BucketNotification() *schema.Resource {
|
|||
Read: resourceAwsS3BucketNotificationRead,
|
||||
Update: resourceAwsS3BucketNotificationPut,
|
||||
Delete: resourceAwsS3BucketNotificationDelete,
|
||||
Importer: &schema.ResourceImporter{
|
||||
State: schema.ImportStatePassthrough,
|
||||
},
|
||||
|
||||
Schema: map[string]*schema.Schema{
|
||||
"bucket": &schema.Schema{
|
||||
|
|
|
@ -16,6 +16,16 @@ func dataSourceRemoteState() *schema.Resource {
|
|||
"backend": {
|
||||
Type: schema.TypeString,
|
||||
Required: true,
|
||||
ValidateFunc: func(v interface{}, k string) (ws []string, errors []error) {
|
||||
if vStr, ok := v.(string); ok && vStr == "_local" {
|
||||
ws = append(ws, "Use of the %q backend is now officially "+
|
||||
"supported as %q. Please update your configuration to ensure "+
|
||||
"compatibility with future versions of Terraform.",
|
||||
"_local", "local")
|
||||
}
|
||||
|
||||
return
|
||||
},
|
||||
},
|
||||
|
||||
"config": {
|
||||
|
@ -38,6 +48,12 @@ func dataSourceRemoteStateRead(d *schema.ResourceData, meta interface{}) error {
|
|||
config[k] = v.(string)
|
||||
}
|
||||
|
||||
// Don't break people using the old _local syntax - but note warning above
|
||||
if backend == "_local" {
|
||||
log.Println(`[INFO] Switching old (unsupported) backend "_local" to "local"`)
|
||||
backend = "local"
|
||||
}
|
||||
|
||||
// Create the client to access our remote state
|
||||
log.Printf("[DEBUG] Initializing remote state client: %s", backend)
|
||||
client, err := remote.NewClient(backend, config)
|
||||
|
|
|
@ -32,7 +32,7 @@ func TestState_complexOutputs(t *testing.T) {
|
|||
{
|
||||
Config: testAccState_complexOutputs,
|
||||
Check: resource.ComposeTestCheckFunc(
|
||||
testAccCheckStateValue("terraform_remote_state.foo", "backend", "_local"),
|
||||
testAccCheckStateValue("terraform_remote_state.foo", "backend", "local"),
|
||||
testAccCheckStateValue("terraform_remote_state.foo", "config.path", "./test-fixtures/complex_outputs.tfstate"),
|
||||
testAccCheckStateValue("terraform_remote_state.foo", "computed_set.#", "2"),
|
||||
testAccCheckStateValue("terraform_remote_state.foo", `map.%`, "2"),
|
||||
|
@ -65,7 +65,7 @@ func testAccCheckStateValue(id, name, value string) resource.TestCheckFunc {
|
|||
|
||||
const testAccState_basic = `
|
||||
data "terraform_remote_state" "foo" {
|
||||
backend = "_local"
|
||||
backend = "local"
|
||||
|
||||
config {
|
||||
path = "./test-fixtures/basic.tfstate"
|
||||
|
@ -74,7 +74,7 @@ data "terraform_remote_state" "foo" {
|
|||
|
||||
const testAccState_complexOutputs = `
|
||||
resource "terraform_remote_state" "foo" {
|
||||
backend = "_local"
|
||||
backend = "local"
|
||||
|
||||
config {
|
||||
path = "./test-fixtures/complex_outputs.tfstate"
|
||||
|
|
|
@ -2,6 +2,7 @@ package command
|
|||
|
||||
import (
|
||||
"fmt"
|
||||
"log"
|
||||
|
||||
"github.com/hashicorp/terraform/terraform"
|
||||
"github.com/mitchellh/cli"
|
||||
|
@ -27,7 +28,11 @@ const DefaultBackupExtension = ".backup"
|
|||
const DefaultParallelism = 10
|
||||
|
||||
func validateContext(ctx *terraform.Context, ui cli.Ui) bool {
|
||||
if ws, es := ctx.Validate(); len(ws) > 0 || len(es) > 0 {
|
||||
log.Println("[INFO] Validating the context...")
|
||||
ws, es := ctx.Validate()
|
||||
log.Printf("[INFO] Validation result: %d warnings, %d errors", len(ws), len(es))
|
||||
|
||||
if len(ws) > 0 || len(es) > 0 {
|
||||
ui.Output(
|
||||
"There are warnings and/or errors related to your configuration. Please\n" +
|
||||
"fix these before continuing.\n")
|
||||
|
|
|
@ -165,6 +165,11 @@ func (m *Meta) Context(copts contextOpts) (*terraform.Context, bool, error) {
|
|||
return nil, false, fmt.Errorf("Error downloading modules: %s", err)
|
||||
}
|
||||
|
||||
// Validate the module right away
|
||||
if err := mod.Validate(); err != nil {
|
||||
return nil, false, err
|
||||
}
|
||||
|
||||
opts.Module = mod
|
||||
opts.Parallelism = copts.Parallelism
|
||||
opts.State = state.State()
|
||||
|
|
|
@ -395,6 +395,40 @@ func TestPlan_statePast(t *testing.T) {
|
|||
}
|
||||
}
|
||||
|
||||
func TestPlan_validate(t *testing.T) {
|
||||
// This is triggered by not asking for input so we have to set this to false
|
||||
test = false
|
||||
defer func() { test = true }()
|
||||
|
||||
cwd, err := os.Getwd()
|
||||
if err != nil {
|
||||
t.Fatalf("err: %s", err)
|
||||
}
|
||||
if err := os.Chdir(testFixturePath("plan-invalid")); err != nil {
|
||||
t.Fatalf("err: %s", err)
|
||||
}
|
||||
defer os.Chdir(cwd)
|
||||
|
||||
p := testProvider()
|
||||
ui := new(cli.MockUi)
|
||||
c := &PlanCommand{
|
||||
Meta: Meta{
|
||||
ContextOpts: testCtxConfig(p),
|
||||
Ui: ui,
|
||||
},
|
||||
}
|
||||
|
||||
args := []string{}
|
||||
if code := c.Run(args); code != 1 {
|
||||
t.Fatalf("bad: %d\n\n%s", code, ui.ErrorWriter.String())
|
||||
}
|
||||
|
||||
actual := ui.ErrorWriter.String()
|
||||
if !strings.Contains(actual, "can't reference") {
|
||||
t.Fatalf("bad: %s", actual)
|
||||
}
|
||||
}
|
||||
|
||||
func TestPlan_vars(t *testing.T) {
|
||||
p := testProvider()
|
||||
ui := new(cli.MockUi)
|
||||
|
|
|
@ -765,8 +765,7 @@ func pushTFVars() []atlas.TFVar {
|
|||
return []atlas.TFVar{
|
||||
{"bar", "foo", false},
|
||||
{"baz", `{
|
||||
A = "a"
|
||||
interp = "${file("t.txt")}"
|
||||
A = "a"
|
||||
}`, true},
|
||||
{"fob", `["a", "quotes \"in\" quotes"]`, true},
|
||||
{"foo", "bar", false},
|
||||
|
|
|
@ -0,0 +1,7 @@
|
|||
resource "test_instance" "foo" {
|
||||
count = 5
|
||||
}
|
||||
|
||||
resource "test_instance" "bar" {
|
||||
count = "${length(test_instance.foo.*.id)}"
|
||||
}
|
|
@ -7,7 +7,6 @@ variable "baz" {
|
|||
|
||||
default = {
|
||||
"A" = "a"
|
||||
interp = "${file("t.txt")}"
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,17 @@
|
|||
package shared
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net"
|
||||
)
|
||||
|
||||
// IpFormat formats the IP correctly, so we don't provide IPv6 address in an IPv4 format during node communication. We return the ip parameter as is if it's an IPv4 address or a hostname.
|
||||
func IpFormat(ip string) string {
|
||||
ipObj := net.ParseIP(ip)
|
||||
// Return the ip/host as is if it's either a hostname or an IPv4 address.
|
||||
if ipObj == nil || ipObj.To4() != nil {
|
||||
return ip
|
||||
}
|
||||
|
||||
return fmt.Sprintf("[%s]", ip)
|
||||
}
|
|
@ -0,0 +1,26 @@
|
|||
package shared
|
||||
|
||||
import (
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestIpFormatting_Ipv4(t *testing.T) {
|
||||
formatted := IpFormat("127.0.0.1")
|
||||
if formatted != "127.0.0.1" {
|
||||
t.Fatal("expected", "127.0.0.1", "got", formatted)
|
||||
}
|
||||
}
|
||||
|
||||
func TestIpFormatting_Hostname(t *testing.T) {
|
||||
formatted := IpFormat("example.com")
|
||||
if formatted != "example.com" {
|
||||
t.Fatal("expected", "example.com", "got", formatted)
|
||||
}
|
||||
}
|
||||
|
||||
func TestIpFormatting_Ipv6(t *testing.T) {
|
||||
formatted := IpFormat("::1")
|
||||
if formatted != "[::1]" {
|
||||
t.Fatal("expected", "[::1]", "got", formatted)
|
||||
}
|
||||
}
|
|
@ -8,6 +8,7 @@ import (
|
|||
"os"
|
||||
"time"
|
||||
|
||||
"github.com/hashicorp/terraform/communicator/shared"
|
||||
"github.com/hashicorp/terraform/helper/pathorcontents"
|
||||
"github.com/hashicorp/terraform/terraform"
|
||||
"github.com/mitchellh/mapstructure"
|
||||
|
@ -84,6 +85,11 @@ func parseConnectionInfo(s *terraform.InstanceState) (*connectionInfo, error) {
|
|||
if connInfo.User == "" {
|
||||
connInfo.User = DefaultUser
|
||||
}
|
||||
|
||||
// Format the host if needed.
|
||||
// Needed for IPv6 support.
|
||||
connInfo.Host = shared.IpFormat(connInfo.Host)
|
||||
|
||||
if connInfo.Port == 0 {
|
||||
connInfo.Port = DefaultPort
|
||||
}
|
||||
|
@ -107,6 +113,10 @@ func parseConnectionInfo(s *terraform.InstanceState) (*connectionInfo, error) {
|
|||
|
||||
// Default all bastion config attrs to their non-bastion counterparts
|
||||
if connInfo.BastionHost != "" {
|
||||
// Format the bastion host if needed.
|
||||
// Needed for IPv6 support.
|
||||
connInfo.BastionHost = shared.IpFormat(connInfo.BastionHost)
|
||||
|
||||
if connInfo.BastionUser == "" {
|
||||
connInfo.BastionUser = connInfo.User
|
||||
}
|
||||
|
|
|
@ -66,6 +66,68 @@ func TestProvisioner_connInfo(t *testing.T) {
|
|||
}
|
||||
}
|
||||
|
||||
func TestProvisioner_connInfoIpv6(t *testing.T) {
|
||||
r := &terraform.InstanceState{
|
||||
Ephemeral: terraform.EphemeralState{
|
||||
ConnInfo: map[string]string{
|
||||
"type": "ssh",
|
||||
"user": "root",
|
||||
"password": "supersecret",
|
||||
"private_key": "someprivatekeycontents",
|
||||
"host": "::1",
|
||||
"port": "22",
|
||||
"timeout": "30s",
|
||||
|
||||
"bastion_host": "::1",
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
conf, err := parseConnectionInfo(r)
|
||||
if err != nil {
|
||||
t.Fatalf("err: %v", err)
|
||||
}
|
||||
|
||||
if conf.Host != "[::1]" {
|
||||
t.Fatalf("bad: %v", conf)
|
||||
}
|
||||
|
||||
if conf.BastionHost != "[::1]" {
|
||||
t.Fatalf("bad %v", conf)
|
||||
}
|
||||
}
|
||||
|
||||
func TestProvisioner_connInfoHostname(t *testing.T) {
|
||||
r := &terraform.InstanceState{
|
||||
Ephemeral: terraform.EphemeralState{
|
||||
ConnInfo: map[string]string{
|
||||
"type": "ssh",
|
||||
"user": "root",
|
||||
"password": "supersecret",
|
||||
"private_key": "someprivatekeycontents",
|
||||
"host": "example.com",
|
||||
"port": "22",
|
||||
"timeout": "30s",
|
||||
|
||||
"bastion_host": "example.com",
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
conf, err := parseConnectionInfo(r)
|
||||
if err != nil {
|
||||
t.Fatalf("err: %v", err)
|
||||
}
|
||||
|
||||
if conf.Host != "example.com" {
|
||||
t.Fatalf("bad: %v", conf)
|
||||
}
|
||||
|
||||
if conf.BastionHost != "example.com" {
|
||||
t.Fatalf("bad %v", conf)
|
||||
}
|
||||
}
|
||||
|
||||
func TestProvisioner_connInfoLegacy(t *testing.T) {
|
||||
r := &terraform.InstanceState{
|
||||
Ephemeral: terraform.EphemeralState{
|
||||
|
|
|
@ -7,6 +7,7 @@ import (
|
|||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/hashicorp/terraform/communicator/shared"
|
||||
"github.com/hashicorp/terraform/terraform"
|
||||
"github.com/mitchellh/mapstructure"
|
||||
)
|
||||
|
@ -72,6 +73,11 @@ func parseConnectionInfo(s *terraform.InstanceState) (*connectionInfo, error) {
|
|||
if connInfo.User == "" {
|
||||
connInfo.User = DefaultUser
|
||||
}
|
||||
|
||||
// Format the host if needed.
|
||||
// Needed for IPv6 support.
|
||||
connInfo.Host = shared.IpFormat(connInfo.Host)
|
||||
|
||||
if connInfo.Port == 0 {
|
||||
connInfo.Port = DefaultPort
|
||||
}
|
||||
|
|
|
@ -49,6 +49,92 @@ func TestProvisioner_connInfo(t *testing.T) {
|
|||
}
|
||||
}
|
||||
|
||||
func TestProvisioner_connInfoIpv6(t *testing.T) {
|
||||
r := &terraform.InstanceState{
|
||||
Ephemeral: terraform.EphemeralState{
|
||||
ConnInfo: map[string]string{
|
||||
"type": "winrm",
|
||||
"user": "Administrator",
|
||||
"password": "supersecret",
|
||||
"host": "::1",
|
||||
"port": "5985",
|
||||
"https": "true",
|
||||
"timeout": "30s",
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
conf, err := parseConnectionInfo(r)
|
||||
if err != nil {
|
||||
t.Fatalf("err: %v", err)
|
||||
}
|
||||
|
||||
if conf.User != "Administrator" {
|
||||
t.Fatalf("expected: %v: got: %v", "Administrator", conf)
|
||||
}
|
||||
if conf.Password != "supersecret" {
|
||||
t.Fatalf("expected: %v: got: %v", "supersecret", conf)
|
||||
}
|
||||
if conf.Host != "[::1]" {
|
||||
t.Fatalf("expected: %v: got: %v", "[::1]", conf)
|
||||
}
|
||||
if conf.Port != 5985 {
|
||||
t.Fatalf("expected: %v: got: %v", 5985, conf)
|
||||
}
|
||||
if conf.HTTPS != true {
|
||||
t.Fatalf("expected: %v: got: %v", true, conf)
|
||||
}
|
||||
if conf.Timeout != "30s" {
|
||||
t.Fatalf("expected: %v: got: %v", "30s", conf)
|
||||
}
|
||||
if conf.ScriptPath != DefaultScriptPath {
|
||||
t.Fatalf("expected: %v: got: %v", DefaultScriptPath, conf)
|
||||
}
|
||||
}
|
||||
|
||||
func TestProvisioner_connInfoHostname(t *testing.T) {
|
||||
r := &terraform.InstanceState{
|
||||
Ephemeral: terraform.EphemeralState{
|
||||
ConnInfo: map[string]string{
|
||||
"type": "winrm",
|
||||
"user": "Administrator",
|
||||
"password": "supersecret",
|
||||
"host": "example.com",
|
||||
"port": "5985",
|
||||
"https": "true",
|
||||
"timeout": "30s",
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
conf, err := parseConnectionInfo(r)
|
||||
if err != nil {
|
||||
t.Fatalf("err: %v", err)
|
||||
}
|
||||
|
||||
if conf.User != "Administrator" {
|
||||
t.Fatalf("expected: %v: got: %v", "Administrator", conf)
|
||||
}
|
||||
if conf.Password != "supersecret" {
|
||||
t.Fatalf("expected: %v: got: %v", "supersecret", conf)
|
||||
}
|
||||
if conf.Host != "example.com" {
|
||||
t.Fatalf("expected: %v: got: %v", "example.com", conf)
|
||||
}
|
||||
if conf.Port != 5985 {
|
||||
t.Fatalf("expected: %v: got: %v", 5985, conf)
|
||||
}
|
||||
if conf.HTTPS != true {
|
||||
t.Fatalf("expected: %v: got: %v", true, conf)
|
||||
}
|
||||
if conf.Timeout != "30s" {
|
||||
t.Fatalf("expected: %v: got: %v", "30s", conf)
|
||||
}
|
||||
if conf.ScriptPath != DefaultScriptPath {
|
||||
t.Fatalf("expected: %v: got: %v", DefaultScriptPath, conf)
|
||||
}
|
||||
}
|
||||
|
||||
func TestProvisioner_formatDuration(t *testing.T) {
|
||||
cases := map[string]struct {
|
||||
InstanceState *terraform.InstanceState
|
||||
|
|
|
@ -195,6 +195,13 @@ func TestConfigValidate_countResourceVar(t *testing.T) {
|
|||
}
|
||||
}
|
||||
|
||||
func TestConfigValidate_countResourceVarMulti(t *testing.T) {
|
||||
c := testConfig(t, "validate-count-resource-var-multi")
|
||||
if err := c.Validate(); err == nil {
|
||||
t.Fatal("should not be valid")
|
||||
}
|
||||
}
|
||||
|
||||
func TestConfigValidate_countUserVar(t *testing.T) {
|
||||
c := testConfig(t, "validate-count-user-var")
|
||||
if err := c.Validate(); err != nil {
|
||||
|
|
|
@ -0,0 +1,5 @@
|
|||
resource "aws_instance" "foo" {}
|
||||
|
||||
resource "aws_instance" "web" {
|
||||
count = "${length(aws_instance.foo.*.bar)}"
|
||||
}
|
|
@ -78,7 +78,7 @@ func testStepImportState(
|
|||
// Find the existing resource
|
||||
var oldR *terraform.ResourceState
|
||||
for _, r2 := range old {
|
||||
if r2.Primary != nil && r2.Primary.ID == r.Primary.ID {
|
||||
if r2.Primary != nil && r2.Primary.ID == r.Primary.ID && r2.Type == r.Type {
|
||||
oldR = r2
|
||||
break
|
||||
}
|
||||
|
|
|
@ -36,16 +36,14 @@ func NewClient(t string, conf map[string]string) (Client, error) {
|
|||
// BuiltinClients is the list of built-in clients that can be used with
|
||||
// NewClient.
|
||||
var BuiltinClients = map[string]Factory{
|
||||
"artifactory": artifactoryFactory,
|
||||
"atlas": atlasFactory,
|
||||
"azure": azureFactory,
|
||||
"consul": consulFactory,
|
||||
"etcd": etcdFactory,
|
||||
"gcs": gcsFactory,
|
||||
"http": httpFactory,
|
||||
"local": fileFactory,
|
||||
"s3": s3Factory,
|
||||
"swift": swiftFactory,
|
||||
"artifactory": artifactoryFactory,
|
||||
|
||||
// This is used for development purposes only.
|
||||
"_local": fileFactory,
|
||||
}
|
||||
|
|
|
@ -234,3 +234,10 @@ The `lambda_function` notification configuration supports the following:
|
|||
* `filter_prefix` - (Optional) Specifies object key name prefix.
|
||||
* `filter_suffix` - (Optional) Specifies object key name suffix.
|
||||
|
||||
## Import
|
||||
|
||||
S3 bucket notification can be imported using the `bucket`, e.g.
|
||||
|
||||
```
|
||||
$ terraform import aws_s3_bucket_notification.bucket_notification bucket-name
|
||||
```
|
||||
|
|
|
@ -13,6 +13,10 @@ is created. This invokes a process on the machine running Terraform, not on
|
|||
the resource. See the `remote-exec` [provisioner](/docs/provisioners/remote-exec.html)
|
||||
to run commands on the resource.
|
||||
|
||||
Note that even though the resource will be ifully created when the provisioner is run,
|
||||
there is no guarantee that it will be in an operable state - for example system services
|
||||
such as `sshd` may not be started yet on compute resources.
|
||||
|
||||
## Example usage
|
||||
|
||||
```
|
||||
|
|
|
@ -0,0 +1,36 @@
|
|||
---
|
||||
layout: "remotestate"
|
||||
page_title: "Remote State Backend: local"
|
||||
sidebar_current: "docs-state-remote-local"
|
||||
description: |-
|
||||
Remote state stored using the local file system.
|
||||
---
|
||||
|
||||
# local
|
||||
|
||||
Remote state backend that uses the local file system.
|
||||
|
||||
## Example Usage
|
||||
|
||||
```
|
||||
terraform remote config \
|
||||
-backend=local \
|
||||
-backend-config="path=/path/to/terraform.tfstate"
|
||||
```
|
||||
|
||||
## Example Reference
|
||||
|
||||
```
|
||||
data "terraform_remote_state" "foo" {
|
||||
backend = "local"
|
||||
config {
|
||||
path = "${path.module}/../../terraform.tfstate"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Configuration variables
|
||||
|
||||
The following configuration options are supported:
|
||||
|
||||
* `path` - (Required) The path to the `tfstate` file.
|
|
@ -34,6 +34,9 @@
|
|||
<li<%= sidebar_current("docs-state-remote-http") %>>
|
||||
<a href="/docs/state/remote/http.html">http</a>
|
||||
</li>
|
||||
<li<%= sidebar_current("docs-state-remote-local") %>>
|
||||
<a href="/docs/state/remote/local.html">local</a>
|
||||
</li>
|
||||
<li<%= sidebar_current("docs-state-remote-s3") %>>
|
||||
<a href="/docs/state/remote/s3.html">s3</a>
|
||||
</li>
|
||||
|
|
Loading…
Reference in New Issue