Terraform provider source

Terraform provider source DEFAULT

Terraform Provider for Google Cloud Platform

Maintainers

This provider plugin is maintained by:

Requirements

Using the provider

See the Google Provider documentation to get started using the Google provider.

We also maintain the 'google-beta' provider for preview features and features at a beta launch stage. See Provider Versions for more details on how to use .

Upgrading the provider

The Google provider doesn't upgrade automatically once you've started using it. After a new release you can run

to upgrade to the latest stable version of the Google provider. See the Terraform website for more information on provider upgrades, and how to set version constraints on your provider.

Building the provider

Clone repository to:

$ mkdir -p $GOPATH/src/github.com/hashicorp;cd$GOPATH/src/github.com/hashicorp $ git clone [email protected]:hashicorp/terraform-provider-google

Enter the provider directory and build the provider

$ cd$GOPATH/src/github.com/hashicorp/terraform-provider-google $ make build

Developing the provider

If you wish to work on the provider, you'll first need Go installed on your machine (version + is required). You can use goenv to manage your Go version. You'll also need to correctly setup a GOPATH, as well as adding to your .

To compile the provider, run . This will build the provider and put the provider binary in the directory.

$ make build $ $GOPATH/bin/terraform-provider-google

For guidance on common development practices such as testing changes or vendoring libraries, see the contribution guidelines. If you have other development questions we don't cover, please file an issue!

Sours: https://github.com/hashicorp/terraform-provider-google

» Provider Requirements

Note: This page is about a feature of Terraform and later; it also describes how to use the more limited version of that feature that was available in Terraform

Terraform relies on plugins called "providers" to interact with remote systems.

Terraform configurations must declare which providers they require, so that Terraform can install and use them. Additionally, some providers require configuration (like endpoint URLs or cloud regions) before they can be used.

  • This page documents how to declare providers so Terraform can install them.

  • The Provider Configuration page documents how to configure settings for providers.

» Requiring Providers

Each Terraform module must declare which providers it requires, so that Terraform can install and use them. Provider requirements are declared in a block.

A provider requirement consists of a local name, a source location, and a version constraint:

The block must be nested inside the top-level block (which can also contain other settings).

Each argument in the block enables one provider. The key determines the provider's local name (its unique identifier within this module), and the value is an object with the following elements:

Note: The syntax for was added in Terraform v Previous versions of Terraform used a version constraint string instead of an object (like ), and had no way to specify provider source addresses. If you want to write a module that works with both Terraform v and v, see vCompatible Provider Requirements below.

» Names and Addresses

Each provider has two identifiers:

  • A unique source address, which is only used when requiring a provider.
  • A local name, which is used everywhere else in a Terraform module.

Note: Prior to Terraform , providers only had local names, since Terraform could only automatically download providers distributed by HashiCorp.

» Local Names

Local names are module-specific, and are assigned when requiring a provider. Local names must be unique per-module.

Outside of the block, Terraform configurations always refer to providers by their local names. For example, the following configuration declares as the local name for , then uses that local name when configuring the provider:

Users of a provider can choose any local name for it. However, nearly every provider has a preferred local name, which it uses as a prefix for all of its resource types. (For example, resources from all begin with , like or .)

Whenever possible, you should use a provider's preferred local name. This makes your configurations easier to understand, and lets you omit the meta-argument from most of your resources. (If a resource doesn't specify which provider configuration to use, Terraform interprets the first word of the resource type as a local provider name.)

» Source Addresses

A provider's source address is its global identifier. It also specifies the primary location where Terraform can download it.

Source addresses consist of three parts delimited by slashes (), as follows:

  • Hostname (optional): The hostname of the Terraform registry that distributes the provider. If omitted, this defaults to , the hostname of the public Terraform Registry.

  • Namespace: An organizational namespace within the specified registry. For the public Terraform Registry and for Terraform Cloud's private registry, this represents the organization that publishes the provider. This field may have other meanings for other registry hosts.

  • Type: A short name for the platform or system the provider manages. Must be unique within a particular namespace on a particular registry host.

    The type is usually the provider's preferred local name. (There are exceptions; for example, is an alternate release channel for , so its preferred local name is . If in doubt, check the provider's documentation.)

For example, the official HTTP provider belongs to the namespace on , so its source address is or, more commonly, just .

