|
| 1 | +# How to contribute |
| 2 | + |
| 3 | +Contributions are welcome! That being said, this repository is not meant to contain every combination of every infrastructure as code tool, infrastructure provider, or possible deployment type available. It contains examples for the most common of each, and they are _examples_, not production-ready configurations. |
| 4 | + |
| 5 | +## Making a contribution |
| 6 | + |
| 7 | +- **An example** - please [open an issue](https://github.com/tailscale-dev/examples-infrastructure-as-code/issues) describing your proposed example before spending your time and resources developing the example and submitting a pull request. Contributions for unique or less common deployments may not be accepted. |
| 8 | +- **A bug fix** - please [open an issue](https://github.com/tailscale-dev/examples-infrastructure-as-code/issues) describing the bug if one does not already exist and feel free to submit a pull request with a fix. |
| 9 | +- **Have a question?** - please [open an issue](https://github.com/tailscale-dev/examples-infrastructure-as-code/issues) describing your contribution before spending your time and resources developing it. |
| 10 | +- **Something else** - please [open an issue](https://github.com/tailscale-dev/examples-infrastructure-as-code/issues) describing your contribution before spending your time and resources developing it. |
| 11 | + |
| 12 | +## Guiding principles for this repository |
| 13 | + |
| 14 | +The examples in this repository: |
| 15 | + |
| 16 | +- Are _examples_. They are not production-ready and don't claim to be. |
| 17 | +- Are meant to be generally applicable. If you have a highly-specific use case, this repository is probably not the best place for it. |
| 18 | +- Strive to follow the [style guide](#style-guide) below. |
| 19 | + |
| 20 | +## Style guide |
| 21 | + |
| 22 | +- Include a `README.md` file that describes the use case and the Cloud and Tailscale resources that will be created. |
| 23 | +- Use up-to-date versions of providers, modules, and third-party libraries and avoid deprecated features or arguments of providers, modules, etc. |
| 24 | +- Put all customizable options, such as VPC CIDR blocks, common resource tags, etc., in common variables: |
| 25 | + - In Terraform, use [local values](https://developer.hashicorp.com/terraform/language/values/locals) - e.g. a single `locals { }` block at the top of `main.tf`. |
| 26 | + - In other languages use idiomatic coding practices appropriate to the language - e.g. in TypeScript use [const declarations](https://www.typescriptlang.org/docs/handbook/variable-declarations.html#const-declarations) in as few blocks as possible. |
| 27 | +- Prefix all provisioned resource names with `"example-${basename(path.cwd)}"`, ideally using a local variable for the prefix. |
| 28 | +- Tag all resources with a `Name` tag matching the resource name (e.g. `"example-${basename(path.cwd)}"`). |
| 29 | +- Use community modules for undifferentiated heavy lifting, such as cloud VPCs or virtual networks. When possible, make these modules easy to remove without requiring lots of changes throughout the rest of the example. |
| 30 | +- Format your example code with `terraform fmt` or equivalent fo the language you're using. |
| 31 | + |
| 32 | +### Mock Terraform example |
| 33 | + |
| 34 | +```hcl |
| 35 | +// All customizable parameters in locals for easy customization. |
| 36 | +locals { |
| 37 | + // common name based on the directory name |
| 38 | + name = "example-${basename(path.cwd)}" |
| 39 | +
|
| 40 | + // common tags used across all resources |
| 41 | + tags = { |
| 42 | + Name = local.name |
| 43 | + } |
| 44 | +
|
| 45 | + // tailscale-specific arguments |
| 46 | + tailscale_acl_tags = [ |
| 47 | + "tag:example-infra", |
| 48 | + "tag:example-exitnode", |
| 49 | + ] |
| 50 | + tailscale_set_preferences = [ |
| 51 | + "--auto-update", |
| 52 | + "--ssh", |
| 53 | + "--advertise-connector", |
| 54 | + // ... |
| 55 | + ] |
| 56 | +
|
| 57 | + // other arguments that are easily customized in one place |
| 58 | + vpc_id = module.vpc.vpc_id |
| 59 | + vpc_cidr_block = "10.0.80.0/22" |
| 60 | + vpc_public_subnet_cidr_blocks = ["10.0.80.0/24"] |
| 61 | + vpc_private_subnet_cidr_blocks = ["10.0.81.0/24"] |
| 62 | +
|
| 63 | + instance_subnet_id = module.vpc.public_subnets[0] |
| 64 | + instance_security_group_ids = [fake_security_group.tailscale.id] |
| 65 | + instance_type = "c7g.medium" |
| 66 | +} |
| 67 | +
|
| 68 | +// Remove this to use your own VPC. |
| 69 | +module "vpc" { |
| 70 | + source = "#url" |
| 71 | +
|
| 72 | + // customize the name as applicable |
| 73 | + name = "${local.name}-primary" |
| 74 | + tags = merge(local.tags, { |
| 75 | + Name = "${local.name}-primary", |
| 76 | + }) |
| 77 | +
|
| 78 | + // most critical arguments sourced from locals |
| 79 | + cidr = local.vpc_cidr_block |
| 80 | + public_subnets = local.vpc_public_subnet_cidr_blocks |
| 81 | + private_subnets = local.vpc_private_subnet_cidr_blocks |
| 82 | +} |
| 83 | +
|
| 84 | +resource "fake_security_group" "main" { |
| 85 | + // customize the name as applicable |
| 86 | + name = "${local.name}-main" |
| 87 | + tags = merge(local.tags, { |
| 88 | + Name = "${local.name}-main", |
| 89 | + }) |
| 90 | +
|
| 91 | + // ... |
| 92 | +} |
| 93 | +
|
| 94 | +resource "fake_instance" "main" { |
| 95 | + // customize the name as applicable |
| 96 | + name = "${local.name}-main" |
| 97 | + tags = merge(local.tags, { |
| 98 | + Name = "${local.name}-main", |
| 99 | + }) |
| 100 | +
|
| 101 | + // most critical arguments sourced from locals |
| 102 | + subnet_id = local.instance_subnet_id |
| 103 | + security_group_ids = local.instance_security_group_ids |
| 104 | + type = local.instance_type |
| 105 | +
|
| 106 | + // ... |
| 107 | +} |
| 108 | +``` |
0 commit comments