// Copyright (c) HashiCorp, Inc.
// SPDX-License-Identifier: MPL-2.0

package command

import (
	"bytes"
	"errors"
	"fmt"
	"log"
	"os"
	"os/exec"
	"strings"

	plugin "github.com/hashicorp/go-plugin"

	"github.com/hashicorp/terraform/internal/addrs"
	terraformProvider "github.com/hashicorp/terraform/internal/builtin/providers/terraform"
	"github.com/hashicorp/terraform/internal/getproviders"
	"github.com/hashicorp/terraform/internal/logging"
	"github.com/hashicorp/terraform/internal/moduletest"
	tfplugin "github.com/hashicorp/terraform/internal/plugin"
	tfplugin6 "github.com/hashicorp/terraform/internal/plugin6"
	"github.com/hashicorp/terraform/internal/providercache"
	"github.com/hashicorp/terraform/internal/providers"
	"github.com/hashicorp/terraform/internal/tfdiags"
)

// The TF_DISABLE_PLUGIN_TLS environment variable is intended only for use by
// the plugin SDK test framework, to reduce startup overhead when rapidly
// launching and killing lots of instances of the same provider.
//
// This is not intended to be set by end-users.
var enableProviderAutoMTLS = os.Getenv("TF_DISABLE_PLUGIN_TLS") == ""

// providerInstaller returns an object that knows how to install providers and
// how to recover the selections from a prior installation process.
//
// The resulting provider installer is constructed from the results of
// the other methods providerLocalCacheDir, providerGlobalCacheDir, and
// providerInstallSource.
//
// Only one object returned from this method should be live at any time,
// because objects inside contain caches that must be maintained properly.
// Because this method wraps a result from providerLocalCacheDir, that
// limitation applies also to results from that method.
func (m *Meta) providerInstaller() *providercache.Installer {
	return m.providerInstallerCustomSource(m.providerInstallSource())
}

// providerInstallerCustomSource is a variant of providerInstaller that
// allows the caller to specify a different installation source than the one
// that would naturally be selected.
//
// The result of this method has the same dependencies and constraints as
// providerInstaller.
//
// The result of providerInstallerCustomSource differs from
// providerInstaller only in how it determines package installation locations
// during EnsureProviderVersions. A caller that doesn't call
// EnsureProviderVersions (anything other than "terraform init") can safely
// just use the providerInstaller method unconditionally.
func (m *Meta) providerInstallerCustomSource(source getproviders.Source) *providercache.Installer {
	targetDir := m.providerLocalCacheDir()
	globalCacheDir := m.providerGlobalCacheDir()
	inst := providercache.NewInstaller(targetDir, source)
	if globalCacheDir != nil {
		inst.SetGlobalCacheDir(globalCacheDir)
		inst.SetGlobalCacheDirMayBreakDependencyLockFile(m.PluginCacheMayBreakDependencyLockFile)
	}
	var builtinProviderTypes []string
	for ty := range m.internalProviders() {
		builtinProviderTypes = append(builtinProviderTypes, ty)
	}
	inst.SetBuiltInProviderTypes(builtinProviderTypes)
	unmanagedProviderTypes := make(map[addrs.Provider]struct{}, len(m.UnmanagedProviders))
	for ty := range m.UnmanagedProviders {
		unmanagedProviderTypes[ty] = struct{}{}
	}
	inst.SetUnmanagedProviderTypes(unmanagedProviderTypes)
	return inst
}

// providerCustomLocalDirectorySource produces a provider source that consults
// only the given local filesystem directories for plugins to install.
//
// This is used to implement the -plugin-dir option for "terraform init", where
// the result of this method is used instead of what would've been returned
// from m.providerInstallSource.
//
// If the given list of directories is empty then the resulting source will
// have no providers available for installation at all.
func (m *Meta) providerCustomLocalDirectorySource(dirs []string) getproviders.Source {
	var ret getproviders.MultiSource
	for _, dir := range dirs {
		ret = append(ret, getproviders.MultiSourceSelector{
			Source: getproviders.NewFilesystemMirrorSource(dir),
		})
	}
	return ret
}