The source address with all three components given explicitly is called the provider's fully-qualified address. You will see fully-qualified address in various outputs, like error messages, but in most cases a simplified display version is used. This display version omits the source host when it is the public registry, so you may see the shortened version instead of .

Note: If you omit the argument when requiring a provider, Terraform uses an implied source address of . This is a backward compatibility feature to support the transition to Terraform ; in modules that require or later, we recommend using explicit source addresses for all providers.

» Handling Local Name Conflicts

Whenever possible, we recommend using a provider's preferred local name, which is usually the same as the "type" portion of its source address.

However, it's sometimes necessary to use two providers with the same preferred local name in the same module, usually when the providers are named after a generic infrastructure type. Terraform requires unique local names for each provider in a module, so you'll need to use a non-preferred name for at least one of them.

When this happens, we recommend combining each provider's namespace with its type name to produce compound local names with a dash:

Terraform won't be able to guess either provider's name from its resource types, so you'll need to specify a meta-argument for every affected resource. However, readers and maintainers of your module will be able to easily understand what's happening, and avoiding confusion is much more important than avoiding typing.

» Version Constraints

Each provider plugin has its own set of available versions, allowing the functionality of the provider to evolve over time. Each provider dependency you declare should have a version constraint given in the argument so Terraform can select a single version per provider that all modules are compatible with.

The argument is optional; if omitted, Terraform will accept any version of the provider as compatible. However, we strongly recommend specifying a version constraint for every provider your module depends on.

To ensure Terraform always installs the same provider versions for a given configuration, you can use Terraform CLI to create a dependency lock file and commit it to version control along with your configuration. If a lock file is present, Terraform Cloud, CLI, and Enterprise will all obey it when installing providers.

Hands-on: Try the Lock and Upgrade Provider Versions tutorial on HashiCorp Learn.

» Best Practices for Provider Versions

Each module should at least declare the minimum provider version it is known to work with, using the version constraint syntax:

A module intended to be used as the root of a configuration — that is, as the directory where you'd run — should also specify the maximum provider version it is intended to work with, to avoid accidental upgrades to incompatible new versions. The operator is a convenient shorthand for allowing only patch releases within a specific minor release:

Do not use (or other maximum-version constraints) for modules you intend to reuse across many configurations, even if you know the module isn't compatible with certain newer versions. Doing so can sometimes prevent errors, but more often it forces users of the module to update many modules simultaneously when performing routine upgrades. Specify a minimum version, document any known incompatibilities, and let the root module manage the maximum version.

» Built-in Providers

While most Terraform providers are distributed separately as plugins, there is currently one provider that is built in to Terraform itself, which provides the data source.

Because this provider is built in to Terraform, you don't need to declare it in the block in order to use its features. However, for consistency it does have a special provider source address, which is . This address may sometimes appear in Terraform's error messages and other output in order to unambiguously refer to the built-in provider, as opposed to a hypothetical third-party provider with the type name "terraform".

There is also an existing provider with the source address , which is an older version of the now-built-in provider that was used by older versions of Terraform. is not compatible with Terraform v or later and should never be declared in a block.

» In-house Providers

Anyone can develop and distribute their own Terraform providers. See the Call APIs with Terraform Providers collection on HashiCorp Learn for more about provider development.

Some organizations develop their own providers to configure proprietary systems, and wish to use these providers from Terraform without publishing them on the public Terraform Registry.

One option for distributing such a provider is to run an in-house private registry, by implementing the provider registry protocol.

Running an additional service just to distribute a single provider internally may be undesirable, so Terraform also supports other provider installation methods, including placing provider plugins directly in specific directories in the local filesystem, via filesystem mirrors.

All providers must have a source address that includes (or implies) the hostname of a registry, but that hostname does not need to provide an actual registry service. For in-house providers that you intend to distribute from a local filesystem directory, you can use an arbitrary hostname in a domain your organization controls.

For example, if your corporate domain were then you might choose to use as your placeholder hostname, even if that hostname doesn't actually resolve in DNS. You can then choose any namespace and type you wish to represent your in-house provider under that hostname, giving a source address like :

To make version of this provider available for installation from the local filesystem, choose one of the implied local mirror directories and create a directory structure under it like this:

Under that directory, create one additional directory representing the platform where you are running Terraform, such as for Linux on an AMD64/x64 processor, and then place the provider plugin executable and any other needed files in that directory.

