orange-cloudfoundry / terraform-provider-cloudfoundry

A terraform provider to manage a Cloud Foundry instance.
Apache License 2.0
31 stars 8 forks source link
cloud-foundry terraform-provider

terraform-provider-cloudfoundry Build Status

Depreciation and migration steps

This provider is being deprecated in favor of https://github.com/mevansam/terraform-provider-cf which aims at moving to the https://github.com/terraform-providers github organization and becoming an official terraform provider.

The migration from terraform-provider-cloudfoundry to terraform-provider-cf can follow the procedure below:

Potentially, such migration steps can be automated and scheduled into CI/CD such as https://github.com/ljfranklin/terraform-resource/issues/41

Overview

This terraform provider supports the use-case of managing a Cloud Foundry instance, with current support for:

You can also find useful terraform modules at https://github.com/orange-cloudfoundry/terraform-cloudfoundry-modules.

Installations

Requirements: You need, of course, terraform (>=0.8) which is available here: https://www.terraform.io/downloads.html

Automatic

To install a specific version, set PROVIDER_CLOUDFOUNDRY_VERSION before executing the following command

$ export PROVIDER_CLOUDFOUNDRY_VERSION="v0.9.1"

via curl

$ bash -c "$(curl -fsSL https://raw.github.com/orange-cloudfoundry/terraform-provider-cloudfoundry/master/bin/install.sh)"

via wget

$ bash -c "$(wget https://raw.github.com/orange-cloudfoundry/terraform-provider-cloudfoundry/master/bin/install.sh -O -)"

Manually

  1. Get the build for your system in releases: https://github.com/orange-cloudfoundry/terraform-provider-cloudfoundry/releases/latest

  2. Create a providers directory inside terraform user folder: mkdir -p ~/.terraform.d/providers

  3. Move the provider previously downloaded in this folder: mv /path/to/download/directory/terraform-provider-cloudfoundry ~/.terraform.d/providers

  4. Ensure provider is executable: chmod +x ~/.terraform.d/providers/terraform-provider-cloudfoundry

  5. add providers path to your .terraformrc:

    cat <<EOF > ~/.terraformrc
    providers {
    cloudfoundry = "/full/path/to/.terraform.d/providers/terraform-provider-cloudfoundry"
    }
    EOF
  6. you can now performs any terraform action on Cloud Foundry resources

provider configuration

provider "cloudfoundry" {
  api_endpoint = "https://api.of.your.cloudfoundry.com"
  username = "user"
  password = "mypassword"
  skip_ssl_validation = true
  enc_private_key = "${file("secring_b64.gpg")}"
  enc_passphrase = "mypassphrase"
  verbose = false
  user_access_token = "bearer key"
  user_refresh_token = "bearer key"
}

Resources and Data sources


Organizations

Resource

resource "cloudfoundry_organization" "org_mysuperorg" {
  name = "mysuperorg"
  is_system_domain = true
  quota_id = "${cloudfoundry_quota.quota_mysuperquota.id}"
}

Data source

Get one org with all details

Note: every parameters from resource which are not used here are marked as computed and will be filled.

data "cloudfoundry_organization" "org_mysuperorg" {
  name = "mysuperorg"
  // or by_id = "a-guid"
}

// get quota id for example: ${data.cloudfoundry_organization.cloudfoundry_organization.quota_id}
Get all orgs
data "cloudfoundry_organizations" "available" {}

data "cloudfoundry_organization" "cloudfoundry_organization" {
    name = "${data.cloudfoundry_organizations.available.names[0]}"
}

Spaces

Resource

resource "cloudfoundry_space" "space_mysuperspace" {
    name = "mysuperspace"
    org_id = "${cloudfoundry_organization.org_mysuperorg.id}"
    quota_id = "${cloudfoundry_quota.quota_mysuperquota.id}"
    sec_groups = ["${cloudfoundry_sec_group.sec_group_mysupersecgroup.id}"]
    allow_ssh = true
}

Data source

Get one space with all details

Note: every parameters from resource which are not used here are marked as computed and will be filled.