// providerLocalCacheDir returns an object representing the
// configuration-specific local cache directory. This is the
// only location consulted for provider plugin packages for Terraform
// operations other than provider installation.
//
// Only the provider installer (in "terraform init") is permitted to make
// modifications to this cache directory. All other commands must treat it
// as read-only.
//
// Only one object returned from this method should be live at any time,
// because objects inside contain caches that must be maintained properly.
func (m *Meta) providerLocalCacheDir() *providercache.Dir {
	m.fixupMissingWorkingDir()
	dir := m.WorkingDir.ProviderLocalCacheDir()
	return providercache.NewDir(dir)
}

// providerGlobalCacheDir returns an object representing the shared global
// provider cache directory, used as a read-through cache when installing
// new provider plugin packages.
//
// This function may return nil, in which case there is no global cache
// configured and new packages should be downloaded directly into individual
// configuration-specific cache directories.
//
// Only one object returned from this method should be live at any time,
// because objects inside contain caches that must be maintained properly.
func (m *Meta) providerGlobalCacheDir() *providercache.Dir {
	dir := m.PluginCacheDir
	if dir == "" {
		return nil // cache disabled
	}
	return providercache.NewDir(dir)
}

// providerInstallSource returns an object that knows how to consult one or
// more external sources to determine the availability of and package
// locations for versions of Terraform providers that are available for
// automatic installation.
//
// This returns the standard provider install source that consults a number
// of directories selected either automatically or via the CLI configuration.
// Users may choose to override this during a "terraform init" command by
// specifying one or more -plugin-dir options, in which case the installation
// process will construct its own source consulting only those directories
// and use that instead.
func (m *Meta) providerInstallSource() getproviders.Source {
	// A provider source should always be provided in normal use, but our
	// unit tests might not always populate Meta fully and so we'll be robust
	// by returning a non-nil source that just always answers that no plugins
	// are available.
	if m.ProviderSource == nil {
		// A multi-source with no underlying sources is effectively an
		// always-empty source.
		return getproviders.MultiSource(nil)
	}
	return m.ProviderSource
}

// providerDevOverrideInitWarnings returns a diagnostics that contains at
// least one warning if and only if there is at least one provider development
// override in effect. If not, the result is always empty. The result never
// contains error diagnostics.
//
// The init command can use this to include a warning that the results
// may differ from what's expected due to the development overrides. For
// other commands, providerDevOverrideRuntimeWarnings should be used.
func (m *Meta) providerDevOverrideInitWarnings() tfdiags.Diagnostics {
	if len(m.ProviderDevOverrides) == 0 {
		return nil
	}
	var detailMsg strings.Builder
	detailMsg.WriteString("The following provider development overrides are set in the CLI configuration:\n")
	for addr, path := range m.ProviderDevOverrides {
		detailMsg.WriteString(fmt.Sprintf(" - %s in %s\n", addr.ForDisplay(), path))
	}
	detailMsg.WriteString("\nSkip terraform init when using provider development overrides. It is not necessary and may error unexpectedly.")
	return tfdiags.Diagnostics{
		tfdiags.Sourceless(
			tfdiags.Warning,
			"Provider development overrides are in effect",
			detailMsg.String(),
		),
	}
}