Thus, on a Windows system, the provider plugin executable file might be at the following path:

If you later decide to switch to using a real private provider registry rather than distribute binaries out of band, you can deploy the registry server at and retain the same namespace and type names, in which case your existing modules will require no changes to locate the same provider using your registry server.

» vCompatible Provider Requirements

Explicit provider source addresses were introduced with Terraform v, so the full provider requirements syntax is not supported by Terraform v

However, in order to allow writing modules that are compatible with both Terraform v and v, versions of Terraform between v and v will accept but ignore the argument in a block.

Consider the following example written for Terraform v

Terraform v will accept syntax like the above but will understand it in the same way as the following vstyle syntax:

In other words, Terraform v ignores the argument and considers only the argument, using the given local name as the un-namespaced provider type to install.

When writing a module that is compatible with both Terraform v and Terraform v or later, you must follow the following additional rules so that both versions will select the same provider to install:

  • Use only providers that can be automatically installed by Terraform v Third-party providers, such as community providers in the Terraform Registry, cannot be selected by Terraform v because it does not support the hierarchical source address namespace.

  • Ensure that your chosen local name exactly matches the "type" portion of the source address given in the argument, such as both being "aws" in the examples above, because Terraform v will use the local name to determine which provider plugin to download and install.

  • If the provider belongs to the namespace, as with the provider shown above, omit the argument and allow Terraform v to select the namespace by default.

  • Provider type names must always be written in lowercase. Terraform v treats provider source addresses as case-insensitive, but Terraform v considers its legacy-style provider names to be case-sensitive. Using lowercase will ensure that the name is selectable by both Terraform major versions.

This compatibility mechanism is provided as a temporary transitional aid only. When Terraform v detects a use of the new argument it doesn't understand, it will emit a warning to alert the user that it is disregarding the source address given in that argument.

Sours: https://www.terraform.io/docs/language/providers/requirements.html
  1. Roslyn garden apartments
  2. Aliexpress nes
  3. Split ring float
  4. Khaani ep 12

» Providers Within Modules

In a configuration with multiple modules, there are some special considerations for how resources are associated with provider configurations.

Each resource in the configuration must be associated with one provider configuration. Provider configurations, unlike most other concepts in Terraform, are global to an entire Terraform configuration and can be shared across module boundaries. Provider configurations can be defined only in a root Terraform module.

Providers can be passed down to descendent modules in two ways: either implicitly through inheritance, or explicitly via the argument within a block. These two options are discussed in more detail in the following sections.

A module intended to be called by one or more other modules must not contain any blocks. A module containing its own provider configurations is not compatible with the , , and arguments that were introduced in Terraform v For more information, see Legacy Shared Modules with Provider Configurations.

Provider configurations are used for all operations on associated resources, including destroying remote objects and refreshing state. Terraform retains, as part of its state, a reference to the provider configuration that was most recently used to apply changes to each resource. When a block is removed from the configuration, this record in the state will be used to locate the appropriate configuration because the resource's argument (if any) will no longer be present in the configuration.

As a consequence, you must ensure that all resources that belong to a particular provider configuration are destroyed before you can remove that provider configuration's block from your configuration. If Terraform finds a resource instance tracked in the state whose provider configuration block is no longer available then it will return an error during planning, prompting you to reintroduce the provider configuration.

» Provider Version Constraints in Modules

Although provider configurations are shared between modules, each module must declare its own provider requirements, so that Terraform can ensure that there is a single version of the provider that is compatible with all modules in the configuration and to specify the source address that serves as the global (module-agnostic) identifier for a provider.

To declare that a module requires particular versions of a specific provider, use a block inside a block:

A provider requirement says, for example, "This module requires version v of the provider and will refer to it as ." It doesn't, however, specify any of the configuration settings that determine what remote endpoints the provider will access, such as an AWS region; configuration settings come from provider configurations, and a particular overall Terraform configuration can potentially have several different configurations for the same provider.

» Provider Aliases Within Modules

To declare multiple configuration names for a provider within a module, add the argument:

The above requirements are identical to the previous, with the addition of the alias provider configuration name , which can be referenced by resources using the argument.

If you are writing a shared Terraform module, constrain only the minimum required provider version using a constraint. This should specify the minimum version containing the features your module relies on, and thus allow a user of your module to potentially select a newer provider version if other features are needed by other parts of their overall configuration.