data "cloudfoundry_space" "space_mysuperspace" {
    name = "mysuperspace"
    org_id = "${cloudfoundry_organization.org_mysuperorg.id}"
    // or by_id = "a-guid"
}
Get all spaces
data "cloudfoundry_spaces" "available" {
  org_id = "${cloudfoundry_organization.org_mysuperorg.id}"
}

data "cloudfoundry_space" "space_mysuperspace" {
    name = "${data.cloudfoundry_spaces.available.names[0]}"
    org_id = "${cloudfoundry_organization.org_mysuperorg.id}"
}

Quotas

Resource

Note: There is two kinds of quotas inside Cloud Foundry: a space's quota, an organization's quota. This resource is able to find what kind of quota you defined. If you omit org_id the resource will consider this quota as an organization's quota. With it will consider it's a space's quota.

resource "cloudfoundry_quota" "quota_for_ahalet" {
  name = "quotaAhalet"
  org_id = "${cloudfoundry_organization.org_mysuperorg.id}"
  total_memory = "10G"
  instance_memory = "1G"
  routes = 200
  service_instances = 10
  app_instances = -1
  allow_paid_service_plans = true
  reserved_route_ports = 0
}

Data source

Note: every parameters from resource which are not used here are marked as computed and will be filled.

data "cloudfoundry_quota" "quota_for_ahalet" {
  name = "quotaAhalet"
  org_id = "${cloudfoundry_organization.org_mysuperorg.id}"
  // or by_id = "a-guid"
}

Security groups

Resource

resource "cloudfoundry_sec_group" "sec_group_mysupersecgroup" {
  name = "mysupersecgroup"
  on_staging = false
  on_running = false
  rules {
    protocol = "tcp"
    destination = "10.0.0.2"
    ports = "65000"
    log = false
    description = "my description"
  }
  rules {
    protocol = "icmp"
    destination = "192.0.2.0-192.0.1-4"
    type = 3
    code = 1
  }
  rules {
      protocol = "all"
      destination = "10.0.0.0/24"
      log = true
    }
}

Data source

Note: every parameters from resource which are not used here are marked as computed and will be filled.

data "cloudfoundry_sec_group" "sec_group_mysupersecgroup" {
  name = "mysupersecgroup"
  // or by_id = "a-guid"
}

Buildpacks

Resource

resource "cloudfoundry_buildpack" "buildpack_mysuperbuildpack" {
  name = "mysuperbuildpack"
  path = "https://github.com/cloudfoundry/staticfile-buildpack/releases/download/v1.3.13/staticfile_buildpack-cached-v1.3.13.zip"
  position = 13
  locked = false
  enabled = false
}

Data source

Note: every parameters from resource which are not used here are marked as computed and will be filled.

resource "cloudfoundry_buildpack" "buildpack_mysuperbuildpack" {
  name = "mysuperbuildpack"
  // or by_id = "a-guid"
}

Feature flags

Resource

resource "cloudfoundry_feature_flags" "feature_flags" {
  diego_docker = true
  custom_flag {
    name = "my_flag"
    enabled = true
  }
}

List of default feature flags:

Custom flags made for feature flags not in the default resource:

Data source

Feature flags cannot be used as data source


Services

Resource

Service from marketplace:

resource "cloudfoundry_service" "svc_db" {
  name = "my-db"
  space_id = "${cloudfoundry_space.space_mysuperspace.id}"
  service = "p-mysql"
  plan = "100mb"
  params = "{ \"my-param\": 1}"
  update_params = "{ \"my-param\": 1}"
  tags = [ "tag1", "tag2" ]
}

An user provided service:

resource "cloudfoundry_service" "svc_ups" {
  name = "my-ups"
  space_id = "${cloudfoundry_space.space_mysuperspace.id}"
  user_provided = true
  params = "{ \"my-credential\": 1}"
  route_service_url = "http://my.route.com"
  syslog_drain_url = "http://my.syslog.com"
  tags = [ "tag1", "tag2" ]
}

Data source

