Skip to content

Commit

Permalink
new get methods
Browse files Browse the repository at this point in the history
  • Loading branch information
chrislovecnm committed Nov 4, 2017
1 parent 88984d4 commit 4185ca6
Show file tree
Hide file tree
Showing 10 changed files with 221 additions and 88 deletions.
1 change: 1 addition & 0 deletions cmd/kops/create.go
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,7 @@ func RunCreate(f *util.Factory, out io.Writer, c *CreateOptions) error {
return fmt.Errorf("error reading file %q: %v", f, err)
}

// TODO: this does not support a JSON array
sections := bytes.Split(contents, []byte("\n---\n"))
for _, section := range sections {
defaults := &schema.GroupVersionKind{
Expand Down
57 changes: 56 additions & 1 deletion cmd/kops/create_cluster.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,10 +24,13 @@ import (
"io/ioutil"
"strconv"
"strings"
"time"

"github.com/golang/glog"
"github.com/spf13/cobra"
apierrors "k8s.io/apimachinery/pkg/api/errors"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/util/sets"
"k8s.io/kops"
"k8s.io/kops/cmd/kops/util"
Expand Down Expand Up @@ -124,8 +127,17 @@ type CreateClusterOptions struct {

// ConfigBase is the location where we will store the configuration, it defaults to the state store
ConfigBase string

// DryRun we output data
DryRun bool

// Output type during a DryRun
Output string
}

var targetOptions = sets.NewString(cloudup.TargetCloudformation, cloudup.TargetDirect, cloudup.TargetTerraform)
var allTargetOptions = strings.Join(targetOptions.List(), ",")

func (o *CreateClusterOptions) InitDefaults() {
o.Yes = false
o.Target = cloudup.TargetDirect
Expand Down Expand Up @@ -190,6 +202,11 @@ var (
--project my-gce-project \
--image "ubuntu-os-cloud/ubuntu-1604-xenial-v20170202" \
--yes
# Create manifest for a cluster in AWS
kops create cluster --name=kubernetes-cluster.example.com \
--state=s3://kops-state-1234 --zones=eu-west-1a \
--node-count=2 --dry-run -oyaml
`))

create_cluster_short = i18n.T("Create a Kubernetes cluster.")
Expand Down Expand Up @@ -227,7 +244,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, cloudformation")
cmd.Flags().StringVar(&options.Target, "target", options.Target, "Valid targets: "+allTargetOptions)
cmd.Flags().StringVar(&options.Models, "model", options.Models, "Models to apply (separate multiple models with commas)")

// Configuration / state location
Expand Down Expand Up @@ -297,6 +314,10 @@ func NewCmdCreateCluster(f *util.Factory, out io.Writer) *cobra.Command {

cmd.Flags().StringVar(&options.APILoadBalancerType, "api-loadbalancer-type", options.APILoadBalancerType, "Sets the API loadbalancer type to either 'public' or 'internal'")

// DryRun mode that will print YAML or JSON
cmd.Flags().BoolVar(&options.DryRun, "dry-run", options.DryRun, "If true, only print the object that would be sent, without sending it. This flag can be used to create a cluster YAML or JSON manifest.")
cmd.Flags().StringVarP(&options.Output, "output", "o", options.Output, "Ouput format. One of json|yaml")

if featureflag.SpecOverrideFlag.Enabled() {
cmd.Flags().StringSliceVar(&options.Overrides, "override", options.Overrides, "Directly configure values in the spec")
}
Expand Down Expand Up @@ -326,6 +347,11 @@ func RunCreateCluster(f *util.Factory, out io.Writer, c *CreateClusterOptions) e
isDryrun = true
targetName = cloudup.TargetDryRun
}

if c.DryRun && c.Output == "" {
return fmt.Errorf("unable to execute --dry-run without setting --output")
}

clusterName := c.ClusterName
if clusterName == "" {
return fmt.Errorf("--name is required")
Expand Down Expand Up @@ -987,6 +1013,34 @@ func RunCreateCluster(f *util.Factory, out io.Writer, c *CreateClusterOptions) e
return err
}

if c.DryRun {
var obj []runtime.Object
// if we do not set the ts we get creationTimestamp: null
cluster.ObjectMeta.CreationTimestamp = metav1.NewTime(time.Now())
obj = append(obj, cluster)

for _, group := range fullInstanceGroups {
group.ObjectMeta.CreationTimestamp = metav1.NewTime(time.Now())
group.ObjectMeta.Labels = make(map[string]string)
group.ObjectMeta.Labels[api.LabelClusterName] = cluster.ObjectMeta.Name
obj = append(obj, group)
}
switch c.Output {
case OutputYaml:
if err := fullOutputYAML(out, obj...); err != nil {
return fmt.Errorf("error writing cluster yaml to stdout: %v", err)
}
return nil
case OutputJSON:
if err := fullOutputJSON(out, obj...); err != nil {
return fmt.Errorf("error writing cluster json to stdout: %v", err)
}
return nil
default:
return fmt.Errorf("unsupported output type %q", c.Output)
}
}

// Note we perform as much validation as we can, before writing a bad config
err = registry.CreateClusterConfig(clientset, cluster, fullInstanceGroups)
if err != nil {
Expand All @@ -1010,6 +1064,7 @@ func RunCreateCluster(f *util.Factory, out io.Writer, c *CreateClusterOptions) e
}
}

// Can we acutally get to this if??
if targetName != "" {
if isDryrun {
fmt.Fprintf(out, "Previewing changes that will be made:\n\n")
Expand Down
40 changes: 40 additions & 0 deletions cmd/kops/create_ig.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ import (
"os"
"path/filepath"
"strings"
"time"

"github.com/spf13/cobra"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
Expand All @@ -39,6 +40,11 @@ import (
type CreateInstanceGroupOptions struct {
Role string
Subnets []string
// DryRun we output data
DryRun bool

// Output type during a DryRun
Output string
}

var (
Expand All @@ -52,6 +58,10 @@ var (
# Create an instancegroup for the k8s-cluster.example.com cluster.
kops create ig --name=k8s-cluster.example.com node-example \
--role node --subnet my-subnet-name
# Create a YAML manifest for an instancegroup for the k8s-cluster.example.com cluster.
kops create ig --name=k8s-cluster.example.com node-example \
--role node --subnet my-subnet-name --dry-run -oyaml
`))

create_ig_short = i18n.T(`Create an instancegroup.`)
Expand Down Expand Up @@ -85,6 +95,9 @@ func NewCmdCreateInstanceGroup(f *util.Factory, out io.Writer) *cobra.Command {

cmd.Flags().StringVar(&options.Role, "role", options.Role, "Type of instance group to create ("+strings.Join(allRoles, ",")+")")
cmd.Flags().StringSliceVar(&options.Subnets, "subnet", options.Subnets, "Subnets in which to create instance group")
// DryRun mode that will print YAML or JSON
cmd.Flags().BoolVar(&options.DryRun, "dry-run", options.DryRun, "If true, only print the object that would be sent, without sending it. This flag can be used to create a cluster YAML or JSON manifest.")
cmd.Flags().StringVarP(&options.Output, "output", "o", options.Output, "Ouput format. One of json|yaml")

return cmd
}
Expand Down Expand Up @@ -142,6 +155,33 @@ func RunCreateInstanceGroup(f *util.Factory, cmd *cobra.Command, args []string,
return err
}

if options.DryRun {

if options.Output == "" {
return fmt.Errorf("must set output flag; yaml or json")
}

ig.ObjectMeta.CreationTimestamp = metav1.NewTime(time.Now())
ig.ObjectMeta.Labels = make(map[string]string)
ig.ObjectMeta.Labels[api.LabelClusterName] = cluster.ObjectMeta.Name

switch options.Output {
case OutputYaml:

if err := fullOutputYAML(out, ig); err != nil {
return fmt.Errorf("error writing cluster yaml to stdout: %v", err)
}
return nil
case OutputJSON:
if err := fullOutputJSON(out, ig); err != nil {
return fmt.Errorf("error writing cluster json to stdout: %v", err)
}
return nil
default:
return fmt.Errorf("unsupported output type %q", options.Output)
}
}

var (
edit = editor.NewDefaultEditor(editorEnvs)
)
Expand Down
46 changes: 21 additions & 25 deletions cmd/kops/get.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@ limitations under the License.
package main

import (
"encoding/json"
"fmt"
"io"

Expand Down Expand Up @@ -125,7 +124,7 @@ func RunGet(context Factory, out io.Writer, options *GetOptions) error {
}

if cluster == nil {
return fmt.Errorf("No cluster found")
return fmt.Errorf("no cluster found")
}

clusterList := &api.ClusterList{}
Expand Down Expand Up @@ -155,33 +154,30 @@ func RunGet(context Factory, out io.Writer, options *GetOptions) error {

switch options.output {
case OutputYaml:
var obj []runtime.Object
obj = append(obj, cluster)

err = clusterOutputYAML(clusters, out)
if err != nil {
return err
for _, group := range instancegroups {
obj = append(obj, group)
}

if err := writeYAMLSep(out); err != nil {
return err
if err := fullOutputYAML(out, obj...); err != nil {
return fmt.Errorf("error writing cluster yaml to stdout: %v", err)
}

err = igOutputYAML(instancegroups, out)
if err != nil {
return err
}
return nil

case OutputJSON:
return fmt.Errorf("not implemented")
// TODO this is not outputing valid json. Not sure what cluster and instance groups should look like
/*
err = clusterOutputJson(clusters,out)
if err != nil {
return err
}
err = igOutputJson(instancegroups,out)
if err != nil {
return err
}*/

var obj []runtime.Object
obj = append(obj, cluster)

for _, group := range instancegroups {
obj = append(obj, group)
}
if err := fullOutputJSON(out, obj...); err != nil {
return fmt.Errorf("error writing cluster yaml to stdout: %v", err)
}
return nil

case OutputTable:
fmt.Fprintf(os.Stdout, "Cluster\n")
Expand All @@ -196,7 +192,7 @@ func RunGet(context Factory, out io.Writer, options *GetOptions) error {
}

default:
return fmt.Errorf("Unknown output format: %q", options.output)
return fmt.Errorf("unknown output format: %q", options.output)
}

return nil
Expand Down Expand Up @@ -235,7 +231,7 @@ func marshalYaml(obj runtime.Object) ([]byte, error) {

// obj must be a pointer to a marshalable object
func marshalJSON(obj runtime.Object) ([]byte, error) {
j, err := json.MarshalIndent(obj, "", " ")
j, err := kopscodecs.ToVersionedJSON(obj)
if err != nil {
return nil, fmt.Errorf("error marshaling json: %v", err)
}
Expand Down
58 changes: 46 additions & 12 deletions cmd/kops/get_cluster.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,13 +18,13 @@ package main

import (
"fmt"
"io"
"os"
"strings"

"io"

"github.com/spf13/cobra"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/util/sets"
"k8s.io/kops/cmd/kops/util"
api "k8s.io/kops/pkg/apis/kops"
Expand Down Expand Up @@ -133,7 +133,7 @@ func RunGetClusters(context Factory, out io.Writer, options *GetClusterOptions)
}

if len(clusters) == 0 {
return fmt.Errorf("No clusters found")
return fmt.Errorf("no clusters found")
}

if options.FullSpec {
Expand All @@ -150,12 +150,20 @@ func RunGetClusters(context Factory, out io.Writer, options *GetClusterOptions)
case OutputTable:
return clusterOutputTable(clusters, out)
case OutputYaml:
return clusterOutputYAML(clusters, out)
var obj []runtime.Object
for _, c := range clusters {
obj = append(obj, c)
}
return fullOutputYAML(out, obj...)
case OutputJSON:
return clusterOutputJson(clusters, out)
var obj []runtime.Object
for _, c := range clusters {
obj = append(obj, c)
}
return fullOutputJSON(out, obj...)

default:
return fmt.Errorf("Unknown output format: %q", options.output)
return fmt.Errorf("unknown output format: %q", options.output)
}
}

Expand Down Expand Up @@ -206,26 +214,52 @@ func clusterOutputTable(clusters []*api.Cluster, out io.Writer) error {
return t.Render(clusters, out, "NAME", "CLOUD", "ZONES")
}

func clusterOutputJson(clusters []*api.Cluster, out io.Writer) error {
for _, cluster := range clusters {
if err := marshalToWriter(cluster, marshalJSON, out); err != nil {
// fullOutputJson outputs the marshalled JSON of a list of clusters and instance groups. It will handle
// nils for clusters and instanceGroups slices.
func fullOutputJSON(out io.Writer, args ...runtime.Object) error {
argsLen := len(args)

if argsLen > 1 {
if _, err := fmt.Fprint(out, "["); err != nil {
return err
}
}

for i, arg := range args {
if i != 0 {
if _, err := fmt.Fprint(out, ","); err != nil {
return err
}
}
if err := marshalToWriter(arg, marshalJSON, out); err != nil {
return err
}
}

if argsLen > 1 {
if _, err := fmt.Fprint(out, "]"); err != nil {
return err
}
}

return nil
}

func clusterOutputYAML(clusters []*api.Cluster, out io.Writer) error {
for i, cluster := range clusters {
// fullOutputJson outputs the marshalled YAML of a list of clusters and instance groups. It will handle
// nils for clusters and instanceGroups slices.
func fullOutputYAML(out io.Writer, args ...runtime.Object) error {

for i, obj := range args {
if i != 0 {
if err := writeYAMLSep(out); err != nil {
return fmt.Errorf("error writing to stdout: %v", err)
}
}
if err := marshalToWriter(cluster, marshalYaml, out); err != nil {
if err := marshalToWriter(obj, marshalYaml, out); err != nil {
return err
}
}

return nil
}

Expand Down
Loading

0 comments on commit 4185ca6

Please sign in to comment.