Skip to content

Commit ef82357

Browse files
committed
Allow reattached providers to be used during init for PSS
1 parent 78e2657 commit ef82357

File tree

1 file changed

+49
-1
lines changed

1 file changed

+49
-1
lines changed

internal/command/meta_backend.go

Lines changed: 49 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ import (
1414
"fmt"
1515
"log"
1616
"maps"
17+
"os"
1718
"path/filepath"
1819
"slices"
1920
"strconv"
@@ -1698,6 +1699,29 @@ func (m *Meta) stateStore_C_s(c *configs.StateStore, stateStoreHash int, provide
16981699
// We must record a value into the backend state file, and we cannot include a value that changes (e.g. the Terraform core binary version) as migration
16991700
// is impossible with builtin providers.
17001701
// So, we use an arbitrary stand-in version.
1702+
standInVersion, err := version.NewVersion("0.0.1")
1703+
if err != nil {
1704+
diags = diags.Append(fmt.Errorf("Error when creating a backend state file. This is a bug in Terraform and should be reported: %w",
1705+
err))
1706+
return nil, diags
1707+
}
1708+
pVersion = standInVersion
1709+
} else {
1710+
isReattached, err := isProviderReattached(c.ProviderAddr)
1711+
if err != nil {
1712+
diags = diags.Append(fmt.Errorf("Error determining if the state storage provider is reattached or not. This is a bug in Terraform and should be reported: %w",
1713+
err))
1714+
return nil, diags
1715+
}
1716+
if isReattached {
1717+
// If the provider is unmanaged then it won't be in the locks.
1718+
// If there are no locks then there's no version information to for us to access and use when creating the backend state file.
1719+
// So, we use an arbitrary stand-in version.
1720+
diags = diags.Append(&hcl.Diagnostic{
1721+
Severity: hcl.DiagWarning,
1722+
Summary: "State storage provider is not managed by Terraform",
1723+
Detail: "Terraform is using a provider supplied via TF_REATTACH_PROVIDERS for initializing state storage. This will affect Terraform's ability to detect when state migrations are required.",
1724+
})
17011725
standInVersion, err := version.NewVersion("0.0.1")
17021726
if err != nil {
17031727
diags = diags.Append(fmt.Errorf("Error when creating a backend state file. This is a bug in Terraform and should be reported: %w",
@@ -1716,7 +1740,7 @@ func (m *Meta) stateStore_C_s(c *configs.StateStore, stateStoreHash int, provide
17161740
c.Type))
17171741
return nil, diags
17181742
}
1719-
var err error
1743+
var err error
17201744
pVersion, err = providerreqs.GoVersionFromVersion(pLock.Version())
17211745
if err != nil {
17221746
diags = diags.Append(fmt.Errorf("Failed obtain the in-use version of provider %s (%q) when recording backend state for state store %q. This is a bug in Terraform and should be reported: %w",
@@ -1725,6 +1749,7 @@ func (m *Meta) stateStore_C_s(c *configs.StateStore, stateStoreHash int, provide
17251749
c.Type,
17261750
err))
17271751
return nil, diags
1752+
}
17281753
}
17291754
}
17301755
s.StateStore = &workdir.StateStoreConfigState{
@@ -1805,6 +1830,29 @@ func (m *Meta) stateStore_C_s(c *configs.StateStore, stateStoreHash int, provide
18051830
return b, diags
18061831
}
18071832

1833+
// isProviderReattached determines if a given provider is being supplied to Terraform via the TF_REATTACH_PROVIDERS
1834+
// environment variable.
1835+
func isProviderReattached(provider addrs.Provider) (bool, error) {
1836+
in := os.Getenv("TF_REATTACH_PROVIDERS")
1837+
if in != "" {
1838+
var m map[string]any
1839+
err := json.Unmarshal([]byte(in), &m)
1840+
if err != nil {
1841+
return false, fmt.Errorf("Invalid format for TF_REATTACH_PROVIDERS: %w", err)
1842+
}
1843+
for p, _ := range m {
1844+
a, diags := addrs.ParseProviderSourceString(p)
1845+
if diags.HasErrors() {
1846+
return false, fmt.Errorf("Error parsing %q as a provider address: %w", a, diags.Err())
1847+
}
1848+
if a.Equals(provider) {
1849+
return true, nil
1850+
}
1851+
}
1852+
}
1853+
return false, nil
1854+
}
1855+
18081856
// createDefaultWorkspace receives a backend made using a pluggable state store, and details about that store's config,
18091857
// and persists an empty state file in the default workspace. By creating this artifact we ensure that the default
18101858
// workspace is created and usable by Terraform in later operations.

0 commit comments

Comments
 (0)