Note: every parameters from resource which are not used here are marked as computed and will be filled, except:

data "cloudfoundry_service" "svc_ups" {
  name = "my-ups"
  space_id = "${cloudfoundry_space.space_mysuperspace.id}"
  // or by_id = "a-guid"
}

Domains

Resource

resource "cloudfoundry_domain" "domain_mydomain" {
  name = "my.domain.com"
  org_owner_id = "${cloudfoundry_organization.org_mysuperorg.id}"
  router_group = "default-router"
  orgs_shared_id = ["${cloudfoundry_organization.org_mysecondorg.id}"]
  shared = false
}

Data source

Get one domain with all details

Note: every parameters from resource which are not used here are marked as computed and will be filled.

data "cloudfoundry_domain" "domain_mydomain" {
  name = "my.domain.com"
  org_owner_id = "${cloudfoundry_organization.org_mysuperorg.id}"
  first = false
  // or by_id = "a-guid"
}
Get all domains
data "cloudfoundry_domains" "available" {
  org_owner_id = "${cloudfoundry_organization.org_mysuperorg.id}"
}

data "cloudfoundry_domain" "space_mysuperspace" {
    name = "${data.cloudfoundry_domains.available.names[0]}"
    org_owner_id = "${cloudfoundry_organization.org_mysuperorg.id}"
}

Routes

Resource

resource "cloudfoundry_route" "route_superroute" {
  hostname = "superroute"
  space_id = "${cloudfoundry_space.space_mysuperspace.id}"
  domain_id = "${cloudfoundry_domain.domain_mydomain.id}"
  port = -1
  path = ""
  service_id = "${cloudfoundry_service.svc_ups.id}"
  service_params = "{ \"my-param\": 1}"
}

Data source

Note: every parameters from resource which are not used here are marked as computed and will be filled, except:

resource "cloudfoundry_route" "route_superroute" {
  hostname = "superroute"
  domain_id = "${cloudfoundry_domain.domain_mydomain.id}"
  port = -1
  path = ""
  // or by_id = "a-guid"
}

Isolation segments

Resource

resource "cloudfoundry_isolation_segment" "my_isolation_segment" {
  name = "isolation_segment_name_set_in_cf_deployment"
}

Data source

Note: every parameters from resource which are not used here are marked as computed and will be filled.

data "cloudfoundry_isolation_segment" "my_isolation_segment" {
  name = "isolation_segment_name_set_in_cf_deployment"
}

Isolation segments entitlement

Resource

resource "cloudfoundry_isolation_segment_entitlement" "private_mysuperorg" {
  segment_id = "${cloudfoundry_isolation_segment.my_isolation_segment.id}"
  org_id = "${cloudfoundry_organization.org_mysuperorg.id}"
  default = false
}

Isolation segments space

Resource

resource "cloudfoundry_isolation_segment_space" "private_mysuperspace" {
  segment_id = "${cloudfoundry_isolation_segment.my_isolation_segment.id}"
  space_id = "${cloudfoundry_organization.space_mysuperspace.id}"
}

Stacks

Resource

Stacks cannot be used as a resource

Data source

Note: every parameters from resource which are not used here are marked as computed and will be filled.

data "cloudfoundry_stack" "my_stack" {
  name = "cflinuxfs2"
  first = false
  // or by_id = "a-guid"
}

Environment Variable Group

Resource

resource "cloudfoundry_env_var_group" "env_var_group" {
  env_var {
    key = "myvar1"
    value = "myvalue1"
    running = true
    staging = true
  }
  env_var {
    key = "myvar2"
    value = "myvalue1"
    running = true
    staging = true
  }
}

Data source

Environment Variable Group cannot be used as a data source


Service brokers

Resource

resource "cloudfoundry_service_broker" "service_broker_mysuperbroker" {
  name = "mysuperbroker"
  url = "http://url.of.my.service.broker.com"
  username = "user"
  password = "mypassword"
  service_access {
    service = "service_name_from_service_broker_catalog"
    plan = "plan_from_service_broker_catalog"
    org_id = "${cloudfoundry_organization.org_mysuperorg.id}"
  }
  service_access {
    service = "service_name_from_service_broker_catalog"
    plan = "plan2_from_service_broker_catalog"
    org_id = "${cloudfoundry_organization.org_mysuperorg.id}"
  }
  #...
}