» Implicit Provider Inheritance

For convenience in simple configurations, a child module automatically inherits default (un-aliased) provider configurations from its parent. This means that explicit blocks appear only in the root module, and downstream modules can simply declare resources for that provider and have them automatically associated with the root provider configurations.

For example, the root module might contain only a block and a block to instantiate a child module:

The child module can then use any resource from this provider with no further provider configuration required:

We recommend using this approach when a single configuration for each provider is sufficient for an entire configuration.

Note: Only provider configurations are inherited by child modules, not provider source or version requirements. Each module must declare its own provider requirements. This is especially important for non-HashiCorp providers.

In more complex situations there may be multiple provider configurations, or a child module may need to use different provider settings than its parent. For such situations, you must pass providers explicitly.

» Passing Providers Explicitly

When child modules each need a different configuration of a particular provider, or where the child module requires a different provider configuration than its parent, you can use the argument within a block to explicitly define which provider configurations are available to the child module. For example:

The argument within a block is similar to the argument within a resource, but is a map rather than a single string because a module may contain resources from many different providers.

The keys of the map are provider configuration names as expected by the child module, and the values are the names of corresponding configurations in the current module.

Once the argument is used in a block, it overrides all of the default inheritance behavior, so it is necessary to enumerate mappings for all of the required providers. This is to avoid confusion and surprises that may result when mixing both implicit and explicit provider passing.

Additional provider configurations (those with the argument set) are never inherited automatically by child modules, and so must always be passed explicitly using the map. For example, a module that configures connectivity between networks in two AWS regions is likely to need both a source and a destination region. In that case, the root module may look something like this:

The subdirectory must then declare the configuration aliases for the provider so the calling module can pass configurations with these names in its argument:

Each resource should then have its own attribute set to either or to choose which of the two provider configurations to use.

» Legacy Shared Modules with Provider Configurations

In Terraform v and earlier there was no explicit way to use different configurations of a provider in different modules in the same configuration, and so module authors commonly worked around this by writing blocks directly inside their modules, making the module have its own separate provider configurations separate from those declared in the root module.

However, that pattern had a significant drawback: because a provider configuration is required to destroy the remote object associated with a resource instance as well as to create or update it, a provider configuration must always stay present in the overall Terraform configuration for longer than all of the resources it manages. If a particular module includes both resources and the provider configurations for those resources then removing the module from its caller would violate that constraint: both the resources and their associated providers would, in effect, be removed simultaneously.

Terraform v introduced the mechanisms described in earlier sections to allow passing provider configurations between modules in a structured way, and thus we explicitly recommended against writing a child module with its own provider configuration blocks. However, that legacy pattern continued to work for compatibility purposes -- though with the same drawback -- until Terraform v

Terraform v introduced the possibility for a module itself to use the , , and arguments, but the implementation of those unfortunately conflicted with the support for the legacy pattern.

To retain the backward compatibility as much as possible, Terraform v continues to support the legacy pattern for module blocks that do not use these new features, but a module with its own provider configurations is not compatible with , , or . Terraform will produce an error if you attempt to combine these features. For example:

To make a module compatible with the new features, you must remove all of the blocks from its definition.

If the new version of the module declares , or if the calling module needs the child module to use different provider configurations than its own default provider configurations, the calling module must then include an explicit argument to describe which provider configurations the child module will use:

Since the association between resources and provider configurations is static, module calls using or cannot pass different provider configurations to different instances. If you need different instances of your module to use different provider configurations then you must use a separate block for each distinct set of provider configurations:

Sours: https://www.terraform.io/docs/language/modules/develop/providers.html
Creating a Terraform Provider for Just About Anything

Terraform Provider for AWS

Terraform logo

Forums

The Terraform AWS provider is a plugin for Terraform that allows for the full lifecycle management of AWS resources. This provider is maintained internally by the HashiCorp AWS Provider team.

Please note: We take Terraform's security and our users' trust very seriously. If you believe you have found a security issue in the Terraform AWS Provider, please responsibly disclose by contacting us at [email protected]

Quick Starts

Documentation

Full, comprehensive documentation is available on the Terraform website:

https://terraform.io/docs/providers/aws/index.html

Roadmap

