diff --git a/Dockerfile b/Dockerfile deleted file mode 100644 index 095c65f94..000000000 --- a/Dockerfile +++ /dev/null @@ -1,24 +0,0 @@ -# This Dockerfile builds on golang:alpine by building Terraform from source -# using the current working directory. -# -# This produces a docker image that contains a working Terraform binary along -# with all of its source code, which is what gets released on hub.docker.com -# as terraform:full. The main releases (terraform:latest, terraform:light and -# the release tags) are lighter images including only the officially-released -# binary from releases.hashicorp.com; these are built instead from -# scripts/docker-release/Dockerfile-release. - -FROM golang:alpine -LABEL maintainer="HashiCorp Terraform Team " - -RUN apk add --no-cache git bash openssh - -ENV TF_DEV=true -ENV TF_RELEASE=1 - -WORKDIR $GOPATH/src/github.com/hashicorp/terraform -COPY . . -RUN /bin/bash scripts/build.sh - -WORKDIR $GOPATH -ENTRYPOINT ["terraform"] diff --git a/backend/backend.go b/backend/backend.go index 391a89246..c92087d5d 100644 --- a/backend/backend.go +++ b/backend/backend.go @@ -34,10 +34,6 @@ var ( ErrDefaultWorkspaceNotSupported = errors.New("default workspace not supported\n" + "You can create a new workspace with the \"workspace new\" command.") - // ErrOperationNotSupported is returned when an unsupported operation - // is detected by the configured backend. - ErrOperationNotSupported = errors.New("operation not supported") - // ErrWorkspacesNotSupported is an error returned when a caller attempts // to perform an operation on a workspace other than "default" for a // backend that doesn't support multiple workspaces. diff --git a/backend/nil.go b/backend/nil.go deleted file mode 100644 index 8c46f49d0..000000000 --- a/backend/nil.go +++ /dev/null @@ -1,40 +0,0 @@ -package backend - -import ( - "github.com/hashicorp/terraform/configs/configschema" - "github.com/hashicorp/terraform/states/statemgr" - "github.com/hashicorp/terraform/tfdiags" - "github.com/zclconf/go-cty/cty" -) - -// Nil is a no-op implementation of Backend. -// -// This is useful to embed within another struct to implement all of the -// backend interface for testing. -type Nil struct{} - -func (Nil) ConfigSchema() *configschema.Block { - return &configschema.Block{} -} - -func (Nil) PrepareConfig(v cty.Value) (cty.Value, tfdiags.Diagnostics) { - return v, nil -} - -func (Nil) Configure(cty.Value) tfdiags.Diagnostics { - return nil -} - -func (Nil) StateMgr(string) (statemgr.Full, error) { - // We must return a non-nil manager to adhere to the interface, so - // we'll return an in-memory-only one. - return statemgr.NewFullFake(statemgr.NewTransientInMemory(nil), nil), nil -} - -func (Nil) DeleteWorkspace(string) error { - return nil -} - -func (Nil) Workspaces() ([]string, error) { - return []string{DefaultStateName}, nil -} diff --git a/backend/nil_test.go b/backend/nil_test.go deleted file mode 100644 index c20dc9012..000000000 --- a/backend/nil_test.go +++ /dev/null @@ -1,9 +0,0 @@ -package backend - -import ( - "testing" -) - -func TestNil_impl(t *testing.T) { - var _ Backend = new(Nil) -} diff --git a/backend/remote-state/oss/backend.go b/backend/remote-state/oss/backend.go index b8681df6f..9b1227634 100644 --- a/backend/remote-state/oss/backend.go +++ b/backend/remote-state/oss/backend.go @@ -5,33 +5,30 @@ import ( "encoding/json" "fmt" "io/ioutil" - "os" - "runtime" - "strings" - - "github.com/aliyun/alibaba-cloud-sdk-go/sdk/requests" - "github.com/aliyun/alibaba-cloud-sdk-go/sdk/responses" - "github.com/aliyun/alibaba-cloud-sdk-go/services/sts" - "github.com/aliyun/aliyun-oss-go-sdk/oss" - "github.com/hashicorp/terraform/backend" - "github.com/hashicorp/terraform/helper/schema" - "github.com/hashicorp/terraform/helper/validation" - "github.com/jmespath/go-jmespath" - "log" "net/http" + "net/url" + "os" + "regexp" + "runtime" "strconv" + "strings" "time" "github.com/aliyun/alibaba-cloud-sdk-go/sdk" "github.com/aliyun/alibaba-cloud-sdk-go/sdk/auth/credentials" + "github.com/aliyun/alibaba-cloud-sdk-go/sdk/requests" + "github.com/aliyun/alibaba-cloud-sdk-go/sdk/responses" "github.com/aliyun/alibaba-cloud-sdk-go/services/location" + "github.com/aliyun/alibaba-cloud-sdk-go/services/sts" + "github.com/aliyun/aliyun-oss-go-sdk/oss" "github.com/aliyun/aliyun-tablestore-go-sdk/tablestore" "github.com/hashicorp/go-cleanhttp" + "github.com/hashicorp/terraform/backend" + "github.com/hashicorp/terraform/helper/schema" "github.com/hashicorp/terraform/version" + "github.com/jmespath/go-jmespath" "github.com/mitchellh/go-homedir" - "net/url" - "regexp" ) // New creates a new backend for OSS remote state. @@ -196,10 +193,23 @@ func assumeRoleSchema() *schema.Schema { Description: "The permissions applied when assuming a role. You cannot use this policy to grant permissions which exceed those of the role that is being assumed.", }, "session_expiration": { - Type: schema.TypeInt, - Optional: true, - Description: "The time after which the established session for assuming role expires.", - ValidateFunc: validation.IntBetween(900, 3600), + Type: schema.TypeInt, + Optional: true, + Description: "The time after which the established session for assuming role expires.", + ValidateFunc: func(v interface{}, k string) ([]string, []error) { + min := 900 + max := 3600 + value, ok := v.(int) + if !ok { + return nil, []error{fmt.Errorf("expected type of %s to be int", k)} + } + + if value < min || value > max { + return nil, []error{fmt.Errorf("expected %s to be in the range (%d - %d), got %d", k, min, max, v)} + } + + return nil, nil + }, }, }, }, diff --git a/command/init.go b/command/init.go index e37e1dad3..475d5c9ba 100644 --- a/command/init.go +++ b/command/init.go @@ -427,9 +427,8 @@ func (c *InitCommand) getProviders(config *configs.Config, state *states.State, if moreDiags.HasErrors() { return false, true, diags } - stateReqs := make(getproviders.Requirements, 0) if state != nil { - stateReqs = state.ProviderRequirements() + stateReqs := state.ProviderRequirements() reqs = reqs.Merge(stateReqs) } @@ -774,16 +773,6 @@ func (c *InitCommand) getProviders(config *configs.Config, state *states.State, return true, false, diags } -func (c *InitCommand) populateProviderToReqs(reqs map[addrs.Provider][]*configs.ModuleRequirements, node *configs.ModuleRequirements) { - for fqn := range node.Requirements { - reqs[fqn] = append(reqs[fqn], node) - } - - for _, child := range node.Children { - c.populateProviderToReqs(reqs, child) - } -} - // backendConfigOverrideBody interprets the raw values of -backend-config // arguments into a hcl Body that should override the backend settings given // in the configuration. @@ -1030,117 +1019,6 @@ changes, we recommend adding version constraints in a required_providers block in your configuration, with the constraint strings suggested below. ` -const errDiscoveryServiceUnreachable = ` -[reset][bold][red]Registry service unreachable.[reset][red] - -This may indicate a network issue, or an issue with the requested Terraform Registry. -` - -const errProviderNotFound = ` -[reset][bold][red]Provider %[1]q not available for installation.[reset][red] - -A provider named %[1]q could not be found in the Terraform Registry. - -This may result from mistyping the provider name, or the given provider may -be a third-party provider that cannot be installed automatically. - -In the latter case, the plugin must be installed manually by locating and -downloading a suitable distribution package and placing the plugin's executable -file in the following directory: - %[2]s - -Terraform detects necessary plugins by inspecting the configuration and state. -To view the provider versions requested by each module, run -"terraform providers". -` - -const errProviderVersionsUnsuitable = ` -[reset][bold][red]No provider %[1]q plugins meet the constraint %[2]q.[reset][red] - -The version constraint is derived from the "version" argument within the -provider %[1]q block in configuration. Child modules may also apply -provider version constraints. To view the provider versions requested by each -module in the current configuration, run "terraform providers". - -To proceed, the version constraints for this provider must be relaxed by -either adjusting or removing the "version" argument in the provider blocks -throughout the configuration. -` - -const errProviderIncompatible = ` -[reset][bold][red]No available provider %[1]q plugins are compatible with this Terraform version.[reset][red] - -From time to time, new Terraform major releases can change the requirements for -plugins such that older plugins become incompatible. - -Terraform checked all of the plugin versions matching the given constraint: - %[2]s - -Unfortunately, none of the suitable versions are compatible with this version -of Terraform. If you have recently upgraded Terraform, it may be necessary to -move to a newer major release of this provider. Alternatively, if you are -attempting to upgrade the provider to a new major version you may need to -also upgrade Terraform to support the new version. - -Consult the documentation for this provider for more information on -compatibility between provider versions and Terraform versions. -` - -const errProviderInstallError = ` -[reset][bold][red]Error installing provider %[1]q: %[2]s.[reset][red] - -Terraform analyses the configuration and state and automatically downloads -plugins for the providers used. However, when attempting to download this -plugin an unexpected error occurred. - -This may be caused if for some reason Terraform is unable to reach the -plugin repository. The repository may be unreachable if access is blocked -by a firewall. - -If automatic installation is not possible or desirable in your environment, -you may alternatively manually install plugins by downloading a suitable -distribution package and placing the plugin's executable file in the -following directory: - %[3]s -` - -const errMissingProvidersNoInstall = ` -[reset][bold][red]Missing required providers.[reset][red] - -The following provider constraints are not met by the currently-installed -provider plugins: - -%[1]s -Terraform can automatically download and install plugins to meet the given -constraints, but this step was skipped due to the use of -get-plugins=false -and/or -plugin-dir on the command line. - -If automatic installation is not possible or desirable in your environment, -you may manually install plugins by downloading a suitable distribution package -and placing the plugin's executable file in one of the directories given in -by -plugin-dir on the command line, or in the following directory if custom -plugin directories are not set: - %[2]s -` - -const errChecksumVerification = ` -[reset][bold][red]Error verifying checksum for provider %[1]q[reset][red] -The checksum for provider distribution from the Terraform Registry -did not match the source. This may mean that the distributed files -were changed after this version was released to the Registry. -` - -const errSignatureVerification = ` -[reset][bold][red]Error:[reset][bold] Untrusted signing key for provider %[1]q[reset] - -This provider package is not signed with the HashiCorp signing key, and is -therefore incompatible with Terraform v%[2]s. - -A later version of Terraform may have introduced other signing keys that would -accept this provider. Alternatively, an earlier version of this provider may -be compatible with Terraform v%[2]s. -` - // providerProtocolTooOld is a message sent to the CLI UI if the provider's // supported protocol versions are too old for the user's version of terraform, // but a newer version of the provider is compatible. @@ -1171,20 +1049,3 @@ Alternatively, upgrade to the latest version of Terraform for compatibility with // No version of the provider is compatible. const errProviderVersionIncompatible = `No compatible versions of provider %s were found.` - -// Logic from internal/initwd/getter.go -var localSourcePrefixes = []string{ - "./", - "../", - ".\\", - "..\\", -} - -func isLocalSourceAddr(addr string) bool { - for _, prefix := range localSourcePrefixes { - if strings.HasPrefix(addr, prefix) { - return true - } - } - return false -} diff --git a/command/meta_backend.go b/command/meta_backend.go index 77706242f..61c645aaf 100644 --- a/command/meta_backend.go +++ b/command/meta_backend.go @@ -316,20 +316,6 @@ func (m *Meta) backendCLIOpts() (*backend.CLIOpts, error) { }, nil } -// IsLocalBackend returns true if the backend is a local backend. We use this -// for some checks that require a remote backend. -func (m *Meta) IsLocalBackend(b backend.Backend) bool { - // Is it a local backend? - bLocal, ok := b.(*backendLocal.Local) - - // If it is, does it not have an alternate state backend? - if ok { - ok = bLocal.Backend == nil - } - - return ok -} - // Operation initializes a new backend.Operation struct. // // This prepares the operation. After calling this, the caller is expected @@ -728,36 +714,6 @@ func (m *Meta) backend_c_r_S(c *configs.Backend, cHash int, sMgr *clistate.Local return nil, diags } -// Legacy remote state -func (m *Meta) backend_c_R_s(c *configs.Backend, sMgr *clistate.LocalState) (backend.Backend, tfdiags.Diagnostics) { - var diags tfdiags.Diagnostics - - m.Ui.Error(strings.TrimSpace(errBackendLegacy) + "\n") - - diags = diags.Append(fmt.Errorf("Cannot initialize legacy remote state")) - return nil, diags -} - -// Unsetting backend, saved backend, legacy remote state -func (m *Meta) backend_c_R_S(c *configs.Backend, cHash int, sMgr *clistate.LocalState) (backend.Backend, tfdiags.Diagnostics) { - var diags tfdiags.Diagnostics - - m.Ui.Error(strings.TrimSpace(errBackendLegacy) + "\n") - - diags = diags.Append(fmt.Errorf("Cannot initialize legacy remote state")) - return nil, diags -} - -// Configuring a backend for the first time with legacy remote state. -func (m *Meta) backend_C_R_s(c *configs.Backend, sMgr *clistate.LocalState) (backend.Backend, tfdiags.Diagnostics) { - var diags tfdiags.Diagnostics - - m.Ui.Error(strings.TrimSpace(errBackendLegacy) + "\n") - - diags = diags.Append(fmt.Errorf("Cannot initialize legacy remote state")) - return nil, diags -} - // Configuring a backend for the first time. func (m *Meta) backend_C_r_s(c *configs.Backend, cHash int, sMgr *clistate.LocalState) (backend.Backend, tfdiags.Diagnostics) { // Get the backend @@ -1025,26 +981,6 @@ func (m *Meta) backend_C_r_S_unchanged(c *configs.Backend, cHash int, sMgr *clis return b, diags } -// Initiailizing a changed saved backend with legacy remote state. -func (m *Meta) backend_C_R_S_changed(c *configs.Backend, sMgr *clistate.LocalState) (backend.Backend, tfdiags.Diagnostics) { - var diags tfdiags.Diagnostics - - m.Ui.Error(strings.TrimSpace(errBackendLegacy) + "\n") - - diags = diags.Append(fmt.Errorf("Cannot initialize legacy remote state")) - return nil, diags -} - -// Initiailizing an unchanged saved backend with legacy remote state. -func (m *Meta) backend_C_R_S_unchanged(c *configs.Backend, sMgr *clistate.LocalState, output bool) (backend.Backend, tfdiags.Diagnostics) { - var diags tfdiags.Diagnostics - - m.Ui.Error(strings.TrimSpace(errBackendLegacy) + "\n") - - diags = diags.Append(fmt.Errorf("Cannot initialize legacy remote state")) - return nil, diags -} - //------------------------------------------------------------------- // Reusable helper functions for backend management //------------------------------------------------------------------- @@ -1150,36 +1086,6 @@ func (m *Meta) backendInitFromConfig(c *configs.Backend) (backend.Backend, cty.V return b, configVal, diags } -func (m *Meta) backendInitFromSaved(s *terraform.BackendState) (backend.Backend, tfdiags.Diagnostics) { - var diags tfdiags.Diagnostics - - // Get the backend - f := backendInit.Backend(s.Type) - if f == nil { - diags = diags.Append(fmt.Errorf(strings.TrimSpace(errBackendSavedUnknown), s.Type)) - return nil, diags - } - b := f() - - schema := b.ConfigSchema() - configVal, err := s.Config(schema) - if err != nil { - diags = diags.Append(errwrap.Wrapf("saved backend configuration is invalid: {{err}}", err)) - return nil, diags - } - - newVal, validateDiags := b.PrepareConfig(configVal) - diags = diags.Append(validateDiags) - if validateDiags.HasErrors() { - return nil, diags - } - - configureDiags := b.Configure(newVal) - diags = diags.Append(configureDiags) - - return b, diags -} - func (m *Meta) backendInitRequired(reason string) { m.Ui.Output(m.Colorize().Color(fmt.Sprintf( "[reset]"+strings.TrimSpace(errBackendInit)+"\n", reason))) @@ -1194,30 +1100,6 @@ func (m *Meta) backendInitRequired(reason string) { var errBackendInitRequired = errors.New( "Initialization required. Please see the error message above.") -const errBackendLegacyConfig = ` -One or more errors occurred while configuring the legacy remote state. -If fixing these errors requires changing your remote state configuration, -you must switch your configuration to the new remote backend configuration. -You can learn more about remote backends at the URL below: - -https://www.terraform.io/docs/backends/index.html - -The error(s) configuring the legacy remote state: - -%s -` - -const errBackendLegacyUnknown = ` -The legacy remote state type %q could not be found. - -Terraform 0.9.0 shipped with backwards compatibility for all built-in -legacy remote state types. This error may mean that you were using a -custom Terraform build that perhaps supported a different type of -remote state. - -Please check with the creator of the remote state above and try again. -` - const errBackendLocalRead = ` Error reading local state: %s @@ -1237,29 +1119,6 @@ with a backend, we must delete the local state file. Please resolve the issue above and retry the command. ` -const errBackendMigrateNew = ` -Error migrating local state to backend: %s - -Your local state remains intact and unmodified. Please resolve the error -above and try again. -` - -const errBackendNewConfig = ` -Error configuring the backend %q: %s - -Please update the configuration in your Terraform files to fix this error -then run this command again. -` - -const errBackendNewRead = ` -Error reading newly configured backend state: %s - -Terraform is trying to read the state from your newly configured backend -to determine the copy process for your existing state. Backends are expected -to not error even if there is no state yet written. Please resolve the -error above and try again. -` - const errBackendNewUnknown = ` The backend %q could not be found. @@ -1280,34 +1139,6 @@ If the backend already contains existing workspaces, you may need to update the backend configuration. ` -const errBackendRemoteRead = ` -Error reading backend state: %s - -Terraform is trying to read the state from your configured backend to -determine if there is any migration steps necessary. Terraform can't continue -without this check because that would risk losing state. Please resolve the -error above and try again. -` - -const errBackendSavedConfig = ` -Error configuring the backend %q: %s - -Please update the configuration in your Terraform files to fix this error. -If you'd like to update the configuration interactively without storing -the values in your configuration, run "terraform init". -` - -const errBackendSavedUnsetConfig = ` -Error configuring the existing backend %q: %s - -Terraform must configure the existing backend in order to copy the state -from the existing backend, as requested. Please resolve the error and try -again. If you choose to not copy the existing state, Terraform will not -configure the backend. If the configuration is invalid, please update your -Terraform configuration with proper configuration for this backend first -before unsetting the backend. -` - const errBackendSavedUnknown = ` The backend %q could not be found. @@ -1321,14 +1152,6 @@ If you'd like to force remove this backend, you must update your configuration to not use the backend and run "terraform init" (or any other command) again. ` -const errBackendClearLegacy = ` -Error clearing the legacy remote state configuration: %s - -Terraform completed configuring your backend. It is now safe to remove -the legacy remote state configuration, but an error occurred while trying -to do so. Please look at the error above, resolve it, and try again. -` - const errBackendClearSaved = ` Error clearing the backend configuration: %s @@ -1365,72 +1188,14 @@ are usually due to simple file permission errors. Please look at the error above, resolve it, and try again. ` -const errBackendPlanBoth = ` -The plan file contained both a legacy remote state and backend configuration. -This is not allowed. Please recreate the plan file with the latest version of -Terraform. -` - -const errBackendPlanLineageDiff = ` -The plan file contains a state with a differing lineage than the current -state. By continuing, your current state would be overwritten by the state -in the plan. Please either update the plan with the latest state or delete -your current state and try again. - -"Lineage" is a unique identifier generated only once on the creation of -a new, empty state. If these values differ, it means they were created new -at different times. Therefore, Terraform must assume that they're completely -different states. - -The most common cause of seeing this error is using a plan that was -created against a different state. Perhaps the plan is very old and the -state has since been recreated, or perhaps the plan was against a completely -different infrastructure. -` - -const errBackendPlanStateFlag = ` -The -state and -state-out flags cannot be set with a plan that has a remote -state. The plan itself contains the configuration for the remote backend to -store state. The state will be written there for consistency. - -If you wish to change this behavior, please create a plan from local state. -You may use the state flags with plans from local state to affect where -the final state is written. -` - -const errBackendPlanOlder = ` -This plan was created against an older state than is current. Please create -a new plan file against the latest state and try again. - -Terraform doesn't allow you to run plans that were created from older -states since it doesn't properly represent the latest changes Terraform -may have made, and can result in unsafe behavior. - -Plan Serial: %[1]d -Current Serial: %[2]d -` - const outputBackendMigrateChange = ` Terraform detected that the backend type changed from %q to %q. ` -const outputBackendMigrateLegacy = ` -Terraform detected legacy remote state. -` - const outputBackendMigrateLocal = ` Terraform has detected you're unconfiguring your previously set %q backend. ` -const outputBackendConfigureWithLegacy = ` -[reset][bold]New backend configuration detected with legacy remote state![reset] - -Terraform has detected that you're attempting to configure a new backend. -At the same time, legacy remote state configuration was found. Terraform will -first configure the new backend, and then ask if you'd like to migrate -your remote state to the new backend. -` - const outputBackendReconfigure = ` [reset][bold]Backend configuration changed![reset] @@ -1438,45 +1203,6 @@ Terraform has detected that the configuration specified for the backend has changed. Terraform will now check for existing state in the backends. ` -const outputBackendSavedWithLegacy = ` -[reset][bold]Legacy remote state was detected![reset] - -Terraform has detected you still have legacy remote state enabled while -also having a backend configured. Terraform will now ask if you want to -migrate your legacy remote state data to the configured backend. -` - -const outputBackendSavedWithLegacyChanged = ` -[reset][bold]Legacy remote state was detected while also changing your current backend!reset] - -Terraform has detected that you have legacy remote state, a configured -current backend, and you're attempting to reconfigure your backend. To handle -all of these changes, Terraform will first reconfigure your backend. After -this, Terraform will handle optionally copying your legacy remote state -into the newly configured backend. -` - -const outputBackendUnsetWithLegacy = ` -[reset][bold]Detected a request to unset the backend with legacy remote state present![reset] - -Terraform has detected that you're attempting to unset a previously configured -backend (by not having the "backend" configuration set in your Terraform files). -At the same time, legacy remote state was detected. To handle this complex -scenario, Terraform will first unset your configured backend, and then -ask you how to handle the legacy remote state. This will be multi-step -process. -` - -const successBackendLegacyUnset = ` -Terraform has successfully migrated from legacy remote state to your -configured backend (%q). -` - -const successBackendReconfigureWithLegacy = ` -Terraform has successfully reconfigured your backend and migrate -from legacy remote state to the new backend. -` - const successBackendUnset = ` Successfully unset the backend %q. Terraform will now operate locally. ` diff --git a/command/meta_config.go b/command/meta_config.go index 2bb104a11..d5f65355e 100644 --- a/command/meta_config.go +++ b/command/meta_config.go @@ -68,30 +68,6 @@ func (m *Meta) loadConfig(rootDir string) (*configs.Config, tfdiags.Diagnostics) return config, diags } -// loadConfigEarly is a variant of loadConfig that uses the special -// "early config" loader that is more forgiving of unexpected constructs and -// legacy syntax. -// -// Early-loaded config is not registered in the source code cache, so -// diagnostics produced from it may render without source code snippets. In -// practice this is not a big concern because the early config loader also -// cannot generate detailed source locations, so it prefers to produce -// diagnostics without explicit source location information and instead includes -// approximate locations in the message text. -// -// Most callers should use loadConfig. This method exists to support early -// initialization use-cases where the root module must be inspected in order -// to determine what else needs to be installed before the full configuration -// can be used -func (m *Meta) loadConfigEarly(rootDir string) (*earlyconfig.Config, tfdiags.Diagnostics) { - var diags tfdiags.Diagnostics - rootDir = m.normalizePath(rootDir) - - config, hclDiags := initwd.LoadConfig(rootDir, m.modulesDir()) - diags = diags.Append(hclDiags) - return config, diags -} - // loadSingleModule reads configuration from the given directory and returns // a description of that module only, without attempting to assemble a module // tree for referenced child modules. @@ -182,23 +158,6 @@ func (m *Meta) loadBackendConfig(rootDir string) (*configs.Backend, tfdiags.Diag return mod.Backend, nil } -// loadValuesFile loads a file that defines a single map of key/value pairs. -// This is the format used for "tfvars" files. -func (m *Meta) loadValuesFile(filename string) (map[string]cty.Value, tfdiags.Diagnostics) { - var diags tfdiags.Diagnostics - filename = m.normalizePath(filename) - - loader, err := m.initConfigLoader() - if err != nil { - diags = diags.Append(err) - return nil, diags - } - - vals, hclDiags := loader.Parser().LoadValuesFile(filename) - diags = diags.Append(hclDiags) - return vals, diags -} - // loadHCLFile reads an arbitrary HCL file and returns the unprocessed body // representing its toplevel. Most callers should use one of the more // specialized "load..." methods to get a higher-level representation. diff --git a/command/output.go b/command/output.go index 01f988cc6..e389c458c 100644 --- a/command/output.go +++ b/command/output.go @@ -1,10 +1,8 @@ package command import ( - "bytes" "encoding/json" "fmt" - "sort" "strings" ctyjson "github.com/zclconf/go-cty/cty/json" @@ -201,119 +199,6 @@ func (c *OutputCommand) Run(args []string) int { return 0 } -func formatNestedList(indent string, outputList []interface{}) string { - outputBuf := new(bytes.Buffer) - outputBuf.WriteString(fmt.Sprintf("%s[", indent)) - - lastIdx := len(outputList) - 1 - - for i, value := range outputList { - outputBuf.WriteString(fmt.Sprintf("\n%s%s%s", indent, " ", value)) - if i != lastIdx { - outputBuf.WriteString(",") - } - } - - outputBuf.WriteString(fmt.Sprintf("\n%s]", indent)) - return strings.TrimPrefix(outputBuf.String(), "\n") -} - -func formatListOutput(indent, outputName string, outputList []interface{}) string { - keyIndent := "" - - outputBuf := new(bytes.Buffer) - - if outputName != "" { - outputBuf.WriteString(fmt.Sprintf("%s%s = [", indent, outputName)) - keyIndent = " " - } - - lastIdx := len(outputList) - 1 - - for i, value := range outputList { - switch typedValue := value.(type) { - case string: - outputBuf.WriteString(fmt.Sprintf("\n%s%s%s", indent, keyIndent, value)) - case []interface{}: - outputBuf.WriteString(fmt.Sprintf("\n%s%s", indent, - formatNestedList(indent+keyIndent, typedValue))) - case map[string]interface{}: - outputBuf.WriteString(fmt.Sprintf("\n%s%s", indent, - formatNestedMap(indent+keyIndent, typedValue))) - } - - if lastIdx != i { - outputBuf.WriteString(",") - } - } - - if outputName != "" { - if len(outputList) > 0 { - outputBuf.WriteString(fmt.Sprintf("\n%s]", indent)) - } else { - outputBuf.WriteString("]") - } - } - - return strings.TrimPrefix(outputBuf.String(), "\n") -} - -func formatNestedMap(indent string, outputMap map[string]interface{}) string { - ks := make([]string, 0, len(outputMap)) - for k, _ := range outputMap { - ks = append(ks, k) - } - sort.Strings(ks) - - outputBuf := new(bytes.Buffer) - outputBuf.WriteString(fmt.Sprintf("%s{", indent)) - - lastIdx := len(outputMap) - 1 - for i, k := range ks { - v := outputMap[k] - outputBuf.WriteString(fmt.Sprintf("\n%s%s = %v", indent+" ", k, v)) - - if lastIdx != i { - outputBuf.WriteString(",") - } - } - - outputBuf.WriteString(fmt.Sprintf("\n%s}", indent)) - - return strings.TrimPrefix(outputBuf.String(), "\n") -} - -func formatMapOutput(indent, outputName string, outputMap map[string]interface{}) string { - ks := make([]string, 0, len(outputMap)) - for k, _ := range outputMap { - ks = append(ks, k) - } - sort.Strings(ks) - - keyIndent := "" - - outputBuf := new(bytes.Buffer) - if outputName != "" { - outputBuf.WriteString(fmt.Sprintf("%s%s = {", indent, outputName)) - keyIndent = " " - } - - for _, k := range ks { - v := outputMap[k] - outputBuf.WriteString(fmt.Sprintf("\n%s%s%s = %v", indent, keyIndent, k, v)) - } - - if outputName != "" { - if len(outputMap) > 0 { - outputBuf.WriteString(fmt.Sprintf("\n%s}", indent)) - } else { - outputBuf.WriteString("}") - } - } - - return strings.TrimPrefix(outputBuf.String(), "\n") -} - func (c *OutputCommand) Help() string { helpText := ` Usage: terraform output [options] [NAME] diff --git a/command/plugins.go b/command/plugins.go index 74584b699..45d9176c7 100644 --- a/command/plugins.go +++ b/command/plugins.go @@ -119,17 +119,6 @@ func (m *Meta) pluginDirs(includeAutoInstalled bool) []string { return dirs } -func (m *Meta) pluginCache() discovery.PluginCache { - dir := m.PluginCacheDir - if dir == "" { - return nil // cache disabled - } - - dir = filepath.Join(dir, pluginMachineName) - - return discovery.NewLocalPluginCache(dir) -} - func (m *Meta) provisionerFactories() map[string]terraform.ProvisionerFactory { dirs := m.pluginDirs(true) plugins := discovery.FindPlugins("provisioner", dirs) diff --git a/command/show.go b/command/show.go index 7defadf76..17f4a3d7a 100644 --- a/command/show.go +++ b/command/show.go @@ -143,7 +143,7 @@ func (c *ShowCommand) Run(args []string) int { } if plan != nil { - if jsonOutput == true { + if jsonOutput { config := ctx.Config() jsonPlan, err := jsonplan.Marshal(config, plan, stateFile, schemas) @@ -170,7 +170,7 @@ func (c *ShowCommand) Run(args []string) int { return 0 } - if jsonOutput == true { + if jsonOutput { // At this point, it is possible that there is neither state nor a plan. // That's ok, we'll just return an empty object. jsonState, err := jsonstate.Marshal(stateFile, schemas) diff --git a/command/state_list.go b/command/state_list.go index 3442e1c3c..8c8a23906 100644 --- a/command/state_list.go +++ b/command/state_list.go @@ -126,10 +126,6 @@ func (c *StateListCommand) Synopsis() string { return "List resources in the state" } -const errStateFilter = `Error filtering state: %[1]s - -Please ensure that all your addresses are formatted properly.` - const errStateLoadingState = `Error loading the state: %[1]s Please ensure that your Terraform state exists and that you've diff --git a/command/state_meta.go b/command/state_meta.go index 884b618a4..bc70649ac 100644 --- a/command/state_meta.go +++ b/command/state_meta.go @@ -148,10 +148,6 @@ func (c *StateMeta) lookupResourceInstanceAddr(state *states.State, allowMissing return ret, diags } -func (c *StateMeta) lookupSingleResourceInstanceAddr(state *states.State, addrStr string) (addrs.AbsResourceInstance, tfdiags.Diagnostics) { - return addrs.ParseAbsResourceInstanceStr(addrStr) -} - func (c *StateMeta) lookupSingleStateObjectAddr(state *states.State, addrStr string) (addrs.Targetable, tfdiags.Diagnostics) { target, diags := addrs.ParseTargetStr(addrStr) if diags.HasErrors() { diff --git a/command/state_mv.go b/command/state_mv.go index 812441699..dcaaf23a6 100644 --- a/command/state_mv.go +++ b/command/state_mv.go @@ -503,9 +503,3 @@ const errStateMv = `Error moving state: %s Please ensure your addresses and state paths are valid. No state was persisted. Your existing states are untouched.` - -const errStateMvPersist = `Error saving the state: %s - -The state wasn't saved properly. If the error happening after a partial -write occurred, a backup file will have been created. Otherwise, the state -is in the same state it was when the operation started.` diff --git a/command/state_push.go b/command/state_push.go index 5271c477c..facbf786a 100644 --- a/command/state_push.go +++ b/command/state_push.go @@ -153,25 +153,3 @@ Options: func (c *StatePushCommand) Synopsis() string { return "Update remote state from a local state file" } - -const errStatePushLineage = ` -The lineages do not match! The state will not be pushed. - -The "lineage" is a unique identifier given to a state on creation. It helps -protect Terraform from overwriting a seemingly unrelated state file since it -represents potentially losing real state. - -Please verify you're pushing the correct state. If you're sure you are, you -can force the behavior with the "-force" flag. -` - -const errStatePushSerialNewer = ` -The destination state has a higher serial number! The state will not be pushed. - -A higher serial could indicate that there is data in the destination state -that was not present when the source state was created. As a protection measure, -Terraform will not automatically overwrite this state. - -Please verify you're pushing the correct state. If you're sure you are, you -can force the behavior with the "-force" flag. -` diff --git a/command/state_rm.go b/command/state_rm.go index 1fdb69d1d..1254de417 100644 --- a/command/state_rm.go +++ b/command/state_rm.go @@ -167,12 +167,6 @@ func (c *StateRmCommand) Synopsis() string { return "Remove instances from the state" } -const errStateRm = `Error removing items from the state: %s - -The state was not saved. No items were removed from the persisted -state. No backup was created since no modification occurred. Please -resolve the issue above and try again.` - const errStateRmPersist = `Error saving the state: %s The state was not saved. No items were removed from the persisted diff --git a/command/validate.go b/command/validate.go index e3dafceed..8641e5de7 100644 --- a/command/validate.go +++ b/command/validate.go @@ -17,8 +17,6 @@ type ValidateCommand struct { Meta } -const defaultPath = "." - func (c *ValidateCommand) Run(args []string) int { args = c.Meta.process(args) // TODO: The `var` and `var-file` options are not actually used, and should diff --git a/command/workspace_command.go b/command/workspace_command.go index c35097560..3de83dbcc 100644 --- a/command/workspace_command.go +++ b/command/workspace_command.go @@ -63,8 +63,6 @@ will be removed in a future Terraform version. } const ( - envNotSupported = `Backend does not support multiple workspaces` - envExists = `Workspace %q already exists` envDoesNotExist = ` diff --git a/examples/README.md b/examples/README.md deleted file mode 100644 index 9200b9147..000000000 --- a/examples/README.md +++ /dev/null @@ -1,27 +0,0 @@ -# Terraform Examples - -This folder contains a set of Terraform examples. These examples each -have their own README you can read for more details on what the example -does. - -To try any example, clone this repository and run the following commands -from within the example's directory: - -```shell -$ terraform init -$ terraform apply -``` - -## Provider-specific Examples - -Terraform providers each live in their own repository. Some of these -repositories contain documentation specific to their provider: - -* [AliCloud Examples](https://github.com/terraform-providers/terraform-provider-alicloud/tree/master/examples) -* [Amazon Web Services Examples](https://github.com/terraform-providers/terraform-provider-aws/tree/master/examples) -* [Azure Examples](https://github.com/terraform-providers/terraform-provider-azurerm/tree/master/examples) -* [CenturyLink Cloud Examples](https://github.com/terraform-providers/terraform-provider-clc/tree/master/examples) -* [Consul Examples](https://github.com/terraform-providers/terraform-provider-consul/tree/master/examples) -* [DigitalOcean Examples](https://github.com/terraform-providers/terraform-provider-digitalocean/tree/master/examples) -* [Google Cloud Platform Examples](https://github.com/terraform-providers/terraform-provider-google/tree/master/examples) -* [OpenStack Examples](https://github.com/terraform-providers/terraform-provider-openstack/tree/master/examples) diff --git a/examples/cross-provider/README.md b/examples/cross-provider/README.md deleted file mode 100644 index 7b69faea8..000000000 --- a/examples/cross-provider/README.md +++ /dev/null @@ -1,11 +0,0 @@ -# Cross Provider Examples - -This is a simple example of the cross-provider capabilities of -Terraform. - -Very simply, this creates a Heroku application and points a DNS -CNAME record at the result via DNSimple. A `host` query to the outputted -hostname should reveal the correct DNS configuration. - -As with all examples, just copy and paste the example and run -`terraform apply` to see it work. diff --git a/examples/cross-provider/main.tf b/examples/cross-provider/main.tf deleted file mode 100644 index 05c53c507..000000000 --- a/examples/cross-provider/main.tf +++ /dev/null @@ -1,26 +0,0 @@ -# Create our Heroku application. Heroku will -# automatically assign a name. -resource "heroku_app" "web" {} - -# Create our DNSimple record to point to the -# heroku application. -resource "dnsimple_record" "web" { - domain = "${var.dnsimple_domain}" - - name = "terraform" - - # heroku_hostname is a computed attribute on the heroku - # application we can use to determine the hostname - value = "${heroku_app.web.heroku_hostname}" - - type = "CNAME" - ttl = 3600 -} - -# The Heroku domain, which will be created and added -# to the heroku application after we have assigned the domain -# in DNSimple -resource "heroku_domain" "foobar" { - app = "${heroku_app.web.name}" - hostname = "${dnsimple_record.web.hostname}" -} diff --git a/examples/cross-provider/outputs.tf b/examples/cross-provider/outputs.tf deleted file mode 100644 index 9afbf5d61..000000000 --- a/examples/cross-provider/outputs.tf +++ /dev/null @@ -1,3 +0,0 @@ -output "address" { - value = "${dnsimple_record.web.hostname}" -} diff --git a/examples/cross-provider/variables.tf b/examples/cross-provider/variables.tf deleted file mode 100644 index b1024dc57..000000000 --- a/examples/cross-provider/variables.tf +++ /dev/null @@ -1,3 +0,0 @@ -variable "dnsimple_domain" { - description = "The domain we are creating a record for." -} diff --git a/registry/client.go b/registry/client.go index c51854325..61c89c65a 100644 --- a/registry/client.go +++ b/registry/client.go @@ -273,121 +273,6 @@ func (c *Client) ModuleLocation(module *regsrc.Module, version string) (string, return location, nil } -// TerraformProviderVersions queries the registry for a provider, and returns the available versions. -func (c *Client) TerraformProviderVersions(provider *regsrc.TerraformProvider) (*response.TerraformProviderVersions, error) { - host, err := provider.SvcHost() - if err != nil { - return nil, err - } - - service, err := c.Discover(host, providersServiceID) - if err != nil { - return nil, err - } - - p, err := url.Parse(path.Join(provider.TerraformProvider(), "versions")) - if err != nil { - return nil, err - } - - service = service.ResolveReference(p) - - log.Printf("[DEBUG] fetching provider versions from %q", service) - - req, err := retryablehttp.NewRequest("GET", service.String(), nil) - if err != nil { - return nil, err - } - - c.addRequestCreds(host, req.Request) - req.Header.Set(xTerraformVersion, tfVersion) - - resp, err := c.client.Do(req) - if err != nil { - return nil, err - } - defer resp.Body.Close() - - switch resp.StatusCode { - case http.StatusOK: - // OK - case http.StatusNotFound: - return nil, &errProviderNotFound{addr: provider} - default: - return nil, fmt.Errorf("error looking up provider versions: %s", resp.Status) - } - - var versions response.TerraformProviderVersions - - dec := json.NewDecoder(resp.Body) - if err := dec.Decode(&versions); err != nil { - return nil, err - } - - return &versions, nil -} - -// TerraformProviderLocation queries the registry for a provider download metadata -func (c *Client) TerraformProviderLocation(provider *regsrc.TerraformProvider, version string) (*response.TerraformProviderPlatformLocation, error) { - host, err := provider.SvcHost() - if err != nil { - return nil, err - } - - service, err := c.Discover(host, providersServiceID) - if err != nil { - return nil, err - } - - p, err := url.Parse(path.Join( - provider.TerraformProvider(), - version, - "download", - provider.OS, - provider.Arch, - )) - if err != nil { - return nil, err - } - - service = service.ResolveReference(p) - - log.Printf("[DEBUG] fetching provider location from %q", service) - - req, err := retryablehttp.NewRequest("GET", service.String(), nil) - if err != nil { - return nil, err - } - - c.addRequestCreds(host, req.Request) - req.Header.Set(xTerraformVersion, tfVersion) - - resp, err := c.client.Do(req) - if err != nil { - return nil, err - } - defer resp.Body.Close() - - var loc response.TerraformProviderPlatformLocation - - dec := json.NewDecoder(resp.Body) - if err := dec.Decode(&loc); err != nil { - return nil, err - } - - switch resp.StatusCode { - case http.StatusOK, http.StatusNoContent: - // OK - case http.StatusNotFound: - return nil, fmt.Errorf("provider %q version %q not found", provider.TerraformProvider(), version) - default: - // anything else is an error: - return nil, fmt.Errorf("error getting download location for %q: %s", provider.TerraformProvider(), resp.Status) - } - - return &loc, nil -} - // configureDiscoveryRetry configures the number of retries the registry client // will attempt for requests with retryable errors, like 502 status codes func configureDiscoveryRetry() { diff --git a/registry/client_test.go b/registry/client_test.go index 3647c2ccb..ad5270fa1 100644 --- a/registry/client_test.go +++ b/registry/client_test.go @@ -2,7 +2,6 @@ package registry import ( "context" - "fmt" "net/http" "os" "strings" @@ -368,90 +367,3 @@ func TestLookupModuleNetworkError(t *testing.T) { t.Fatal("unexpected error, got:", err) } } - -func TestLookupProviderVersions(t *testing.T) { - server := test.Registry() - defer server.Close() - - client := NewClient(test.Disco(server), nil) - - tests := []struct { - name string - }{ - {"foo"}, - {"bar"}, - } - for _, tt := range tests { - provider := regsrc.NewTerraformProvider(tt.name, "", "") - resp, err := client.TerraformProviderVersions(provider) - if err != nil { - t.Fatal(err) - } - - name := fmt.Sprintf("terraform-providers/%s", tt.name) - if resp.ID != name { - t.Fatalf("expected provider name %q, got %q", name, resp.ID) - } - - if len(resp.Versions) != 2 { - t.Fatal("expected 2 versions, got", len(resp.Versions)) - } - - for _, v := range resp.Versions { - _, err := version.NewVersion(v.Version) - if err != nil { - t.Fatalf("invalid version %#v: %v", v, err) - } - } - } -} - -func TestLookupProviderLocation(t *testing.T) { - server := test.Registry() - defer server.Close() - - client := NewClient(test.Disco(server), nil) - - tests := []struct { - Name string - Version string - Err bool - }{ - { - "foo", - "0.2.3", - false, - }, - { - "bar", - "0.1.1", - false, - }, - { - "baz", - "0.0.0", - true, - }, - } - for _, tt := range tests { - // FIXME: the tests are set up to succeed - os/arch is not being validated at this time - p := regsrc.NewTerraformProvider(tt.Name, "linux", "amd64") - - locationMetadata, err := client.TerraformProviderLocation(p, tt.Version) - if tt.Err { - if err == nil { - t.Fatal("succeeded; want error") - } - return - } else if err != nil { - t.Fatalf("unexpected error: %s", err) - } - - downloadURL := fmt.Sprintf("https://releases.hashicorp.com/terraform-provider-%s/%s/terraform-provider-%s.zip", tt.Name, tt.Version, tt.Name) - - if locationMetadata.DownloadURL != downloadURL { - t.Fatalf("incorrect download URL: expected %q, got %q", downloadURL, locationMetadata.DownloadURL) - } - } - -} diff --git a/registry/errors.go b/registry/errors.go index 3b99b34d8..5ae022fd2 100644 --- a/registry/errors.go +++ b/registry/errors.go @@ -23,22 +23,6 @@ func IsModuleNotFound(err error) bool { return ok } -type errProviderNotFound struct { - addr *regsrc.TerraformProvider -} - -func (e *errProviderNotFound) Error() string { - return fmt.Sprintf("provider %s not found", e.addr) -} - -// IsProviderNotFound returns true only if the given error is a "provider not found" -// error. This allows callers to recognize this particular error condition -// as distinct from operational errors such as poor network connectivity. -func IsProviderNotFound(err error) bool { - _, ok := err.(*errProviderNotFound) - return ok -} - // IsServiceNotProvided returns true only if the given error is a "service not provided" // error. This allows callers to recognize this particular error condition // as distinct from operational errors such as poor network connectivity. diff --git a/registry/regsrc/terraform_provider.go b/registry/regsrc/terraform_provider.go deleted file mode 100644 index 7205d03b8..000000000 --- a/registry/regsrc/terraform_provider.go +++ /dev/null @@ -1,60 +0,0 @@ -package regsrc - -import ( - "fmt" - "runtime" - "strings" - - "github.com/hashicorp/terraform-svchost" -) - -var ( - // DefaultProviderNamespace represents the namespace for canonical - // HashiCorp-controlled providers. - DefaultProviderNamespace = "-" -) - -// TerraformProvider describes a Terraform Registry Provider source. -type TerraformProvider struct { - RawHost *FriendlyHost - RawNamespace string - RawName string - OS string - Arch string -} - -// NewTerraformProvider constructs a new provider source. -func NewTerraformProvider(name, os, arch string) *TerraformProvider { - if os == "" { - os = runtime.GOOS - } - if arch == "" { - arch = runtime.GOARCH - } - - // separate namespace if included - namespace := DefaultProviderNamespace - if names := strings.SplitN(name, "/", 2); len(names) == 2 { - namespace, name = names[0], names[1] - } - p := &TerraformProvider{ - RawHost: PublicRegistryHost, - RawNamespace: namespace, - RawName: name, - OS: os, - Arch: arch, - } - - return p -} - -// Provider returns just the registry ID of the provider -func (p *TerraformProvider) TerraformProvider() string { - return fmt.Sprintf("%s/%s", p.RawNamespace, p.RawName) -} - -// SvcHost returns the svchost.Hostname for this provider. The -// default PublicRegistryHost is returned. -func (p *TerraformProvider) SvcHost() (svchost.Hostname, error) { - return svchost.ForComparison(PublicRegistryHost.Raw) -} diff --git a/registry/regsrc/terraform_provider_test.go b/registry/regsrc/terraform_provider_test.go deleted file mode 100644 index 50ffab073..000000000 --- a/registry/regsrc/terraform_provider_test.go +++ /dev/null @@ -1,48 +0,0 @@ -package regsrc - -import ( - "testing" -) - -func TestNewTerraformProviderNamespace(t *testing.T) { - tests := []struct { - name string - provider string - expectedNamespace string - expectedName string - }{ - { - name: "default", - provider: "null", - expectedNamespace: "-", - expectedName: "null", - }, { - name: "explicit", - provider: "terraform-providers/null", - expectedNamespace: "terraform-providers", - expectedName: "null", - }, { - name: "community", - provider: "community-providers/null", - expectedNamespace: "community-providers", - expectedName: "null", - }, - } - - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - actual := NewTerraformProvider(tt.provider, "", "") - - if actual == nil { - t.Fatal("NewTerraformProvider() unexpectedly returned nil provider") - } - - if v := actual.RawNamespace; v != tt.expectedNamespace { - t.Fatalf("RawNamespace = %v, wanted %v", v, tt.expectedNamespace) - } - if v := actual.RawName; v != tt.expectedName { - t.Fatalf("RawName = %v, wanted %v", v, tt.expectedName) - } - }) - } -} diff --git a/registry/response/provider.go b/registry/response/provider.go deleted file mode 100644 index 5e8bae354..000000000 --- a/registry/response/provider.go +++ /dev/null @@ -1,36 +0,0 @@ -package response - -import ( - "time" -) - -// Provider is the response structure with the data for a single provider -// version. This is just the metadata. A full provider response will be -// ProviderDetail. -type Provider struct { - ID string `json:"id"` - - //--------------------------------------------------------------- - // Metadata about the overall provider. - - Owner string `json:"owner"` - Namespace string `json:"namespace"` - Name string `json:"name"` - Version string `json:"version"` - Description string `json:"description"` - Source string `json:"source"` - PublishedAt time.Time `json:"published_at"` - Downloads int `json:"downloads"` -} - -// ProviderDetail represents a Provider with full detail. -type ProviderDetail struct { - Provider - - //--------------------------------------------------------------- - // The fields below are only set when requesting this specific - // module. They are available to easily know all available versions - // without multiple API calls. - - Versions []string `json:"versions"` // All versions -} diff --git a/registry/response/provider_list.go b/registry/response/provider_list.go deleted file mode 100644 index 1dc7d237f..000000000 --- a/registry/response/provider_list.go +++ /dev/null @@ -1,7 +0,0 @@ -package response - -// ProviderList is the response structure for a pageable list of providers. -type ProviderList struct { - Meta PaginationMeta `json:"meta"` - Providers []*Provider `json:"providers"` -} diff --git a/registry/response/terraform_provider.go b/registry/response/terraform_provider.go deleted file mode 100644 index c2c333b0d..000000000 --- a/registry/response/terraform_provider.go +++ /dev/null @@ -1,95 +0,0 @@ -package response - -import ( - "sort" - "strings" - - version "github.com/hashicorp/go-version" -) - -// TerraformProvider is the response structure for all required information for -// Terraform to choose a download URL. It must include all versions and all -// platforms for Terraform to perform version and os/arch constraint matching -// locally. -type TerraformProvider struct { - ID string `json:"id"` - - Versions []*TerraformProviderVersion `json:"versions"` -} - -// TerraformProviderVersion is the Terraform-specific response structure for a -// provider version. -type TerraformProviderVersion struct { - Version string `json:"version"` - Protocols []string `json:"protocols"` - - Platforms []*TerraformProviderPlatform `json:"platforms"` -} - -// TerraformProviderVersions is the Terraform-specific response structure for an -// array of provider versions -type TerraformProviderVersions struct { - ID string `json:"id"` - Versions []*TerraformProviderVersion `json:"versions"` - Warnings []string `json:"warnings"` -} - -// TerraformProviderPlatform is the Terraform-specific response structure for a -// provider platform. -type TerraformProviderPlatform struct { - OS string `json:"os"` - Arch string `json:"arch"` -} - -// TerraformProviderPlatformLocation is the Terraform-specific response -// structure for a provider platform with all details required to perform a -// download. -type TerraformProviderPlatformLocation struct { - Protocols []string `json:"protocols"` - OS string `json:"os"` - Arch string `json:"arch"` - Filename string `json:"filename"` - DownloadURL string `json:"download_url"` - ShasumsURL string `json:"shasums_url"` - ShasumsSignatureURL string `json:"shasums_signature_url"` - Shasum string `json:"shasum"` - - SigningKeys SigningKeyList `json:"signing_keys"` -} - -// SigningKeyList is the response structure for a list of signing keys. -type SigningKeyList struct { - GPGKeys []*GPGKey `json:"gpg_public_keys"` -} - -// GPGKey is the response structure for a GPG key. -type GPGKey struct { - ASCIIArmor string `json:"ascii_armor"` - Source string `json:"source"` - SourceURL *string `json:"source_url"` -} - -// Collection type for TerraformProviderVersion -type ProviderVersionCollection []*TerraformProviderVersion - -// GPGASCIIArmor returns an ASCII-armor-formatted string for all of the gpg -// keys in the response. -func (signingKeys *SigningKeyList) GPGASCIIArmor() string { - keys := []string{} - - for _, gpgKey := range signingKeys.GPGKeys { - keys = append(keys, gpgKey.ASCIIArmor) - } - - return strings.Join(keys, "\n") -} - -// Sort sorts versions from newest to oldest. -func (v ProviderVersionCollection) Sort() { - sort.Slice(v, func(i, j int) bool { - versionA, _ := version.NewVersion(v[i].Version) - versionB, _ := version.NewVersion(v[j].Version) - - return versionA.GreaterThan(versionB) - }) -} diff --git a/registry/response/terraform_provider_test.go b/registry/response/terraform_provider_test.go deleted file mode 100644 index 09a976b95..000000000 --- a/registry/response/terraform_provider_test.go +++ /dev/null @@ -1,52 +0,0 @@ -package response - -import ( - "fmt" - "testing" -) - -var ( - testGPGKeyOne = &GPGKey{ - ASCIIArmor: "---\none\n---", - } - testGPGKeyTwo = &GPGKey{ - ASCIIArmor: "---\ntwo\n---", - } -) - -func TestSigningKeyList_GPGASCIIArmor(t *testing.T) { - var tests = []struct { - name string - gpgKeys []*GPGKey - expected string - }{ - { - name: "no keys", - gpgKeys: []*GPGKey{}, - expected: "", - }, - { - name: "one key", - gpgKeys: []*GPGKey{testGPGKeyOne}, - expected: testGPGKeyOne.ASCIIArmor, - }, - { - name: "two keys", - gpgKeys: []*GPGKey{testGPGKeyOne, testGPGKeyTwo}, - expected: fmt.Sprintf("%s\n%s", - testGPGKeyOne.ASCIIArmor, testGPGKeyTwo.ASCIIArmor), - }, - } - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - signingKeys := &SigningKeyList{ - GPGKeys: tt.gpgKeys, - } - actual := signingKeys.GPGASCIIArmor() - - if actual != tt.expected { - t.Errorf("expected %s, got %s", tt.expected, actual) - } - }) - } -} diff --git a/registry/test/mock_registry.go b/registry/test/mock_registry.go index 68af193d7..c6a8ef70d 100644 --- a/registry/test/mock_registry.go +++ b/registry/test/mock_registry.go @@ -256,102 +256,6 @@ func mockRegHandler() http.Handler { })), ) - providerDownload := func(w http.ResponseWriter, r *http.Request) { - p := strings.TrimLeft(r.URL.Path, "/") - v := strings.Split(string(p), "/") - - if len(v) != 6 { - w.WriteHeader(http.StatusBadRequest) - return - } - - name := fmt.Sprintf("%s/%s", v[0], v[1]) - - providers, ok := testProviders[name] - if !ok { - http.NotFound(w, r) - return - } - - // for this test / moment we will only return the one provider - loc := response.TerraformProviderPlatformLocation{ - DownloadURL: providers[0].url, - } - - js, err := json.Marshal(loc) - if err != nil { - http.Error(w, err.Error(), http.StatusInternalServerError) - return - } - - w.Header().Set("Content-Type", "application/json") - w.Write(js) - - } - - providerVersions := func(w http.ResponseWriter, r *http.Request) { - p := strings.TrimLeft(r.URL.Path, "/") - re := regexp.MustCompile(`^([-a-z]+/\w+)/versions$`) - matches := re.FindStringSubmatch(p) - - if len(matches) != 2 { - w.WriteHeader(http.StatusBadRequest) - return - } - - // check for auth - if strings.Contains(matches[1], "private/") { - if !strings.Contains(r.Header.Get("Authorization"), testCred) { - http.Error(w, "", http.StatusForbidden) - } - } - - name := providerAlias(fmt.Sprintf("%s", matches[1])) - versions, ok := testProviders[name] - if !ok { - http.NotFound(w, r) - return - } - - // only adding the single requested provider for now - // this is the minimal that any registry is expected to support - pvs := &response.TerraformProviderVersions{ - ID: name, - } - - for _, v := range versions { - pv := &response.TerraformProviderVersion{ - Version: v.version, - } - pvs.Versions = append(pvs.Versions, pv) - } - - js, err := json.Marshal(pvs) - if err != nil { - http.Error(w, err.Error(), http.StatusInternalServerError) - return - } - - w.Header().Set("Content-Type", "application/json") - w.Write(js) - } - - mux.Handle("/v1/providers/", - http.StripPrefix("/v1/providers/", http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - if strings.Contains(r.URL.Path, "/download") { - providerDownload(w, r) - return - } - - if strings.HasSuffix(r.URL.Path, "/versions") { - providerVersions(w, r) - return - } - - http.NotFound(w, r) - })), - ) - mux.HandleFunc("/.well-known/terraform.json", func(w http.ResponseWriter, r *http.Request) { w.Header().Set("Content-Type", "application/json") io.WriteString(w, `{"modules.v1":"http://localhost/v1/modules/", "providers.v1":"http://localhost/v1/providers/"}`) diff --git a/terraform/ui_input_prefix_test.go b/terraform/ui_input_prefix_test.go index c4b294773..dff42c39c 100644 --- a/terraform/ui_input_prefix_test.go +++ b/terraform/ui_input_prefix_test.go @@ -9,7 +9,7 @@ func TestPrefixUIInput_impl(t *testing.T) { var _ UIInput = new(PrefixUIInput) } -func testPrefixUIInput(t *testing.T) { +func TestPrefixUIInput(t *testing.T) { input := new(MockUIInput) prefix := &PrefixUIInput{ IdPrefix: "foo", diff --git a/terraform/user_agent.go b/terraform/user_agent.go deleted file mode 100644 index 97f1ec1f6..000000000 --- a/terraform/user_agent.go +++ /dev/null @@ -1,12 +0,0 @@ -package terraform - -import ( - "github.com/hashicorp/terraform/httpclient" -) - -// Generate a UserAgent string -// -// Deprecated: Use httpclient.UserAgent(version) instead -func UserAgentString() string { - return httpclient.UserAgentString() -}