Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added kubernetes specs #34

Merged
merged 8 commits into from
Oct 29, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
17 changes: 14 additions & 3 deletions cmd/generate.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import (
"github.com/commitdev/commit0/internal/generate/docker"
"github.com/commitdev/commit0/internal/generate/golang"
"github.com/commitdev/commit0/internal/generate/http"
"github.com/commitdev/commit0/internal/generate/kubernetes"
"github.com/commitdev/commit0/internal/generate/proto"
"github.com/commitdev/commit0/internal/generate/react"
"github.com/commitdev/commit0/internal/templator"
Expand All @@ -20,11 +21,12 @@ var configPath string
var language string

const (
Go = "go"
React = "react"
Go = "go"
React = "react"
Kubernetes = "kubernetes"
)

var supportedLanguages = [...]string{Go, React}
var supportedLanguages = [...]string{Go, React, Kubernetes}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe this should be called something else rather than "languages" if it's the right place for this. Or maybe we should start splitting this into sections.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I agree, rename it modules? @Pritesh-Patel

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Don't worry about this for now, I'll do some refactoring.


func init() {

Expand Down Expand Up @@ -59,6 +61,8 @@ var generateCmd = &cobra.Command{
docker.GenerateGoDockerCompose(t, cfg, &wg)
case React:
react.Generate(t, cfg, &wg)
case Kubernetes:
kubernetes.Generate(t, cfg, &wg)
}

util.TemplateFileIfDoesNotExist("", "README.md", t.Readme, &wg, cfg)
Expand All @@ -68,7 +72,14 @@ var generateCmd = &cobra.Command{
docker.GenerateGoHTTPGWDockerFile(t, cfg, &wg)
}

// Wait for all the templates to be generated
wg.Wait()

switch language {
case Kubernetes:
kubernetes.Execute(cfg)
}

},
}

Expand Down
5 changes: 3 additions & 2 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,12 @@ require (
github.com/k0kubun/colorstring v0.0.0-20150214042306-9440f1994b88 // indirect
github.com/k0kubun/pp v3.0.1+incompatible
github.com/mattn/go-colorable v0.1.2 // indirect
github.com/rogpeppe/go-internal v1.3.2 // indirect
github.com/rogpeppe/go-internal v1.5.0 // indirect
github.com/spf13/cobra v0.0.5
github.com/stretchr/testify v1.4.0 // indirect
golang.org/x/crypto v0.0.0-20190923035154-9ee001bba392 // indirect
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550 // indirect
golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e // indirect
golang.org/x/sys v0.0.0-20191010194322-b09406accb47 // indirect
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 // indirect
gopkg.in/yaml.v2 v2.2.4
)
12 changes: 6 additions & 6 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -48,8 +48,8 @@ github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZb
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/rogpeppe/go-internal v1.1.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
github.com/rogpeppe/go-internal v1.3.2 h1:XU784Pr0wdahMY2bYcyK6N1KuaRAdLtqD4qd8D18Bfs=
github.com/rogpeppe/go-internal v1.3.2/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc=
github.com/rogpeppe/go-internal v1.5.0 h1:Usqs0/lDK/NqTkvrmKSwA/3XkZAs7ZAW/eLeQ2MVBTw=
github.com/rogpeppe/go-internal v1.5.0/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc=
github.com/russross/blackfriday v1.5.2/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR/rfWxYHBV53g=
github.com/sirupsen/logrus v1.4.2 h1:SPIRibHv4MatM3XXNO2BJeFLZwZ2LvZgfQ5+UNI2im4=
github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE=
Expand All @@ -72,8 +72,8 @@ github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77/go.mod h1:
golang.org/x/crypto v0.0.0-20181203042331-505ab145d0a9/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20190621222207-cc06ce4a13d4/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20190923035154-9ee001bba392 h1:ACG4HJsFiNMf47Y4PeRoebLNy/2lXT9EtprMuTFWt1M=
golang.org/x/crypto v0.0.0-20190923035154-9ee001bba392/go.mod h1:/lpIB1dKB+9EgE3H3cr1v9wB50oz8l4C4h62xy7jSTY=
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550 h1:ObdrDkeb4kJdCP557AjRjq69pTHfNouLtWZG7j9rPN8=
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3 h1:0GoQqolDA55aaLxZyTzK/Y2ePZzZTUrRacwib7cNsYQ=
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
Expand All @@ -86,8 +86,8 @@ golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5h
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190515120540-06a5c4944438/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190922100055-0a153f010e69 h1:rOhMmluY6kLMhdnrivzec6lLgaVbMHMn2ISQXJeJ5EM=
golang.org/x/sys v0.0.0-20190922100055-0a153f010e69/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191010194322-b09406accb47 h1:/XfQ9z7ib8eEJX2hdgFTZJ/ntt0swNk5oYBziWeTCvY=
golang.org/x/sys v0.0.0-20191010194322-b09406accb47/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/text v0.3.0 h1:g61tztE5qeGQ89tm6NTjjM9VPIm088od1l6aSorWRWg=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/tools v0.0.0-20190628153133-6cdbf07be9d0 h1:Dh6fw+p6FyRl5x/FvNswO1ji0lIGzm3KP8Y9VkS9PTE=
Expand Down
10 changes: 9 additions & 1 deletion internal/config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,15 @@ type Commit0Config struct {
Maintainers []Maintainers `yaml:"maintainers"`
Network Network `yaml:"network"`
Services []Service `yaml:"services"`
React React `yaml:react`
React React `yaml:"react"`
Kubernetes Kubernetes `yaml:"kubernetes"`
}

