Component Modules

Providers

The providers component modules is where the cloud providers for the deployment are specified. Cloudscript also supports the deployment of different components within the same service to different providers.

providers {
  aws {
    provider = "aws"
    region   = "us-east-1"
  }
  google {
    provider = "google"
    project  = "my-gcp-project"
    region   = "us-central1"
  }
}
Providers

Custom Types

As mentioned within syntax features, custom types can be defined to reduce repetition and enforce variable definition.

type Instance {
    base: ComputeInstance
    name: string = "default-instance"
    size: "t2.micro" | "t2.small" = "t2.micro"
}
Syntax Features

Service Blocks

Service blocks contain the majority of the Cloudscript code, including the default provider, infrastructure, configuration, containers and deployment specifications.

service "webapp" {
  provider = "aws"
  
  infrastructure {
    network "vpc" {
      cidr_block           = "10.0.0.0/16"
      enable_dns_hostnames = true
      enable_dns_support   = true
      tags = {
        Name = "main-vpc"
      }
      resource_type = "aws_vpc"
    }

    network "subnet1" {
      vpc_id            = "${infrastructure.network.vpc.id}"
      cidr_block        = "10.0.1.0/24"
      availability_zone = "us-east-1a"
      resource_type     = "aws_subnet"
    }

    network "subnet2" {
      vpc_id            = "${infrastructure.network.vpc.id}"
      cidr_block        = "10.0.2.0/24"
      availability_zone = "us-east-1b"
      resource_type     = "aws_subnet"
    }

    network "internet_gateway" {
      vpc_id        = "${infrastructure.network.vpc.id}"
      tags = {
        Name = "main"
      }
      resource_type = "aws_internet_gateway"
    }

    network "route_table" {
      vpc_id = "${infrastructure.network.vpc.id}"
      route = [
        {
          cidr_block = "0.0.0.0/0"
          gateway_id = "${infrastructure.network.internet_gateway.id}"
        }
      ]
      resource_type = "aws_route_table"
    }

    network "route_table_association_subnet1" {
      subnet_id      = "${infrastructure.network.subnet1.id}"
      route_table_id = "${infrastructure.network.route_table.id}"
      resource_type  = "aws_route_table_association"
    }

    network "route_table_association_subnet2" {
      subnet_id      = "${infrastructure.network.subnet2.id}"
      route_table_id = "${infrastructure.network.route_table.id}"
      resource_type  = "aws_route_table_association"
    }

    iam "eks_cluster" {
      name               = "eks_cluster"
      assume_role_policy = file("role.json")
      resource_type      = "aws_iam_role"
    }

    iam "eks_cluster_policy_attachment" {
      role        = "${infrastructure.iam.eks_cluster.name}"
      policy_arn  = "arn:aws:iam::aws:policy/AmazonEKSClusterPolicy"
      resource_type = "aws_iam_role_policy_attachment"
    }

    compute "eks_cluster" {
      name       = "main"
      role_arn   = "${infrastructure.iam.eks_cluster.arn}"
      vpc_config = {
        subnet_ids = [
          "${infrastructure.network.subnet1.id}",
          "${infrastructure.network.subnet2.id}"
        ]
      }
      depends_on    = ["infrastructure.iam.eks_cluster_policy_attachment"]
      resource_type  = "aws_eks_cluster"
    }

    compute "web_server" {
      instance_type         = "t2.micro"
      ami                   = "ami-005fc0f236362e99f"
      subnet_id             = "${infrastructure.network.subnet1.id}"
      tags = {
        Name = "main_web_server"
      }
      key_name              = "cloud-cli-key"
      depends_on            = ["infrastructure.network.vpc"]
      resource_type         = "aws_instance"
    }
  }

  configuration {
    play "webapp" {
      name   = "Configure webapp"
      hosts  = "{{ target_servers | default('all') }}"
      become = true
      vars = {
        target_web_servers = "web_servers"
        target_db_servers  = "db_servers"
      }

      task {
        name = "Packages tasks"
        block {
          task {
            name          = "Install required packages"
            package {
              name          = "{{ item }}"
              state         = "present"
              update_cache  = true
            }
            loop = ["nginx", "docker"]
          }
        }
      }

      task {
        name = "Other tasks"
        block {
          task {
            name     = "Create/modify /etc/nginx/nginx.conf"
            copy {
              dest    = "/etc/nginx/nginx.conf"
              content = file("nginx.conf")
              mode    = "0644"
              owner   = "root"
              group   = "root"
            }
            notify = ["restart nginx"]
            when   = "ansible_distribution == 'Ubuntu'"
          }

          task {
            name            = "Ensure nginx is started"
            service {
              name    = "nginx"
              state   = "started"
              enabled = "yes"
            }
            register          = "nginx_started_result"
            retries           = 3
            delay             = 5
            failed_when       = "nginx_started_result is failed"
            changed_when      = "nginx_started_result is changed"
            when              = "ansible_distribution == 'Ubuntu'"
          }

          task {
            name            = "Verify nginx"
            command         = "systemctl is-active nginx"
            register        = "verify_nginx"
            failed_when     = "verify_nginx.rc != 0"
            changed_when    = false
            retries         = 1
            delay           = 5
          }
        }
      }

      handler {
        name    = "restart nginx"
        service {
          name  = "nginx"
          state = "restarted"
        }
      }
    }
  }

  containers {
    app "web_app" {
      image             = "nginx:latest"
      type              = "Deployment"
      replicas          = 3
      command           = ["/bin/sh"]
      args              = ["-c", "nginx -g 'daemon off;'"]
      working_dir       = "/usr/share/nginx/html"

      readiness_probe = {
        http_get = {
          path = "/healthz"
          port = 80
        }
        initial_delay_seconds = 5
        period_seconds        = 10
      }

      resources = {
        limits = {
          cpu    = "500m"
          memory = "512Mi"
        }
        requests = {
          cpu    = "250m"
          memory = "256Mi"
        }
      }

      empty_dir_volumes = [
        {
          name       = "cache"
          size_limit = "1Gi"
        }
      ]

      volume_mounts = [
        {
          name      = "cache"
          mountPath = "/cache"
        }
      ]

      ports = [
        {
          container_port = 80
          service_port   = 80
        }
      ]

      service = {
        type        = "LoadBalancer"
        annotations = {
          "service.beta.kubernetes.io/aws-load-balancer-type" = "nlb"
        }
      }

      node_selector = {
        "kubernetes.io/os" = "linux"
        "node-type"        = "web"
      }

      auto_scaling = {
        min_replicas                      = 2
        max_replicas                      = 10
        target_cpu_utilization_percentage = 80
      }
    }
  }

  deployment {
    "infrastructure.compute.web_server" maps_to "configuration.play.webapp"
  }
}
Service Blocks

Last updated