Our roadmap for expanding support in Terraform for AWS resources can be found in our Roadmap which is published quarterly.

Frequently Asked Questions

Responses to our most frequently asked questions can be found in our FAQ

Contributing

The Terraform AWS Provider is the work of thousands of contributors. We appreciate your help!

To contribute, please read the contribution guidelines: Contributing to Terraform - AWS Provider

Sours: https://github.com/hashicorp/terraform-provider-aws

Source terraform provider

» Providers

Hands-on: Try the Perform CRUD Operations with Providers tutorial on HashiCorp Learn.

Terraform relies on plugins called "providers" to interact with cloud providers, SaaS providers, and other APIs.

Terraform configurations must declare which providers they require so that Terraform can install and use them. Additionally, some providers require configuration (like endpoint URLs or cloud regions) before they can be used.

» What Providers Do

Each provider adds a set of resource types and/or data sources that Terraform can manage.

Every resource type is implemented by a provider; without providers, Terraform can't manage any kind of infrastructure.

Most providers configure a specific infrastructure platform (either cloud or self-hosted). Providers can also offer local utilities for tasks like generating random numbers for unique resource names.

» Where Providers Come From

Providers are distributed separately from Terraform itself, and each provider has its own release cadence and version numbers.

The Terraform Registry is the main directory of publicly available Terraform providers, and hosts providers for most major infrastructure platforms.

» Provider Documentation

Each provider has its own documentation, describing its resource types and their arguments.

The Terraform Registry includes documentation for a wide range of providers developed by HashiCorp, third-party vendors, and our Terraform community. Use the "Documentation" link in a provider's header to browse its documentation.

Provider documentation in the Registry is versioned; you can use the version menu in the header to change which version you're viewing.

For details about writing, generating, and previewing provider documentation, see the provider publishing documentation.

» How to Use Providers

To use resources from a given provider, you need to include some information about it in your configuration. See the following pages for details:

  • Provider Requirements documents how to declare providers so Terraform can install them.

  • Provider Configuration documents how to configure settings for providers.

  • Dependency Lock File documents an additional HCL file that can be included with a configuration, which tells Terraform to always use a specific set of provider versions.

» Provider Installation

  • Terraform Cloud and Terraform Enterprise install providers as part of every run.

  • Terraform CLI finds and installs providers when initializing a working directory. It can automatically download providers from a Terraform registry, or load them from a local mirror or cache. If you are using a persistent working directory, you must reinitialize whenever you change a configuration's providers.

    To save time and bandwidth, Terraform CLI supports an optional plugin cache. You can enable the cache using the setting in the CLI configuration file.

To ensure Terraform always installs the same provider versions for a given configuration, you can use Terraform CLI to create a dependency lock file and commit it to version control along with your configuration. If a lock file is present, Terraform Cloud, CLI, and Enterprise will all obey it when installing providers.

Hands-on: Try the Lock and Upgrade Provider Versions tutorial on HashiCorp Learn.

» How to Find Providers

To find providers for the infrastructure platforms you use, browse the providers section of the Terraform Registry.

Some providers on the Registry are developed and published by HashiCorp, some are published by platform maintainers, and some are published by users and volunteers. The provider listings use the following badges to indicate who develops and maintains a given provider.

» How to Develop Providers

Providers are written in Go, using the Terraform Plugin SDK. For more information on developing providers, see:

Sours: https://www.terraform.io/docs/language/providers/index.html
Terraform Modules \u0026 Providers: Check Your Source

Recently, we announced some exciting plans for the HashiCorp Terraform Registry: we will be adding Terraform providers in the Registry. We've started with HashiCorp maintained providers, which will continue to be installed automatically on , and are working to include all Terraform providers. Once that happens, Terraform will be able to automatically download and install all providers published in the Registry, including community providers.

While the installation process for HashiCorp maintained providers isn't changing, the configuration language is getting an update to support the eventual inclusion of partner and community providers in the Terraform Registry. Note, however, that we are not planning to make any breaking changes before the release of Terraform As we work on these updates to the configuration language, we'll keep you posted on what will change or look different. For now, we're excited to show you some new—and optional—enhancements to the configuration language in upcoming releases.

»Provider Source

When using the setting to specify a version constraint, Terraform currently assumes the source is (or for older versions). Both and are populated by the providers grouped within the the terraform-providers organization on GitHub.

