Skip to content
This repository has been archived by the owner on Jan 21, 2020. It is now read-only.

Commit

Permalink
New flags for playbook backends with AWS examples (#828)
Browse files Browse the repository at this point in the history
Signed-off-by: David Chung <[email protected]>
  • Loading branch information
David Chung authored Jan 8, 2018
1 parent ed1107f commit 07d7dbe
Show file tree
Hide file tree
Showing 15 changed files with 342 additions and 176 deletions.
2 changes: 1 addition & 1 deletion cmd/infrakit/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,10 +34,10 @@ import (
// CLI backends
_ "github.com/docker/infrakit/pkg/cli/backend/http"
_ "github.com/docker/infrakit/pkg/cli/backend/instance"
_ "github.com/docker/infrakit/pkg/cli/backend/manager"
_ "github.com/docker/infrakit/pkg/cli/backend/print"
_ "github.com/docker/infrakit/pkg/cli/backend/sh"
_ "github.com/docker/infrakit/pkg/cli/backend/ssh"
_ "github.com/docker/infrakit/pkg/cli/backend/stack"
_ "github.com/docker/infrakit/pkg/cli/backend/vmwscript"

// Supported "kinds"
Expand Down
21 changes: 21 additions & 0 deletions examples/playbooks/aws/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
Example Playbook for AWS
========================

This playbook contains example of working with AWS. There are commands for
starting up infrakit (which assumes you have used AWS CLI on your local computer and
the `.aws/credentials` file exists) and commands for spinning up an on-demand or
spot instance configured with Docker, Git and Go compiler.

## Adding this playbook

Adding files locally:

```
infrakit playbook add aws file://$(pwd)/index.yml
```

Adding the playbook from Github:

```
infrakit playbook add aws https://raw.githubusercontent.com/docker/infrakit/master/examples/playbooks/aws/index.yml
```
9 changes: 9 additions & 0 deletions examples/playbooks/aws/index.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@

# Start infrakit
start : start.sh

# Create a single instance
ondemand : provision-instance.yml

# Create a spot instance
spot : provision-spot-instance.yml
56 changes: 56 additions & 0 deletions examples/playbooks/aws/provision-instance.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
{{/* Input to create instance using the AWS instance plugin */}}
{{/* =% instanceProvision `aws/ec2-instance` %= */}}

{{ $user := flag "user" "string" "username" | prompt "Please enter your user name:" "string" (env "USER")}}
{{ $project := flag "project" "string" "project" | prompt "Project?" "string" "myproject" }}
{{ $imageId := flag "image-id" "string" "Image ID" | prompt "AMI?" "string" "ami-df8406b0" }}
{{ $instanceType := flag "instance-type" "string" "instance type" | prompt "Instance type?" "string" "t2.micro" }}
{{ $privateIp := flag "private-ip" "string" "Private IP" | prompt "Private IP address (IPv4)?" "string" "172.31.20.100" }}


{{ $keyName := flag "key" "string" "ssh key name" | prompt "SSH key?" "string" "infrakit"}}
{{ $az := flag "az" "string" "availability zone" | prompt "Availability zone?" "string" "eu-central-1b"}}
{{ $subnetId := flag "subnet" "string" "subnet id" | prompt "Subnet ID?" "string" "subnet-11b8376a" }}
{{ $securityGroupId := flag "security-group-id" "string" "security group id" | prompt "Security group ID?" "string" "sg-975500fe" }}

Tags:
infrakit.scope: {{ $project }}
infrakit.created: {{ now | htmlDate }}
infrakit.user: {{ $user }}

Init: |
#!/bin/bash
sudo add-apt-repository ppa:gophers/archive
sudo apt-get update -y
sudo apt-get install -y wget curl git golang-1.9-go
wget -qO- https://get.docker.com | sh
ln -s /usr/lib/go-1.9/bin/go /usr/local/bin/go
Properties:
RunInstancesInput:
BlockDeviceMappings: null
DisableApiTermination: null
EbsOptimized: null
IamInstanceProfile: null
ImageId: {{ $imageId }}
InstanceInitiatedShutdownBehavior: null
InstanceType: {{ $instanceType }}
KeyName: {{ $keyName }}
NetworkInterfaces:
- AssociatePublicIpAddress: true
PrivateIpAddress: {{ $privateIp }}
DeleteOnTermination: true
DeviceIndex: 0
Groups:
- {{ $securityGroupId }}
NetworkInterfaceId: null
SubnetId: {{ $subnetId }}
Placement:
Affinity: null
AvailabilityZone: {{ $az }}
Tenancy: null
RamdiskId: null
SubnetId: null
UserData: null
Tags:
infrakit.user: {{ $user }}
49 changes: 49 additions & 0 deletions examples/playbooks/aws/provision-spot-instance.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
{{/* Input to create a spot instance using the AWS instance plugin */}}
{{/* =% instanceProvision `aws/ec2-spot-instance` %= */}}

{{ $user := flag "user" "string" "username" | prompt "Please enter your user name:" "string" (env "USER")}}
{{ $project := flag "project" "string" "project" | prompt "Project?" "string" "myproject" }}
{{ $imageId := flag "image-id" "string" "Image ID" | prompt "AMI?" "string" "ami-df8406b0" }}
{{ $instanceType := flag "instance-type" "string" "instance type" | prompt "Instance type?" "string" "t2.micro" }}
{{ $privateIp := flag "private-ip" "string" "Private IP" | prompt "Private IP address (IPv4)?" "string" "172.31.20.100" }}
{{ $spotPrice := flag "spot-price" "string" "Spot price" | prompt "Spot price?" "string" "0.03" }}

{{ $keyName := flag "key" "string" "ssh key name" | prompt "SSH key?" "string" "infrakit"}}
{{ $az := flag "az" "string" "availability zone" | prompt "Availability zone?" "string" "eu-central-1b"}}
{{ $subnetId := flag "subnet" "string" "subnet id" | prompt "Subnet ID?" "string" "subnet-11b8376a" }}
{{ $securityGroupId := flag "security-group-id" "string" "security group id" | prompt "Security group ID?" "string" "sg-975500fe" }}

Tags:
infrakit.scope: {{ $project }}
infrakit.created: {{ now | htmlDate }}
infrakit.user: {{ $user }}

Init: |
#!/bin/bash
sudo add-apt-repository ppa:gophers/archive
sudo apt-get update -y
sudo apt-get install -y wget curl git golang-1.9-go
wget -qO- https://get.docker.com | sh
ln -s /usr/lib/go-1.9/bin/go /usr/local/bin/go
Properties:
RequestSpotInstancesInput:
LaunchSpecification:
ImageId: {{ $imageId }}
InstanceType: {{ $instanceType }}
KeyName: infrakit
NetworkInterfaces:
- AssociatePublicIpAddress: true
DeleteOnTermination: true
DeviceIndex: 0
Groups:
- {{ $securityGroupId }}
NetworkInterfaceId: null
PrivateIpAddress: {{ $privateIp }}
PrivateIpAddresses: null
SecondaryPrivateIpAddressCount: null
SubnetId: {{ $subnetId }}
Placement:
AvailabilityZone: {{ $az }}
SpotPrice: "{{ $spotPrice }}"
Type: one-time
26 changes: 26 additions & 0 deletions examples/playbooks/aws/start.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
{{/* =% sh %= */}}

{{ $profile := flag "aws-cred-profile" "string" "Profile name" | prompt "Profile for your .aws/credentials?" "string" "default" }}
{{ $region := flag "region" "string" "aws region" | prompt "Region?" "string" "eu-central-1"}}
{{ $project := flag "project" "string" "project name" | prompt "Project?" "string" "myproject" }}

echo "Starting infrakit with aws plugin..."

{{/* Pick a credential from the local user's ~/.aws folder. You should have this if you use awscli. */}}
{{ $creds := (source (cat "file://" (env "HOME") "/.aws/credentials" | nospace) | iniDecode | k $profile ) }}
FOUND="{{ not (empty $creds) }}"
if [ $FOUND = "false" ]; then
echo "no credentials found. bye"
exit 1
fi
{{ echo "Found your credential for profile" $profile }}
AWS_ACCESS_KEY_ID={{ $creds.aws_access_key_id }} \
AWS_SECRET_ACCESS_KEY={{ $creds.aws_secret_access_key }} \
INFRAKIT_AWS_REGION={{ $region }} \
INFRAKIT_AWS_STACK_NAME={{ $project }} \
INFRAKIT_AWS_NAMESPACE_TAGS="infrakit.scope={{ $project }}" \
INFRAKIT_AWS_MONITOR_POLL_INTERVAL=5s \
infrakit plugin start aws
54 changes: 25 additions & 29 deletions pkg/cli/backend/instance/provision.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,51 +8,47 @@ import (
"github.com/docker/infrakit/pkg/spi/instance"
"github.com/docker/infrakit/pkg/types"
"github.com/spf13/cobra"
"github.com/spf13/pflag"
)

func init() {
backend.Register("instanceProvision", Provision, nil)
backend.Register("instanceProvision", Provision,
func(flags *pflag.FlagSet) {
flags.String("plugin", "", "plugin")
})
}

// Provision backend requires the name of the plugin and a boolean to indicate if the content is yaml.
// It then returns an executable function based on that specification to call the named instance plugin's provision
// method.
// Provision returns an executable function based on that specification to call the named instance plugin's provision
// method. The optional parameter in the playbook script can be overridden by the value of the `--plugin` flag
// in the command line.
func Provision(scope scope.Scope, test bool, opt ...interface{}) (backend.ExecFunc, error) {

if len(opt) != 2 {
return nil, fmt.Errorf("require params: pluginName (string) and isYAML (bool)")
}

name, is := opt[0].(string)
if !is {
return nil, fmt.Errorf("first param (pluginName) must be string")
}
return func(script string, cmd *cobra.Command, args []string) error {

isYAML, is := opt[1].(bool)
if !is {
return nil, fmt.Errorf("second param (isYAML) must be a bool")
}
var name string

return func(script string, cmd *cobra.Command, args []string) error {
// Optional parameter for plugin name can be overridden by the value of the flag (--plugin):
if len(opt) > 0 {
s, is := opt[0].(string)
if !is {
return fmt.Errorf("first param (pluginName) must be string")
}
name = s
}
if n, err := cmd.Flags().GetString("plugin"); err != nil {
return err
} else if n != "" {
name = n
}

plugin, err := scope.Instance(name)
if err != nil {
return err
}

spec := instance.Spec{}
if isYAML {
y, err := types.AnyYAML([]byte(script))
if err != nil {
return err
}
if err := y.Decode(&spec); err != nil {
return err
}
} else {
if err := types.AnyString(script).Decode(&spec); err != nil {
return err
}
if err := types.Decode([]byte(script), &spec); err != nil {
return err
}

id, err := plugin.Provision(spec)
Expand Down
85 changes: 0 additions & 85 deletions pkg/cli/backend/manager/commit.go

This file was deleted.

54 changes: 54 additions & 0 deletions pkg/cli/backend/stack/enforce.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
package stack

import (
"fmt"

"github.com/docker/infrakit/pkg/cli/backend"
"github.com/docker/infrakit/pkg/run/scope"
"github.com/docker/infrakit/pkg/types"
"github.com/spf13/cobra"
"github.com/spf13/pflag"
)

func init() {
backend.Register("stackEnforce", Enforce,
func(flags *pflag.FlagSet) {
flags.String("stack", "", "Name of stack")
})
}

// Enforce backend requires the name of the plugin and a boolean to indicate if the content is yaml.
// It then returns an executable function based on that specification to call the named instance plugin's provision
// method.
func Enforce(scope scope.Scope, test bool, opt ...interface{}) (backend.ExecFunc, error) {

return func(script string, cmd *cobra.Command, args []string) error {

var name string

// Optional parameter for plugin name can be overridden by the value of the flag (--stack):
if len(opt) > 0 {
n, is := opt[0].(string)
if !is {
return fmt.Errorf("first param (stackName) must be string")
}
name = n
}
name, err := cmd.Flags().GetString("stack")
if err != nil {
return err
}

stack, err := scope.Stack(name)
if err != nil {
return err
}

specs := types.Specs{}
if err := types.Decode([]byte(script), &specs); err != nil {
return err
}

return stack.Enforce(specs)
}, nil
}
Loading

0 comments on commit 07d7dbe

Please sign in to comment.