From 2802d319d29893e5b7b882590a16294cceddbc49 Mon Sep 17 00:00:00 2001 From: Chris Marchesi Date: Wed, 19 Apr 2017 16:56:54 -0700 Subject: [PATCH 01/49] core: Move CountBoundaryTransformer to the plan graph builder This fixes interpolation issues on grandchild data sources that have multiple instances (ie: counts). For example, baz depends on bar, which depends on foo. In this instance, after an initial TF run is done and state is saved, the next refresh/plan is not properly transformed, and instead of the graph/state coming through as data.x.bar.0, it comes through as data.x.bar. This breaks interpolations that rely on splat operators - ie: data.x.bar.*.out. --- builtin/providers/test/data_source_test.go | 56 ++++++++++++++++++++++ terraform/graph_builder_apply.go | 3 -- terraform/graph_builder_plan.go | 3 ++ 3 files changed, 59 insertions(+), 3 deletions(-) diff --git a/builtin/providers/test/data_source_test.go b/builtin/providers/test/data_source_test.go index 3f4e5ada6..44622c0c5 100644 --- a/builtin/providers/test/data_source_test.go +++ b/builtin/providers/test/data_source_test.go @@ -99,3 +99,59 @@ resource "test_resource" "foo" { }, }) } + +// Test that a grandchild data source that is based off of count works, ie: +// dependency chain foo -> bar -> baz. This was failing because +// CountBoundaryTransformer is being run during apply instead of plan, which +// meant that it wasn't firing after data sources were potentially changing +// state and causing diff/interpolation issues. +// +// This happens after the initial apply, after state is saved. +func TestDataSource_dataSourceCountGrandChild(t *testing.T) { + resource.UnitTest(t, resource.TestCase{ + Providers: testAccProviders, + CheckDestroy: func(s *terraform.State) error { + return nil + }, + Steps: []resource.TestStep{ + { + Config: dataSourceCountGrandChildConfig, + }, + { + Config: dataSourceCountGrandChildConfig, + Check: func(s *terraform.State) error { + for _, v := range []string{"foo", "bar", "baz"} { + count := 0 + for k := range s.RootModule().Resources { + if strings.HasPrefix(k, fmt.Sprintf("data.test_data_source.%s.", v)) { + count++ + } + } + + if count != 2 { + return fmt.Errorf("bad count for data.test_data_source.%s: %d", v, count) + } + } + return nil + }, + }, + }, + }) +} + +const dataSourceCountGrandChildConfig = ` +data "test_data_source" "foo" { + count = 2 + input = "one" +} + +data "test_data_source" "bar" { + count = "${length(data.test_data_source.foo.*.id)}" + input = "${data.test_data_source.foo.*.output[count.index]}" +} + +data "test_data_source" "baz" { + count = "${length(data.test_data_source.bar.*.id)}" + input = "${data.test_data_source.bar.*.output[count.index]}" +} +` diff --git a/terraform/graph_builder_apply.go b/terraform/graph_builder_apply.go index 38a90f277..251b517e1 100644 --- a/terraform/graph_builder_apply.go +++ b/terraform/graph_builder_apply.go @@ -117,9 +117,6 @@ func (b *ApplyGraphBuilder) Steps() []GraphTransformer { // Connect references so ordering is correct &ReferenceTransformer{}, - // Add the node to fix the state count boundaries - &CountBoundaryTransformer{}, - // Target &TargetsTransformer{Targets: b.Targets}, diff --git a/terraform/graph_builder_plan.go b/terraform/graph_builder_plan.go index 02d869700..b8ba4da10 100644 --- a/terraform/graph_builder_plan.go +++ b/terraform/graph_builder_plan.go @@ -120,6 +120,9 @@ func (b *PlanGraphBuilder) Steps() []GraphTransformer { &CloseProviderTransformer{}, &CloseProvisionerTransformer{}, + // Add the node to fix the state count boundaries + &CountBoundaryTransformer{}, + // Single root &RootTransformer{}, } From d41b80678958f9b448acfc4dfd12ffe5d288ce9e Mon Sep 17 00:00:00 2001 From: Chris Marchesi Date: Wed, 19 Apr 2017 22:23:52 -0700 Subject: [PATCH 02/49] core: Restore CountBoundaryTransformer to apply, add/adjust tests Moving the transformer wholesale looks like it broke some tests, with some actually doing legit work in normalizing singular resources from a foo.0 notation to just foo. Adjusted the TestPlanGraphBuilder to account for the extra meta.count-boundary nodes in the graph output now, as well as added another context test that tests this case. It appears the issue happens during validate, as this is where the state can be altered to a broken state if things are not properly transformed in the plan graph. --- builtin/providers/test/data_source_test.go | 10 +- terraform/context_plan_test.go | 142 ++++++++++++++++++ terraform/graph_builder_apply.go | 3 + terraform/graph_builder_plan.go | 6 +- terraform/graph_builder_plan_test.go | 11 +- .../nested-resource-count-plan/main.tf | 11 ++ 6 files changed, 174 insertions(+), 9 deletions(-) create mode 100644 terraform/test-fixtures/nested-resource-count-plan/main.tf diff --git a/builtin/providers/test/data_source_test.go b/builtin/providers/test/data_source_test.go index 44622c0c5..77e235f3d 100644 --- a/builtin/providers/test/data_source_test.go +++ b/builtin/providers/test/data_source_test.go @@ -100,11 +100,11 @@ resource "test_resource" "foo" { }) } -// Test that a grandchild data source that is based off of count works, ie: -// dependency chain foo -> bar -> baz. This was failing because -// CountBoundaryTransformer is being run during apply instead of plan, which -// meant that it wasn't firing after data sources were potentially changing -// state and causing diff/interpolation issues. +// TestDataSource_dataSourceCountGrandChild tests that a grandchild data source +// that is based off of count works, ie: dependency chain foo -> bar -> baz. +// This was failing because CountBoundaryTransformer is being run during apply +// instead of plan, which meant that it wasn't firing after data sources were +// potentially changing state and causing diff/interpolation issues. // // This happens after the initial apply, after state is saved. func TestDataSource_dataSourceCountGrandChild(t *testing.T) { diff --git a/terraform/context_plan_test.go b/terraform/context_plan_test.go index 7064f6465..4d9e35430 100644 --- a/terraform/context_plan_test.go +++ b/terraform/context_plan_test.go @@ -3146,3 +3146,145 @@ func TestContext2Plan_ignoreChangesWithFlatmaps(t *testing.T) { t.Fatalf("bad:\n%s\n\nexpected\n\n%s", actual, expected) } } + +// TestContext2Plan_resourceNestedCount ensures resource sets that depend on +// the count of another resource set (ie: count of a data source that depends +// on another data source's instance count - data.x.foo.*.id) get properly +// normalized to the indexes they should be. This case comes up when there is +// an existing state (after an initial apply). +func TestContext2Plan_resourceNestedCount(t *testing.T) { + m := testModule(t, "nested-resource-count-plan") + p := testProvider("aws") + p.DiffFn = testDiffFn + p.RefreshFn = func(i *InstanceInfo, is *InstanceState) (*InstanceState, error) { + return is, nil + } + s := &State{ + Modules: []*ModuleState{ + &ModuleState{ + Path: rootModulePath, + Resources: map[string]*ResourceState{ + "aws_instance.foo.0": &ResourceState{ + Type: "aws_instance", + Primary: &InstanceState{ + ID: "foo0", + Attributes: map[string]string{ + "id": "foo0", + }, + }, + }, + "aws_instance.foo.1": &ResourceState{ + Type: "aws_instance", + Primary: &InstanceState{ + ID: "foo1", + Attributes: map[string]string{ + "id": "foo1", + }, + }, + }, + "aws_instance.bar.0": &ResourceState{ + Type: "aws_instance", + Dependencies: []string{"aws_instance.foo.*"}, + Primary: &InstanceState{ + ID: "bar0", + Attributes: map[string]string{ + "id": "bar0", + }, + }, + }, + "aws_instance.bar.1": &ResourceState{ + Type: "aws_instance", + Dependencies: []string{"aws_instance.foo.*"}, + Primary: &InstanceState{ + ID: "bar1", + Attributes: map[string]string{ + "id": "bar1", + }, + }, + }, + "aws_instance.baz.0": &ResourceState{ + Type: "aws_instance", + Dependencies: []string{"aws_instance.bar.*"}, + Primary: &InstanceState{ + ID: "baz0", + Attributes: map[string]string{ + "id": "baz0", + }, + }, + }, + "aws_instance.baz.1": &ResourceState{ + Type: "aws_instance", + Dependencies: []string{"aws_instance.bar.*"}, + Primary: &InstanceState{ + ID: "baz1", + Attributes: map[string]string{ + "id": "baz1", + }, + }, + }, + }, + }, + }, + } + ctx := testContext2(t, &ContextOpts{ + Module: m, + Providers: map[string]ResourceProviderFactory{ + "aws": testProviderFuncFixed(p), + }, + State: s, + }) + + _, e := ctx.Validate() + if len(e) > 0 { + for _, err := range e { + t.Errorf("bad: %s", err) + } + } + + _, err := ctx.Refresh() + if err != nil { + t.Fatalf("refresh err: %s", err) + } + + plan, err := ctx.Plan() + if err != nil { + t.Fatalf("plan err: %s", err) + } + + actual := strings.TrimSpace(plan.String()) + expected := strings.TrimSpace(` +DIFF: + + + +STATE: + +aws_instance.bar.0: + ID = bar0 + + Dependencies: + aws_instance.foo.* +aws_instance.bar.1: + ID = bar1 + + Dependencies: + aws_instance.foo.* +aws_instance.baz.0: + ID = baz0 + + Dependencies: + aws_instance.bar.* +aws_instance.baz.1: + ID = baz1 + + Dependencies: + aws_instance.bar.* +aws_instance.foo.0: + ID = foo0 +aws_instance.foo.1: + ID = foo1 +`) + if actual != expected { + t.Fatalf("bad:\n%s\n\nexpected\n\n%s", actual, expected) + } +} diff --git a/terraform/graph_builder_apply.go b/terraform/graph_builder_apply.go index 251b517e1..38a90f277 100644 --- a/terraform/graph_builder_apply.go +++ b/terraform/graph_builder_apply.go @@ -117,6 +117,9 @@ func (b *ApplyGraphBuilder) Steps() []GraphTransformer { // Connect references so ordering is correct &ReferenceTransformer{}, + // Add the node to fix the state count boundaries + &CountBoundaryTransformer{}, + // Target &TargetsTransformer{Targets: b.Targets}, diff --git a/terraform/graph_builder_plan.go b/terraform/graph_builder_plan.go index b8ba4da10..a6a3a90d4 100644 --- a/terraform/graph_builder_plan.go +++ b/terraform/graph_builder_plan.go @@ -113,6 +113,9 @@ func (b *PlanGraphBuilder) Steps() []GraphTransformer { // have to connect again later for providers and so on. &ReferenceTransformer{}, + // Add the node to fix the state count boundaries + &CountBoundaryTransformer{}, + // Target &TargetsTransformer{Targets: b.Targets}, @@ -120,9 +123,6 @@ func (b *PlanGraphBuilder) Steps() []GraphTransformer { &CloseProviderTransformer{}, &CloseProvisionerTransformer{}, - // Add the node to fix the state count boundaries - &CountBoundaryTransformer{}, - // Single root &RootTransformer{}, } diff --git a/terraform/graph_builder_plan_test.go b/terraform/graph_builder_plan_test.go index 23526a9ac..25578ebaf 100644 --- a/terraform/graph_builder_plan_test.go +++ b/terraform/graph_builder_plan_test.go @@ -29,7 +29,7 @@ func TestPlanGraphBuilder(t *testing.T) { actual := strings.TrimSpace(g.String()) expected := strings.TrimSpace(testPlanGraphBuilderStr) if actual != expected { - t.Fatalf("bad: %s", actual) + t.Fatalf("expected:\n%s\n\ngot:\n%s", expected, actual) } } @@ -61,6 +61,14 @@ aws_load_balancer.weblb provider.aws aws_security_group.firewall provider.aws +meta.count-boundary (count boundary fixup) + aws_instance.web + aws_load_balancer.weblb + aws_security_group.firewall + openstack_floating_ip.random + provider.aws + provider.openstack + var.foo openstack_floating_ip.random provider.openstack provider.aws @@ -75,6 +83,7 @@ provider.openstack (close) openstack_floating_ip.random provider.openstack root + meta.count-boundary (count boundary fixup) provider.aws (close) provider.openstack (close) var.foo diff --git a/terraform/test-fixtures/nested-resource-count-plan/main.tf b/terraform/test-fixtures/nested-resource-count-plan/main.tf new file mode 100644 index 000000000..f803fd1f6 --- /dev/null +++ b/terraform/test-fixtures/nested-resource-count-plan/main.tf @@ -0,0 +1,11 @@ +resource "aws_instance" "foo" { + count = 2 +} + +resource "aws_instance" "bar" { + count = "${length(aws_instance.foo.*.id)}" +} + +resource "aws_instance" "baz" { + count = "${length(aws_instance.bar.*.id)}" +} From 744727a28a502710fe0f41a1ef2790be13faae97 Mon Sep 17 00:00:00 2001 From: Chris Marchesi Date: Thu, 20 Apr 2017 07:31:44 -0700 Subject: [PATCH 03/49] core: Trap warnings as well as errors on resourceNestedCount test --- terraform/context_plan_test.go | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/terraform/context_plan_test.go b/terraform/context_plan_test.go index 4d9e35430..16f0d16e9 100644 --- a/terraform/context_plan_test.go +++ b/terraform/context_plan_test.go @@ -3234,11 +3234,12 @@ func TestContext2Plan_resourceNestedCount(t *testing.T) { State: s, }) - _, e := ctx.Validate() + w, e := ctx.Validate() + if len(w) > 0 { + t.Fatalf("warnings generated on validate: %#v", w) + } if len(e) > 0 { - for _, err := range e { - t.Errorf("bad: %s", err) - } + t.Fatalf("errors generated on validate: %#v", e) } _, err := ctx.Refresh() From ad604d91dc380d1c41c08a442017f8fbb8cdd55a Mon Sep 17 00:00:00 2001 From: Pete Wildsmith Date: Tue, 25 Apr 2017 23:11:24 +0100 Subject: [PATCH 04/49] Add TLS options to Nomad provider schema --- builtin/providers/nomad/provider.go | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/builtin/providers/nomad/provider.go b/builtin/providers/nomad/provider.go index d23c4ad97..abefb3ce8 100644 --- a/builtin/providers/nomad/provider.go +++ b/builtin/providers/nomad/provider.go @@ -24,6 +24,24 @@ func Provider() terraform.ResourceProvider { DefaultFunc: schema.EnvDefaultFunc("NOMAD_REGION", ""), Description: "Region of the target Nomad agent.", }, + "ca_file": &schema.Schema{ + Type: schema.TypeString, + Optional: true, + DefaultFunc: schema.EnvDefaultFunc("NOMAD_CACERT", ""), + Description: "A path to a PEM-encoded certificate authority used to verify the remote agent's certificate.", + }, + "cert_file": &schema.Schema{ + Type: schema.TypeString, + Optional: true, + DefaultFunc: schema.EnvDefaultFunc("NOMAD_CLIENT_CERT", ""), + Description: "A path to a PEM-encoded certificate provided to the remote agent; requires use of key_file.", + }, + "key_file": &schema.Schema{ + Type: schema.TypeString, + Optional: true, + DefaultFunc: schema.EnvDefaultFunc("NOMAD_CLIENT_KEY", ""), + Description: "A path to a PEM-encoded private key, required if cert_file is specified.", + }, }, ConfigureFunc: providerConfigure, @@ -38,6 +56,9 @@ func providerConfigure(d *schema.ResourceData) (interface{}, error) { config := api.DefaultConfig() config.Address = d.Get("address").(string) config.Region = d.Get("region").(string) + config.TLSConfig.CACert = d.Get("ca_file").(string) + config.TLSConfig.ClientCert = d.Get("cert_file").(string) + config.TLSConfig.ClientKey = d.Get("key_file").(string) client, err := api.NewClient(config) if err != nil { From b1c03e93df06ff8f00e332e2d4c188c2dab43456 Mon Sep 17 00:00:00 2001 From: Pete Wildsmith Date: Tue, 25 Apr 2017 23:17:32 +0100 Subject: [PATCH 05/49] Document TLS options in Nomad provider --- website/source/docs/providers/nomad/index.html.markdown | 3 +++ 1 file changed, 3 insertions(+) diff --git a/website/source/docs/providers/nomad/index.html.markdown b/website/source/docs/providers/nomad/index.html.markdown index acf696d2e..129a9540b 100644 --- a/website/source/docs/providers/nomad/index.html.markdown +++ b/website/source/docs/providers/nomad/index.html.markdown @@ -34,3 +34,6 @@ The following arguments are supported: * `address` - (Optional) The HTTP(S) API address of the Nomad agent to use. Defaults to `http://127.0.0.1:4646`. The `NOMAD_ADDR` environment variable can also be used. * `region` - (Optional) The Nomad region to target. The `NOMAD_REGION` environment variable can also be used. +* `ca_file` - (Optional) A path to a PEM-encoded certificate authority used to verify the remote agent's certificate. The `NOMAD_CACERT` environment variable can also be used. +* `cert_file` - (Optional) A path to a PEM-encoded certificate provided to the remote agent; requires use of `key_file`. The `NOMAD_CLIENT_CERT` environment variable can also be used. +* `key_file`- (Optional) A path to a PEM-encoded private key, required if `cert_file` is specified. The `NOMAD_CLIENT_KEY` environment variable can also be used. From d3687fc9e9a09f2081ea7ce82c50e63c505db95e Mon Sep 17 00:00:00 2001 From: Josh VanderLinden Date: Wed, 26 Apr 2017 05:22:01 +0000 Subject: [PATCH 06/49] Expose any dynamically-assigned private IP address --- .../azurerm/resource_arm_loadbalancer.go | 18 +++++++++++++++++- .../azurerm/r/loadbalancer.html.markdown | 1 + 2 files changed, 18 insertions(+), 1 deletion(-) diff --git a/builtin/providers/azurerm/resource_arm_loadbalancer.go b/builtin/providers/azurerm/resource_arm_loadbalancer.go index 60bb95990..22ea3359f 100644 --- a/builtin/providers/azurerm/resource_arm_loadbalancer.go +++ b/builtin/providers/azurerm/resource_arm_loadbalancer.go @@ -92,6 +92,11 @@ func resourceArmLoadBalancer() *schema.Resource { }, }, + "private_ip_address": { + Type: schema.TypeString, + Computed: true, + }, + "tags": tagsSchema(), }, } @@ -172,7 +177,18 @@ func resourecArmLoadBalancerRead(d *schema.ResourceData, meta interface{}) error d.Set("resource_group_name", id.ResourceGroup) if loadBalancer.LoadBalancerPropertiesFormat != nil && loadBalancer.LoadBalancerPropertiesFormat.FrontendIPConfigurations != nil { - d.Set("frontend_ip_configuration", flattenLoadBalancerFrontendIpConfiguration(loadBalancer.LoadBalancerPropertiesFormat.FrontendIPConfigurations)) + ipconfig := flattenLoadBalancerFrontendIpConfiguration(loadBalancer.LoadBalancerPropertiesFormat.FrontendIPConfigurations) + d.Set("frontend_ip_configuration", ipconfig) + + for _, config := range ipconfig { + cfg := config.(map[string]interface{}) + if priv_ip, ok := cfg["private_ip_address"]; ok { + d.Set("private_ip_address", priv_ip) + + // set the private IP address at most once + break + } + } } flattenAndSetTags(d, loadBalancer.Tags) diff --git a/website/source/docs/providers/azurerm/r/loadbalancer.html.markdown b/website/source/docs/providers/azurerm/r/loadbalancer.html.markdown index e659bf2ec..7753a5ca5 100644 --- a/website/source/docs/providers/azurerm/r/loadbalancer.html.markdown +++ b/website/source/docs/providers/azurerm/r/loadbalancer.html.markdown @@ -60,6 +60,7 @@ The following arguments are supported: The following attributes are exported: * `id` - The LoadBalancer ID. +* `private_ip_address` - The private IP address assigned to the load balancer, if any. ## Import From 790874b372ae52d14efcaa4aefd883fa96b448ce Mon Sep 17 00:00:00 2001 From: Josh VanderLinden Date: Wed, 26 Apr 2017 15:03:42 +0000 Subject: [PATCH 07/49] Iterate over loadBalancer.LoadBalancerPropertiesFormat.FrontendIPConfigurations directly --- .../providers/azurerm/resource_arm_loadbalancer.go | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/builtin/providers/azurerm/resource_arm_loadbalancer.go b/builtin/providers/azurerm/resource_arm_loadbalancer.go index 22ea3359f..940b3fb98 100644 --- a/builtin/providers/azurerm/resource_arm_loadbalancer.go +++ b/builtin/providers/azurerm/resource_arm_loadbalancer.go @@ -177,13 +177,12 @@ func resourecArmLoadBalancerRead(d *schema.ResourceData, meta interface{}) error d.Set("resource_group_name", id.ResourceGroup) if loadBalancer.LoadBalancerPropertiesFormat != nil && loadBalancer.LoadBalancerPropertiesFormat.FrontendIPConfigurations != nil { - ipconfig := flattenLoadBalancerFrontendIpConfiguration(loadBalancer.LoadBalancerPropertiesFormat.FrontendIPConfigurations) - d.Set("frontend_ip_configuration", ipconfig) + ipconfigs := loadBalancer.LoadBalancerPropertiesFormat.FrontendIPConfigurations + d.Set("frontend_ip_configuration", flattenLoadBalancerFrontendIpConfiguration(ipconfigs)) - for _, config := range ipconfig { - cfg := config.(map[string]interface{}) - if priv_ip, ok := cfg["private_ip_address"]; ok { - d.Set("private_ip_address", priv_ip) + for _, config := range *ipconfigs { + if config.FrontendIPConfigurationPropertiesFormat.PrivateIPAddress != nil { + d.Set("private_ip_address", config.FrontendIPConfigurationPropertiesFormat.PrivateIPAddress) // set the private IP address at most once break From 5d40be32091a2c0d8ff342dfd8434ca20766120a Mon Sep 17 00:00:00 2001 From: Pete Wildsmith Date: Wed, 26 Apr 2017 18:48:57 +0100 Subject: [PATCH 08/49] reformat incorrectly formatted file --- builtin/providers/nomad/provider.go | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/builtin/providers/nomad/provider.go b/builtin/providers/nomad/provider.go index abefb3ce8..61f8603bc 100644 --- a/builtin/providers/nomad/provider.go +++ b/builtin/providers/nomad/provider.go @@ -25,22 +25,22 @@ func Provider() terraform.ResourceProvider { Description: "Region of the target Nomad agent.", }, "ca_file": &schema.Schema{ - Type: schema.TypeString, + Type: schema.TypeString, Optional: true, DefaultFunc: schema.EnvDefaultFunc("NOMAD_CACERT", ""), - Description: "A path to a PEM-encoded certificate authority used to verify the remote agent's certificate.", + Description: "A path to a PEM-encoded certificate authority used to verify the remote agent's certificate.", }, "cert_file": &schema.Schema{ - Type: schema.TypeString, + Type: schema.TypeString, Optional: true, DefaultFunc: schema.EnvDefaultFunc("NOMAD_CLIENT_CERT", ""), - Description: "A path to a PEM-encoded certificate provided to the remote agent; requires use of key_file.", + Description: "A path to a PEM-encoded certificate provided to the remote agent; requires use of key_file.", }, "key_file": &schema.Schema{ - Type: schema.TypeString, + Type: schema.TypeString, Optional: true, DefaultFunc: schema.EnvDefaultFunc("NOMAD_CLIENT_KEY", ""), - Description: "A path to a PEM-encoded private key, required if cert_file is specified.", + Description: "A path to a PEM-encoded private key, required if cert_file is specified.", }, }, From 05a76297e72710a38fdfb70a0351b74182c1ef0f Mon Sep 17 00:00:00 2001 From: Maciej Skierkowski Date: Wed, 26 Apr 2017 15:49:36 -0700 Subject: [PATCH 09/49] Removing reference to remote state pushing in TFE --- .../docs/enterprise/state/pushing.html.md | 23 ------------------- website/source/layouts/enterprise.erb | 3 --- 2 files changed, 26 deletions(-) delete mode 100755 website/source/docs/enterprise/state/pushing.html.md diff --git a/website/source/docs/enterprise/state/pushing.html.md b/website/source/docs/enterprise/state/pushing.html.md deleted file mode 100755 index 4e9545fda..000000000 --- a/website/source/docs/enterprise/state/pushing.html.md +++ /dev/null @@ -1,23 +0,0 @@ ---- -layout: "enterprise" -page_title: "Pushing - State - Terraform Enterprise" -sidebar_current: "docs-enterprise-state-pushing" -description: |- - Pushing remote states. ---- - -# Pushing Terraform Remote State to Terraform Enterprise - -Terraform Enterprise is one of a few options to store [remote state](/docs/enterprise/state). - -Remote state gives you the ability to version and collaborate on Terraform -changes. It stores information about the changes Terraform makes based on -configuration. - -To use Terraform Enterprise to store remote state, you'll first need to have the -`ATLAS_TOKEN` environment variable set and run the following command. - -```shell -$ terraform remote config \ - -backend-config="name=$USERNAME/product" -``` diff --git a/website/source/layouts/enterprise.erb b/website/source/layouts/enterprise.erb index 127074249..3aaf4cc1d 100644 --- a/website/source/layouts/enterprise.erb +++ b/website/source/layouts/enterprise.erb @@ -79,9 +79,6 @@ > State