Skip to content

Commit

Permalink
Initial support for cloudformation output
Browse files Browse the repository at this point in the history
  • Loading branch information
justinsb committed Feb 17, 2017
1 parent e5b5737 commit 7d68f74
Show file tree
Hide file tree
Showing 34 changed files with 2,099 additions and 21 deletions.
4 changes: 3 additions & 1 deletion cmd/kops/create_cluster.go
Original file line number Diff line number Diff line change
Expand Up @@ -126,7 +126,7 @@ func NewCmdCreateCluster(f *util.Factory, out io.Writer) *cobra.Command {
}

cmd.Flags().BoolVar(&options.Yes, "yes", options.Yes, "Specify --yes to immediately create the cluster")
cmd.Flags().StringVar(&options.Target, "target", options.Target, "Target - direct, terraform")
cmd.Flags().StringVar(&options.Target, "target", options.Target, "Target - direct, terraform, cloudformation")
cmd.Flags().StringVar(&options.Models, "model", options.Models, "Models to apply (separate multiple models with commas)")

cmd.Flags().StringVar(&options.Cloud, "cloud", options.Cloud, "Cloud provider to use - gce, aws")
Expand Down Expand Up @@ -201,6 +201,8 @@ func RunCreateCluster(f *util.Factory, out io.Writer, c *CreateClusterOptions) e
if c.OutDir == "" {
if c.Target == cloudup.TargetTerraform {
c.OutDir = "out/terraform"
} else if c.Target == cloudup.TargetCloudformation {
c.OutDir = "out/cloudformation"
} else {
c.OutDir = "out"
}
Expand Down
100 changes: 100 additions & 0 deletions cmd/kops/integration_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,13 @@ func TestMinimal(t *testing.T) {
runTest(t, "minimal.example.com", "../../tests/integration/minimal", "v1alpha2", false)
}

// TestMinimalCloudformation runs the test on a minimum configuration, similar to kops create cluster minimal.example.com --zones us-west-1a
func TestMinimalCloudformation(t *testing.T) {
//runTestCloudformation(t, "minimal.example.com", "../../tests/integration/minimal", "v1alpha0", false)
//runTestCloudformation(t, "minimal.example.com", "../../tests/integration/minimal", "v1alpha1", false)
runTestCloudformation(t, "minimal.example.com", "../../tests/integration/minimal", "v1alpha2", false)
}

// TestMinimal_141 runs the test on a configuration from 1.4.1 release
func TestMinimal_141(t *testing.T) {
runTest(t, "minimal-141.example.com", "../../tests/integration/minimal-141", "v1alpha0", false)
Expand Down Expand Up @@ -209,6 +216,97 @@ func runTest(t *testing.T, clusterName string, srcDir string, version string, pr
}
}

func runTestCloudformation(t *testing.T, clusterName string, srcDir string, version string, private bool) {
var stdout bytes.Buffer

inputYAML := "in-" + version + ".yaml"
expectedCfPath := "cloudformation.json"

factoryOptions := &util.FactoryOptions{}
factoryOptions.RegistryPath = "memfs://tests"

h := NewIntegrationTestHarness(t)
defer h.Close()

h.SetupMockAWS()

factory := util.NewFactory(factoryOptions)

{
options := &CreateOptions{}
options.Filenames = []string{path.Join(srcDir, inputYAML)}

err := RunCreate(factory, &stdout, options)
if err != nil {
t.Fatalf("error running %q create: %v", inputYAML, err)
}
}

{
options := &CreateSecretPublickeyOptions{}
options.ClusterName = clusterName
options.Name = "admin"
options.PublicKeyPath = path.Join(srcDir, "id_rsa.pub")

err := RunCreateSecretPublicKey(factory, &stdout, options)
if err != nil {
t.Fatalf("error running %q create: %v", inputYAML, err)
}
}

{
options := &UpdateClusterOptions{}
options.InitDefaults()
options.Target = "cloudformation"
options.OutDir = path.Join(h.TempDir, "out")
options.MaxTaskDuration = 30 * time.Second

// We don't test it here, and it adds a dependency on kubectl
options.CreateKubecfg = false

err := RunUpdateCluster(factory, clusterName, &stdout, options)
if err != nil {
t.Fatalf("error running update cluster %q: %v", clusterName, err)
}
}

// Compare main files
{
files, err := ioutil.ReadDir(path.Join(h.TempDir, "out"))
if err != nil {
t.Fatalf("failed to read dir: %v", err)
}

var fileNames []string
for _, f := range files {
fileNames = append(fileNames, f.Name())
}
sort.Strings(fileNames)

actualFilenames := strings.Join(fileNames, ",")
expectedFilenames := "kubernetes.json"
if actualFilenames != expectedFilenames {
t.Fatalf("unexpected files. actual=%q, expected=%q", actualFilenames, expectedFilenames)
}

actualCF, err := ioutil.ReadFile(path.Join(h.TempDir, "out", "kubernetes.json"))
if err != nil {
t.Fatalf("unexpected error reading actual cloudformation output: %v", err)
}
expectedCF, err := ioutil.ReadFile(path.Join(srcDir, expectedCfPath))
if err != nil {
t.Fatalf("unexpected error reading expected cloudformation output: %v", err)
}

if !bytes.Equal(actualCF, expectedCF) {
diffString := diff.FormatDiff(string(expectedCF), string(actualCF))
t.Logf("diff:\n%s\n", diffString)

t.Fatalf("cloudformation output differed from expected")
}
}
}

type IntegrationTestHarness struct {
TempDir string
T *testing.T
Expand Down Expand Up @@ -256,6 +354,8 @@ func (h *IntegrationTestHarness) SetupMockAWS() {
ImageId: aws.String("ami-12345678"),
Name: aws.String("k8s-1.4-debian-jessie-amd64-hvm-ebs-2016-10-21"),
OwnerId: aws.String(awsup.WellKnownAccountKopeio),

RootDeviceName: aws.String("/dev/xvda"),
})
}

