{"id":16370814,"url":"https://github.com/integralist/terraform-provider-mock","last_synced_at":"2025-07-27T15:12:54.818Z","repository":{"id":57712657,"uuid":"337767519","full_name":"Integralist/terraform-provider-mock","owner":"Integralist","description":"Boilerplate template for a custom terraform provider.","archived":false,"fork":false,"pushed_at":"2022-11-12T19:31:33.000Z","size":6215,"stargazers_count":11,"open_issues_count":0,"forks_count":13,"subscribers_count":3,"default_branch":"main","last_synced_at":"2025-04-07T17:21:59.365Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/Integralist.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2021-02-10T15:32:30.000Z","updated_at":"2024-10-21T16:19:55.000Z","dependencies_parsed_at":"2022-09-26T21:30:45.903Z","dependency_job_id":null,"html_url":"https://github.com/Integralist/terraform-provider-mock","commit_stats":null,"previous_names":[],"tags_count":1,"template":false,"template_full_name":null,"purl":"pkg:github/Integralist/terraform-provider-mock","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Integralist%2Fterraform-provider-mock","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Integralist%2Fterraform-provider-mock/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Integralist%2Fterraform-provider-mock/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Integralist%2Fterraform-provider-mock/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/Integralist","download_url":"https://codeload.github.com/Integralist/terraform-provider-mock/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Integralist%2Fterraform-provider-mock/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":267376369,"owners_count":24077300,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","status":"online","status_checked_at":"2025-07-27T02:00:11.917Z","response_time":82,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-10-11T03:06:04.146Z","updated_at":"2025-07-27T15:12:54.799Z","avatar_url":"https://github.com/Integralist.png","language":"Go","funding_links":[],"categories":[],"sub_categories":[],"readme":"# terraform-provider-mock\n\nThis is an empty boilerplate repository for creating a terraform provider. \n\nThe motivation for creating this repo was:\n\n1. To learn how to create a terraform provider.\n2. To be a _simple_ resource for others to do the same.\n3. Demonstrate how to test a provider locally without needing to publish it.\n4. Anything else that might be of interest.\n\n## What is a terraform provider?\n\nA 'provider' is an abstraction over an existing API, that will enable you to manage the creation of resources using terraform. If you don't know what terraform is, then I recommend reading up on that subject first.\n\nIn summary: if you have an API (or you are a user of an existing API), then you can manage that API via terraform.\n\n## Things to know about this repository\n\nThis is quite literally a _skeleton_ repo. It's intentionally designed that way. Most tutorials online teach the details of a terraform provider by first implementing an API backend, but I personally find this an unnecessary mental hurdle. So I have avoided that in favour of heavily commented code that explains what you need to do, when, and why. This makes it easier for you to strip out what you don't want.\n\n## Terraform Execution Flow\n\nWhen there is no terraform state file, then terraform won't execute any CRUD functions.\n\nOn the initial `terraform apply` you'll find CREATE is called first but what happens from there depends on how your provider works. For example, fastly and aws both call UPDATE at the end of the CREATE, where in this mock provider I call READ instead.\n\nOnce a terraform state file has been created, and you make a change to your terraform configuration file, you'll find the first operation called when running `terraform plan` is READ. This is because terraform wants to get the latest version of your infrastructure to compare against what you have defined locally in your configuration.\n\nIf you run `terraform apply` to ensure your changes are applied, then you'll find the first operation called by terraform is a READ. This is because if you don't have `terraform plan` set to save the 'execution plan' using the `-out` flag, then terraform is going to go off and get the latest data it can (you'll have noticed this as you would have had to type in \"yes\" manually to force the changes to be applied). After the READ, terraform calls UPDATE and what follows that is typically a READ because that's what most terraform providers do in their UPDATE function logic.\n\n## Requirements for creating a terraform provider\n\n1. Provider code\n2. Provider documentation\n3. A tagged release\n\nIf you intend on publishing a provider on `registry.terraform.io` you'll need to follow [these steps](https://www.terraform.io/docs/registry/providers/publishing.html) which includes generating documentation (for which I have: `make generate-docs` defined in this repo's `Makefile`). \n\nYou'll also want to tag a commit to be used as the release version, which you'd then reference in the `version` field in your terraform code, for example a consumer of this provider should define something like the following:\n\n```tf\nterraform {\n  required_providers {\n    mock = {\n      source = \"integralist/mock\"\n      version = \"\u003ctag_version_here\u003e\"\n    }\n  }\n}\n```\n\n\u003e NOTE: when developing your own provider, remember not just to update the `source` value but also the parent key (in this case `mock`). I've forgotten to do this in the past and had it confuse me for hours because it's such a subtle thing to miss. \n\n## Linting a Provider\n\nThere is no official tool but `tfproviderlint` is written by a HashiCorp software engineer and has been used on many projects so is worth installing:\n\n```bash\ngo install github.com/bflad/tfproviderlint/cmd/tfproviderlintx@latest\n```\n\n\u003e NOTE: I suggest installing the 'extended' binary (notice `x` at the end of the name).\n\n## How to use this provider\n\nTo consume this provider without it being published to the terraform registry, follow these steps:\n\n- Clone this repo and build the `terraform-provider-mock` binary:  \n  ```bash\n  make build\n  ```\n- Create a separate directory for your own terraform project.\n  - e.g. `cd ../ \u0026\u0026 mkdir example-tf`\n- Create a `dev.tfrc` file in your own terraform project's directory:\n  ```tf\n  provider_installation {\n    dev_overrides {\n      \"integralist/mock\" = \"../terraform-provider-mock\" // the directory where the binary was built.\n    }\n    direct {}\n  }\n  ```\n- In that shell instance set the `TF_CLI_CONFIG_FILE` environment variable.\n  - e.g. `export TF_CLI_CONFIG_FILE=/example-tf/dev.tfrc`\n- Create terraform project files.\n  - e.g. see [Example Terraform Consumer Code](#example-terraform-consumer-code) below.\n- Initialize your terraform project and then execute a plan.\n  - e.g. `terraform init \u0026\u0026 terraform plan` \n\n\u003e **NOTE**: every time you make a change to the terraform provider code, you'll need to rebuild the binary and then go to your consuming terraform project and reinitialize (i.e. `terraform init`) so it picks up the latest version of the `terraform-provider-mock` binary.\n\n## Local Development\n\nWhen running:\n\n```bash\n$ TF_LOG=TRACE terraform init\n```\n\nYou should notice a couple of things different from what you'd normally see when initializing a new terraform project.\n\nThe first is a message highlighting the fact that a provider 'override' is in place:\n\n```\nWarning: Provider development overrides are in effect\n\nThe following provider development overrides are set in the CLI configuration:\n - integralist/mock in /Users/integralist/Code/terraform/terraform-provider-mock\n\nThe behavior may therefore not match any released version of the provider and\napplying changes may cause the state to become incompatible with published\nreleases.\n```\n\nThat is expected in this case we've followed the instructions above, which tells us how to implement an override for the sake of local testing of the provider code.\n\nThe other thing you'll notice is an error:\n\n```\nError: Failed to query available provider packages\n\nCould not retrieve the list of available versions for provider\nintegralist/mock: provider registry registry.terraform.io does not have a\nprovider named registry.terraform.io/integralist/mock\n\nIf you have just upgraded directly from Terraform v0.12 to Terraform v0.14\nthen please upgrade to Terraform v0.13 first and follow the upgrade guide for\nthat release, which might help you address this problem.\n```\n\nThis error is expected because we've not actually published this provider to the terraform registry, so indeed it cannot be found. But the error doesn't prevent you from consuming the local provider binary still.\n\n\u003e NOTE: don't use Print functions from the `fmt` package in the terraform provider as depending on the execution flow terraform can treat it as input to its internal program and treat it as an error. So use Print functions from the `log` package instead.\n\n## Debugging a Terraform Provider\n\nThere are essentially two approaches:\n\n1. Log-Based Debugging\n2. Debugger-Based Debugging. \n\nRefer to the [official Hashicorp plugin documentation](https://www.terraform.io/plugin/sdkv2/debugging) and also the [Fastly Terraform provider](https://github.com/fastly/terraform-provider-fastly#debugging-the-provider) documents and demonstrates the latter approach.\n\n## Example Terraform Consumer Code\n\nBelow are two code files you can use to validate how to use this provider in its current form:\n\n1. `service.tf`\n2. `outputs.tf`\n\nHere is the `service.tf` contents:\n\n```tf\nterraform {\n  required_providers {\n    mock = {\n      source = \"integralist/mock\"\n    }\n  }\n}\n\nprovider \"mock\" {\n  foo = \"example_value\"\n  #\n  # if 'foo' wasn't set here by us, then the value would default to the value \n  # assigned to the environment variable 'MOCK_FOO' or the default value of nil\n  # if the environment variable wasn't set.\n}\n\nresource \"mock_example\" \"testing\" {\n  not_computed_required = \"some value\"\n\n  dynamic \"foo\" {\n    for_each = [{ number = 1 }, { number = 2 }, { number = 3 }]\n    content {\n      bar {\n        number = foo.value.number\n      }\n    }\n  }\n  /*\n   * The above is equivalent to:\n   *\n   * foo {\n   *   bar {\n   *     number = 1\n   *   }\n   * }\n   * foo {\n   *   bar {\n   *     number = 2\n   *   }\n   * }\n   * foo {\n   *   bar {\n   *     number = 3\n   *   }\n   * }\n  */\n\n  dynamic \"baz\" {\n    // The variable inside the for_each block doesn't have to be the same as \n    // what you're assigning the value to.\n    for_each = [{ something = \"x\" }, { something = \"y\" }, { something = \"z\" }]\n    content {\n      qux = baz.value.something\n    }\n  }\n  /*\n   * The above is equivalent to:\n   *\n   * baz {\n   *   qux = \"x\"\n   * }\n   * baz {\n   *   qux = \"y\"\n   * }\n   * baz {\n   *   qux = \"z\"\n   * }\n  */\n\n  some_list = [\"a\", \"b\", \"c\"]\n}\n```\n\nHere is the `outputs.tf` contents:\n\n```tf\noutput \"last_updated\" {\n  value = mock_example.testing.last_updated\n}\n```\n\nThe `outputs.tf` is a terraform convention where you can specify what 'computed' values you would like to see displayed once a planned set of changes has been successfully applied.\n\nOnce you've written the above code, and you run a plan, you should see the following output:\n\n```bash\n$ terraform plan\n\nAn execution plan has been generated and is shown below.\nResource actions are indicated with the following symbols:\n  + create\n\nTerraform will perform the following actions:\n\n  # mock_example.testing will be created\n  + resource \"mock_example\" \"testing\" {\n      + id                    = (known after apply)\n      + last_updated          = (known after apply)\n      + not_computed_required = \"some value\"\n      + some_list             = [\n          + \"a\",\n          + \"b\",\n          + \"c\",\n        ]\n\n      + baz {\n          + qux = \"x\"\n        }\n      + baz {\n          + qux = \"y\"\n        }\n      + baz {\n          + qux = \"z\"\n        }\n\n      + foo {\n          + bar {\n              + number  = 1\n              + version = (known after apply)\n            }\n        }\n      + foo {\n          + bar {\n              + number  = 2\n              + version = (known after apply)\n            }\n        }\n      + foo {\n          + bar {\n              + number  = 3\n              + version = (known after apply)\n            }\n        }\n    }\n\nPlan: 1 to add, 0 to change, 0 to destroy.\n\nChanges to Outputs:\n  + last_updated = (known after apply)\n\n------------------------------------------------------------------------\n\nNote: You didn't specify an \"-out\" parameter to save this plan, so Terraform\ncan't guarantee that exactly these actions will be performed if\n\"terraform apply\" is subsequently run.\n```\n\nIf you were to run `terraform show` you would see `No state.` returned.\n\nSo let's run `terraform apply` to apply the 'planned' changes:\n\n```bash\n$ terraform apply\n\nWarning: Provider development overrides are in effect\n\nThe following provider development overrides are set in the CLI configuration:\n - integralist/mock in /Users/integralist/Code/terraform/terraform-provider-mock\n\nThe behavior may therefore not match any released version of the provider and\napplying changes may cause the state to become incompatible with published\nreleases.\n\n\nAn execution plan has been generated and is shown below.\nResource actions are indicated with the following symbols:\n  + create\n\nTerraform will perform the following actions:\n\n  # mock_example.testing will be created\n  + resource \"mock_example\" \"testing\" {\n      + id                    = (known after apply)\n      + last_updated          = (known after apply)\n      + not_computed_required = \"some value\"\n      + some_list             = [\n          + \"a\",\n          + \"b\",\n          + \"c\",\n        ]\n\n      + baz {\n          + qux = \"x\"\n        }\n      + baz {\n          + qux = \"y\"\n        }\n      + baz {\n          + qux = \"z\"\n        }\n\n      + foo {\n          + bar {\n              + number  = 1\n              + version = (known after apply)\n            }\n        }\n      + foo {\n          + bar {\n              + number  = 2\n              + version = (known after apply)\n            }\n        }\n      + foo {\n          + bar {\n              + number  = 3\n              + version = (known after apply)\n            }\n        }\n    }\n\nPlan: 1 to add, 0 to change, 0 to destroy.\n\nChanges to Outputs:\n  + last_updated = (known after apply)\n\nDo you want to perform these actions?\n  Terraform will perform the actions described above.\n  Only 'yes' will be accepted to approve.\n\n  Enter a value: yes\n\nmock_example.testing: Creating...\nmock_example.testing: Creation complete after 0s [id=123]\n\nApply complete! Resources: 1 added, 0 changed, 0 destroyed.\n\nOutputs:\n\nlast_updated = \"Saturday, 20-Feb-21 13:33:11 GMT\"\n```\n\nNotice at the bottom of this output we see the `Outputs` section which is displaying what you had defined inside of `outputs.tf`.\n\nIf you were to now run `terraform show` you would see some state!\n\n```bash\n$ terraform show\n\n# mock_example.testing:\nresource \"mock_example\" \"testing\" {\n    id                    = \"123\"\n    last_updated          = \"Saturday, 20-Feb-21 13:33:11 GMT\"\n    not_computed_required = \"some value\"\n    some_list             = [\n        \"a\",\n        \"b\",\n        \"c\",\n    ]\n\n    baz {\n        qux = \"x\"\n    }\n    baz {\n        qux = \"y\"\n    }\n    baz {\n        qux = \"z\"\n    }\n\n    foo {\n        bar {\n            number  = 1\n            version = \"27356913-3cf2-4296-b78e-509d487f4fd0\"\n        }\n    }\n    foo {\n        bar {\n            number  = 2\n            version = \"8bd02c94-1e65-4eac-b106-f977c15ff173\"\n        }\n    }\n    foo {\n        bar {\n            number  = 3\n            version = \"b931c027-2cb0-463d-b289-f48ec2943a5e\"\n        }\n    }\n}\n\n\nOutputs:\n\nlast_updated = \"Saturday, 20-Feb-21 13:33:11 GMT\"\n```\n\n## Reference Material\n\n- [How Terraform Works](https://www.terraform.io/docs/extend/how-terraform-works.html): explains how providers are sourced, versioned and upgraded.\n- [Schema Attributes and Types](https://www.terraform.io/docs/extend/schemas/schema-types.html): explains the various schema types you can define in your provider.\n- [Writing a custom terraform provider](https://boxboat.com/2020/02/04/writing-a-custom-terraform-provider/): there actually isn't that many articles on the topic.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fintegralist%2Fterraform-provider-mock","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fintegralist%2Fterraform-provider-mock","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fintegralist%2Fterraform-provider-mock/lists"}