// providerDevOverrideRuntimeWarnings returns a diagnostics that contains at
// least one warning if and only if there is at least one provider development
// override in effect. If not, the result is always empty. The result never
// contains error diagnostics.
//
// Certain commands can use this to include a warning that their results
// may differ from what's expected due to the development overrides. It's
// not necessary to bother the user with this warning on every command, but
// it's helpful to return it on commands that have externally-visible side
// effects and on commands that are used to verify conformance to schemas.
//
// See providerDevOverrideInitWarnings for warnings specific to the init
// command.
func (m *Meta) providerDevOverrideRuntimeWarnings() tfdiags.Diagnostics {
	if len(m.ProviderDevOverrides) == 0 {
		return nil
	}
	var detailMsg strings.Builder
	detailMsg.WriteString("The following provider development overrides are set in the CLI configuration:\n")
	for addr, path := range m.ProviderDevOverrides {
		detailMsg.WriteString(fmt.Sprintf(" - %s in %s\n", addr.ForDisplay(), path))
	}
	detailMsg.WriteString("\nThe behavior may therefore not match any released version of the provider and applying changes may cause the state to become incompatible with published releases.")
	return tfdiags.Diagnostics{
		tfdiags.Sourceless(
			tfdiags.Warning,
			"Provider development overrides are in effect",
			detailMsg.String(),
		),
	}
}

// providerFactories uses the selections made previously by an installer in
// the local cache directory (m.providerLocalCacheDir) to produce a map
// from provider addresses to factory functions to create instances of
// those providers.
//
// providerFactories will return an error if the installer's selections cannot
// be honored with what is currently in the cache, such as if a selected
// package has been removed from the cache or if the contents of a selected
// package have been modified outside of the installer. If it returns an error,
// the returned map may be incomplete or invalid, but will be as complete
// as possible given the cause of the error.
func (m *Meta) providerFactories() (map[addrs.Provider]providers.Factory, error) {
	locks, diags := m.lockedDependencies()
	if diags.HasErrors() {
		return nil, fmt.Errorf("failed to read dependency lock file: %s", diags.Err())
	}

	// We'll always run through all of our providers, even if one of them
	// encounters an error, so that we can potentially report multiple errors
	// where appropriate and so that callers can potentially make use of the
	// partial result we return if e.g. they want to enumerate which providers
	// are available, or call into one of the providers that didn't fail.
	errs := make(map[addrs.Provider]error)

	// For the providers from the lock file, we expect them to be already
	// available in the provider cache because "terraform init" should already
	// have put them there.
	providerLocks := locks.AllProviders()
	cacheDir := m.providerLocalCacheDir()

	// The internal providers are _always_ available, even if the configuration
	// doesn't request them, because they don't need any special installation
	// and they'll just be ignored if not used.
	internalFactories := m.internalProviders()

	// We have two different special cases aimed at provider development
	// use-cases, which are not for "production" use:
	// - The CLI config can specify that a particular provider should always
	// use a plugin from a particular local directory, ignoring anything the
	// lock file or cache directory might have to say about it. This is useful
	// for manual testing of local development builds.
	// - The Terraform SDK test harness (and possibly other callers in future)
	// can ask that we use its own already-started provider servers, which we
	// call "unmanaged" because Terraform isn't responsible for starting
	// and stopping them. This is intended for automated testing where a
	// calling harness is responsible both for starting the provider server
	// and orchestrating one or more non-interactive Terraform runs that then
	// exercise it.
	// Unmanaged providers take precedence over overridden providers because
	// overrides are typically a "session-level" setting while unmanaged
	// providers are typically scoped to a single unattended command.
	devOverrideProviders := m.ProviderDevOverrides
	unmanagedProviders := m.UnmanagedProviders

	factories := make(map[addrs.Provider]providers.Factory, len(providerLocks)+len(internalFactories)+len(unmanagedProviders))
	for name, factory := range internalFactories {
		factories[addrs.NewBuiltInProvider(name)] = factory
	}
	for provider, lock := range providerLocks {
		reportError := func(thisErr error) {
			errs[provider] = thisErr
			// We'll populate a provider factory that just echoes our error
			// again if called, which allows us to still report a helpful
			// error even if it gets detected downstream somewhere from the
			// caller using our partial result.
			factories[provider] = providerFactoryError(thisErr)
		}

		if locks.ProviderIsOverridden(provider) {
			// Overridden providers we'll handle with the other separate
			// loops below, for dev overrides etc.
			continue
		}

		version := lock.Version()
		cached := cacheDir.ProviderVersion(provider, version)
		if cached == nil {
			reportError(fmt.Errorf(
				"there is no package for %s %s cached in %s",
				provider, version, cacheDir.BasePath(),
			))
			continue
		}
		// The cached package must match one of the checksums recorded in
		// the lock file, if any.
		if allowedHashes := lock.PreferredHashes(); len(allowedHashes) != 0 {
			matched, err := cached.MatchesAnyHash(allowedHashes)
			if err != nil {
				reportError(fmt.Errorf(
					"failed to verify checksum of %s %s package cached in in %s: %s",
					provider, version, cacheDir.BasePath(), err,
				))
				continue
			}
			if !matched {
				reportError(fmt.Errorf(
					"the cached package for %s %s (in %s) does not match any of the checksums recorded in the dependency lock file",
					provider, version, cacheDir.BasePath(),
				))
				continue
			}
		}
		factories[provider] = providerFactory(cached)
	}
	for provider, localDir := range devOverrideProviders {
		factories[provider] = devOverrideProviderFactory(provider, localDir)
	}
	for provider, reattach := range unmanagedProviders {
		factories[provider] = unmanagedProviderFactory(provider, reattach)
	}

	var err error
	if len(errs) > 0 {
		err = providerPluginErrors(errs)
	}
	return factories, err
}