Expand Down
14 changes: 14 additions & 0 deletions cmd/kops/update_cluster.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ import (
"fmt"
"io"
"io/ioutil"
"path/filepath"
"strings"
"time"

Expand Down Expand Up @@ -107,6 +108,8 @@ func RunUpdateCluster(f *util.Factory, clusterName string, out io.Writer, c *Upd
if c.OutDir == "" {
if c.Target == cloudup.TargetTerraform {
c.OutDir = "out/terraform"
} else if c.Target == cloudup.TargetCloudformation {
c.OutDir = "out/cloudformation"
} else {
c.OutDir = "out"
}
Expand Down Expand Up @@ -233,6 +236,17 @@ func RunUpdateCluster(f *util.Factory, clusterName string, out io.Writer, c *Upd
fmt.Fprintf(sb, " terraform apply\n")
fmt.Fprintf(sb, "\n")
}
} else if c.Target == cloudup.TargetCloudformation {
fmt.Fprintf(sb, "\n")
fmt.Fprintf(sb, "Cloudformation output has been placed into %s\n", c.OutDir)

if firstRun {
cfName := "kubernetes-" + strings.Replace(clusterName, ".", "-", -1)
cfPath := filepath.Join(c.OutDir, "kubernetes.json")
fmt.Fprintf(sb, "Run this command to apply the configuration:\n")
fmt.Fprintf(sb, " aws cloudformation create-stack --capabilities CAPABILITY_NAMED_IAM --stack-name %s --template-body file://%s\n", cfName, cfPath)
fmt.Fprintf(sb, "\n")
}
} else if firstRun {
fmt.Fprintf(sb, "\n")
fmt.Fprintf(sb, "Cluster is starting. It should be ready in a few minutes.\n")
Expand Down
Loading

0 comments on commit 7d68f74

Please sign in to comment.