terraform-bundle tool for bundling Terraform with providers
Normally "terraform init" will download and install the plugins necessary
to work with a particular configuration, but sometimes Terraform is
deployed in a network that, for one reason or another, cannot access the
official plugin repository for automatic download.
terraform-bundle provides an alternative method, allowing the
auto-download process to be run out-of-band on a separate machine that
_does_ have access to the repository. The result is a zip file that can
be extracted onto the target system to install both the desired
Terraform version and a selection of providers, thus avoiding the need
for on-the-fly plugin installation.
This is provided as a separate tool from Terraform because it is not
something that most users will need. In the rare case where this is
needed, we will for the moment assume that users are able to build this
tool themselves. We may later release it in a pre-built form, if it proves
to be generally useful.
It uses the same API from the plugin/discovery package is is used by the
auto-install behavior in "terraform init", so plugin versions are resolved
in the same way. However, it's expected that several different Terraform
configurations will run from the same bundle, so this tool allows the
bundle to include potentially many versions of the same provider and thus
allows each Terraform configuration to select from the available versions
in the bundle, avoiding the need to upgrade all configurations to new
provider versions in lockstep.
2017-07-05 18:44:50 +02:00
|
|
|
package main
|
|
|
|
|
|
|
|
import (
|
|
|
|
"archive/zip"
|
|
|
|
"fmt"
|
|
|
|
"io/ioutil"
|
|
|
|
"os"
|
|
|
|
"path/filepath"
|
|
|
|
"runtime"
|
|
|
|
"time"
|
|
|
|
|
|
|
|
"flag"
|
|
|
|
|
|
|
|
"io"
|
|
|
|
|
|
|
|
getter "github.com/hashicorp/go-getter"
|
2018-03-17 00:28:58 +01:00
|
|
|
discovery "github.com/hashicorp/terraform/plugin/discovery"
|
terraform-bundle tool for bundling Terraform with providers
Normally "terraform init" will download and install the plugins necessary
to work with a particular configuration, but sometimes Terraform is
deployed in a network that, for one reason or another, cannot access the
official plugin repository for automatic download.
terraform-bundle provides an alternative method, allowing the
auto-download process to be run out-of-band on a separate machine that
_does_ have access to the repository. The result is a zip file that can
be extracted onto the target system to install both the desired
Terraform version and a selection of providers, thus avoiding the need
for on-the-fly plugin installation.
This is provided as a separate tool from Terraform because it is not
something that most users will need. In the rare case where this is
needed, we will for the moment assume that users are able to build this
tool themselves. We may later release it in a pre-built form, if it proves
to be generally useful.
It uses the same API from the plugin/discovery package is is used by the
auto-install behavior in "terraform init", so plugin versions are resolved
in the same way. However, it's expected that several different Terraform
configurations will run from the same bundle, so this tool allows the
bundle to include potentially many versions of the same provider and thus
allows each Terraform configuration to select from the available versions
in the bundle, avoiding the need to upgrade all configurations to new
provider versions in lockstep.
2017-07-05 18:44:50 +02:00
|
|
|
"github.com/mitchellh/cli"
|
|
|
|
)
|
|
|
|
|
2018-08-09 00:04:51 +02:00
|
|
|
var releaseHost = "https://releases.hashicorp.com"
|
|
|
|
|
terraform-bundle tool for bundling Terraform with providers
Normally "terraform init" will download and install the plugins necessary
to work with a particular configuration, but sometimes Terraform is
deployed in a network that, for one reason or another, cannot access the
official plugin repository for automatic download.
terraform-bundle provides an alternative method, allowing the
auto-download process to be run out-of-band on a separate machine that
_does_ have access to the repository. The result is a zip file that can
be extracted onto the target system to install both the desired
Terraform version and a selection of providers, thus avoiding the need
for on-the-fly plugin installation.
This is provided as a separate tool from Terraform because it is not
something that most users will need. In the rare case where this is
needed, we will for the moment assume that users are able to build this
tool themselves. We may later release it in a pre-built form, if it proves
to be generally useful.
It uses the same API from the plugin/discovery package is is used by the
auto-install behavior in "terraform init", so plugin versions are resolved
in the same way. However, it's expected that several different Terraform
configurations will run from the same bundle, so this tool allows the
bundle to include potentially many versions of the same provider and thus
allows each Terraform configuration to select from the available versions
in the bundle, avoiding the need to upgrade all configurations to new
provider versions in lockstep.
2017-07-05 18:44:50 +02:00
|
|
|
type PackageCommand struct {
|
|
|
|
ui cli.Ui
|
|
|
|
}
|
|
|
|
|
2018-03-17 00:28:58 +01:00
|
|
|
// shameless stackoverflow copy + pasta https://stackoverflow.com/questions/21060945/simple-way-to-copy-a-file-in-golang
|
|
|
|
func CopyFile(src, dst string) (err error) {
|
|
|
|
sfi, err := os.Stat(src)
|
|
|
|
if err != nil {
|
|
|
|
return
|
|
|
|
}
|
|
|
|
if !sfi.Mode().IsRegular() {
|
|
|
|
// cannot copy non-regular files (e.g., directories,
|
|
|
|
// symlinks, devices, etc.)
|
|
|
|
return fmt.Errorf("CopyFile: non-regular source file %s (%q)", sfi.Name(), sfi.Mode().String())
|
|
|
|
}
|
|
|
|
dfi, err := os.Stat(dst)
|
|
|
|
if err != nil {
|
|
|
|
if !os.IsNotExist(err) {
|
|
|
|
return
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
if !(dfi.Mode().IsRegular()) {
|
|
|
|
return fmt.Errorf("CopyFile: non-regular destination file %s (%q)", dfi.Name(), dfi.Mode().String())
|
|
|
|
}
|
|
|
|
if os.SameFile(sfi, dfi) {
|
|
|
|
return
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if err = os.Link(src, dst); err == nil {
|
|
|
|
return
|
|
|
|
}
|
|
|
|
err = copyFileContents(src, dst)
|
2018-03-29 23:18:09 +02:00
|
|
|
os.Chmod(dst, sfi.Mode())
|
2018-03-17 00:28:58 +01:00
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
// see above
|
|
|
|
func copyFileContents(src, dst string) (err error) {
|
|
|
|
in, err := os.Open(src)
|
|
|
|
if err != nil {
|
|
|
|
return
|
|
|
|
}
|
|
|
|
defer in.Close()
|
|
|
|
out, err := os.Create(dst)
|
|
|
|
if err != nil {
|
|
|
|
return
|
|
|
|
}
|
|
|
|
defer func() {
|
|
|
|
cerr := out.Close()
|
|
|
|
if err == nil {
|
|
|
|
err = cerr
|
|
|
|
}
|
|
|
|
}()
|
|
|
|
if _, err = io.Copy(out, in); err != nil {
|
|
|
|
return
|
|
|
|
}
|
|
|
|
err = out.Sync()
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
terraform-bundle tool for bundling Terraform with providers
Normally "terraform init" will download and install the plugins necessary
to work with a particular configuration, but sometimes Terraform is
deployed in a network that, for one reason or another, cannot access the
official plugin repository for automatic download.
terraform-bundle provides an alternative method, allowing the
auto-download process to be run out-of-band on a separate machine that
_does_ have access to the repository. The result is a zip file that can
be extracted onto the target system to install both the desired
Terraform version and a selection of providers, thus avoiding the need
for on-the-fly plugin installation.
This is provided as a separate tool from Terraform because it is not
something that most users will need. In the rare case where this is
needed, we will for the moment assume that users are able to build this
tool themselves. We may later release it in a pre-built form, if it proves
to be generally useful.
It uses the same API from the plugin/discovery package is is used by the
auto-install behavior in "terraform init", so plugin versions are resolved
in the same way. However, it's expected that several different Terraform
configurations will run from the same bundle, so this tool allows the
bundle to include potentially many versions of the same provider and thus
allows each Terraform configuration to select from the available versions
in the bundle, avoiding the need to upgrade all configurations to new
provider versions in lockstep.
2017-07-05 18:44:50 +02:00
|
|
|
func (c *PackageCommand) Run(args []string) int {
|
|
|
|
flags := flag.NewFlagSet("package", flag.ExitOnError)
|
|
|
|
osPtr := flags.String("os", "", "Target operating system")
|
|
|
|
archPtr := flags.String("arch", "", "Target CPU architecture")
|
2018-03-17 00:28:58 +01:00
|
|
|
pluginDirPtr := flags.String("plugin-dir", "", "Path to custom plugins directory")
|
terraform-bundle tool for bundling Terraform with providers
Normally "terraform init" will download and install the plugins necessary
to work with a particular configuration, but sometimes Terraform is
deployed in a network that, for one reason or another, cannot access the
official plugin repository for automatic download.
terraform-bundle provides an alternative method, allowing the
auto-download process to be run out-of-band on a separate machine that
_does_ have access to the repository. The result is a zip file that can
be extracted onto the target system to install both the desired
Terraform version and a selection of providers, thus avoiding the need
for on-the-fly plugin installation.
This is provided as a separate tool from Terraform because it is not
something that most users will need. In the rare case where this is
needed, we will for the moment assume that users are able to build this
tool themselves. We may later release it in a pre-built form, if it proves
to be generally useful.
It uses the same API from the plugin/discovery package is is used by the
auto-install behavior in "terraform init", so plugin versions are resolved
in the same way. However, it's expected that several different Terraform
configurations will run from the same bundle, so this tool allows the
bundle to include potentially many versions of the same provider and thus
allows each Terraform configuration to select from the available versions
in the bundle, avoiding the need to upgrade all configurations to new
provider versions in lockstep.
2017-07-05 18:44:50 +02:00
|
|
|
err := flags.Parse(args)
|
|
|
|
if err != nil {
|
|
|
|
c.ui.Error(err.Error())
|
|
|
|
return 1
|
|
|
|
}
|
|
|
|
|
|
|
|
osName := runtime.GOOS
|
|
|
|
archName := runtime.GOARCH
|
2018-03-17 00:28:58 +01:00
|
|
|
pluginDir := "./plugins"
|
terraform-bundle tool for bundling Terraform with providers
Normally "terraform init" will download and install the plugins necessary
to work with a particular configuration, but sometimes Terraform is
deployed in a network that, for one reason or another, cannot access the
official plugin repository for automatic download.
terraform-bundle provides an alternative method, allowing the
auto-download process to be run out-of-band on a separate machine that
_does_ have access to the repository. The result is a zip file that can
be extracted onto the target system to install both the desired
Terraform version and a selection of providers, thus avoiding the need
for on-the-fly plugin installation.
This is provided as a separate tool from Terraform because it is not
something that most users will need. In the rare case where this is
needed, we will for the moment assume that users are able to build this
tool themselves. We may later release it in a pre-built form, if it proves
to be generally useful.
It uses the same API from the plugin/discovery package is is used by the
auto-install behavior in "terraform init", so plugin versions are resolved
in the same way. However, it's expected that several different Terraform
configurations will run from the same bundle, so this tool allows the
bundle to include potentially many versions of the same provider and thus
allows each Terraform configuration to select from the available versions
in the bundle, avoiding the need to upgrade all configurations to new
provider versions in lockstep.
2017-07-05 18:44:50 +02:00
|
|
|
if *osPtr != "" {
|
|
|
|
osName = *osPtr
|
|
|
|
}
|
|
|
|
if *archPtr != "" {
|
|
|
|
archName = *archPtr
|
|
|
|
}
|
2018-03-17 00:28:58 +01:00
|
|
|
if *pluginDirPtr != "" {
|
|
|
|
pluginDir = *pluginDirPtr
|
|
|
|
}
|
terraform-bundle tool for bundling Terraform with providers
Normally "terraform init" will download and install the plugins necessary
to work with a particular configuration, but sometimes Terraform is
deployed in a network that, for one reason or another, cannot access the
official plugin repository for automatic download.
terraform-bundle provides an alternative method, allowing the
auto-download process to be run out-of-band on a separate machine that
_does_ have access to the repository. The result is a zip file that can
be extracted onto the target system to install both the desired
Terraform version and a selection of providers, thus avoiding the need
for on-the-fly plugin installation.
This is provided as a separate tool from Terraform because it is not
something that most users will need. In the rare case where this is
needed, we will for the moment assume that users are able to build this
tool themselves. We may later release it in a pre-built form, if it proves
to be generally useful.
It uses the same API from the plugin/discovery package is is used by the
auto-install behavior in "terraform init", so plugin versions are resolved
in the same way. However, it's expected that several different Terraform
configurations will run from the same bundle, so this tool allows the
bundle to include potentially many versions of the same provider and thus
allows each Terraform configuration to select from the available versions
in the bundle, avoiding the need to upgrade all configurations to new
provider versions in lockstep.
2017-07-05 18:44:50 +02:00
|
|
|
|
|
|
|
if flags.NArg() != 1 {
|
|
|
|
c.ui.Error("Configuration filename is required")
|
|
|
|
return 1
|
|
|
|
}
|
|
|
|
configFn := flags.Arg(0)
|
|
|
|
|
|
|
|
config, err := LoadConfigFile(configFn)
|
|
|
|
if err != nil {
|
|
|
|
c.ui.Error(fmt.Sprintf("Failed to read config: %s", err))
|
|
|
|
return 1
|
|
|
|
}
|
|
|
|
|
|
|
|
if discovery.ConstraintStr("< 0.10.0-beta1").MustParse().Allows(config.Terraform.Version.MustParse()) {
|
|
|
|
c.ui.Error("Bundles can be created only for Terraform 0.10 or newer")
|
|
|
|
return 1
|
|
|
|
}
|
|
|
|
|
|
|
|
workDir, err := ioutil.TempDir("", "terraform-bundle")
|
|
|
|
if err != nil {
|
|
|
|
c.ui.Error(fmt.Sprintf("Could not create temporary dir: %s", err))
|
|
|
|
return 1
|
|
|
|
}
|
|
|
|
defer os.RemoveAll(workDir)
|
|
|
|
|
|
|
|
c.ui.Info(fmt.Sprintf("Fetching Terraform %s core package...", config.Terraform.Version))
|
|
|
|
|
|
|
|
coreZipURL := c.coreURL(config.Terraform.Version, osName, archName)
|
|
|
|
err = getter.Get(workDir, coreZipURL)
|
2018-03-17 00:28:58 +01:00
|
|
|
|
terraform-bundle tool for bundling Terraform with providers
Normally "terraform init" will download and install the plugins necessary
to work with a particular configuration, but sometimes Terraform is
deployed in a network that, for one reason or another, cannot access the
official plugin repository for automatic download.
terraform-bundle provides an alternative method, allowing the
auto-download process to be run out-of-band on a separate machine that
_does_ have access to the repository. The result is a zip file that can
be extracted onto the target system to install both the desired
Terraform version and a selection of providers, thus avoiding the need
for on-the-fly plugin installation.
This is provided as a separate tool from Terraform because it is not
something that most users will need. In the rare case where this is
needed, we will for the moment assume that users are able to build this
tool themselves. We may later release it in a pre-built form, if it proves
to be generally useful.
It uses the same API from the plugin/discovery package is is used by the
auto-install behavior in "terraform init", so plugin versions are resolved
in the same way. However, it's expected that several different Terraform
configurations will run from the same bundle, so this tool allows the
bundle to include potentially many versions of the same provider and thus
allows each Terraform configuration to select from the available versions
in the bundle, avoiding the need to upgrade all configurations to new
provider versions in lockstep.
2017-07-05 18:44:50 +02:00
|
|
|
if err != nil {
|
|
|
|
c.ui.Error(fmt.Sprintf("Failed to fetch core package from %s: %s", coreZipURL, err))
|
|
|
|
}
|
|
|
|
|
2018-03-17 00:28:58 +01:00
|
|
|
c.ui.Info(fmt.Sprintf("Fetching 3rd party plugins in directory: %s", pluginDir))
|
|
|
|
dirs := []string{pluginDir} //FindPlugins requires an array
|
|
|
|
localPlugins := discovery.FindPlugins("provider", dirs)
|
|
|
|
for k, _ := range localPlugins {
|
|
|
|
c.ui.Info(fmt.Sprintf("plugin: %s (%s)", k.Name, k.Version))
|
|
|
|
}
|
terraform-bundle tool for bundling Terraform with providers
Normally "terraform init" will download and install the plugins necessary
to work with a particular configuration, but sometimes Terraform is
deployed in a network that, for one reason or another, cannot access the
official plugin repository for automatic download.
terraform-bundle provides an alternative method, allowing the
auto-download process to be run out-of-band on a separate machine that
_does_ have access to the repository. The result is a zip file that can
be extracted onto the target system to install both the desired
Terraform version and a selection of providers, thus avoiding the need
for on-the-fly plugin installation.
This is provided as a separate tool from Terraform because it is not
something that most users will need. In the rare case where this is
needed, we will for the moment assume that users are able to build this
tool themselves. We may later release it in a pre-built form, if it proves
to be generally useful.
It uses the same API from the plugin/discovery package is is used by the
auto-install behavior in "terraform init", so plugin versions are resolved
in the same way. However, it's expected that several different Terraform
configurations will run from the same bundle, so this tool allows the
bundle to include potentially many versions of the same provider and thus
allows each Terraform configuration to select from the available versions
in the bundle, avoiding the need to upgrade all configurations to new
provider versions in lockstep.
2017-07-05 18:44:50 +02:00
|
|
|
installer := &discovery.ProviderInstaller{
|
|
|
|
Dir: workDir,
|
|
|
|
|
|
|
|
// FIXME: This is incorrect because it uses the protocol version of
|
|
|
|
// this tool, rather than of the Terraform binary we just downloaded.
|
|
|
|
// But we can't get this information from a Terraform binary, so
|
2019-01-16 23:15:52 +01:00
|
|
|
// we'll just ignore this for now and use the same plugin installer
|
|
|
|
// protocol version for terraform-bundle as the terraform shipped
|
|
|
|
// with this release.
|
|
|
|
//
|
|
|
|
// NOTE: To target older versions of terraform, use the terraform-bundle
|
|
|
|
// from the same tag.
|
|
|
|
PluginProtocolVersion: discovery.PluginInstallProtocolVersion,
|
terraform-bundle tool for bundling Terraform with providers
Normally "terraform init" will download and install the plugins necessary
to work with a particular configuration, but sometimes Terraform is
deployed in a network that, for one reason or another, cannot access the
official plugin repository for automatic download.
terraform-bundle provides an alternative method, allowing the
auto-download process to be run out-of-band on a separate machine that
_does_ have access to the repository. The result is a zip file that can
be extracted onto the target system to install both the desired
Terraform version and a selection of providers, thus avoiding the need
for on-the-fly plugin installation.
This is provided as a separate tool from Terraform because it is not
something that most users will need. In the rare case where this is
needed, we will for the moment assume that users are able to build this
tool themselves. We may later release it in a pre-built form, if it proves
to be generally useful.
It uses the same API from the plugin/discovery package is is used by the
auto-install behavior in "terraform init", so plugin versions are resolved
in the same way. However, it's expected that several different Terraform
configurations will run from the same bundle, so this tool allows the
bundle to include potentially many versions of the same provider and thus
allows each Terraform configuration to select from the available versions
in the bundle, avoiding the need to upgrade all configurations to new
provider versions in lockstep.
2017-07-05 18:44:50 +02:00
|
|
|
|
|
|
|
OS: osName,
|
|
|
|
Arch: archName,
|
2017-08-16 16:37:48 +02:00
|
|
|
Ui: c.ui,
|
terraform-bundle tool for bundling Terraform with providers
Normally "terraform init" will download and install the plugins necessary
to work with a particular configuration, but sometimes Terraform is
deployed in a network that, for one reason or another, cannot access the
official plugin repository for automatic download.
terraform-bundle provides an alternative method, allowing the
auto-download process to be run out-of-band on a separate machine that
_does_ have access to the repository. The result is a zip file that can
be extracted onto the target system to install both the desired
Terraform version and a selection of providers, thus avoiding the need
for on-the-fly plugin installation.
This is provided as a separate tool from Terraform because it is not
something that most users will need. In the rare case where this is
needed, we will for the moment assume that users are able to build this
tool themselves. We may later release it in a pre-built form, if it proves
to be generally useful.
It uses the same API from the plugin/discovery package is is used by the
auto-install behavior in "terraform init", so plugin versions are resolved
in the same way. However, it's expected that several different Terraform
configurations will run from the same bundle, so this tool allows the
bundle to include potentially many versions of the same provider and thus
allows each Terraform configuration to select from the available versions
in the bundle, avoiding the need to upgrade all configurations to new
provider versions in lockstep.
2017-07-05 18:44:50 +02:00
|
|
|
}
|
|
|
|
|
2018-03-17 00:28:58 +01:00
|
|
|
for name, constraintStrs := range config.Providers {
|
|
|
|
for _, constraintStr := range constraintStrs {
|
2017-08-16 17:30:10 +02:00
|
|
|
c.ui.Output(fmt.Sprintf("- Resolving %q provider (%s)...",
|
2018-03-17 00:28:58 +01:00
|
|
|
name, constraintStr))
|
|
|
|
foundPlugins := discovery.PluginMetaSet{}
|
|
|
|
constraint := constraintStr.MustParse()
|
|
|
|
for plugin, _ := range localPlugins {
|
|
|
|
if plugin.Name == name && constraint.Allows(plugin.Version.MustParse()) {
|
|
|
|
foundPlugins.Add(plugin)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if len(foundPlugins) > 0 {
|
|
|
|
plugin := foundPlugins.Newest()
|
2018-03-27 05:22:53 +02:00
|
|
|
CopyFile(plugin.Path, workDir+"/terraform-provider-"+plugin.Name+"_v"+plugin.Version.MustParse().String()) //put into temp dir
|
2018-03-17 00:28:58 +01:00
|
|
|
} else { //attempt to get from the public registry if not found locally
|
|
|
|
c.ui.Output(fmt.Sprintf("- Checking for provider plugin on %s...",
|
2018-08-09 00:04:51 +02:00
|
|
|
releaseHost))
|
2018-03-17 00:28:58 +01:00
|
|
|
_, err := installer.Get(name, constraint)
|
|
|
|
if err != nil {
|
|
|
|
c.ui.Error(fmt.Sprintf("- Failed to resolve %s provider %s: %s", name, constraint, err))
|
|
|
|
return 1
|
|
|
|
}
|
terraform-bundle tool for bundling Terraform with providers
Normally "terraform init" will download and install the plugins necessary
to work with a particular configuration, but sometimes Terraform is
deployed in a network that, for one reason or another, cannot access the
official plugin repository for automatic download.
terraform-bundle provides an alternative method, allowing the
auto-download process to be run out-of-band on a separate machine that
_does_ have access to the repository. The result is a zip file that can
be extracted onto the target system to install both the desired
Terraform version and a selection of providers, thus avoiding the need
for on-the-fly plugin installation.
This is provided as a separate tool from Terraform because it is not
something that most users will need. In the rare case where this is
needed, we will for the moment assume that users are able to build this
tool themselves. We may later release it in a pre-built form, if it proves
to be generally useful.
It uses the same API from the plugin/discovery package is is used by the
auto-install behavior in "terraform init", so plugin versions are resolved
in the same way. However, it's expected that several different Terraform
configurations will run from the same bundle, so this tool allows the
bundle to include potentially many versions of the same provider and thus
allows each Terraform configuration to select from the available versions
in the bundle, avoiding the need to upgrade all configurations to new
provider versions in lockstep.
2017-07-05 18:44:50 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
files, err := ioutil.ReadDir(workDir)
|
|
|
|
if err != nil {
|
|
|
|
c.ui.Error(fmt.Sprintf("Failed to read work directory %s: %s", workDir, err))
|
|
|
|
return 1
|
|
|
|
}
|
|
|
|
|
|
|
|
// If we get this far then our workDir now contains the union of the
|
|
|
|
// contents of all the zip files we downloaded above. We can now create
|
|
|
|
// our output file.
|
|
|
|
outFn := c.bundleFilename(config.Terraform.Version, time.Now(), osName, archName)
|
|
|
|
c.ui.Info(fmt.Sprintf("Creating %s ...", outFn))
|
|
|
|
outF, err := os.OpenFile(outFn, os.O_TRUNC|os.O_CREATE|os.O_WRONLY, os.ModePerm)
|
|
|
|
if err != nil {
|
|
|
|
c.ui.Error(fmt.Sprintf("Failed to create %s: %s", outFn, err))
|
|
|
|
return 1
|
|
|
|
}
|
|
|
|
outZ := zip.NewWriter(outF)
|
|
|
|
defer func() {
|
|
|
|
err := outZ.Close()
|
|
|
|
if err != nil {
|
|
|
|
c.ui.Error(fmt.Sprintf("Failed to close %s: %s", outFn, err))
|
|
|
|
os.Exit(1)
|
|
|
|
}
|
|
|
|
err = outF.Close()
|
|
|
|
if err != nil {
|
|
|
|
c.ui.Error(fmt.Sprintf("Failed to close %s: %s", outFn, err))
|
|
|
|
os.Exit(1)
|
|
|
|
}
|
|
|
|
}()
|
|
|
|
|
|
|
|
for _, file := range files {
|
|
|
|
if file.IsDir() {
|
|
|
|
// should never happen unless something tampers with our tmpdir
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
|
|
|
|
fn := filepath.Join(workDir, file.Name())
|
|
|
|
r, err := os.Open(fn)
|
|
|
|
if err != nil {
|
|
|
|
c.ui.Error(fmt.Sprintf("Failed to open %s: %s", fn, err))
|
|
|
|
return 1
|
|
|
|
}
|
|
|
|
hdr, err := zip.FileInfoHeader(file)
|
|
|
|
if err != nil {
|
|
|
|
c.ui.Error(fmt.Sprintf("Failed to add zip entry for %s: %s", fn, err))
|
|
|
|
return 1
|
|
|
|
}
|
2018-04-07 04:16:25 +02:00
|
|
|
hdr.Method = zip.Deflate // be sure to compress files
|
terraform-bundle tool for bundling Terraform with providers
Normally "terraform init" will download and install the plugins necessary
to work with a particular configuration, but sometimes Terraform is
deployed in a network that, for one reason or another, cannot access the
official plugin repository for automatic download.
terraform-bundle provides an alternative method, allowing the
auto-download process to be run out-of-band on a separate machine that
_does_ have access to the repository. The result is a zip file that can
be extracted onto the target system to install both the desired
Terraform version and a selection of providers, thus avoiding the need
for on-the-fly plugin installation.
This is provided as a separate tool from Terraform because it is not
something that most users will need. In the rare case where this is
needed, we will for the moment assume that users are able to build this
tool themselves. We may later release it in a pre-built form, if it proves
to be generally useful.
It uses the same API from the plugin/discovery package is is used by the
auto-install behavior in "terraform init", so plugin versions are resolved
in the same way. However, it's expected that several different Terraform
configurations will run from the same bundle, so this tool allows the
bundle to include potentially many versions of the same provider and thus
allows each Terraform configuration to select from the available versions
in the bundle, avoiding the need to upgrade all configurations to new
provider versions in lockstep.
2017-07-05 18:44:50 +02:00
|
|
|
w, err := outZ.CreateHeader(hdr)
|
|
|
|
if err != nil {
|
|
|
|
c.ui.Error(fmt.Sprintf("Failed to add zip entry for %s: %s", fn, err))
|
|
|
|
return 1
|
|
|
|
}
|
|
|
|
_, err = io.Copy(w, r)
|
|
|
|
if err != nil {
|
|
|
|
c.ui.Error(fmt.Sprintf("Failed to write %s to bundle: %s", fn, err))
|
|
|
|
return 1
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
c.ui.Info("All done!")
|
|
|
|
|
|
|
|
return 0
|
|
|
|
}
|
|
|
|
|
|
|
|
func (c *PackageCommand) bundleFilename(version discovery.VersionStr, time time.Time, osName, archName string) string {
|
|
|
|
time = time.UTC()
|
|
|
|
return fmt.Sprintf(
|
|
|
|
"terraform_%s-bundle%04d%02d%02d%02d_%s_%s.zip",
|
|
|
|
version,
|
|
|
|
time.Year(), time.Month(), time.Day(), time.Hour(),
|
|
|
|
osName, archName,
|
|
|
|
)
|
|
|
|
}
|
|
|
|
|
|
|
|
func (c *PackageCommand) coreURL(version discovery.VersionStr, osName, archName string) string {
|
|
|
|
return fmt.Sprintf(
|
|
|
|
"%s/terraform/%s/terraform_%s_%s_%s.zip",
|
2018-08-09 00:04:51 +02:00
|
|
|
releaseHost, version, version, osName, archName,
|
terraform-bundle tool for bundling Terraform with providers
Normally "terraform init" will download and install the plugins necessary
to work with a particular configuration, but sometimes Terraform is
deployed in a network that, for one reason or another, cannot access the
official plugin repository for automatic download.
terraform-bundle provides an alternative method, allowing the
auto-download process to be run out-of-band on a separate machine that
_does_ have access to the repository. The result is a zip file that can
be extracted onto the target system to install both the desired
Terraform version and a selection of providers, thus avoiding the need
for on-the-fly plugin installation.
This is provided as a separate tool from Terraform because it is not
something that most users will need. In the rare case where this is
needed, we will for the moment assume that users are able to build this
tool themselves. We may later release it in a pre-built form, if it proves
to be generally useful.
It uses the same API from the plugin/discovery package is is used by the
auto-install behavior in "terraform init", so plugin versions are resolved
in the same way. However, it's expected that several different Terraform
configurations will run from the same bundle, so this tool allows the
bundle to include potentially many versions of the same provider and thus
allows each Terraform configuration to select from the available versions
in the bundle, avoiding the need to upgrade all configurations to new
provider versions in lockstep.
2017-07-05 18:44:50 +02:00
|
|
|
)
|
|
|
|
}
|
|
|
|
|
|
|
|
func (c *PackageCommand) Synopsis() string {
|
|
|
|
return "Produces a bundle archive"
|
|
|
|
}
|
|
|
|
|
|
|
|
func (c *PackageCommand) Help() string {
|
|
|
|
return `Usage: terraform-bundle package [options] <config-file>
|
|
|
|
|
|
|
|
Uses the given bundle configuration file to produce a zip file in the
|
|
|
|
current working directory containing a Terraform binary along with zero or
|
|
|
|
more provider plugin binaries.
|
|
|
|
|
|
|
|
Options:
|
2018-03-17 00:28:58 +01:00
|
|
|
-os=name Target operating system the archive will be built for. Defaults
|
|
|
|
to that of the system where the command is being run.
|
terraform-bundle tool for bundling Terraform with providers
Normally "terraform init" will download and install the plugins necessary
to work with a particular configuration, but sometimes Terraform is
deployed in a network that, for one reason or another, cannot access the
official plugin repository for automatic download.
terraform-bundle provides an alternative method, allowing the
auto-download process to be run out-of-band on a separate machine that
_does_ have access to the repository. The result is a zip file that can
be extracted onto the target system to install both the desired
Terraform version and a selection of providers, thus avoiding the need
for on-the-fly plugin installation.
This is provided as a separate tool from Terraform because it is not
something that most users will need. In the rare case where this is
needed, we will for the moment assume that users are able to build this
tool themselves. We may later release it in a pre-built form, if it proves
to be generally useful.
It uses the same API from the plugin/discovery package is is used by the
auto-install behavior in "terraform init", so plugin versions are resolved
in the same way. However, it's expected that several different Terraform
configurations will run from the same bundle, so this tool allows the
bundle to include potentially many versions of the same provider and thus
allows each Terraform configuration to select from the available versions
in the bundle, avoiding the need to upgrade all configurations to new
provider versions in lockstep.
2017-07-05 18:44:50 +02:00
|
|
|
|
2018-03-17 00:28:58 +01:00
|
|
|
-arch=name Target CPU architecture the archive will be built for. Defaults
|
|
|
|
to that of the system where the command is being run.
|
|
|
|
|
|
|
|
-plugin-dir=path The path to the custom plugins directory. Defaults to "./plugins".
|
terraform-bundle tool for bundling Terraform with providers
Normally "terraform init" will download and install the plugins necessary
to work with a particular configuration, but sometimes Terraform is
deployed in a network that, for one reason or another, cannot access the
official plugin repository for automatic download.
terraform-bundle provides an alternative method, allowing the
auto-download process to be run out-of-band on a separate machine that
_does_ have access to the repository. The result is a zip file that can
be extracted onto the target system to install both the desired
Terraform version and a selection of providers, thus avoiding the need
for on-the-fly plugin installation.
This is provided as a separate tool from Terraform because it is not
something that most users will need. In the rare case where this is
needed, we will for the moment assume that users are able to build this
tool themselves. We may later release it in a pre-built form, if it proves
to be generally useful.
It uses the same API from the plugin/discovery package is is used by the
auto-install behavior in "terraform init", so plugin versions are resolved
in the same way. However, it's expected that several different Terraform
configurations will run from the same bundle, so this tool allows the
bundle to include potentially many versions of the same provider and thus
allows each Terraform configuration to select from the available versions
in the bundle, avoiding the need to upgrade all configurations to new
provider versions in lockstep.
2017-07-05 18:44:50 +02:00
|
|
|
|
|
|
|
The resulting zip file can be used to more easily install Terraform and
|
|
|
|
a fixed set of providers together on a server, so that Terraform's provider
|
|
|
|
auto-installation mechanism can be avoided.
|
|
|
|
|
|
|
|
To build an archive for Terraform Enterprise, use:
|
|
|
|
-os=linux -arch=amd64
|
|
|
|
|
|
|
|
Note that the given configuration file is a format specific to this command,
|
|
|
|
not a normal Terraform configuration file. The file format looks like this:
|
|
|
|
|
|
|
|
terraform {
|
|
|
|
# Version of Terraform to include in the bundle. An exact version number
|
|
|
|
# is required.
|
|
|
|
version = "0.10.0"
|
|
|
|
}
|
|
|
|
|
|
|
|
# Define which provider plugins are to be included
|
|
|
|
providers {
|
|
|
|
# Include the newest "aws" provider version in the 1.0 series.
|
|
|
|
aws = ["~> 1.0"]
|
|
|
|
|
|
|
|
# Include both the newest 1.0 and 2.0 versions of the "google" provider.
|
|
|
|
# Each item in these lists allows a distinct version to be added. If the
|
|
|
|
# two expressions match different versions then _both_ are included in
|
|
|
|
# the bundle archive.
|
2018-03-17 00:28:58 +01:00
|
|
|
google = ["~> 1.0", "~> 2.0"]
|
|
|
|
|
|
|
|
#Include a custom plugin to the bundle. Will search for the plugin in the
|
|
|
|
#plugins directory, and package it with the bundle archive. Plugin must have
|
|
|
|
#a name of the form: terraform-provider-*-v*, and must be built with the operating
|
|
|
|
#system and architecture that terraform enterprise is running, e.g. linux and amd64
|
|
|
|
customplugin = ["0.1"]
|
terraform-bundle tool for bundling Terraform with providers
Normally "terraform init" will download and install the plugins necessary
to work with a particular configuration, but sometimes Terraform is
deployed in a network that, for one reason or another, cannot access the
official plugin repository for automatic download.
terraform-bundle provides an alternative method, allowing the
auto-download process to be run out-of-band on a separate machine that
_does_ have access to the repository. The result is a zip file that can
be extracted onto the target system to install both the desired
Terraform version and a selection of providers, thus avoiding the need
for on-the-fly plugin installation.
This is provided as a separate tool from Terraform because it is not
something that most users will need. In the rare case where this is
needed, we will for the moment assume that users are able to build this
tool themselves. We may later release it in a pre-built form, if it proves
to be generally useful.
It uses the same API from the plugin/discovery package is is used by the
auto-install behavior in "terraform init", so plugin versions are resolved
in the same way. However, it's expected that several different Terraform
configurations will run from the same bundle, so this tool allows the
bundle to include potentially many versions of the same provider and thus
allows each Terraform configuration to select from the available versions
in the bundle, avoiding the need to upgrade all configurations to new
provider versions in lockstep.
2017-07-05 18:44:50 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
`
|
|
|
|
}
|