func (m *Meta) internalProviders() map[string]providers.Factory {
	return map[string]providers.Factory{
		"terraform": func() (providers.Interface, error) {
			return terraformProvider.NewProvider(), nil
		},
		"test": func() (providers.Interface, error) {
			return moduletest.NewProvider(), nil
		},
	}
}

// providerFactory produces a provider factory that runs up the executable
// file in the given cache package and uses go-plugin to implement
// providers.Interface against it.
func providerFactory(meta *providercache.CachedProvider) providers.Factory {
	return func() (providers.Interface, error) {
		execFile, err := meta.ExecutableFile()
		if err != nil {
			return nil, err
		}

		config := &plugin.ClientConfig{
			HandshakeConfig:  tfplugin.Handshake,
			Logger:           logging.NewProviderLogger(""),
			AllowedProtocols: []plugin.Protocol{plugin.ProtocolGRPC},
			Managed:          true,
			Cmd:              exec.Command(execFile),
			AutoMTLS:         enableProviderAutoMTLS,
			VersionedPlugins: tfplugin.VersionedPlugins,
			SyncStdout:       logging.PluginOutputMonitor(fmt.Sprintf("%s:stdout", meta.Provider)),
			SyncStderr:       logging.PluginOutputMonitor(fmt.Sprintf("%s:stderr", meta.Provider)),
		}

		client := plugin.NewClient(config)
		rpcClient, err := client.Client()
		if err != nil {
			return nil, err
		}

		raw, err := rpcClient.Dispense(tfplugin.ProviderPluginName)
		if err != nil {
			return nil, err
		}

		// store the client so that the plugin can kill the child process
		protoVer := client.NegotiatedVersion()
		switch protoVer {
		case 5:
			p := raw.(*tfplugin.GRPCProvider)
			p.PluginClient = client
			return p, nil
		case 6:
			p := raw.(*tfplugin6.GRPCProvider)
			p.PluginClient = client
			return p, nil
		default:
			panic("unsupported protocol version")
		}
	}
}

func devOverrideProviderFactory(provider addrs.Provider, localDir getproviders.PackageLocalDir) providers.Factory {
	// A dev override is essentially a synthetic cache entry for our purposes
	// here, so that's how we'll construct it. The providerFactory function
	// doesn't actually care about the version, so we can leave it
	// unspecified: overridden providers are not explicitly versioned.
	log.Printf("[DEBUG] Provider %s is overridden to load from %s", provider, localDir)
	return providerFactory(&providercache.CachedProvider{
		Provider:   provider,
		Version:    getproviders.UnspecifiedVersion,
		PackageDir: string(localDir),
	})
}

