services/jenkins-master/infrastructure.tf (232 lines of code) (raw):
# Licensed to the Apache Software Foundation (ASF) under one
# or more contributor license agreements. See the NOTICE file
# distributed with this work for additional information
# regarding copyright ownership. The ASF licenses this file
# to you under the Apache License, Version 2.0 (the
# "License"); you may not use this file except in compliance
# with the License. You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing,
# software distributed under the License is distributed on an
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
# KIND, either express or implied. See the License for the
# specific language governing permissions and limitations
# under the License.
variable "key_name" {
type = "string"
}
variable "key_path" {
type = "string"
}
variable "instance_type" {
type = "string"
}
variable "vpc_id" {
type = "string"
}
variable "additional_security_group_ids" {
type = "list"
}
variable "jenkins_config_bucket" {
type = "string"
}
variable "zone_id" {
type = "string"
}
variable "domain" {
type = "string"
}
variable "shell_variables_file" {
type = "string"
}
# AMI IDs can be retrieved at
# ftp://64.50.236.216/pub/ubuntu-cloud-images/query/xenial/server/released.txt
variable "ami" {
type = "string"
default = "ami-bd8f33c5" # Ubuntu 16.04 from 20180122
}
variable "instance_name" {
type = "string"
}
variable "aws_availability_zone" {
type = "string"
}
variable "aws_region" {
type = "string"
}
variable "aws_access_key" {
type = "string"
}
variable "aws_secret_key" {
type = "string"
}
variable "ebs_volume_jenkins_master_state_volume_id" {
type = "string"
}
provider "aws" {
access_key = "${var.aws_access_key}"
secret_key = "${var.aws_secret_key}"
region = "${var.aws_region}"
}
# Store terraform state in S3 instead of local.
terraform {
backend "s3" {
key = "terraform.tfstate"
# TODO: Lock statefile using dynamo db to prevent overriding statefiles if multiple
# people run terraform at the same time
# dynamodb_table = "terraform-state-${var.jenkins_config_bucket}-dynamo"
# Remaining config is defined in $CONFIG_DIR/infrastructure_backend.tfvars
# See https://www.terraform.io/docs/backends/config.html for more details
}
}
data "template_cloudinit_config" "user_data" {
# gzip = true
base64_encode = true
# Important: This part has to be in first place as it gets mapped to
# /var/lib/cloud/instance/scripts/part-001
# This is a hack, but there's no other way to reference other scripts
part {
content_type = "text/x-shellscript"
content = "${file("${var.shell_variables_file}")}"
}
# part-002
part {
content_type = "text/x-shellscript"
content = "${file("temp/jenkins_symlinks.sh")}"
}
# No Docker required on jenkins master
#part {
# content_type = "text/x-shellscript"
# content = "${file("scripts/docker_setup.sh")}"
#}
part {
content_type = "text/x-shellscript"
content = "${file("scripts/jenkins_setup.sh")}"
}
}
# Require in order to allow attaching policies, so called trust relationship policy document
resource "aws_iam_role" "jenkins_master_role" {
name = "jenkins_master_role"
assume_role_policy = <<POLICY
{
"Version": "2012-10-17",
"Statement": [
{
"Action": "sts:AssumeRole",
"Principal": {
"Service": "ec2.amazonaws.com"
},
"Effect": "Allow",
"Sid": ""
}
]
}
POLICY
}
resource "aws_iam_policy" "jenkins_master_s3_read_policy" {
name = "jenkins_master_s3_read_policy"
description = "Policy to grant Jenkins Master S3 read-access to the associated bucket"
policy = <<POLICY
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"s3:GetBucketLocation",
"s3:ListAllMyBuckets"
],
"Resource": "arn:aws:s3:::*"
},
{
"Effect": "Allow",
"Action": [
"s3:ListBucket"
],
"Resource": [
"arn:aws:s3:::${var.jenkins_config_bucket}"
]
},
{
"Effect": "Allow",
"Action": [
"s3:GetObject"
],
"Resource": [
"arn:aws:s3:::${var.jenkins_config_bucket}/*"
]
}
]
}
POLICY
}
resource "aws_iam_policy_attachment" "jenkins_master_s3_read_policy_attach" {
name = "jenkins_master_s3_read_policy_attach"
roles = ["${aws_iam_role.jenkins_master_role.name}"]
policy_arn = "${aws_iam_policy.jenkins_master_s3_read_policy.arn}"
}
resource "aws_iam_instance_profile" "jenkins_master_profile" {
name = "jenkins_master_profile"
role = "${aws_iam_role.jenkins_master_role.name}"
}
resource "aws_security_group" "allow_all_https" {
name = "tf_allow_all_https2"
description = "Allow all inbound traffic to https"
ingress {
from_port = 443
to_port = 443
protocol = "tcp"
cidr_blocks = ["0.0.0.0/0"]
ipv6_cidr_blocks = ["::/0"]
}
}
resource "aws_security_group" "allow_all_www" {
name = "tf_allow_all_www2"
description = "Allow all inbound traffic to www"
ingress {
from_port = 80
to_port = 80
protocol = "tcp"
cidr_blocks = ["0.0.0.0/0"]
ipv6_cidr_blocks = ["::/0"]
}
}
resource "aws_instance" "mxnet-ci" {
# The connection block tells our provisioner how to
# communicate with the resource (instance)
connection {
# The default username for our AMI
user = "ubuntu"
# The path to your keyfile
key_file = "${var.key_path}"
}
# subnet ID for our VPC TODO
# subnet_id = "${var.vpc_id}"
# the instance type we want, comes from rundeck
instance_type = "${var.instance_type}"
availability_zone = "${var.aws_availability_zone}"
# Spot instance params:
#spot_price = "${var.spot_price}"
#wait_for_fulfillment = "true"
# Lookup the correct AMI based on the region
# we specified
ami = "${var.ami}"
iam_instance_profile = "${aws_iam_instance_profile.jenkins_master_profile.name}"
# The name of our SSH keypair you've created and downloaded
# from the AWS console.
#
# https://console.aws.amazon.com/ec2/v2/home?region=us-west-2#KeyPairs:
#
key_name = "${var.key_name}"
#vpc_security_group_ids = "${var.security_groups_ids}"
vpc_security_group_ids = ["${
concat(
list(aws_security_group.allow_all_https.id),
list(aws_security_group.allow_all_www.id),
var.additional_security_group_ids
)
}"]
user_data = "${data.template_cloudinit_config.user_data.rendered}"
# We set the name as a tag. Not supported for spot instances:
# See https://github.com/hashicorp/terraform/issues/3263
tags {
"Name" = "${var.instance_name}"
}
root_block_device {
volume_type = "gp2"
volume_size = 1000
#iops = 15000
delete_on_termination = true
}
# Wait for S3 bucket as it's needed during startup
depends_on = [
"aws_s3_bucket_object.jenkins_config_s3",
"aws_s3_bucket_object.jenkins_plugins_s3"
]
}
resource "aws_s3_bucket" "jenkins_config_bucket" {
bucket = "${var.jenkins_config_bucket}"
acl = "private"
}
resource "aws_s3_bucket_object" "jenkins_config_s3" {
bucket = "${aws_s3_bucket.jenkins_config_bucket.id}"
key = "jenkins/jenkins.tar.bz2"
source = "temp/jenkins.tar.bz2"
etag = "${md5(file("temp/jenkins.tar.bz2"))}"
}
resource "aws_s3_bucket_object" "jenkins_plugins_s3" {
bucket = "${aws_s3_bucket.jenkins_config_bucket.id}"
key = "jenkins/jenkins_plugins.tar.bz2"
source = "temp/jenkins_plugins.tar.bz2"
etag = "${md5(file("temp/jenkins_plugins.tar.bz2"))}"
}
# TODO: Check for race conditions. Just in case:
# https://github.com/hashicorp/terraform/issues/2740#issuecomment-288549352
resource "aws_volume_attachment" "ebs_jenkins_master_state" {
device_name = "/dev/sdf"
volume_id = "${var.ebs_volume_jenkins_master_state_volume_id}"
instance_id = "${aws_instance.mxnet-ci.id}"
}
#output "user_data" {
# value = "${data.template_cloudinit_config.user_data.rendered}"
#}
resource "aws_route53_record" "mxnet-ci" {
zone_id = "${var.zone_id}"
name = "jenkins.${var.domain}"
type = "A"
ttl = "60"
records = ["${aws_instance.mxnet-ci.public_ip}"]
}
resource "aws_route53_record" "mxnet-ci-private" {
zone_id = "${var.zone_id}"
name = "jenkins-priv.${var.domain}"
type = "A"
ttl = "60"
records = ["${aws_instance.mxnet-ci.private_ip}"]
}
output "address" {
value = "${aws_instance.mxnet-ci.public_dns}"
}
output "mxnet-ci" {
value = "${aws_route53_record.mxnet-ci.fqdn}"
}