In order to simplify using providers from other sources, we will be extending to allow a registry source for any provider. Authors can host and publish providers to the Registry from their own GitHub repositories.

You won't need to declare the source if you are using one of HashiCorp's providers. Terraform will continue to automatically download them from the appropriate source. Instead, this feature enables you to declare the provider source and Terraform will automatically download it during . Our goal is to simplify provider use, offering streamlined access to partner and community providers while also providing clear links to the ownership of all providers.

Let’s examine these changes in a Terraform configuration using both the existing and new syntax:

Starting with Terraform , Terraform can parse a block with the new syntax, though any source attribute will be ignored silently for now.

The goal of these changes is to simplify the installation and use of providers for all workflows. While the current focus is on how Terraform interacts with the public registry, we are also working to improve the experience for practitioners using providers not listed in our registry, private providers, and those working in air-gapped environments.

We would love to hear your feedback on these changes. Please use our community forums for questions, and open an issue in GitHub if you come across any problems with the new syntax or have a feature request.

Sours: https://www.hashicorp.com/blog/adding-provider-source-to-hashicorp-terraform

You will also like:

Setup and Implement Read

In these tutorials, you will write a custom provider against the API of a fictional coffee-shop application called HashiCups using the Terraform Plugin SDKv2. Through the process, you will learn how to create data sources, authenticate the provider to the HashiCups client, and create resources with CRUD functionality.

There are a few possible reasons for authoring a custom Terraform provider, including:

  • An internal private cloud whose functionality is either proprietary or would not benefit the open source community.
  • Extending the capabilities of an existing provider (bug fixes, new features, or customizations)

In this tutorial, you will set up your Terraform provider development environment and create a coffees data source that will return all coffees HashiCups serves. To do this, you will:

  1. Set up your development environment.
    You will clone the HashiCups repository and checkout the branch. This contains a scaffold for a generic Terraform provider.
  2. Define the coffees data source.
    You will add a scaffold that defines an empty schema and functions to retrieve a list of coffees.
  3. Define the coffees schema.
    The schema defines properties that allow Terraform to recognize, reference and store the coffees data resource.
  4. Implement read.
    This read function invokes a request to the endpoint, then maps its value to the schema defined above.
  5. Add coffees data source to the provider schema.
    This allows you to use the data source in your configuration.

»Prerequisites

To follow this tutorial, you need:

»Set up your development environment

Clone the branch of the Terraform HashiCups Provider repository. This serves as the boilerplate for your provider workspace.

$git clone --branch boilerplate https://github.com/hashicorp/terraform-provider-hashicups

Change into the cloned repository.

$cd terraform-provider-hashicups

The HashiCups provider requires an instance of HashiCups. Navigate to the directory then run to spin up a local instance of HashiCups on port .

$cd docker_compose && docker-compose up

Leave this terminal running.

In another terminal, verify that HashiCups is running by sending a request to its health check endpoint.

$curl localhost/healthok

The directory should have the following structure.

$tree -L 3.├── Makefile├── README.md├── docker_compose│ ├── conf.json│ └── docker-compose.yml├── examples│ ├── coffee│ │ └── main.tf│ ├── main.tf├── hashicups│ └── provider.go├── main.go

If you're stuck at any point during this tutorial, refer to the branch to see the changes implemented in this tutorial.

»Explore your development environment

The boilerplate includes the following:

  • contains helper functions used to build, package and install the HashiCups provider.
    It's currently written for MacOS Terraform provider development, but you can change the variables at the top of the file to match your . If you're using Windows, update your . You can find a full list of supported GO_ARCH here.
    - BINARY=terraform-provider-${NAME}+ BINARY=terraform-provider-${NAME}.exe- OS_ARCH=darwin_amd64+ OS_ARCH=windows_amd64
    The function is configured to install the provider into the appropriate subdirectory within the default MacOS and Linux user plugins directory as defined by Terraform specifications.
  • contains the files required to initialize a local instance of HashiCups.
  • contains sample Terraform configuration that can be used to test the HashiCups provider.
  • contains the main provider code. This will be where the provider's resources and data source implementations will be defined.
  • is the main entry point. This file creates a valid, executable Go binary that Terraform Core can consume.

»Explore file

Open in the root of the repository. The contents of the main function consume the Plugin SDK's library which facilitates the RPC communication between Terraform Core and the plugin.