// unmanagedProviderFactory produces a provider factory that uses the passed
// reattach information to connect to go-plugin processes that are already
// running, and implements providers.Interface against it.
func unmanagedProviderFactory(provider addrs.Provider, reattach *plugin.ReattachConfig) providers.Factory {
	return func() (providers.Interface, error) {
		config := &plugin.ClientConfig{
			HandshakeConfig:  tfplugin.Handshake,
			Logger:           logging.NewProviderLogger("unmanaged."),
			AllowedProtocols: []plugin.Protocol{plugin.ProtocolGRPC},
			Managed:          false,
			Reattach:         reattach,
			SyncStdout:       logging.PluginOutputMonitor(fmt.Sprintf("%s:stdout", provider)),
			SyncStderr:       logging.PluginOutputMonitor(fmt.Sprintf("%s:stderr", provider)),
		}

		if reattach.ProtocolVersion == 0 {
			// As of the 0.15 release, sdk.v2 doesn't include the protocol
			// version in the ReattachConfig (only recently added to
			// go-plugin), so client.NegotiatedVersion() always returns 0. We
			// assume that an unmanaged provider reporting protocol version 0 is
			// actually using proto v5 for backwards compatibility.
			if defaultPlugins, ok := tfplugin.VersionedPlugins[5]; ok {
				config.Plugins = defaultPlugins
			} else {
				return nil, errors.New("no supported plugins for protocol 0")
			}
		} else if plugins, ok := tfplugin.VersionedPlugins[reattach.ProtocolVersion]; !ok {
			return nil, fmt.Errorf("no supported plugins for protocol %d", reattach.ProtocolVersion)
		} else {
			config.Plugins = plugins
		}

		client := plugin.NewClient(config)
		rpcClient, err := client.Client()
		if err != nil {
			return nil, err
		}

		raw, err := rpcClient.Dispense(tfplugin.ProviderPluginName)
		if err != nil {
			return nil, err
		}

		// store the client so that the plugin can kill the child process
		protoVer := client.NegotiatedVersion()
		switch protoVer {
		case 0, 5:
			// As of the 0.15 release, sdk.v2 doesn't include the protocol
			// version in the ReattachConfig (only recently added to
			// go-plugin), so client.NegotiatedVersion() always returns 0. We
			// assume that an unmanaged provider reporting protocol version 0 is
			// actually using proto v5 for backwards compatibility.
			p := raw.(*tfplugin.GRPCProvider)
			p.PluginClient = client
			return p, nil
		case 6:
			p := raw.(*tfplugin6.GRPCProvider)
			p.PluginClient = client
			return p, nil
		default:
			return nil, fmt.Errorf("unsupported protocol version %d", protoVer)
		}
	}
}

// providerFactoryError is a stub providers.Factory that returns an error
// when called. It's used to allow providerFactories to still produce a
// factory for each available provider in an error case, for situations
// where the caller can do something useful with that partial result.
func providerFactoryError(err error) providers.Factory {
	return func() (providers.Interface, error) {
		return nil, err
	}
}

// providerPluginErrors is an error implementation we can return from
// Meta.providerFactories to capture potentially multiple errors about the
// locally-cached plugins (or lack thereof) for particular external providers.
//
// Some functions closer to the UI layer can sniff for this error type in order
// to return a more helpful error message.
type providerPluginErrors map[addrs.Provider]error

func (errs providerPluginErrors) Error() string {
	if len(errs) == 1 {
		for addr, err := range errs {
			return fmt.Sprintf("%s: %s", addr, err)
		}
	}
	var buf bytes.Buffer
	fmt.Fprintf(&buf, "missing or corrupted provider plugins:")
	for addr, err := range errs {
		fmt.Fprintf(&buf, "\n  - %s: %s", addr, err)
	}
	return buf.String()
}
