diff --git a/_docs/config/backend.md b/_docs/config/backend.md index 1e7d988..24a3f6a 100644 --- a/_docs/config/backend.md +++ b/_docs/config/backend.md @@ -29,9 +29,14 @@ Running: terraspace up demo -Builds a `.terraspace-cache/dev/stacks/demo/backend.tf` using the `config/terraform/backend.tf`. If you want to just build the files without deploying, you can also use `terraspace build`. Below are examples of backends. +Builds a `.terraspace-cache/dev/stacks/demo/backend.tf` using the `config/terraform/backend.tf`. If you want to just build the files without deploying, you can also use `terraspace build`. -{% include tabs.html %} +## Backend Examples + +{% assign docs = site.docs | where: "categories","backend-examples" | sort:"order" %} +{% for doc in docs -%} +* [{{ doc.nav_text }}]({{ doc.url }}) +{% endfor %} ___ @@ -50,9 +55,3 @@ Terraspace expansion will remove the trailing dashes and slashes in case the ins Will result in: us-west-2/dev/demo # notice there's no trailing slash - -___ - -## Why Is Env in Bucket Name? - -By default, the bucket name has the ENV at the end. This is done so we can easily see which environment the bucket stores Terraform statefiles for. This quickly helps with debugging. If you prefer not to have the ENV at the end of the bucket name, remove it after generating the project with `terraspace new project`. \ No newline at end of file diff --git a/_docs/config/backend/examples.md b/_docs/config/backend/examples.md new file mode 100644 index 0000000..8ba24db --- /dev/null +++ b/_docs/config/backend/examples.md @@ -0,0 +1,10 @@ +--- +title: Backend Examples +--- + +Here are several backend examples: + +{% assign docs = site.docs | where: "categories","backend-examples" | sort:"order" %} +{% for doc in docs -%} +* [{{ doc.nav_text }}]({{ doc.url }}) +{% endfor %} diff --git a/_docs/config/backend/examples/azurerm.md b/_docs/config/backend/examples/azurerm.md new file mode 100644 index 0000000..ab13fc5 --- /dev/null +++ b/_docs/config/backend/examples/azurerm.md @@ -0,0 +1,87 @@ +--- +title: Backend Azurerm +nav_text: Azurerm +categories: backend-examples +order: 2 +--- + +Here's an example with the [azurerm backend](https://www.terraform.io/language/settings/backends/azurerm). + +config/terraform/backend.tf: + +{% highlight sh %} +terraform + terraform { + backend "azurerm" { + resource_group_name = "<%= expansion(':ENV-:LOCATION') %>" + storage_account_name = "<%= expansion('ts:SUBSCRIPTION_HASH:LOCATION:ENV') %>" + container_name = "terraform-state" + key = "<%= expansion(':LOCATION/:ENV/:BUILD_DIR/terraform.tfstate') %>" + } +} +{% endhighlight %} + +Notice the variable notation. Terraspace expands it out, substituting the values. The starter `backend.tf` + accounts for `LOCATION`, `ENV`, etc. Here's an expanded example: + +{% highlight sh %} +terraform { + backend "azurerm" { + resource_group_name = "dev-eastus" + storage_account_name = "tswxyzeastusdev" + container_name = "terraform-state" + key = "eastus/dev/stacks/demo/terraform.tfstate" + } +} +{% endhighlight %} + +Note, the `SUBSCRIPTION_HASH` is a short 4-char consistent hash of the longer subscription id. This is useful because azure storage account names are not allowed special characters and are limited to 24 chars. + +## Resource Group Name Thoughts + +The default `resource_group_name` name is env-focused. Azure Resource Groups often make more sense to be app-env scoped. For example: + +app-env focused: + + * app1-dev + * app1-prod + * app2-dev + * app2-prod + +Azure Resource groups help know the exact resources that belong to an app-env. IE: VMs, DBs, Firewalls, etc. It becomes easy to identify and clean up resources. + +There are some resources that are more env-focused. AKS clusters are a good example. It often makes sense to share a dev cluster and deploy your applications onto that cluster. Container density and less maintenance overhead are benefits. + +The default `resource_group_name` is env-focused and nicely accounts for the use-case of shared resources like AKS clusters. + + resource_group_name = "<%= expansion(':ENV-:LOCATION') %>" + +It does not account for app-env focused resources, though. Since Terraspace does not know what app name, you need to provide the context. One approach is to configure resource_group_name more dynamically: + +config/terraform/backend.tf: + +{% highlight sh %} +<% +def resource_group_name + if ENV['APP'] + expansion("#{ENV['APP']}-:ENV-:LOCATION") + else + expansion(":ENV-:LOCATION") + end +end +%> + +terraform { + backend "azurerm" { + resource_group_name = "<%= resource_group_name %>" + storage_account_name = "<%= expansion('ts:SUBSCRIPTION_HASH:LOCATION:ENV') %>" + container_name = "terraform-state" + key = "<%= expansion(':LOCATION/:ENV/:BUILD_DIR/terraform.tfstate') %>" +} +{% endhighlight %} + +You can now provide `APP` and the resource group will account for it. Example: + + APP=app1 terraspace up demo + +If the infrastructure components for the app are really unique, then it may also make sense to have an entirely different terraspace project. diff --git a/_docs/config/backend/examples/gcs.md b/_docs/config/backend/examples/gcs.md new file mode 100644 index 0000000..731eb13 --- /dev/null +++ b/_docs/config/backend/examples/gcs.md @@ -0,0 +1,34 @@ +--- +title: Backend GCS +nav_text: GCS +categories: backend-examples +order: 3 +--- + +Here's an example with the [gcs backend](https://www.terraform.io/language/settings/backends/gcs). + +config/terraform/backend.tf: + +{% highlight sh %} +terraform + terraform { + backend "gcs" { + bucket = "<%= expansion('terraform-state-:PROJECT-:REGION-:ENV') %>" + prefix = "<%= expansion(':REGION/:ENV/:BUILD_DIR') %>" + } +} +{% endhighlight %} + +Notice the variable notation. Terraspace expands it out, substituting the values. The starter `backend.tf` accounts for `PROJECT`, `ENV`, etc. Here's an expanded example: + +{% highlight sh %} +terraform + terraform { + backend "gcs" { + bucket = "terraform-state-google-project-id-us-central1-dev" + prefix = "us-central1/dev/stacks/demo" + } +} +{% endhighlight %} + +{% include config/backend/env-in-bucket-name.md %} diff --git a/_docs/config/backend/examples/gitlab.md b/_docs/config/backend/examples/gitlab.md new file mode 100644 index 0000000..11b1ee3 --- /dev/null +++ b/_docs/config/backend/examples/gitlab.md @@ -0,0 +1,69 @@ +--- +title: "Backend GitLab" +nav_text: "GitLab" +categories: backend-examples +order: 6 +--- + +Here's an example with the [GitLab](https://docs.gitlab.com/ee/user/infrastructure/iac/terraform_state.html) [http backend](https://www.terraform.io/language/settings/backends/http). + +config/terraform/backend.tf: + +``` +terraform { + backend "http" { + address = "<%= ENV['GITLAB_PROJECT_URL'] %>/<%= expansion(":ENV-:TYPE_DIR-:MOD_NAME") %>" + lock_address = "<%= ENV['GITLAB_PROJECT_URL'] %>/<%= expansion(":ENV-:TYPE_DIR-:MOD_NAME") %>/lock" + unlock_address = "<%= ENV['GITLAB_PROJECT_URL'] %>/<%= expansion(":ENV-:TYPE_DIR-:MOD_NAME") %>/lock" + username = "<%= ENV['GITLAB_USER'] %>" + password = "<%= ENV['GITLAB_ACCESS_TOKEN'] %>" + lock_method = "POST" + unlock_method = "DELETE" + retry_wait_min = 5 + } +} +``` + +You can set the env var defaults with the [config/boot.rb]({% link _docs/config/boot.md %}) hook. + +config/boot.rb: + +```ruby +ENV['GITLAB_PROJECT_ID'] ||= 'your project id' +ENV['GITLAB_USER'] ||= 'gitlab-user' +ENV['GITLAB_ACCESS_TOKEN'] ||= 'gitlab-api-access-token' +ENV['GITLAB_PROJECT_URL'] = "https://gitlab.com/api/v4/projects/#{ENV['GITLAB_PROJECT_ID']}/terraform/state" +``` + +## Including Region + +When a http backend is used, a generic expander is used and `:REGION` is not expanded. This is because you can use the http backend without any `terraspace_plugin_*` at all . If you want to include `:REGION` in the expansion helper, here's one way to do that: + +config/terraform/backend.tf: + +``` +terraform { + backend "http" { + address = "<%= ENV['GITLAB_PROJECT_URL'] %>/<%= expansion("#{ENV['AWS_REGION']}-:ENV-:TYPE_DIR-:MOD_NAME") %>" + lock_address = "<%= ENV['GITLAB_PROJECT_URL'] %>/<%= expansion("#{ENV['AWS_REGION']}-:ENV-:TYPE_DIR-:MOD_NAME") %>/lock" + unlock_address = "<%= ENV['GITLAB_PROJECT_URL'] %>/<%= expansion("#{ENV['AWS_REGION']}-:ENV-:TYPE_DIR-:MOD_NAME") %>/lock" + username = "<%= ENV['GITLAB_USER'] %>" + password = "<%= ENV['GITLAB_ACCESS_TOKEN'] %>" + lock_method = "POST" + unlock_method = "DELETE" + retry_wait_min = 5 + } +} +``` + +You can set the env var defaults with the [config/boot.rb]({% link _docs/config/boot.md %}) hook. + +config/boot.rb: + +```ruby +ENV['GITLAB_PROJECT_ID'] ||= 'your project id' +ENV['GITLAB_USER'] ||= 'gitlab-user' +ENV['GITLAB_ACCESS_TOKEN'] ||= 'gitlab-api-access-token' +ENV['GITLAB_PROJECT_URL'] = "https://gitlab.com/api/v4/projects/#{ENV['GITLAB_PROJECT_ID']}/terraform/state" +ENV['AWS_REGION'] ||= "us-east-1" +``` diff --git a/_docs/config/backend/examples/local.md b/_docs/config/backend/examples/local.md new file mode 100644 index 0000000..ec3ee06 --- /dev/null +++ b/_docs/config/backend/examples/local.md @@ -0,0 +1,38 @@ +--- +title: "Backend Local" +nav_text: "Local" +categories: backend-examples +order: 5 +--- + +Here's an example with the [local backend](https://www.terraform.io/language/settings/backends/local). + +config/terraform/backend.tf: + +{% highlight sh %} +terraform { + backend "local" { + path = "terraform.tfstate" + } +} +{% endhighlight %} + +The local statefile is stored at: + + ls .terraspace-cache/dev/stacks/demo/terraform.tfstate + +Note: When using a local backend, the `config/terraform/backend.tf` file is entirely optional. Terraform defaults to a local backend with the `path = "terraform.tfstate"`. The `backend.tf` is provided as an example and shows you how to change the path. + +## Prefix Path + +If you're wondering how the prefix path `.terraspace-cache/dev/stacks/demo` was determined. It's controlled by + +config/app.rb: + +```ruby +Terraspace.configure do |config| + config.build.cache_dir = ":CACHE_ROOT/:REGION/:ENV/:BUILD_DIR" +end +``` + +For defaults, see: [config/reference]({% link _docs/config/reference.md %}) diff --git a/_docs/config/backend/examples/remote.md b/_docs/config/backend/examples/remote.md new file mode 100644 index 0000000..e363633 --- /dev/null +++ b/_docs/config/backend/examples/remote.md @@ -0,0 +1,36 @@ +--- +title: "Backend Remote: TFC and TFE" +nav_text: "Remote TFC" +categories: backend-examples +order: 4 +--- + +Here's an example with the [TFC](https://www.terraform.io/cloud) or [TFE](https://www.terraform.io/enterprise/admin/agents-on-tfe) [remote](https://www.terraform.io/language/settings/backends/remote) backend. + +config/terraform/backend.tf: + +{% highlight sh %} +terraform + terraform { + backend "remote" { + organization = "ORG" + workspaces { + name = "<%= expansion(':MOD_NAME-:ENV-:REGION-:INSTANCE') %>" + } + } +} +{% endhighlight %} + +Here's an expanded example: + +{% highlight sh %} +terraform + terraform { + backend "remote" { + organization = "boltops" + workspaces { + name = "demo-dev-us-west-2" + } + } +} +{% endhighlight %} diff --git a/_docs/config/backend/examples/s3.md b/_docs/config/backend/examples/s3.md new file mode 100644 index 0000000..cf3618b --- /dev/null +++ b/_docs/config/backend/examples/s3.md @@ -0,0 +1,43 @@ +--- +title: Backend S3 +nav_text: S3 +categories: backend-examples +order: 1 +--- + +Here's an example with the [s3 backend](https://www.terraform.io/language/settings/backends/s3). + +config/terraform/backend.tf: + +{% highlight sh %} +terraform { + backend "s3" { + bucket = "<%= expansion('terraform-state-:ACCOUNT-:REGION-:ENV') %>" + key = "<%= expansion(':REGION/:ENV/:BUILD_DIR/terraform.tfstate') %>" + region = "<%= expansion(':REGION') %>" + encrypt = true + dynamodb_table = "terraform_locks" + } +} +{% endhighlight %} + +Notice the variable notation. Terraspace expands it out, substituting the values. The starter `backend.tf` + accounts for `REGION`, `ENV`, etc. Here's an expanded example: + +{% highlight sh %} +terraform + terraform { + backend "s3" { + bucket = "terraform-state-111111111111-us-west-2-dev" + key = "us-west-2/dev/stacks/demo/terraform.tfstate" + region = "us-west-2" + encrypt = true + dynamodb_table = "terraform_locks" + } +} +{% endhighlight %} + +You can fully control the state file path by adjusting this. The string substitution also makes it clear what + the state path looks like. + +{% include config/backend/env-in-bucket-name.md %} diff --git a/_docs/config/cache-dir.md b/_docs/config/cache-dir.md index bc2b7dc..9633888 100644 --- a/_docs/config/cache-dir.md +++ b/_docs/config/cache-dir.md @@ -22,6 +22,8 @@ The `build.cache_dir` can take: When setting it as a **String**, Terraspace uses it as a pattern and substitute values. For example, +config/app.rb: + ```ruby Terraspace.configure do |config| config.build.cache_dir = ":CACHE_ROOT/:REGION/:ENV/:BUILD_DIR" diff --git a/_docs/install/bundle-exec.md b/_docs/install/bundle-exec.md new file mode 100644 index 0000000..c4a8f84 --- /dev/null +++ b/_docs/install/bundle-exec.md @@ -0,0 +1,46 @@ +--- +title: Bundle Exec +--- + +## Already Activated Errors + +If you are seeing an error that says a gem dependency is "already activated", for example: + + You have already activated faraday 1.7.0, but your Gemfile requires faraday 0.17.4. Prepending `bundle exec` to your command may solve this. + +Prepending `bundle exec` should resolve the issue. + +## The Short Answer: Use A Shim + +It can be annoying to remember typing `bundle exec`, though. You can generate a shim to ensure that `bundle exec` is prepended: + + terraspace new shim + +The shim looks something like this: + + #!/bin/bash + if [ -f config/app.rb ]; then + exec bundle exec terraspace "$@" + else + exec terraspace "$@" + fi + +It simply ensures that when you are within a Terraspace project, `bundle exec` is prepended. + +By default, the shim is written to `/usr/local/bin/terraspace`. As long as `/usr/local/bin` is early enough in your system `$PATH`, you can then type `terraspace` instead of `bundle exec terraspace`. + +You can change the path with the `--path` option. More info: [terraspace new shim]({% link _reference/terraspace-new-shim.md %}). + +## The Long Answer: Why? + +The key understanding why the "already activated" error happens is understanding how Ruby, bundler, and system load paths work. The `bundle exec` is essentially a wrapper script that adjusts the load path **before** calling the Ruby world. Using `bundle exec` affects the system load paths. It ensures that the exact versions specified in `Gemfile.lock` are used. + +Example without: + + terraspace version + +Example with: + + bundle exec terraspace version + +When `bundle exec` is not prepended, the gem versions that get used are more dependent on how your environment has been configured. In this case, Ruby usually uses the latest gem dependency versions - it depends on your system load path. Terraspace takes an extra measure to help and calls `bundle exec` early [internally](https://github.com/boltops-tools/terraspace/blob/master/lib/terraspace/autoloader.rb#L2). But it doesn't work for all cases. In this case, you'll need to use `bundle exec`, uninstall other versions of gems from your system, or run `bundle update` to hopefully match gems in `Gemfile.lock` with the other gem versions installed on your system. diff --git a/_docs/install/docker/versioning.md b/_docs/install/docker/versioning.md new file mode 100644 index 0000000..cb7729a --- /dev/null +++ b/_docs/install/docker/versioning.md @@ -0,0 +1,40 @@ +--- +title: "Docker Versioning" +nav_text: Versioning +category: docker-guides +--- + +Docker images with terraspace installed are published with the OS and version tag. Dockerhub tags: [boltops/terraspace](https://hub.docker.com/r/boltops/terraspace/tags) + +The version naming convention is: + + boltops/terraspace:$OS-$VERSION + +When the version is not including in the name, it's the latest version of terraspace. + +Examples + + boltops/terraspace:amzn2 # latest + boltops/terraspace:amzn2-0.7.0 + boltops/terraspace:ubuntu # latest + boltops/terraspace:ubuntu-0.7.0 + +More examples: + + boltops/terraspace:alpine + boltops/terraspace:amzn2 + boltops/terraspace:centos + boltops/terraspace:debian + boltops/terraspace:fedora + boltops/terraspace:ubuntu + +## Main Latest Version + +The top-level main latest version is ubuntu. So + + boltops/terraspace + +Is the same as + + boltops/terraspace:ubuntu + diff --git a/_docs/install/gem.md b/_docs/install/gem.md index 9ead548..580a5a7 100644 --- a/_docs/install/gem.md +++ b/_docs/install/gem.md @@ -6,15 +6,15 @@ To install terraspace via RubyGems. gem install terraspace -Ruby 2.7 and above is recommended. +Ruby 3.0 and above is recommended. -The nice thing about this installation method is that is the standard way to install ruby libraries and gems. It integrates with your existing Ruby installation. +The nice thing about this installation method is that is the standard way to install Ruby libraries and gems. It integrates with your existing Ruby installation. And you have the most control over the installation. If you're looking for Ruby installation help: [Ruby Install]({% link _docs/install/ruby.md %}) docs. ## Updating -To update terraspace it is recommend you update project's `Gemfile` and use bundler. Update: +To update terraspace, update project's `Gemfile` and use bundler. Update: Gemfile @@ -28,3 +28,7 @@ Then run: bundle update Bundler will update terraspace and other dependencies to the latest. + +## Shim + +With a gem install, consider generating a [shim]({% link _docs/install/shim.md %}) so you don't have to remember to type `bundle exec` when running `terraspace` within the Terraspace project folder. diff --git a/_docs/install/gem/custom-version.md b/_docs/install/gem/custom-version.md index b3ed5ad..b60ec38 100644 --- a/_docs/install/gem/custom-version.md +++ b/_docs/install/gem/custom-version.md @@ -5,9 +5,11 @@ category: gem order: 2 --- -If you want or need to run a forked version of terraspace, here's how. +If you want or need to run a forked version of terraspace, here's how: -Clone down the project: +## Change Version Number + +First, clone down the source and change version number so you can identify that it's a custom version. Clone down the project: $ git clone https://github.com/boltops-tools/terraspace @@ -19,6 +21,30 @@ module Terraspace end ``` +There are 2 ways to use the custom version: + +1. Gemfile: Forked Git Source +2. Gem Package: Build and Install + +## Gemfile: Forked Git Source + +Point `terraspace ` to use your repo with the forked version. Example: + +Gemfile: + +```ruby +source "https://rubygems.org" +gem 'terraspace', git: 'https://github.com/REPO/terraspace', branch: "master" +``` + +Remember to change `REPO`, to your repo name. + +Then run: + + bundle + +## Gem Package: Build and Install + Build the gem package: $ bundle @@ -38,3 +64,7 @@ Or on any machine with Ruby installed. You can copy it to the machine, ssh into $ gem install terraspace-0.6.22.custom.gem $ terraspace -v 0.6.22.custom + +## Contributing + +Learning how to run a forked version of terraspace allows you to make changes to the framework. Consider improving terraspace by submitting a Pull Request. See: [Contributing]({% link _docs/contributing.md %}). diff --git a/_docs/install/gem/multiple-versions.md b/_docs/install/gem/multiple-versions.md index d1d6c13..06d1850 100644 --- a/_docs/install/gem/multiple-versions.md +++ b/_docs/install/gem/multiple-versions.md @@ -2,7 +2,7 @@ title: Installing and Using Multiple Versions of Terraspace nav_text: Multiple Versions category: gem -order: 3 +order: 1 --- If you're interested in running multiple or different versions of terraspace on the same machine, this page can help. @@ -31,25 +31,7 @@ Change terraspace version in Gemfile: 0.6.2 $ -## Long Answer: Why bundle exec? - -The key to running multiple versions is understanding how ruby, bundler, and system paths work. You see, when you run **any** cli command with `bundle exec` pretended, it affects the system load path. - -Example without: - - terraspace version - -Example with: - - bundle exec terraspace version - -The `bundle exec` is a wrapper that adjusts the load path. By using `bundle exec`, it ensures that the exact versions specified in `Gemfile.lock` are used. This includes, not only terraspace, but all ruby gems. - -When you don't use `bundle exec`, ruby uses the system load path. The versions that then get used are more dependent on your environment and how your system has been configured. In this case, Ruby has little choice but to make some assumptions, and usually, it uses the latest version. - -So when using terraspace without `bundle exec`, the latest terraspace version is used. Terraspace takes an extra step to help. It calls `bundle exec` early [internally](https://github.com/boltops-tools/terraspace/blob/master/lib/terraspace/autoloader.rb#L2) also. This ensures that all other dependencies are locked to `Gemfile.lock`. Terraspace is only able to pin all other gems at that point, though. This approach does conveniently spare you from having to type `bundle exec` and works great for most cases. - -It won't work when there's a later version of terraspace installed on the system, and your `Gemfile.lock` pins a different terraspace version. In this case, you'll need to use `bundle exec` or uninstall other versions of terraspace from your system. +To avoid having to remember to type `bundle exec`, you can use a [shim]({% link _docs/install/shim.md %}). ## Version Checking within Project Code @@ -86,4 +68,4 @@ The code starts to get messy, but it's an option. Instead, the general recommend ## Shim Wrapper -If have multiple versions of terraspace on the same system, you should always use the `bundle exec` command when you're inside the Terraspace project. This ensures that the terraspace version in the project's `Gemfile.lock` is used. Typing `bundle exec` can get old quick, so you can use a [shim wrapper]({% link _docs/misc/shim.md %}) to save yourself previous finger-typing energy. +If have multiple versions of terraspace on the same system, you should always use the `bundle exec` command when you're inside the Terraspace project. This ensures that the terraspace version in the project's `Gemfile.lock` is used. Typing `bundle exec` can get old quick, so you can use a [shim wrapper]({% link _docs/install/shim.md %}) to save yourself previous finger-typing energy. diff --git a/_docs/install/gem/version-locking.md b/_docs/install/gems-locking.md similarity index 74% rename from _docs/install/gem/version-locking.md rename to _docs/install/gems-locking.md index 3200a9c..3299320 100644 --- a/_docs/install/gem/version-locking.md +++ b/_docs/install/gems-locking.md @@ -1,22 +1,18 @@ --- -title: How to Lock Gem Versions -nav_text: Version Locking -category: gem -order: 1 +title: Gem Versions Locking +nav_text: Gems Locking --- -One of the benefits of installing terraspace as a gem is more control over the installation process. - -In the Ruby world locking dependencies are usually handled with [bundler](https://bundler.io/), `Gemfile` and `Gemfile.lock`. The generated Terraspace project with [terraspace new project]({% link _reference/terraspace-new-project.md %}) provides a starter Gemfile. It looks something like this: +Gem version locking is handled with [bundler](https://bundler.io/), `Gemfile` and `Gemfile.lock`. The generated Terraspace project with [terraspace new project]({% link _reference/terraspace-new-project.md %}) provides a starter `Gemfile`. It looks something like this: ```ruby source "https://rubygems.org" -gem "terraspace", '~> 0.6.20' +gem "terraspace", '~> 0.7.0' gem "rspec-terraspace" gem "terraspace_plugin_aws" ``` -In this example, terraspace itself is pinned by using a version specifier `~>`. This means that when `bundle` runs it will use at least version 0.6.20 and other patch versions above within the minor version are also ok. +In this example, terraspace itself is pinned by using a version specifier `~>`. This means that when `bundle` runs it will use at least version `0.7.0` and other patch versions above within the minor version are also ok. * Bundler Docs: [Gemfile](https://bundler.io/gemfile.html) @@ -24,7 +20,7 @@ You can add and specify additional gem version dependencies if you wish or need ```ruby source "https://rubygems.org" -gem "terraspace", '~> 0.6.20' +gem "terraspace", '~> 0.7.0' gem "rspec-terraspace" gem "terraspace_plugin_aws" # added for more control over the dependencies @@ -55,4 +51,4 @@ The issue can also be helped in another way: by reducing the dependencies footpr ## Terrapace Shim Wrapper -On certain system setups, you may also want or need to add a [terraspace shim]({% link _docs/misc/shim.md %}) to ensure that `bundle exec` gets called early enough. It's really system-dependent. Details are covered here: [Shim Wrapper]({% link _docs/misc/shim.md %}). +On certain system setups, you may want or need to add a [terraspace shim]({% link _docs/install/shim.md %}) to ensure that `bundle exec` gets called early enough. It's really system-dependent. Details are covered here: [Shim Wrapper]({% link _docs/install/shim.md %}). diff --git a/_docs/install/shim.md b/_docs/install/shim.md new file mode 100644 index 0000000..4a94e2b --- /dev/null +++ b/_docs/install/shim.md @@ -0,0 +1,80 @@ +--- +title: Shim Wrapper +--- + +Terraspace projects have a `Gemfile.lock`. This file ensures that gem dependencies for are pinned. To use it, you run `bundle exec terraspace`. It can be annoying to remember typing `bundle exec`, though. Using a shim spares you from having to remember this, saving you precious finger-typing energy. + +## Using a Shim + +A shim wrapper ensures that `bundle exec` is prepended in front of terraspace when you're within a project. You only have to set up the shim once. You can generate a shim with: + + $ terraspace new shim + create /usr/local/bin/terraspace + chmod /usr/local/bin/terraspace + +The shim looks something like this: + + #!/bin/bash + if [ -f config/app.rb ]; then + exec bundle exec terraspace "$@" + else + exec terraspace "$@" + fi + +By default, the shim is written to `/usr/local/bin/terraspace`. As long as `/usr/local/bin` is early enough in your system `$PATH`, you can type `terraspace` instead of `bundle exec terraspace`. + +You can change the path with the `--path` option. More info: [terraspace new shim]({% link _reference/terraspace-new-shim.md %}). + +The shim wrapper generally work for most systems, it might require adjustments depending on your system. + +## Standlone Installer Shim + +The [standalone installers]({% link _docs/install/standalone.md %}) actually generate a shim similar to above for you already. It looks something like this: + +{% include install/standalone-shim.md %} + +## Rbenv Shim Slowness + +If you are using rbenv, it can be [slow](https://github.com/rbenv/rbenv/issues/70) on some systems. You may want to consider replacing the shim that rbenv generates with a faster one. Here's an example: + +~/.rbenv/shims/terraspace + + #!/usr/bin/env bash + EXE=$(gem which terraspace | sed 's|lib/terraspace.rb|exe/terraspace|') + if [ -f config/app.rb ]; then + exec bundle exec $EXE "$@" + else + exec $EXE "$@" + fi + +## Multiple Terraspace Versions + +A shim is recommended when you have multiple versions of Terraspace installed on the same system. See: [Multiple Terraspace Versions]({% link _docs/install/gem/multiple-versions.md %}) + +## Long Answer: Why bundle exec? + +The key to understanding why `bundle exec` is needed sometimes is understadning Ruby, bundler, and system paths work. You see, when you run **any** cli command with `bundle exec` pretended, it affects the system load path. + +Example without: + + terraspace version + +Example with: + + bundle exec terraspace version + +Using `bundle exec` adjusts the load path. The load paths are adjusted to ensure that the exact versions specified in `Gemfile.lock` are used. This includes, not only terraspace, but all Ruby gem dependencies. + +When you don't use `bundle exec`, Ruby uses the first gems found in your system's load path. The versions are more dependent on your environment is configured. In this case, Ruby has little choice but to make some assumptions, and usually, it uses the latest version. + +So when using terraspace without `bundle exec`, the latest terraspace version installed on the system is used. Terraspace actually calls `bundle exec` super early on [internally](https://github.com/boltops-tools/terraspace/blob/master/lib/terraspace/autoloader.rb#L2). This also helps to ensure that dependencies are locked to `Gemfile.lock`. Terraspace is only able to pin all other gems at that point, though. This approach does conveniently spare you from having to type `bundle exec` and works great for most cases, but not all. + +It won't work when there's a later version of terraspace installed on the system, and your `Gemfile.lock` pins a different terraspace version. In this case, you'll need to use `bundle exec` or uninstall other versions of terraspace from your system. + +## Bundler already activated Warnings + +If you are seeing an error that says a gem dependency is "already activated", for example: + + You have already activated faraday 1.7.0, but your Gemfile requires faraday 0.17.4. Prepending `bundle exec` to your command may solve this. + +Prepending `bundle exec` should resolve the issue. Or you can generate a [shim]({% link _reference/terraspace-new-shim.md %}) as described above. diff --git a/_docs/install/standalone/centos.md b/_docs/install/standalone/centos.md index e42c923..ff4e9fa 100644 --- a/_docs/install/standalone/centos.md +++ b/_docs/install/standalone/centos.md @@ -57,6 +57,10 @@ You can also download the rpm package and install it directly. Here are the comm rpm -ivh terraspace-latest.rpm terraspace -h +To upgrade an existing install also use the `-U` flag. + + rpm -Uivh terraspace-latest.rpm + You can check [terraspace-latest.rpm.metadata.json](https://yum.boltops.com/packages/terraspace/terraspace-latest.rpm.metadata.json) to verify the package checksum. Here's the checksum command. sha256sum terraspace-latest.rpm diff --git a/_docs/install/standalone/details.md b/_docs/install/standalone/details.md index 386a900..8f9b9a4 100644 --- a/_docs/install/standalone/details.md +++ b/_docs/install/standalone/details.md @@ -25,6 +25,12 @@ Most users have `/usr/local/bin` configured in there PATH. So these wrappers sho If you wish not to have these wrappers generated for you, set `export TS_WRAPPERS=0` before running the installer. Without the wrapper scripts, to complete the terraspace standalone installation, you must add `/opt/terraspace/embedded/bin` to your PATH. See: [embedded bin path]({% link _docs/install/standalone/details/path.md %}). +## Terraspace wrapper + +The terraspace wrapper shim is unique in that it ensures that `bundle exec` is prepended when you are within a Terraspace project. It looks something like this: + +{% include install/standalone-shim.md %} + ## Terraform Terraform is not included with the standalone installer. This allows you to install and run the Terraform version you want to use. Here are [Terraform Install instructions]({% link _docs/install/terraform.md %}). diff --git a/_docs/install/standalone/details/permissions.md b/_docs/install/standalone/details/permissions.md index 627b57a..b428507 100644 --- a/_docs/install/standalone/details/permissions.md +++ b/_docs/install/standalone/details/permissions.md @@ -40,3 +40,5 @@ When the `/opt/terraspace` folder is not owned by your user, you won't be able t Password: To fix this issue, make sure `/opt/terraspace` is owned by your user, instead of repeatedly having to type your password for sudo. + +Also, running `sudo` means you're using bare shell with pretty much none of your environment settings or variables configured. Though there are ways to [preserve](https://stackoverflow.com/questions/8633461/how-to-keep-environment-variables-when-using-sudo) environment variables with `--preserve-env`, it's often better to avoid sudo as you'll run into different environmental differences and quirks. diff --git a/_docs/learn/aws/change.md b/_docs/learn/aws/change.md index 36e80f5..534b737 100644 --- a/_docs/learn/aws/change.md +++ b/_docs/learn/aws/change.md @@ -21,7 +21,7 @@ module "bucket" { } ``` -As, you can see there's a `var.acl` variable. One way to update the infrastructure is to change the variable in the `variables.tf` file directly. +As you can see there's a `var.acl` variable. One way to update the infrastructure is to change the variable in the `variables.tf` file directly. app/stacks/demo/variables.tf diff --git a/_docs/learn/azure/change.md b/_docs/learn/azure/change.md index 26b1f90..564f6d4 100644 --- a/_docs/learn/azure/change.md +++ b/_docs/learn/azure/change.md @@ -28,7 +28,7 @@ module "storage_account" { } ``` -As, you can see there's a `var.enable_https_traffic_only` variable. One way to update the infrastructure is to change the variable in the `variables.tf` file directly. +As you can see there's a `var.enable_https_traffic_only` variable. One way to update the infrastructure is to change the variable in the `variables.tf` file directly. app/stacks/demo/variables.tf diff --git a/_docs/learn/azure/next-steps.md b/_docs/learn/azure/next-steps.md index 8e19f63..3837fbc 100644 --- a/_docs/learn/azure/next-steps.md +++ b/_docs/learn/azure/next-steps.md @@ -4,6 +4,7 @@ search_title: Next Steps Azure --- {% include learn/next-steps.md provider="Azure" %} + * [Terraspace Azure Videos](https://learn.boltops.com/courses/terraspace-azure/lessons/terraspace-getting-started-with-azure-cloud) {% include learn/next-steps-more.md %} diff --git a/_docs/learn/gcp/change.md b/_docs/learn/gcp/change.md index f3d48ad..c8208fa 100644 --- a/_docs/learn/gcp/change.md +++ b/_docs/learn/gcp/change.md @@ -23,7 +23,7 @@ module "bucket" { } ``` -As, you can see there's a `var.uniform_bucket_level_access` variable. One way to update the infrastructure is to change the variable in the `variables.tf` file directly. +As you can see there's a `var.uniform_bucket_level_access` variable. One way to update the infrastructure is to change the variable in the `variables.tf` file directly. app/stacks/demo/variables.tf diff --git a/_docs/learn/onprem.md b/_docs/learn/onprem.md new file mode 100644 index 0000000..42702d1 --- /dev/null +++ b/_docs/learn/onprem.md @@ -0,0 +1,5 @@ +--- +title: Getting Started with Non-Cloud +--- + +{% include learn/start.md provider="Non-Cloud" %} diff --git a/_docs/learn/onprem/change.md b/_docs/learn/onprem/change.md new file mode 100644 index 0000000..3012c0a --- /dev/null +++ b/_docs/learn/onprem/change.md @@ -0,0 +1,57 @@ +--- +title: Change Infrastructure +search_title: Change Infrastructure AWS +--- + +Now that we have `random_pet` created, let's modify it. Here's the `demo/main.tf` again. + +app/stacks/demo/main.tf + +```terraform +module "pet" { + source = "../../modules/example" + length = var.length +} +``` + +As you can see there's a `var.length` variable. One way to update the infrastructure is to change the variable in the `variables.tf` file directly. + +app/stacks/demo/variables.tf + +```terraform +variable "length" { + type = number + description = "number of words" + default = 2 +} +``` + +However, you can also use `tfvars` files. Terraspace will automatically use `app/stacks/demo/tfvars` files according the `TS_ENV` value. The default value is `TS_ENV=dev`. We'll use tfvars files so we can use the same code for different environments. + +## Generate Starter Tfvars Files + +Addtionally, Terraspace can generate starter tfvar files for us with the `terraspace seed` command. + + $ terraspace seed demo + Reading: .terraspace-cache/us-west-2/dev/stacks/demo/variables.tf + create app/stacks/demo/tfvars/dev.tfvars + $ + +The produced file looks something like this: + +app/stacks/demo/tfvars/dev.tfvars + +```terraform +# Optional variables: +# length = "2" +``` + +Terraspace parses the `demo/variables.tf` file to generate the `tfvars/dev.tfvars` file. It detected that all the variables are optional. We'll uncomment length and change it to `length = 3`. + +app/stacks/demo/tfvars/dev.tfvars + +```terraform +# length = "3" # <= was changed +``` + +Next, we'll update the infrastructure. \ No newline at end of file diff --git a/_docs/learn/onprem/deploy.md b/_docs/learn/onprem/deploy.md new file mode 100644 index 0000000..7f8e238 --- /dev/null +++ b/_docs/learn/onprem/deploy.md @@ -0,0 +1,61 @@ +--- +title: Deploy Infrastructure +search_title: Deploy Infrastructure AWS +--- + +Let's go ahead and deploy the infrastructure + + $ terraspace up demo + +The `terraspace up` command will build the files and then essentially run `terraform apply`. + + $ terraspace up demo + Building .terraspace-cache/dev/stacks/demo + Built in .terraspace-cache/dev/stacks/demo + Current directory: .terraspace-cache/dev/stacks/demo + => terraform apply -input=false + + Terraform used the selected providers to generate the following execution + plan. Resource actions are indicated with the following symbols: + + create + + Terraform will perform the following actions: + + # module.pet.random_pet.this will be created + + resource "random_pet" "this" { + + id = (known after apply) + + length = 2 + + separator = "-" + } + + Plan: 1 to add, 0 to change, 0 to destroy. + + Changes to Outputs: + + pet_id = (known after apply) + + Do you want to perform these actions? + Terraform will perform the actions described above. + Only 'yes' will be accepted to approve. + + Enter a value: + +You get shown what will be provisioned and prompted with `Enter a value:` + +Type `yes` and press enter and you'll see terraform apply finishing. + + Enter a value: yes + module.pet.random_pet.this: Creating... + module.pet.random_pet.this: Creation complete after 0s [id=charmed-bee] + + Apply complete! Resources: 1 added, 0 changed, 0 destroyed. + + Outputs: + + pet_id = "charmed-bee" + $ + +You can see the `random_pet` got created. + +Note, you can also use the `-y` option to bypass the prompt. IE: `terraspace up demo -y`. + +Next, we'll make some changes to the infrastructure code. diff --git a/_docs/learn/onprem/destroy.md b/_docs/learn/onprem/destroy.md new file mode 100644 index 0000000..520c34e --- /dev/null +++ b/_docs/learn/onprem/destroy.md @@ -0,0 +1,55 @@ +--- +title: Destroy Infrastructure +search_title: Destroy Infrastructure AWS +--- + +Now that we've seen how to deploy infra, let's clean up and tear down the resources. + +To destroy the resources, run: + + terraspace down demo + +You'll be prompted to make sure you really want to delete these resources. + + $ terraspace down demo + Building .terraspace-cache/dev/stacks/demo + Built in .terraspace-cache/dev/stacks/demo + Current directory: .terraspace-cache/dev/stacks/demo + => terraform destroy + module.pet.random_pet.this: Refreshing state... [id=indirectly-game-grub] + + Terraform used the selected providers to generate the following execution + plan. Resource actions are indicated with the following symbols: + - destroy + + Terraform will perform the following actions: + # module.pet.random_pet.this will be destroyed + - resource "random_pet" "this" { + - id = "indirectly-game-grub" -> null + - length = 3 -> null + - separator = "-" -> null + } + Plan: 0 to add, 0 to change, 1 to destroy. + + + Changes to Outputs: + - pet_id = "indirectly-game-grub" -> null + + Do you really want to destroy all resources? + Terraform will destroy all your managed infrastructure, as shown above. + There is no undo. Only 'yes' will be accepted to confirm. + + Enter a value: + +Once again, we prompted to `Enter a value:`. Type `yes` and press enter to destroy the infrastructure. + + Enter a value: yes + module.pet.random_pet.this: Destroying... [id=indirectly-game-grub] + module.pet.random_pet.this: Destruction complete after 0s + + Destroy complete! Resources: 1 destroyed. + $ + +Congrats! You have successfully created, modified, and destroy infrastructure with terraspace. + +Next, we'll look at some next steps. diff --git a/_docs/learn/onprem/install.md b/_docs/learn/onprem/install.md new file mode 100644 index 0000000..e873e16 --- /dev/null +++ b/_docs/learn/onprem/install.md @@ -0,0 +1,6 @@ +--- +title: Install Terraspace +search_title: Install Terraspace Non-Cloud +--- + +{% include intro/install.md provider="Non-Cloud" %} \ No newline at end of file diff --git a/_docs/learn/onprem/new-project.md b/_docs/learn/onprem/new-project.md new file mode 100644 index 0000000..195581a --- /dev/null +++ b/_docs/learn/onprem/new-project.md @@ -0,0 +1,71 @@ +--- +title: New Project +search_title: New Project Non-Cloud +--- + +We'll use [terraspace new project]({% link _reference/terraspace-new-project.md %}) to generate a new terraspace project. + + $ terraspace new project infra --plugin none --examples + +For this tutorial, we're using the `--examples` option to generate a starter example. + + $ terraspace new project infra --plugin none --examples + => Creating new project called infra. + create infra + create infra/.gitignore + exist infra + create infra/config/terraform/backend.tf + create infra/config/terraform/provider.tf + => Creating new module called example. + create infra/app/modules/example + create infra/app/modules/example/main.tf + create infra/app/modules/example/outputs.tf + create infra/app/modules/example/variables.tf + => Creating new stack called demo. + create infra/app/stacks/demo + create infra/app/stacks/demo/main.tf + create infra/app/stacks/demo/outputs.tf + create infra/app/stacks/demo/variables.tf + $ cd infra # and start checking out the files + +The `--plugin none` option means no [cloud provider plugin]({% link _docs/plugins.md %}) is used at all. It's a lighter project. + +For more information about the folders see [Project Structure]({% link _docs/intro/structure.md %}). + +## Config Files + +Let's look at `config/terraform/backend.tf` + +```terraform +# This is where you put your backend declaration. Example: +# +# terraform { +# backend "local" { +# path = "terraform.tfstate" +# } +# } +# +# More examples: https://terraspace.cloud/docs/config/backend/examples/ +# +``` + +The backend is completely commented out. With a non-cloud generated project, Terraspace makes no assumptions about the backend you'll like to use. + +The default Terraform behavior is to use a local backend with a state file path at `terraform.tfstate`. So it works the same commented or uncommented out. + +You might want to check out how to configure different backends: [Backend Examples]({% link _docs/config/backend/examples/local.md %}). The [GitLab backend example]({% link _docs/config/backend/examples/gitlab.md %}) uses a http backend. + +Next, let's take a look at `config/terraform/provider.tf` + +```terraform +# This is where you put your provider declaration. +# +# If you end up adding a cloud provider, you should also configure a terraspace_plugin_* gem +# in the Terraspace project Gemfile and run bundle. +# +# See: https://terraspace.cloud/docs/plugins/ +``` + +The `provider.tf` is also just commented out with some instructions. Again, no cloud provider assumptions are made. + +Next, we'll review generated app folder files. diff --git a/_docs/learn/onprem/next-steps.md b/_docs/learn/onprem/next-steps.md new file mode 100644 index 0000000..eded74a --- /dev/null +++ b/_docs/learn/onprem/next-steps.md @@ -0,0 +1,10 @@ +--- +title: Next Steps +search_title: Next Steps Non-Cloud +--- + +{% include learn/next-steps.md provider="none" %} + +* [Terraspace Videos](https://learn.boltops.com/courses/terraspace-fundamentals/lessons/terraspace-quick-start) + +{% include learn/next-steps-more.md %} diff --git a/_docs/learn/onprem/review-project.md b/_docs/learn/onprem/review-project.md new file mode 100644 index 0000000..4654089 --- /dev/null +++ b/_docs/learn/onprem/review-project.md @@ -0,0 +1,49 @@ +--- +title: Review Project +search_title: Review Project Non-Cloud +--- + +Let's explore the generated app folder. + +## App Modules + +Let's check out the `app/modules/example` folder. + +main.tf + +```terraform +resource "random_pet" "this" { + length = var.length +} +``` + +variables.tf + +```terraform +variable "length" { + type = number + description = "number of words" + default = 2 +} +``` + +You can see that the starter example module creates a `random_pet` resource. + +## Stack Modules + +Next let's look at the generated `app/stacks/demo` that was created: + +app/stacks/demo/main.tf + +```terraform +module "pet" { + source = "../../modules/example" + length = var.length +} +``` + +You can see that it's just another terraform module, that will use the `app/modules/example` module to create the `random_pet`. + +{% include intro/modules-vs-stacks.md provider="none" %} + +Next, we'll deploy the infrastructure. diff --git a/_docs/learn/onprem/update.md b/_docs/learn/onprem/update.md new file mode 100644 index 0000000..495b2c4 --- /dev/null +++ b/_docs/learn/onprem/update.md @@ -0,0 +1,58 @@ +--- +title: Update Infrastructure +search_title: Update Infrastructure Non-Cloud +--- + +Let's update the infrastructure. + + $ terraspace up demo + +Terraspace will show you a preview of the changes and prompt you to update the infrastructure. + + $ terraspace up demo + Building .terraspace-cache/dev/stacks/demo + Built in .terraspace-cache/dev/stacks/demo + Current directory: .terraspace-cache/dev/stacks/demo + => terraform apply -input=false + module.pet.random_pet.this: Refreshing state... [id=charmed-bee] + + Terraform used the selected providers to generate the following execution + plan. Resource actions are indicated with the following symbols: + -/+ destroy and then create replacement + + Terraform will perform the following actions: + # module.pet.random_pet.this must be replaced + -/+ resource "random_pet" "this" { + ~ id = "charmed-bee" -> (known after apply) + ~ length = 2 -> 3 # forces replacement + # (1 unchanged attribute hidden) + } + Plan: 1 to add, 0 to change, 1 to destroy. + + Changes to Outputs: + ~ pet_id = "charmed-bee" -> (known after apply) + + Do you want to perform these actions? + Terraform will perform the actions described above. + Only 'yes' will be accepted to approve. + + Enter a value: + +Once again, we shown what will change and prompted to `Enter a value:`. Type `yes` and press enter. + + Enter a value: yes + module.pet.random_pet.this: Destroying... [id=charmed-bee] + module.pet.random_pet.this: Destruction complete after 0s + module.pet.random_pet.this: Creating... + module.pet.random_pet.this: Creation complete after 0s [id=indirectly-game-grub] + + Apply complete! Resources: 1 added, 0 changed, 1 destroyed. + + Outputs: + + pet_id = "indirectly-game-grub" + $ + +The modification has been applied. + +Next, we'll destroy the infrastructure. \ No newline at end of file diff --git a/_docs/misc/shim.md b/_docs/misc/shim.md deleted file mode 100644 index ff8aa98..0000000 --- a/_docs/misc/shim.md +++ /dev/null @@ -1,80 +0,0 @@ ---- -title: Shim Wrapper ---- - -A shim wrapper can be useful for some cases. - -## Bundler already activated Warnings - -For example, if you've [multiple versions of terraspace installed]({% link _docs/install/gem/multiple-versions.md %}) it can sometimes lead to dependencies resolution issues, and you'll see errors like this: - - You have already activated google-apis-core 0.3.0, but your Gemfile requires google-apis-core 0.2.1. Prepending `bundle exec` to your command may solve this. - -This is due to the ruby system and bundler `Gemfile.lock` dependencies not matching. There are a couple of options: - -1. **bundle update**: Update `Gemfile.lock` with bundle update. -2. **shim wrapper**: Run `bundle exec` in front of your commands with a shim wrapper. - -Approach #1 updates the `Gemfile.lock` dependencies to match the system and removes the warning. You won't need a shim in this case. We'll cover #2 next. - -## Shim Wrapper - -The shim wrapper essentially ensures that `bundle exec` is prepended in front of terraspace when you're within a project. This saves you precious finger-typing energy. You only have to set up the shim once. - -Here's a wrapper shim that will work with rbenv. We'll create it at `~/bin/terraspace` - -~/bin/terraspace - - #!/bin/bash - eval "$(rbenv init -)" - if [ -f config/app.rb ]; then - exec bundle exec terraspace "$@" - else - exec terraspace "$@" - fi - -Make the file executable: - - chmod a+x ~/bin/terraspace - -Then add `~/bin` to your PATH in your `~/.bash_profile` - - export PATH="~/bin:$PATH" - -The wrapper shim will prepend `bundle exec` whenever in a Terraspace project folder with a Gemfile. It will not prepend `bundle exec` outside of a Terraspace project. For example, if you are using `terraspace new project` generator. - -## Generating the Shim Wrapper - -You can also use terraspace to generate the shim wrapper. - - terraspace new shim - -You'll see something like this: - - $ terraspace new shim - create /usr/local/bin/terraspace - chmod /usr/local/bin/terraspace - -If you want to specify the path where you want the shim to be saved like so: - - terraspace new shim --path ~/bin/terraspace - -Note, the shim wrapper contains starter code. Though it should generally work for most systems, it might require adjustments depending on your system. - -## Rbenv Shim Slowness - -If you are using rbenv, it can be [slow](https://github.com/rbenv/rbenv/issues/70) on some systems. You may want to consider replacing the shim that rbenv generates with a faster one. Here's an example: - -~/.rbenv/shims/terraspace - - #!/usr/bin/env bash - EXE=$(gem which terraspace | sed 's|lib/terraspace.rb|exe/terraspace|') - if [ -f config/app.rb ]; then - exec bundle exec $EXE "$@" - else - exec $EXE "$@" - fi - -## Why The Need For bundle exec? - -See: [Multiple Terraspace Versions]({% link _docs/install/gem/multiple-versions.md %}) diff --git a/_docs/plugins.md b/_docs/plugins.md index 7b79d4d..9b17295 100644 --- a/_docs/plugins.md +++ b/_docs/plugins.md @@ -4,18 +4,22 @@ title: Terraspace Plugins Terraspace is a framework that adds conveniences to your Terraform workflow. For example, Terraspace automatically creates the backend storage like the s3 bucket, azure storage account, and gcs bucket. Each of these implementations are cloud-specific. Terraspace Plugins add cloud-specific functionality. -## Custom Plugins +## Cloud Plugins -The baseline plugins that currently ship with Terraspace Core are: +The baseline plugins are: * [terraspace_plugin_aws]({% link _docs/plugins/aws.md %}) * [terraspace_plugin_azurerm]({% link _docs/plugins/azurerm.md %}) * [terraspace_plugin_google]({% link _docs/plugins/google.md %}) -You can make a custom plugin by looking at one of the baseline plugins. You create interface classes and register them to Terrapace. +## Custom Plugin -Then you install the plugin with: +You can make a custom plugin by looking at one of the baseline plugins. You create interface classes and register them to Terrapace. You can install the plugin by adding to your Terraspace project's `Gemfile`: - gem install terraspace_plugin_MY_PLUGIN + gem "terraspace_plugin_MY_PLUGIN" + +And running + + bundle Once installed, the custom plugin integrates with Terraspace directly for a smooth user experience. diff --git a/_docs/plugins/aws.md b/_docs/plugins/aws.md index c606683..171a37a 100644 --- a/_docs/plugins/aws.md +++ b/_docs/plugins/aws.md @@ -4,7 +4,7 @@ title: AWS Terraspace Plugin The AWS Terraspace Plugin adds support for the automatic creation of the backend storage s3 bucket and dynamodb table. By default: -* S3 Buckets are secured with [encryption](https://docs.aws.amazon.com/AmazonS3/latest/dev/bucket-encryption.html), have an [enforce ssl bucket policy](https://aws.amazon.com/premiumsupport/knowledge-center/s3-bucket-policy-for-config-rule/), have [versioning enabled](https://docs.aws.amazon.com/AmazonS3/latest/dev/Versioning.html), and have a [lifecycle policy](https://docs.aws.amazon.com/AmazonS3/latest/user-guide/create-lifecycle.html). [Bucket server access logging](https://docs.aws.amazon.com/AmazonS3/latest/dev/ServerLogs.html) and also be optionally enabled. +* S3 Buckets are secured with [encryption](https://docs.aws.amazon.com/AmazonS3/latest/dev/bucket-encryption.html), have an [enforce ssl bucket policy](https://aws.amazon.com/premiumsupport/knowledge-center/s3-bucket-policy-for-config-rule/), have [versioning enabled](https://docs.aws.amazon.com/AmazonS3/latest/dev/Versioning.html), have a [lifecycle policy](https://docs.aws.amazon.com/AmazonS3/latest/user-guide/create-lifecycle.html), and [block public access](https://aws.amazon.com/s3/features/block-public-access/). [Bucket server access logging](https://docs.aws.amazon.com/AmazonS3/latest/dev/ServerLogs.html) and also be optionally enabled. * DynamoDB tables have [encryption enabled](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/EncryptionAtRest.html) using the AWS Managed KMS Key for DynamoDB. The plugin settings are configurable with: @@ -14,17 +14,22 @@ config/plugins/aws.rb ```ruby TerraspacePluginAws.configure do |config| config.auto_create = true # set to false to completely disable auto creation + config.tags = {key1: "value1". key2: "value2"} # set for both s3 bucket and dynamodb table + config.tag_existing = true # if bucket or dynamodb already exists will tag them. Tags are appended. + config.s3.access_logging = false # false is the default setting + config.s3.block_public_access = true config.s3.encryption = true config.s3.enforce_ssl = true - config.s3.versioning = true config.s3.lifecycle = true - config.s3.access_logging = false # false is the default setting + config.s3.versioning = true config.s3.secure_existing = false # run the security controls on existing buckets. by default, only run on newly created bucket the first time + # config.s3.tags = {} # override config.tags setting config.dynamodb.encryption = true config.dynamodb.kms_master_key_id = nil config.dynamodb.sse_type = "KMS" + # config.dynamodb.tags = {} # override config.tags setting end ``` @@ -33,14 +38,18 @@ end Name | Description | Default ---|---|--- auto_create | Whether or not to automatically create the S3 bucket and DynamoDB table. | true +tag_existing | Whether or not to tag already created or existing buckets. When turned off, tagging on runs when the s3 bucket or dynamo table is initially created. | true +tags | Tags for both the s3 bucket and dynamodb table. Respected if the `s3.tags` and `dynamodb.tags` are not set. | {} +dynamodb.encryption | Whether or not enable encryption on the DynamoDB table. | true +dynamodb.kms_master_key_id | Specify the KMS key to use. By default, the default DynamoDB key associated with the AWS account is used. | nil +dynamodb.sse_type | Server-side encryption type. | "KMS" +dynamodb.tags | Tags the dynamodb table. Overrides `tags`. | {} +s3.access_logging | Whether or not to enable access logging on the S3 bucket. | false s3.encryption | Whether or not to enable S3 bucket encryption. | true s3.enforce_ssl | Whether or not to add a S3 bucket policy that enforces SSL. | true -s3.versioning | Whether or not to enable versioning on the S3 bucket. | true s3.lifecycle | Whether or not to add a lifecycle policy that cleans up old versions to the S3 bucket. | true -s3.access_logging | Whether or not to enable access logging on the S3 bucket. | false s3.secure_existing | Whether or not to run the security controls on existing buckets. By default, only run on newly created bucket the first time. | false -dynamodb.encryption | Whether or not enable encryption on the DynamoDB table. | true -dynamodb.kms_master_key_id | Specify the KMS key to use. By default, the default DynamoDB key associated with the AWS account is used. | nil -dynamodb.sse_type | Server-side encryption type. | "KMS" +s3.tags | Tags the s3 bucket. Overrides `tags`. | {} +s3.versioning | Whether or not to enable versioning on the S3 bucket. | true The full list refer to plugin source code: [terraspace_plugin_aws](https://github.com/boltops-tools/terraspace_plugin_aws/blob/master/lib/terraspace_plugin_aws/interfaces/config.rb). diff --git a/_includes/config/backend/env-in-bucket-name.md b/_includes/config/backend/env-in-bucket-name.md new file mode 100644 index 0000000..c6d4a47 --- /dev/null +++ b/_includes/config/backend/env-in-bucket-name.md @@ -0,0 +1,5 @@ +___ + +## Why Is Env in Bucket Name? + +By default, the bucket name has the `ENV` at the end. This is done so we can easily see which environment the bucket stores Terraform statefiles for. This quickly helps with debugging. If you prefer not to have the `ENV` at the end of the bucket name, remove it after generating the project with `terraspace new project`. diff --git a/_includes/install/standalone-shim.md b/_includes/install/standalone-shim.md new file mode 100644 index 0000000..2f09820 --- /dev/null +++ b/_includes/install/standalone-shim.md @@ -0,0 +1,11 @@ +/usr/local/bin/terraspace + + #!/bin/bash + unset GEM_HOME + unset GEM_PATH + export PATH=/opt/terraspace/embedded/bin:$PATH + if [ -f config/app.rb ]; then + exec bundle exec terraspace "$@" + else + exec terraspace "$@" + fi diff --git a/_includes/intro/install.md b/_includes/intro/install.md index 8927541..8c5a6de 100644 --- a/_includes/intro/install.md +++ b/_includes/intro/install.md @@ -4,15 +4,15 @@ Install terraspace via RubyGems. gem install terraspace -Ruby 2.7 and above is recommended. For other ways to install Terraspace see: [Install Docs]({% link _docs/install.md %}). +Ruby 3.0 and above is recommended. For other ways to install Terraspace see: [Install Docs]({% link _docs/install.md %}). ## Terraform Terraspace calls the `terraform` CLI. You will need terraform installed. Refer to the [Terraform installation instructions]({% link _docs/install/terraform.md %}) to install terraform for your system. Terraform Terraform v0.12 and above is recommended. -## Check Setup +## Setup Check You can use this command to check your setup: - terraspace check_setup + terraspace setup check diff --git a/_includes/intro/modules-vs-stacks.md b/_includes/intro/modules-vs-stacks.md index 018db1e..f7dce0e 100644 --- a/_includes/intro/modules-vs-stacks.md +++ b/_includes/intro/modules-vs-stacks.md @@ -5,4 +5,8 @@ Both modules and stacks are terraform modules. The difference is organizational * Modules are reusable pieces of code. Generally, it contains non-business specific logic. * Stacks are meant to be used to group together modules. Generally, this is where business-specific logic goes. -For example, the `app1` stack could be designed to use the `instance` module. Another, `app2` stack could use the `instance` and `rds` modules. +{% if include.provider == "none" %} +For example, the `app1` stack could be designed to use a `server` module. Another, `app2` stack could use a `server` and a `database` modules. +{% else %} +For example, the `app1` stack could be designed to use an `instance` module. Another, `app2` stack could use an `instance` and `rds` modules. +{% endif %} \ No newline at end of file diff --git a/_includes/learn/next-steps.md b/_includes/learn/next-steps.md index 78bad63..e4605dc 100644 --- a/_includes/learn/next-steps.md +++ b/_includes/learn/next-steps.md @@ -1,4 +1,13 @@ -You've seen how to get started with Terraspace and {{ include.provider }}. From here, you can check out the Docs to learn more: +{% if include.provider == "none" %} +You've seen how to get started with Terraspace without a cloud provider at all. Next, you might be interested in a provider with on-prem capabilities. + +* [OpenStack](https://registry.terraform.io/providers/terraform-provider-openstack/openstack/latest/docs) +* [VMWare vSphere](https://registry.terraform.io/providers/hashicorp/vsphere/latest/docs) + +From here, you can check out the Docs to learn more: +{% else %} +You've seen how to get started with Terraspace and {{ include.provider }}. You can also check out the Docs to learn more: +{% endif %} * [Intro]({% link _docs/intro.md %}): Review Terraform intro features. * [Backend Config]({% link _docs/config/backend.md %}): Configure the backend, where to store the state file: @@ -8,5 +17,4 @@ You've seen how to get started with Terraspace and {{ include.provider }}. From ## Learn Videos -Watch BoltOps Learn video series: - +Watch BoltOps Learn video series: \ No newline at end of file diff --git a/_includes/sidebar.html b/_includes/sidebar.html index a4b96ee..9bc922b 100644 --- a/_includes/sidebar.html +++ b/_includes/sidebar.html @@ -41,6 +41,18 @@
  • Next Steps
  • +
  • Non-Cloud + +
  • Terraspace vs Others
  • Config @@ -108,6 +122,14 @@
  • App
  • Backend @@ -312,7 +334,6 @@
  • Misc