package main import("github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema""github.com/hashicorp/terraform-plugin-sdk/v2/plugin""terraform-provider-hashicups/hashicups")funcmain(){ plugin.Serve(&plugin.ServeOpts{ ProviderFunc:func()*schema.Provider {return hashicups.Provider()},})}

Notice the returns a from the package.

»Explore provider schema

The file currently defines an empty provider.

package hashicups import("github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema")// Provider -funcProvider()*schema.Provider {return&schema.Provider{ ResourcesMap:map[string]*schema.Resource{}, DataSourcesMap:map[string]*schema.Resource{},}}

The library is part of Terraform Core. It abstracts many of the complexities and ensures consistency between providers. The type can accept:

  • the resources it supports ( and )
  • configuration keys (properties in )
  • any callbacks to configure ()

You can use configuration keys and callbacks to authenticate and configure the provider. You will add them in the Add Authentication to a Provider tutorial.

»Build provider

Run the command to define this directory as the root of a module.

$go mod init terraform-provider-hashicupsgo: creating new go.mod: module terraform-provider-hashicups

Then, run to create a directory that contains all the provider's dependencies.

$go mod vendor

Next, build the provider using the Makefile.

$make buildgo build -o terraform-provider-hashicups

This runs the command. Terraform searches for plugins in the format of . In the case above, the plugin is of type "provider" and of name "hashicups".

To verify things are working correctly, execute the recently created binary.

$./terraform-provider-hashicupsThis binary is a plugin. These are not meant to be executed directly.Please execute the program that consumes these plugins, which willload any plugins automatically

»Define coffees data resource

Now that you have created the provider, add the coffees data resource. The coffees data source will pull information on all coffees served by HashiCups.

Create a new file named in the directory and add the following code snippet. As a general convention, Terraform providers put each data source in their own file, named after the resource, prefixed with .

The libraries imported here will be used in .

package hashicups import("context""encoding/json""fmt""net/http""strconv""time""github.com/hashicorp/terraform-plugin-sdk/v2/diag""github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema")funcdataSourceCoffees()*schema.Resource {return&schema.Resource{ ReadContext: dataSourceCoffeesRead, Schema:map[string]*schema.Schema{},}}

The coffees data source function returns a which defines the schema and CRUD operations for the resource. Since Terraform data resources should only read information (not create, update or delete), only read () is defined.

»Define coffees schema

All Terraform resources must have a schema. This allows the provider to map the JSON response to the schema.

The endpoint returns an array of coffees. The sample below shows a truncated output.