BUG FOUND: if you set both plan and org_id in your service_access Cloud Foundry will enable all plans on this org. It's maybe only on the version of Cloud Foundry I am. Feedbacks are needed on other versions.

Data source

Note: every parameters from resource which are not used here are marked as computed and will be filled, except:

resource "cloudfoundry_service_broker" "service_broker_mysuperbroker" {
  name = "mysuperbroker"
  // or by_id = "a-guid"
}

Applications

This resource is used in order to deploy and update an application. It can see changes between code you have locally and code you have in your cloud foundry to do the update fastly (It compares a checksum from a chunk of data between local and remotely)

By default, when updating, your app will never shutdown. It always use blue-green deployment when app bits changed, rename or scale number of instances instantly and do blue-green restage in all others modification.

As a terraform resource, creating an app give you more control but can also be more painful than using the cli. To be painless, terraform modules can be use to deploy you app like you could do with a manifest.yml file. This can be found on https://github.com/orange-cloudfoundry/terraform-cloudfoundry-modules

Resource

resource "cloudfoundry_app" "myapp" {
  name = "myapp"
  stack_id = "${data.cloudfoundry_stack.my_stack.id}"
  space_id = "${data.cloudfoundry_space.space_mysuperspace.id}"
  started = true
  instances = 2
  memory = "64M"
  disk_quota = "1G"
  command = ""
  path = "/path/to/folder"
  diego = true
  buildpack = "php_buildpack"
  health_check_type = "port"
  health_check_http_endpoint = ""
  health_check_timeout = ""
  docker_image = ""
  enable_ssh = false
  ports = [8080]
  routes = ["${cloudfoundry_route.route_superroute.id}"]
  services = ["${cloudfoundry_service.svc_db.id}"]
  env_var = {
    "MY_ENV_KEY" = "myvalue"
    "MY_ENV_KEY2" = "myvalue2"
    #...
  }
}

Note:

Data source

Note: every parameters from resource which are not used here are marked as computed and will be filled.

resource "cloudfoundry_service_broker" "myapp" {
  name = "mysuperbroker"
  space_id = "${data.cloudfoundry_space.space_mysuperspace.id}"
  // or by_id = "a-guid"
}

Enable password encryption

You can use gpg encryption to encrypt your service broker password.

Create a private key for the provider

Requirements: you will need to have gpg on your system.

  1. run gpg --gen-key, next steps will assume that you put cloudfoudry as real name. (Do not forget to remember your passphrase!)
  2. go on your terraform folder config in command line
  3. run gpg --export-secret-key -a cloudfoudry > private.key
  4. inside provider configuration put those two key/value pairs (you can also copy content of private.key and export CF_ENC_PRIVATE_KEY=content_of_private.key && export CF_ENC_PASSPHRASE=your_passphrase_that_you_remembered:)):
    provider "cloudfoundry" {
    enc_private_key = "${file("private.key")}"
    enc_passphrase = "your_passphrase_that_you_remembered:)"
    }
  5. create the public key with gpg --export -a cloudfoudry > public.key
  6. Share the public key to the rest of your team to let them encrypt password with it (see Encrypt password)
  7. you're done

Encrypt password

  1. Get the public key previously created (public.key)
  2. Import the key with gpg --import public.key
  3. generate the encrypted password with commands echo "mypassword" | gpg --encrypt --armor -r cloudfoudry > encrypted_pass.key
  4. Retrieve it from your resource, e.g.:
    resource "cloudfoundry_service_broker" "service_broker_mysuperbroker" {
    name = "mysuperbroker"
    url = "http://url.of.my.service.broker.com"
    username = "user"
    password = "${file("encrypted_pass.key")}"
    service_access {
    service = "service_name_from_service_broker_catalog"
    }
    }
  5. you're done