type Kubernetes struct {
ClusterName string `yaml:"clusterName"`
Deploy bool `yaml:"deploy"`
AWSAccountId string `yaml:"awsAccountId"`
AWSRegion string `yaml:"awsRegion"`
}

func LoadConfig(filePath string) *Commit0Config {
Expand Down
64 changes: 64 additions & 0 deletions internal/generate/kubernetes/generate.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
package kubernetes

import (
"fmt"
"io"
"log"
"os"
"os/exec"
"sync"

"github.com/commitdev/commit0/internal/config"
"github.com/commitdev/commit0/internal/templator"
)

func Generate(templator *templator.Templator, config *config.Commit0Config, wg *sync.WaitGroup) {
templator.Kubernetes.TemplateFiles(config, false, wg)

}

func Execute(config *config.Commit0Config) {
if config.Kubernetes.Deploy {
log.Println("Planning infrastructure...")
execute(exec.Command("terraform", "init"))
execute(exec.Command("terraform", "plan"))
}
}

func execute(cmd *exec.Cmd) {
dir, err := os.Getwd()
if err != nil {
log.Fatalf("Getting working directory failed: %v\n", err)
}

cmd.Dir = fmt.Sprintf("%s/kubernetes/terraform/environments/staging", dir)

stdoutPipe, _ := cmd.StdoutPipe()
stderrPipe, _ := cmd.StderrPipe()

var errStdout, errStderr error
err = cmd.Start()
if err != nil {
log.Fatalf("Starting terraform command failed: %v\n", err)
}

go func() {
_, errStdout = io.Copy(os.Stdout, stdoutPipe)
}()
go func() {
_, errStderr = io.Copy(os.Stderr, stderrPipe)
}()

err = cmd.Wait()
if err != nil {
log.Fatalf("Executing terraform command failed: %v\n", err)
}

if errStdout != nil {
log.Printf("Failed to capture stdout: %v\n", errStdout)
}

if errStderr != nil {
log.Printf("Failed to capture stderr: %v\n", errStderr)
}
}
2 changes: 2 additions & 0 deletions internal/templator/templator.go
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ type Templator struct {
Go *GoTemplator
Docker *DockerTemplator
React *DirectoryTemplator
Kubernetes *DirectoryTemplator
}

func NewTemplator(box *packr.Box) *Templator {
Expand All @@ -54,6 +55,7 @@ func NewTemplator(box *packr.Box) *Templator {
Readme: NewSingleFileTemplator(box, "util/README.tmpl"),
Docker: NewDockerFileTemplator(box),
React: NewDirectoryTemplator(box, "react"),
Kubernetes: NewDirectoryTemplator(box, "kubernetes"),
}
}

Expand Down
6 changes: 6 additions & 0 deletions templates/commit0/commit0.tmpl
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,12 @@ maintainers:
# - name: bob
# email: bob@test.com

kubernetes:
clusterName: staging
deploy: true
awsAccountId: 1234
awsRegion: us-east-1

network:
grpc:
host: 0.0.0.0
Expand Down
95 changes: 95 additions & 0 deletions templates/kubernetes/terraform/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
## Guidelines & Style Convention Summary

- All Terraform configuration should be formatted with `terraform fmt` before being accepted into this repository.
- This repository is Terraform version >= 0.12, as such, leverage features from this release whenever possible.
See https://www.terraform.io/upgrade-guides/0-12.html for more information.
- Leverage community-maintained Terraform modules whenever possible.
- Attempt to minimize duplication whenever possible, but only within reason -- sometimes duplication is an acceptable solution.
- Follow style conventions described in `docs/guide.pdf` whenever possible.
- Whenever possible, inject resources down versus referencing resources across modules. This has been made easier with new features in v0.12.
- Whenever possible, define the types of variables.

### Module Conventions

- All modules should contain the following:

`README.md`: A description of the module.
`main.tf`: Module entrypoint where instantiation of resources happens.
`variables.tf`: Module variables.
`outputs.tf`: Output values (optional).
`files/`: Any / all files required by the module.

- All module variables must have a description.
- Again, leverage community-maintained Terraform modules whenever possible.
- Avoid writing a module that is simply a wrapper of a Terraform resource unless absolutely necessary.

### Environment Conventions

- All environments should contain the following:

`main.tf`: Toplevel terraform configuration file that instantiates the `environment` module.

- Configuration should be pushed "top->down" from the `environment` module to it's submodules.

### The Environment Module

- The `environment` module can be considered the top-level module, all other modules are imported from this module.
- Environment-specific variables should be exposed via the `variables.tf` file in this module, where they will be set from within the appropriate environment in the `environments/` directory.
- The `environment` module contains the following:

`main.tf`: Module entrypoint where instantiation of resources happens.
`backend.tf`: Terraform remote state configuration.
`provider.tf`: Provider configuration.
`variables.tf`: Environment-specific variables are desclared here.
`versions.tf`: Terraform version information.
`files/`: (DEPRECATED)

## Directory Structure

```
README.md
environments/
production/
main.tf
staging/
main.tf
development/
main.tf
docs/
guide.pdf
modules/
environment/
...
<module-a>/
files/
scripts/
main.tf
outputs.tf
variables.tf
<module-n>/
...
```

## AWS Guidelines

- TODO: Identity/Access Management (IAM) Guidelines

## Kubernetes Guidelines

- When to use the Terraform Kuberenetes Provider and when to use manifests?

- Use the Terraform Kubernetes Provider (`provider "kubernetes"`) whenever you are provisioning a resource that could be considered relatively static (think Ingress, RoleBinding, CluterRoleBinding, etc).

- Use conventional Kubernetes manifests / `kubectl` when provisioning resouirces that could be considered dynamic (think Deployments).

## Application

1. Set up a profile for your project with your credentials in a specific profile in `~/.aws/credentials` and then export the following env var:
`export AWS_PROFILE=<project_name>`

2. Run the following from the appropriate environment directory under `environments/`:

```
environment/development$ terraform init
environment/development$ terraform plan
```
22 changes: 22 additions & 0 deletions templates/kubernetes/terraform/environments/development/main.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
# Instantiate the development environment
module "development" {
source = "../../modules/environment"
environment = "development"

# Project configuration
project = "{{ .Kubernetes.ClusterName }}"
region = "{{ .Kubernetes.AWSRegion }}"
allowed_account_ids = ["{{ .Kubernetes.AWSAccountId }}"]

# ECR configuration
ecr_repositories = ["{{ .Kubernetes.ClusterName }}"]

# EKS configuration
eks_worker_instance_type = "t2.small"
eks_worker_asg_max_size = 2

# EKS-Optimized AMI for your region: https://docs.aws.amazon.com/eks/latest/userguide/eks-optimized-ami.html
# https://us-east-1.console.aws.amazon.com/systems-manager/parameters/%252Faws%252Fservice%252Feks%252Foptimized-ami%252F1.14%252Famazon-linux-2%252Frecommended%252Fimage_id/description?region=us-east-1
eks_worker_ami = "ami-0392bafc801b7520f"

}
21 changes: 21 additions & 0 deletions templates/kubernetes/terraform/environments/production/main.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
# Instantiate the production environment
module "production" {
source = "../../modules/environment"
environment = "production"

# Project configuration
project = "{{ .Kubernetes.ClusterName }}"
region = "{{ .Kubernetes.AWSRegion }}"
allowed_account_ids = ["{{ .Kubernetes.AWSAccountId }}"]

# ECR configuration
ecr_repositories = ["{{ .Kubernetes.ClusterName }}"]

# EKS configuration
eks_worker_instance_type = "m4.large"
eks_worker_asg_max_size = 3

# EKS-Optimized AMI for your region: https://docs.aws.amazon.com/eks/latest/userguide/eks-optimized-ami.html
# https://us-east-1.console.aws.amazon.com/systems-manager/parameters/%252Faws%252Fservice%252Feks%252Foptimized-ami%252F1.14%252Famazon-linux-2%252Frecommended%252Fimage_id/description?region=us-east-1
eks_worker_ami = "ami-0392bafc801b7520f"
}
21 changes: 21 additions & 0 deletions templates/kubernetes/terraform/environments/staging/main.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
# Instantiate the staging environment
module "staging" {
source = "../../modules/environment"
environment = "staging"

# Project configuration
project = "{{ .Kubernetes.ClusterName }}"
region = "{{ .Kubernetes.AWSRegion }}"
allowed_account_ids = ["{{ .Kubernetes.AWSAccountId }}"]

# ECR configuration
ecr_repositories = ["{{ .Kubernetes.ClusterName }}"]

# EKS configuration
eks_worker_instance_type = "t2.small"
eks_worker_asg_max_size = 2
# EKS-Optimized AMI for your region: https://docs.aws.amazon.com/eks/latest/userguide/eks-optimized-ami.html
# https://us-east-1.console.aws.amazon.com/systems-manager/parameters/%252Faws%252Fservice%252Feks%252Foptimized-ami%252F1.14%252Famazon-linux-2%252Frecommended%252Fimage_id/description?region=us-east-1
eks_worker_ami = "ami-0392bafc801b7520f"

}
9 changes: 9 additions & 0 deletions templates/kubernetes/terraform/modules/ecr/main.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
resource "aws_ecr_repository" "ecr_repository" {
count = length(var.ecr_repositories)
name = element(var.ecr_repositories, count.index)

tags = {
environment = var.environment
}
}

9 changes: 9 additions & 0 deletions templates/kubernetes/terraform/modules/ecr/variables.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
variable "environment" {
description = "The environment (dev/staging/prod)"
}

variable "ecr_repositories" {
description = "List of ECR repository names to create"
type = list(string)
}

4 changes: 4 additions & 0 deletions templates/kubernetes/terraform/modules/ecr/versions.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@

terraform {
required_version = ">= 0.12"
}