$curl localhost/coffees[ { "id": 1, "name": "Packer Spiced Latte", "teaser": "Packed with goodness to spice up your images", "description": "", "price": , "image": "/packer.png", "ingredients": [ { "ingredient_id": 1 }, { "ingredient_id": 2 }, { "ingredient_id": 4 } ] },## ]

Since the response returns a list of coffees, the coffees schema should reflect that. Update your coffees data source's schema with the following code snippet.

Schema:map[string]*schema.Schema{"coffees":&schema.Schema{ Type: schema.TypeList, Computed:true, Elem:&schema.Resource{ Schema:map[string]*schema.Schema{"id":&schema.Schema{ Type: schema.TypeInt, Computed:true,},"name":&schema.Schema{ Type: schema.TypeString, Computed:true,},"teaser":&schema.Schema{ Type: schema.TypeString, Computed:true,},"description":&schema.Schema{ Type: schema.TypeString, Computed:true,},"price":&schema.Schema{ Type: schema.TypeInt, Computed:true,},"image":&schema.Schema{ Type: schema.TypeString, Computed:true,},"ingredients":&schema.Schema{ Type: schema.TypeList, Computed:true, Elem:&schema.Resource{ Schema:map[string]*schema.Schema{"ingredient_id":&schema.Schema{ Type: schema.TypeInt, Computed:true,},},},},},},},},

Format your code.

$go fmt ./

Notice that the coffees schema is a of coffee ().

The coffee resource's properties should map to their respective values in the JSON response. In the above example response:

  • The coffee's is , a .
  • The coffee's is , a .
  • The coffee is an array of ingredient objects, a with elements .

You can use various schema types to define complex data models. You will implement a complex read in the Implement Complex Read tutorial and Implement Create tutorial.

»Implement read

Now that you defined the coffees schema, you can implement the function.

Add the following read function to your file.

funcdataSourceCoffeesRead(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics { client :=&http.Client{Timeout* time.Second}// Warning or errors can be collected in a slice typevar diags diag.Diagnostics req, err := http.NewRequest("GET", fmt.Sprintf("%s/coffees","http://localhost"),nil)if err !=nil{return diag.FromErr(err)} r, err := client.Do(req)if err !=nil{return diag.FromErr(err)}defer r.Body.Close() coffees :=make([]map[string]interface{},0) err = json.NewDecoder(r.Body).Decode(&coffees)if err !=nil{return diag.FromErr(err)}if err := d.Set("coffees", coffees); err !=nil{return diag.FromErr(err)}// always run d.SetId(strconv.FormatInt(time.Now().Unix(),10))return diags }

Format your code.

$go fmt ./

This function creates a new GET request to . Then, it decodes the response into a . The function sets the response body (list of coffees object) to Terraform coffees data source, assigning each value to its respective schema position. Finally, it uses to set the resource ID.

Notice that this function returns a type, which can return multiple errors and warnings to Terraform, giving users more robust error and warning messages. You can use the helper function to convert a Go error to a type. You will implement this in the Debug a Terraform provider tutorial.

Tip: This function doesn't use an API client library to explicitly show the steps involved. The HashiCups client library is used to abstract CRUD functionality in other tutorials.

The existence of a non-blank ID tells Terraform that a resource was created. This ID can be any string value, but should be a value that Terraform can use to read the resource again. Since this data resource doesn't have a unique ID, you set the ID to the current UNIX time, which will force this resource to refresh during every Terraform apply.

When you create something in Terraform but delete it manually, Terraform should gracefully handle it. If the API returns an error when the resource doesn't exist, the read function should check to see if the resource is available first. If the resource isn't available, the function should set the ID to an empty string so Terraform "destroys" the resource in state. The following code snippet is an example of how this can be implemented; you do not need to add this to your configuration for this tutorial.

if resourceDoesntExist { d.SetID("")return}

»Add data source to provider

Now that you've defined your data source, you can add it to your provider.

In your file, add the coffees data source to the . The attribute takes a map of the data source name, , and the defined in . Resources and data sources names must follow the convention.

// Provider - func Provider() *schema.Provider { return &schema.Provider{ ResourcesMap: map[string]*schema.Resource{},- DataSourcesMap: map[string]*schema.Resource{},+ DataSourcesMap: map[string]*schema.Resource{+ "hashicups_coffees": dataSourceCoffees(),+ }, } }

Format your code.

$go fmt ./

»Test the provider

Now that you've implemented read and created the coffees data source, verify that it works.

First, confirm that you are in the root directory.

$pwd~/terraform-provider-hashicups

Next, build the binary and move it into your user Terraform plugins directory. This allows you to sideload and test the custom provider. Select the tab for your operating system for specific instructions.

$makeinstallgo build -o terraform-provider-hashicupsmv terraform-provider-hashicups ~/.terraform.d/plugins/hashicorp.com/edu/hashicups//darwin_amd64

Tip: The Perform CRUD operations with Providers tutorial explains why and how to sideload custom providers. Refer to it to learn more about where to install custom providers and how to reference them in your configuration.

Navigate to the directory. This contains a sample Terraform configuration for the Terraform HashiCups provider.

$cd examples

Finally, initialize your workspace to refresh your HashiCups provider, then apply. This should return the properties of "Packer Spice Latte" in your output.

$terraform init && terraform apply --auto-approveApply complete! Resources: 0 added, 0 changed, 0 destroyed.Outputs:psl = { "1" = { "description" = "" "id" = 1 "image" = "/packer.png" "ingredients" = tolist([ { "ingredient_id" = 1 }, { "ingredient_id" = 2 }, { "ingredient_id" = 4 }, ]) "name" = "Packer Spiced Latte" "price" = "teaser" = "Packed with goodness to spice up your images" }}

»Next steps

Congratulations! You created your first Terraform provider and data resource to reference information from an API in your Terraform configuration.

If you were stuck during this tutorial, checkout the branch to see the changes implemented in this tutorial.

Sours: https://learn.hashicorp.com/tutorials/terraform/provider-setup


1548 1549 1550 1551 1552