Merge pull request #1137 from justinsb/introduce_objectmeta

Mark ObjectMeta as a named field
This commit is contained in:
Chris Love 2016-12-14 22:49:01 -07:00 committed by GitHub
commit c4b258351f
56 changed files with 194 additions and 438 deletions

View File

@ -109,7 +109,7 @@ func RunCreate(f *util.Factory, out io.Writer, c *CreateOptions) error {
_, err = clientset.Federations().Create(v)
if err != nil {
if errors.IsAlreadyExists(err) {
return fmt.Errorf("federation %q already exists", v.Name)
return fmt.Errorf("federation %q already exists", v.ObjectMeta.Name)
}
return fmt.Errorf("error creating federation: %v", err)
}
@ -118,20 +118,20 @@ func RunCreate(f *util.Factory, out io.Writer, c *CreateOptions) error {
_, err = clientset.Clusters().Create(v)
if err != nil {
if errors.IsAlreadyExists(err) {
return fmt.Errorf("cluster %q already exists", v.Name)
return fmt.Errorf("cluster %q already exists", v.ObjectMeta.Name)
}
return fmt.Errorf("error creating cluster: %v", err)
}
case *kopsapi.InstanceGroup:
clusterName := v.Labels[ClusterNameLabel]
clusterName := v.ObjectMeta.Labels[ClusterNameLabel]
if clusterName == "" {
return fmt.Errorf("must specify %q label with cluster name to create instanceGroup", ClusterNameLabel)
}
_, err = clientset.InstanceGroups(clusterName).Create(v)
if err != nil {
if errors.IsAlreadyExists(err) {
return fmt.Errorf("instanceGroup %q already exists", v.Name)
return fmt.Errorf("instanceGroup %q already exists", v.ObjectMeta.Name)
}
return fmt.Errorf("error creating instanceGroup: %v", err)
}

View File

@ -246,7 +246,7 @@ func RunCreateCluster(f *util.Factory, cmd *cobra.Command, args []string, out io
g.Spec.Zones = []string{zone.Name}
g.Spec.MinSize = fi.Int(1)
g.Spec.MaxSize = fi.Int(1)
g.Name = "master-" + zone.Name // Subsequent masters (if we support that) could be <zone>-1, <zone>-2
g.ObjectMeta.Name = "master-" + zone.Name // Subsequent masters (if we support that) could be <zone>-1, <zone>-2
instanceGroups = append(instanceGroups, g)
masters = append(masters, g)
@ -263,7 +263,7 @@ func RunCreateCluster(f *util.Factory, cmd *cobra.Command, args []string, out io
g.Spec.Zones = []string{zone}
g.Spec.MinSize = fi.Int(1)
g.Spec.MaxSize = fi.Int(1)
g.Name = "master-" + zone
g.ObjectMeta.Name = "master-" + zone
instanceGroups = append(instanceGroups, g)
masters = append(masters, g)
}
@ -298,7 +298,7 @@ func RunCreateCluster(f *util.Factory, cmd *cobra.Command, args []string, out io
if len(nodes) == 0 {
g := &api.InstanceGroup{}
g.Spec.Role = api.InstanceGroupRoleNode
g.Name = "nodes"
g.ObjectMeta.Name = "nodes"
instanceGroups = append(instanceGroups, g)
nodes = append(nodes, g)
}
@ -345,7 +345,7 @@ func RunCreateCluster(f *util.Factory, cmd *cobra.Command, args []string, out io
}
if clusterName != "" {
cluster.Name = clusterName
cluster.ObjectMeta.Name = clusterName
}
if c.KubernetesVersion != "" {
@ -431,7 +431,6 @@ func RunCreateCluster(f *util.Factory, cmd *cobra.Command, args []string, out io
glog.Infof("Using SSH public key: %v\n", c.SSHPublicKey)
}
if c.AdminAccess != "" {
cluster.Spec.AdminAccess = []string{c.AdminAccess}
}
@ -525,10 +524,10 @@ func RunCreateCluster(f *util.Factory, cmd *cobra.Command, args []string, out io
fmt.Fprintf(&sb, " * list clusters with: kops get cluster\n")
fmt.Fprintf(&sb, " * edit this cluster with: kops edit cluster %s\n", clusterName)
if len(nodes) > 0 {
fmt.Fprintf(&sb, " * edit your node instance group: kops edit ig --name=%s %s\n", clusterName, nodes[0].Name)
fmt.Fprintf(&sb, " * edit your node instance group: kops edit ig --name=%s %s\n", clusterName, nodes[0].ObjectMeta.Name)
}
if len(masters) > 0 {
fmt.Fprintf(&sb, " * edit your master instance group: kops edit ig --name=%s %s\n", clusterName, masters[0].Name)
fmt.Fprintf(&sb, " * edit your master instance group: kops edit ig --name=%s %s\n", clusterName, masters[0].ObjectMeta.Name)
}
fmt.Fprintf(&sb, "\n")
fmt.Fprintf(&sb, "Finally configure your cluster with: kops update cluster %s --yes\n", clusterName)
@ -542,7 +541,7 @@ func RunCreateCluster(f *util.Factory, cmd *cobra.Command, args []string, out io
glog.Infof("Exporting kubecfg for cluster")
x := &kutil.CreateKubecfg{
ContextName: cluster.Name,
ContextName: cluster.ObjectMeta.Name,
KeyStore: keyStore,
SecretStore: secretStore,
KubeMasterIP: cluster.Spec.MasterPublicName,

View File

@ -84,7 +84,7 @@ func RunCreateInstanceGroup(f *util.Factory, cmd *cobra.Command, args []string,
return err
}
existing, err := clientset.InstanceGroups(cluster.Name).Get(groupName)
existing, err := clientset.InstanceGroups(cluster.ObjectMeta.Name).Get(groupName)
if err != nil {
return err
}
@ -95,7 +95,7 @@ func RunCreateInstanceGroup(f *util.Factory, cmd *cobra.Command, args []string,
// Populate some defaults
ig := &api.InstanceGroup{}
ig.Name = groupName
ig.ObjectMeta.Name = groupName
ig.Spec.Role = api.InstanceGroupRole(options.Role)
ig, err = cloudup.PopulateInstanceGroupSpec(cluster, ig, channel)
@ -138,7 +138,7 @@ func RunCreateInstanceGroup(f *util.Factory, cmd *cobra.Command, args []string,
return err
}
_, err = clientset.InstanceGroups(cluster.Name).Create(group)
_, err = clientset.InstanceGroups(cluster.ObjectMeta.Name).Create(group)
if err != nil {
return fmt.Errorf("error storing InstanceGroup: %v", err)
}

View File

@ -107,7 +107,7 @@ func (c *DeleteClusterCmd) Run(args []string) error {
return fmt.Errorf("cluster %q not found", clusterName)
}
if clusterName != cluster.Name {
if clusterName != cluster.ObjectMeta.Name {
return fmt.Errorf("sanity check failed: cluster name mismatch")
}

View File

@ -67,7 +67,7 @@ func (c *DeleteInstanceceGroupCmd) Run(groupName string) error {
return err
}
group, err := clientset.InstanceGroups(cluster.Name).Get(groupName)
group, err := clientset.InstanceGroups(cluster.ObjectMeta.Name).Get(groupName)
if err != nil {
return fmt.Errorf("error reading InstanceGroup %q: %v", groupName, err)
}
@ -90,7 +90,7 @@ func (c *DeleteInstanceceGroupCmd) Run(groupName string) error {
return err
}
fmt.Printf("InstanceGroup %q deleted\n", group.Name)
fmt.Printf("InstanceGroup %q deleted\n", group.ObjectMeta.Name)
return nil
}

View File

@ -74,7 +74,7 @@ func RunEditCluster(f *util.Factory, cmd *cobra.Command, args []string, out io.W
return err
}
list, err := clientset.InstanceGroups(oldCluster.Name).List(k8sapi.ListOptions{})
list, err := clientset.InstanceGroups(oldCluster.ObjectMeta.Name).List(k8sapi.ListOptions{})
if err != nil {
return err
}

View File

@ -82,7 +82,7 @@ func RunEditInstanceGroup(f *util.Factory, cmd *cobra.Command, args []string, ou
return fmt.Errorf("name is required")
}
oldGroup, err := clientset.InstanceGroups(cluster.Name).Get(groupName)
oldGroup, err := clientset.InstanceGroups(cluster.ObjectMeta.Name).Get(groupName)
if err != nil {
return fmt.Errorf("error reading InstanceGroup %q: %v", groupName, err)
}
@ -154,7 +154,7 @@ func RunEditInstanceGroup(f *util.Factory, cmd *cobra.Command, args []string, ou
}
// Note we perform as much validation as we can, before writing a bad config
_, err = clientset.InstanceGroups(cluster.Name).Update(fullGroup)
_, err = clientset.InstanceGroups(cluster.ObjectMeta.Name).Update(fullGroup)
if err != nil {
return err
}

View File

@ -67,7 +67,7 @@ func (c *ExportKubecfgCommand) Run(args []string) error {
return err
}
clusterName := cluster.Name
clusterName := cluster.ObjectMeta.Name
master := cluster.Spec.MasterPublicName
if master == "" {

View File

@ -69,7 +69,7 @@ func (c *GetClustersCmd) Run(args []string) error {
m := make(map[string]*api.Cluster)
for i := range clusterList.Items {
c := &clusterList.Items[i]
m[c.Name] = c
m[c.ObjectMeta.Name] = c
}
for _, arg := range args {
ig := m[arg]
@ -104,7 +104,7 @@ func (c *GetClustersCmd) Run(args []string) error {
t := &tables.Table{}
t.AddColumn("NAME", func(c *api.Cluster) string {
return c.Name
return c.ObjectMeta.Name
})
t.AddColumn("CLOUD", func(c *api.Cluster) string {
return c.Spec.CloudProvider
@ -143,12 +143,12 @@ func fullClusterSpecs(clusters []*api.Cluster) ([]*api.Cluster, error) {
for _, cluster := range clusters {
configBase, err := registry.ConfigBase(cluster)
if err != nil {
return nil, fmt.Errorf("error reading full cluster spec for %q: %v", cluster.Name, err)
return nil, fmt.Errorf("error reading full cluster spec for %q: %v", cluster.ObjectMeta.Name, err)
}
fullSpec := &api.Cluster{}
err = registry.ReadConfigDeprecated(configBase.Join(registry.PathClusterCompleted), fullSpec)
if err != nil {
return nil, fmt.Errorf("error reading full cluster spec for %q: %v", cluster.Name, err)
return nil, fmt.Errorf("error reading full cluster spec for %q: %v", cluster.ObjectMeta.Name, err)
}
fullSpecs = append(fullSpecs, fullSpec)
}

View File

@ -75,7 +75,7 @@ func RunGetFederations(context Factory, out io.Writer, options *GetFederationOpt
t := &tables.Table{}
t.AddColumn("NAME", func(f *api.Federation) string {
return f.Name
return f.ObjectMeta.Name
})
t.AddColumn("CONTROLLERS", func(f *api.Federation) string {
return strings.Join(f.Spec.Controllers, ",")

View File

@ -71,7 +71,7 @@ func (c *GetInstanceGroupsCmd) Run(args []string) error {
m := make(map[string]*api.InstanceGroup)
for i := range list.Items {
ig := &list.Items[i]
m[ig.Name] = ig
m[ig.ObjectMeta.Name] = ig
}
instancegroups = make([]*api.InstanceGroup, 0, len(args))
for _, arg := range args {
@ -99,7 +99,7 @@ func (c *GetInstanceGroupsCmd) Run(args []string) error {
case OutputTable:
t := &tables.Table{}
t.AddColumn("NAME", func(c *api.InstanceGroup) string {
return c.Name
return c.ObjectMeta.Name
})
t.AddColumn("ROLE", func(c *api.InstanceGroup) string {
return string(c.Spec.Role)

View File

@ -93,7 +93,7 @@ func RunReplace(f *util.Factory, cmd *cobra.Command, out io.Writer, c *ReplaceOp
}
case *kopsapi.InstanceGroup:
clusterName := v.Labels[ClusterNameLabel]
clusterName := v.ObjectMeta.Labels[ClusterNameLabel]
if clusterName == "" {
return fmt.Errorf("must specify %q label with cluster name to replace instanceGroup", ClusterNameLabel)
}

View File

@ -84,7 +84,7 @@ func (c *RollingUpdateClusterCmd) Run(args []string) error {
return err
}
contextName := cluster.Name
contextName := cluster.ObjectMeta.Name
config, err := clientcmd.NewNonInteractiveDeferredLoadingClientConfig(
clientcmd.NewDefaultClientConfigLoadingRules(),
&clientcmd.ConfigOverrides{CurrentContext: contextName}).ClientConfig()
@ -112,7 +112,7 @@ func (c *RollingUpdateClusterCmd) Run(args []string) error {
}
}
list, err := clientset.InstanceGroups(cluster.Name).List(k8sapi.ListOptions{})
list, err := clientset.InstanceGroups(cluster.ObjectMeta.Name).List(k8sapi.ListOptions{})
if err != nil {
return err
}
@ -142,7 +142,7 @@ func (c *RollingUpdateClusterCmd) Run(args []string) error {
{
t := &tables.Table{}
t.AddColumn("NAME", func(r *kutil.CloudInstanceGroup) string {
return r.InstanceGroup.Name
return r.InstanceGroup.ObjectMeta.Name
})
t.AddColumn("STATUS", func(r *kutil.CloudInstanceGroup) string {
return r.Status

View File

@ -248,8 +248,8 @@ func GetCluster(factory *util.Factory, clusterName string) (*kopsapi.Cluster, er
return nil, fmt.Errorf("cluster %q not found", clusterName)
}
if clusterName != cluster.Name {
return nil, fmt.Errorf("cluster name did not match expected name: %v vs %v", clusterName, cluster.Name)
if clusterName != cluster.ObjectMeta.Name {
return nil, fmt.Errorf("cluster name did not match expected name: %v vs %v", clusterName, cluster.ObjectMeta.Name)
}
return cluster, nil
}

View File

@ -63,7 +63,7 @@ func (c *ConvertImportedCmd) Run() error {
return err
}
list, err := clientset.InstanceGroups(cluster.Name).List(k8sapi.ListOptions{})
list, err := clientset.InstanceGroups(cluster.ObjectMeta.Name).List(k8sapi.ListOptions{})
if err != nil {
return err
}
@ -72,15 +72,15 @@ func (c *ConvertImportedCmd) Run() error {
instanceGroups = append(instanceGroups, &list.Items[i])
}
if cluster.Annotations[api.AnnotationNameManagement] != api.AnnotationValueManagementImported {
return fmt.Errorf("cluster %q does not appear to be a cluster imported using kops import", cluster.Name)
if cluster.ObjectMeta.Annotations[api.AnnotationNameManagement] != api.AnnotationValueManagementImported {
return fmt.Errorf("cluster %q does not appear to be a cluster imported using kops import", cluster.ObjectMeta.Name)
}
if c.NewClusterName == "" {
return fmt.Errorf("--newname is required for converting an imported cluster")
}
oldClusterName := cluster.Name
oldClusterName := cluster.ObjectMeta.Name
if oldClusterName == "" {
return fmt.Errorf("(Old) ClusterName must be set in configuration")
}

View File

@ -131,7 +131,7 @@ func RunUpdateCluster(f *util.Factory, clusterName string, out io.Writer, c *Upd
}
if c.SSHPublicKey != "" {
fmt.Fprintf(out, "--ssh-public-key on update is deprecated - please use `kops create secret --name %s sshpublickey admin -i ~/.ssh/id_rsa.pub` instead\n", cluster.Name)
fmt.Fprintf(out, "--ssh-public-key on update is deprecated - please use `kops create secret --name %s sshpublickey admin -i ~/.ssh/id_rsa.pub` instead\n", cluster.ObjectMeta.Name)
c.SSHPublicKey = utils.ExpandPath(c.SSHPublicKey)
authorized, err := ioutil.ReadFile(c.SSHPublicKey)
@ -172,7 +172,7 @@ func RunUpdateCluster(f *util.Factory, clusterName string, out io.Writer, c *Upd
// TODO: Only if not yet set?
if !isDryrun && c.CreateKubecfg {
hasKubecfg, err := hasKubecfg(cluster.Name)
hasKubecfg, err := hasKubecfg(cluster.ObjectMeta.Name)
if err != nil {
glog.Warningf("error reading kubecfg: %v", err)
hasKubecfg = true
@ -187,7 +187,7 @@ func RunUpdateCluster(f *util.Factory, clusterName string, out io.Writer, c *Upd
if kubecfgCert != nil {
glog.Infof("Exporting kubecfg for cluster")
x := &kutil.CreateKubecfg{
ContextName: cluster.Name,
ContextName: cluster.ObjectMeta.Name,
KeyStore: keyStore,
SecretStore: secretStore,
KubeMasterIP: cluster.Spec.MasterPublicName,

View File

@ -80,7 +80,7 @@ func (c *UpgradeClusterCmd) Run(args []string) error {
return err
}
list, err := clientset.InstanceGroups(cluster.Name).List(k8sapi.ListOptions{})
list, err := clientset.InstanceGroups(cluster.ObjectMeta.Name).List(k8sapi.ListOptions{})
if err != nil {
return err
}
@ -90,7 +90,7 @@ func (c *UpgradeClusterCmd) Run(args []string) error {
instanceGroups = append(instanceGroups, &list.Items[i])
}
if cluster.Annotations[api.AnnotationNameManagement] == api.AnnotationValueManagementImported {
if cluster.ObjectMeta.Annotations[api.AnnotationNameManagement] == api.AnnotationValueManagementImported {
return fmt.Errorf("upgrade is not for use with imported clusters (did you mean `kops toolbox convert-imported`?)")
}
@ -181,7 +181,7 @@ func (c *UpgradeClusterCmd) Run(args []string) error {
if ig.Spec.Image != image.Name {
target := ig
actions = append(actions, &upgradeAction{
Item: "InstanceGroup/" + target.Name,
Item: "InstanceGroup/" + target.ObjectMeta.Name,
Property: "Image",
Old: target.Spec.Image,
New: image.Name,
@ -275,16 +275,16 @@ func (c *UpgradeClusterCmd) Run(args []string) error {
}
for _, g := range instanceGroups {
_, err := clientset.InstanceGroups(cluster.Name).Update(g)
_, err := clientset.InstanceGroups(cluster.ObjectMeta.Name).Update(g)
if err != nil {
return fmt.Errorf("error writing InstanceGroup %q: %v", g.Name, err)
return fmt.Errorf("error writing InstanceGroup %q: %v", g.ObjectMeta.Name, err)
}
}
fmt.Printf("\nUpdates applied to configuration.\n")
// TODO: automate this step
fmt.Printf("You can now apply these changes, using `kops update cluster %s`\n", cluster.Name)
fmt.Printf("You can now apply these changes, using `kops update cluster %s`\n", cluster.ObjectMeta.Name)
}
return nil

View File

@ -73,12 +73,12 @@ func RunValidateCluster(f *util.Factory, cmd *cobra.Command, args []string, out
return err
}
list, err := clientSet.InstanceGroups(cluster.Name).List(k8sapi.ListOptions{})
list, err := clientSet.InstanceGroups(cluster.ObjectMeta.Name).List(k8sapi.ListOptions{})
if err != nil {
return fmt.Errorf("cannot get InstanceGroups for %q: %v", cluster.Name, err)
return fmt.Errorf("cannot get InstanceGroups for %q: %v", cluster.ObjectMeta.Name, err)
}
fmt.Fprintf(out, "Validating cluster %v\n\n", cluster.Name)
fmt.Fprintf(out, "Validating cluster %v\n\n", cluster.ObjectMeta.Name)
var instanceGroups []api.InstanceGroup
for _, ig := range list.Items {
@ -91,7 +91,7 @@ func RunValidateCluster(f *util.Factory, cmd *cobra.Command, args []string, out
}
// TODO: Refactor into util.Factory
contextName := cluster.Name
contextName := cluster.ObjectMeta.Name
config, err := clientcmd.NewNonInteractiveDeferredLoadingClientConfig(
clientcmd.NewDefaultClientConfigLoadingRules(),
&clientcmd.ConfigOverrides{CurrentContext: contextName}).ClientConfig()
@ -104,7 +104,7 @@ func RunValidateCluster(f *util.Factory, cmd *cobra.Command, args []string, out
return fmt.Errorf("Cannot build kube api client for %q: %v\n", contextName, err)
}
validationCluster, validationFailed := validation.ValidateCluster(cluster.Name, list, k8sClient)
validationCluster, validationFailed := validation.ValidateCluster(cluster.ObjectMeta.Name, list, k8sClient)
if validationCluster == nil || validationCluster.NodeList == nil || validationCluster.NodeList.Items == nil {
// validationFailed error is already formatted
@ -113,7 +113,7 @@ func RunValidateCluster(f *util.Factory, cmd *cobra.Command, args []string, out
t := &tables.Table{}
t.AddColumn("NAME", func(c api.InstanceGroup) string {
return c.Name
return c.ObjectMeta.Name
})
t.AddColumn("ROLE", func(c api.InstanceGroup) string {
return string(c.Spec.Role)
@ -135,7 +135,7 @@ func RunValidateCluster(f *util.Factory, cmd *cobra.Command, args []string, out
err = t.Render(instanceGroups, out, "NAME", "ROLE", "MACHINETYPE", "MIN", "MAX", "ZONES")
if err != nil {
return fmt.Errorf("cannot render nodes for %q: %v", cluster.Name, err)
return fmt.Errorf("cannot render nodes for %q: %v", cluster.ObjectMeta.Name, err)
}
t = &tables.Table{}
@ -162,11 +162,11 @@ func RunValidateCluster(f *util.Factory, cmd *cobra.Command, args []string, out
err = t.Render(validationCluster.NodeList.Items, out, "NAME", "ROLE", "READY")
if err != nil {
return fmt.Errorf("cannot render nodes for %q: %v", cluster.Name, err)
return fmt.Errorf("cannot render nodes for %q: %v", cluster.ObjectMeta.Name, err)
}
if validationFailed == nil {
fmt.Fprintf(out, "\nYour cluster %s is ready\n", cluster.Name)
fmt.Fprintf(out, "\nYour cluster %s is ready\n", cluster.ObjectMeta.Name)
return nil
} else {
// do we need to print which instance group is not ready?
@ -174,6 +174,6 @@ func RunValidateCluster(f *util.Factory, cmd *cobra.Command, args []string, out
fmt.Fprint(out, "\nValidation Failed\n")
fmt.Fprintf(out, "Master(s) Not Ready %d out of %d.\n", len(validationCluster.MastersNotReadyArray), validationCluster.MastersCount)
fmt.Fprintf(out, "Node(s) Not Ready %d out of %d.\n", len(validationCluster.NodesNotReadyArray), validationCluster.NodesCount)
return fmt.Errorf("Your cluster %s is NOT ready.\n", cluster.Name)
return fmt.Errorf("Your cluster %s is NOT ready.\n", cluster.ObjectMeta.Name)
}
}

View File

@ -31,11 +31,11 @@ func up() error {
clientset := vfsclientset.NewVFSClientset(registryBase)
cluster := &api.Cluster{}
cluster.Name = clusterName
cluster.ObjectMeta.Name = clusterName
cluster.Spec = api.ClusterSpec{
Channel: "stable",
CloudProvider: "aws",
ConfigBase: registryBase.Join(cluster.Name).Path(),
ConfigBase: registryBase.Join(cluster.ObjectMeta.Name).Path(),
Topology: &api.TopologySpec{},
}
cluster.Spec.Topology.Masters = api.TopologyPublic
@ -73,12 +73,12 @@ func up() error {
// Create master ig
{
ig := &api.InstanceGroup{}
ig.Name = "master"
ig.ObjectMeta.Name = "master"
ig.Spec = api.InstanceGroupSpec{
Role: api.InstanceGroupRoleMaster,
Zones: masterZones,
}
_, err := clientset.InstanceGroups(cluster.Name).Create(ig)
_, err := clientset.InstanceGroups(cluster.ObjectMeta.Name).Create(ig)
if err != nil {
return err
}
@ -87,13 +87,13 @@ func up() error {
// Create node ig
{
ig := &api.InstanceGroup{}
ig.Name = "nodes"
ig.ObjectMeta.Name = "nodes"
ig.Spec = api.InstanceGroupSpec{
Role: api.InstanceGroupRoleNode,
Zones: nodeZones,
}
_, err := clientset.InstanceGroups(cluster.Name).Create(ig)
_, err := clientset.InstanceGroups(cluster.ObjectMeta.Name).Create(ig)
if err != nil {
return err
}

View File

@ -156,7 +156,7 @@ func (o *ApplyFederationOperation) Run() error {
return fmt.Errorf("error reading cluster %q: %v", member, err)
}
clusterName := strings.Replace(cluster.Name, ".", "-", -1)
clusterName := strings.Replace(cluster.ObjectMeta.Name, ".", "-", -1)
a := &FederationCluster{
FederationNamespace: o.namespace,
@ -164,7 +164,7 @@ func (o *ApplyFederationOperation) Run() error {
ControllerKubernetesClients: controllerKubernetesClients,
FederationClient: federationControllerClient,
ClusterSecretName: "secret-" + cluster.Name,
ClusterSecretName: "secret-" + cluster.ObjectMeta.Name,
ClusterName: clusterName,
ApiserverHostname: cluster.Spec.MasterPublicName,
}
@ -210,7 +210,7 @@ func (o *ApplyFederationOperation) buildApiserverKeypair() *fitasks.Keypair {
keypairName := "secret-" + o.apiserverHostName
keypair := &fitasks.Keypair{
Name: fi.String(keypairName),
Subject: "cn=" + o.Federation.Name,
Subject: "cn=" + o.Federation.ObjectMeta.Name,
Type: "server",
}

View File

@ -52,7 +52,7 @@ func (o *FederationCluster) Run(cluster *kopsapi.Cluster) error {
}
k := kutil.CreateKubecfg{
ContextName: cluster.Name,
ContextName: cluster.ObjectMeta.Name,
KeyStore: keyStore,
SecretStore: secretStore,
KubeMasterIP: cluster.Spec.MasterPublicName,
@ -60,7 +60,7 @@ func (o *FederationCluster) Run(cluster *kopsapi.Cluster) error {
kubeconfig, err := k.ExtractKubeconfig()
if err != nil {
return fmt.Errorf("error building connection information for cluster %q: %v", cluster.Name, err)
return fmt.Errorf("error building connection information for cluster %q: %v", cluster.ObjectMeta.Name, err)
}
user := kutil.KubectlUser{

View File

@ -47,7 +47,7 @@ func (o *FederationConfiguration) extractKubecfg(c *fi.Context, f *kopsapi.Feder
k := kutil.NewKubeconfigBuilder()
k.KubeMasterIP = masterName
k.Context = "federation-" + f.Name
k.Context = "federation-" + f.ObjectMeta.Name
// CA Cert
caCert, _, err := c.Keystore.FindKeypair(fi.CertificateId_CA)

View File

@ -34,7 +34,7 @@ type KubernetesTarget struct {
func NewKubernetesTarget(clientset simple.Clientset, keystore fi.Keystore, cluster *kopsapi.Cluster) (*KubernetesTarget, error) {
b := &kutil.CreateKubecfg{
ContextName: cluster.Name,
ContextName: cluster.ObjectMeta.Name,
KeyStore: keystore,
SecretStore: nil,
KubeMasterIP: cluster.Spec.MasterPublicName,
@ -42,12 +42,12 @@ func NewKubernetesTarget(clientset simple.Clientset, keystore fi.Keystore, clust
kubeconfig, err := b.ExtractKubeconfig()
if err != nil {
return nil, fmt.Errorf("error building credentials for cluster %q: %v", cluster.Name, err)
return nil, fmt.Errorf("error building credentials for cluster %q: %v", cluster.ObjectMeta.Name, err)
}
clientConfig, err := kubeconfig.BuildRestConfig()
if err != nil {
return nil, fmt.Errorf("error building configuration for cluster %q: %v", cluster.Name, err)
return nil, fmt.Errorf("error building configuration for cluster %q: %v", cluster.ObjectMeta.Name, err)
}
k8sClient, err := release_1_5.NewForConfig(clientConfig)
@ -70,7 +70,7 @@ func (t *KubernetesTarget) Finish(taskMap map[string]fi.Task) error {
}
func (t *KubernetesTarget) Apply(manifest []byte) error {
context := t.cluster.Name
context := t.cluster.ObjectMeta.Name
// Would be nice if we could use RunApply from kubectl's code directly...
// ... but that seems really hard

View File

@ -21,6 +21,7 @@ import (
"github.com/golang/glog"
"k8s.io/kops/upup/pkg/fi"
"k8s.io/kops/util/pkg/vfs"
"k8s.io/kubernetes/pkg/api"
"k8s.io/kubernetes/pkg/api/unversioned"
"net/url"
)
@ -30,7 +31,7 @@ const DefaultChannel = "stable"
type Channel struct {
unversioned.TypeMeta `json:",inline"`
ObjectMeta `json:"metadata,omitempty"`
ObjectMeta api.ObjectMeta `json:"metadata,omitempty"`
Spec ChannelSpec `json:"spec,omitempty"`
}

View File

@ -24,17 +24,21 @@ import (
"github.com/golang/glog"
"k8s.io/kops/util/pkg/vfs"
"k8s.io/kubernetes/pkg/api"
"k8s.io/kubernetes/pkg/api/unversioned"
)
type Cluster struct {
unversioned.TypeMeta `json:",inline"`
ObjectMeta `json:"metadata,omitempty"`
ObjectMeta api.ObjectMeta `json:"metadata,omitempty"`
Spec ClusterSpec `json:"spec,omitempty"`
}
type ClusterList struct {
unversioned.TypeMeta `json:",inline"`
unversioned.ListMeta `json:"metadata,omitempty"`
Items []Cluster `json:"items"`
}
@ -318,8 +322,8 @@ func (c *Cluster) PerformAssignments() error {
}
// TODO: Unclear this should be here - it isn't too hard to change
if c.Spec.MasterPublicName == "" && c.Name != "" {
c.Spec.MasterPublicName = "api." + c.Name
if c.Spec.MasterPublicName == "" && c.ObjectMeta.Name != "" {
c.Spec.MasterPublicName = "api." + c.ObjectMeta.Name
}
for _, zone := range c.Spec.Zones {
@ -371,16 +375,16 @@ func (c *Cluster) FillDefaults() error {
return err
}
if c.Name == "" {
if c.ObjectMeta.Name == "" {
return fmt.Errorf("cluster Name not set in FillDefaults")
}
if c.Spec.MasterInternalName == "" {
c.Spec.MasterInternalName = "api.internal." + c.Name
c.Spec.MasterInternalName = "api.internal." + c.ObjectMeta.Name
}
if c.Spec.MasterPublicName == "" {
c.Spec.MasterPublicName = "api." + c.Name
c.Spec.MasterPublicName = "api." + c.ObjectMeta.Name
}
return nil

View File

@ -16,19 +16,15 @@ limitations under the License.
package kops
import (
"k8s.io/kubernetes/pkg/api/unversioned"
)
// Configuration for each component
// Wherever possible, we try to use the types & names in https://github.com/kubernetes/kubernetes/blob/master/pkg/apis/componentconfig/types.go
type KubeletConfig struct {
unversioned.TypeMeta `json:",inline"`
ObjectMeta `json:"metadata,omitempty"`
Spec ClusterSpec `json:"spec,omitempty"`
}
//type KubeletConfig struct {
// unversioned.TypeMeta `json:",inline"`
// ObjectMeta api.ObjectMeta `json:"metadata,omitempty"`
//
// Spec ClusterSpec `json:"spec,omitempty"`
//}
type KubeletConfigSpec struct {
APIServers string `json:"apiServers,omitempty" flag:"api-servers"`

View File

@ -17,13 +17,14 @@ limitations under the License.
package kops
import (
"k8s.io/kubernetes/pkg/api"
"k8s.io/kubernetes/pkg/api/unversioned"
)
// Federation represents a federated set of kubernetes clusters
type Federation struct {
unversioned.TypeMeta `json:",inline"`
ObjectMeta `json:"metadata,omitempty"`
ObjectMeta api.ObjectMeta `json:"metadata,omitempty"`
Spec FederationSpec `json:"spec,omitempty"`
}

View File

@ -1,124 +0,0 @@
/*
Copyright 2016 The Kubernetes Authors.
Licensed 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.
*/
package kops
import (
"k8s.io/kubernetes/pkg/api"
"k8s.io/kubernetes/pkg/api/unversioned"
"k8s.io/kubernetes/pkg/types"
)
// ObjectMeta is metadata that all persisted resources must have, which includes all objects
// users must create.
type ObjectMeta struct {
// Name is unique within a namespace. Name is required when creating resources, although
// some resources may allow a client to request the generation of an appropriate name
// automatically. Name is primarily intended for creation idempotence and configuration
// definition.
Name string `json:"name,omitempty"`
// GenerateName indicates that the name should be made unique by the server prior to persisting
// it. A non-empty value for the field indicates the name will be made unique (and the name
// returned to the client will be different than the name passed). The value of this field will
// be combined with a unique suffix on the server if the Name field has not been provided.
// The provided value must be valid within the rules for Name, and may be truncated by the length
// of the suffix required to make the value unique on the server.
//
// If this field is specified, and Name is not present, the server will NOT return a 409 if the
// generated name exists - instead, it will either return 201 Created or 500 with Reason
// ServerTimeout indicating a unique name could not be found in the time allotted, and the client
// should retry (optionally after the time indicated in the Retry-After header).
GenerateName string `json:"generateName,omitempty"`
// Namespace defines the space within which name must be unique. An empty namespace is
// equivalent to the "default" namespace, but "default" is the canonical representation.
// Not all objects are required to be scoped to a namespace - the value of this field for
// those objects will be empty.
Namespace string `json:"namespace,omitempty"`
// SelfLink is a URL representing this object.
SelfLink string `json:"selfLink,omitempty"`
// UID is the unique in time and space value for this object. It is typically generated by
// the server on successful creation of a resource and is not allowed to change on PUT
// operations.
UID types.UID `json:"uid,omitempty"`
// An opaque value that represents the version of this resource. May be used for optimistic
// concurrency, change detection, and the watch operation on a resource or set of resources.
// Clients must treat these values as opaque and values may only be valid for a particular
// resource or set of resources. Only servers will generate resource versions.
ResourceVersion string `json:"resourceVersion,omitempty"`
// A sequence number representing a specific generation of the desired state.
// Populated by the system. Read-only.
Generation int64 `json:"generation,omitempty"`
// CreationTimestamp is a timestamp representing the server time when this object was
// created. It is not guaranteed to be set in happens-before order across separate operations.
// Clients may not set this value. It is represented in RFC3339 form and is in UTC.
CreationTimestamp unversioned.Time `json:"creationTimestamp,omitempty"`
// DeletionTimestamp is the time after which this resource will be deleted. This
// field is set by the server when a graceful deletion is requested by the user, and is not
// directly settable by a client. The resource will be deleted (no longer visible from
// resource lists, and not reachable by name) after the time in this field. Once set, this
// value may not be unset or be set further into the future, although it may be shortened
// or the resource may be deleted prior to this time. For example, a user may request that
// a pod is deleted in 30 seconds. The Kubelet will react by sending a graceful termination
// signal to the containers in the pod. Once the resource is deleted in the API, the Kubelet
// will send a hard termination signal to the container.
DeletionTimestamp *unversioned.Time `json:"deletionTimestamp,omitempty"`
// DeletionGracePeriodSeconds records the graceful deletion value set when graceful deletion
// was requested. Represents the most recent grace period, and may only be shortened once set.
DeletionGracePeriodSeconds *int64 `json:"deletionGracePeriodSeconds,omitempty"`
// Labels are key value pairs that may be used to scope and select individual resources.
// Label keys are of the form:
// label-key ::= prefixed-name | name
// prefixed-name ::= prefix '/' name
// prefix ::= DNS_SUBDOMAIN
// name ::= DNS_LABEL
// The prefix is optional. If the prefix is not specified, the key is assumed to be private
// to the user. Other system components that wish to use labels must specify a prefix. The
// "kubernetes.io/" prefix is reserved for use by kubernetes components.
Labels map[string]string `json:"labels,omitempty"`
// Annotations are unstructured key value data stored with a resource that may be set by
// external tooling. They are not queryable and should be preserved when modifying
// objects. Annotation keys have the same formatting restrictions as Label keys. See the
// comments on Labels for details.
Annotations map[string]string `json:"annotations,omitempty"`
// List of objects depended by this object. If ALL objects in the list have
// been deleted, this object will be garbage collected. If this object is managed by a controller,
// then an entry in this list will point to this controller, with the controller field set to true.
// There cannot be more than one managing controller.
OwnerReferences []api.OwnerReference `json:"ownerReferences,omitempty"`
// Must be empty before the object is deleted from the registry. Each entry
// is an identifier for the responsible component that will remove the entry
// from the list. If the deletionTimestamp of the object is non-nil, entries
// in this list can only be removed.
Finalizers []string `json:"finalizers,omitempty"`
// The name of the cluster which the object belongs to.
// This is used to distinguish resources with same name and namespace in different clusters.
// This field is not set anywhere right now and apiserver is going to ignore it if set in create or update request.
ClusterName string `json:"clusterName,omitempty"`
}

View File

@ -19,6 +19,7 @@ package kops
import (
"fmt"
"github.com/golang/glog"
"k8s.io/kubernetes/pkg/api"
"k8s.io/kubernetes/pkg/api/unversioned"
"k8s.io/kubernetes/pkg/util/validation/field"
)
@ -26,12 +27,15 @@ import (
// InstanceGroup represents a group of instances (either nodes or masters) with the same configuration
type InstanceGroup struct {
unversioned.TypeMeta `json:",inline"`
ObjectMeta `json:"metadata,omitempty"`
ObjectMeta api.ObjectMeta `json:"metadata,omitempty"`
Spec InstanceGroupSpec `json:"spec,omitempty"`
}
type InstanceGroupList struct {
unversioned.TypeMeta `json:",inline"`
unversioned.ListMeta `json:"metadata,omitempty"`
Items []InstanceGroup `json:"items"`
}
@ -84,18 +88,18 @@ type InstanceGroupSpec struct {
func PerformAssignmentsInstanceGroups(groups []*InstanceGroup) error {
names := map[string]bool{}
for _, group := range groups {
names[group.Name] = true
names[group.ObjectMeta.Name] = true
}
for _, group := range groups {
// We want to give them a stable Name as soon as possible
if group.Name == "" {
if group.ObjectMeta.Name == "" {
// Loop to find the first unassigned name like `nodes-%d`
i := 0
for {
key := fmt.Sprintf("nodes-%d", i)
if !names[key] {
group.Name = key
group.ObjectMeta.Name = key
names[key] = true
break
}
@ -121,7 +125,7 @@ func (g *InstanceGroup) IsMaster() bool {
}
func (g *InstanceGroup) Validate() error {
if g.Name == "" {
if g.ObjectMeta.Name == "" {
return field.Required(field.NewPath("Name"), "")
}
@ -139,7 +143,7 @@ func (g *InstanceGroup) Validate() error {
if g.IsMaster() {
if len(g.Spec.Zones) == 0 {
return fmt.Errorf("Master InstanceGroup %s did not specify any Zones", g.Name)
return fmt.Errorf("Master InstanceGroup %s did not specify any Zones", g.ObjectMeta.Name)
}
}
@ -166,7 +170,7 @@ func (g *InstanceGroup) CrossValidate(cluster *Cluster, strict bool) error {
for _, z := range g.Spec.Zones {
if clusterZones[z] == nil {
return fmt.Errorf("InstanceGroup %q is configured in %q, but this is not configured as a Zone in the cluster", g.Name, z)
return fmt.Errorf("InstanceGroup %q is configured in %q, but this is not configured as a Zone in the cluster", g.ObjectMeta.Name, z)
}
}
}

View File

@ -27,13 +27,13 @@ func CreateClusterConfig(clientset simple.Clientset, cluster *api.Cluster, group
{
names := map[string]bool{}
for i, ns := range groups {
if ns.Name == "" {
if ns.ObjectMeta.Name == "" {
return fmt.Errorf("InstanceGroup #%d did not have a Name", i+1)
}
if names[ns.Name] {
return fmt.Errorf("Duplicate InstanceGroup Name found: %q", ns.Name)
if names[ns.ObjectMeta.Name] {
return fmt.Errorf("Duplicate InstanceGroup Name found: %q", ns.ObjectMeta.Name)
}
names[ns.Name] = true
names[ns.ObjectMeta.Name] = true
}
}
@ -43,7 +43,7 @@ func CreateClusterConfig(clientset simple.Clientset, cluster *api.Cluster, group
}
for _, ig := range groups {
_, err = clientset.InstanceGroups(cluster.Name).Create(ig)
_, err = clientset.InstanceGroups(cluster.ObjectMeta.Name).Create(ig)
if err != nil {
return fmt.Errorf("error writing updated instancegroup configuration: %v", err)
}

View File

@ -17,12 +17,13 @@ limitations under the License.
package v1alpha1
import (
"k8s.io/kubernetes/pkg/api"
"k8s.io/kubernetes/pkg/api/unversioned"
)
type Cluster struct {
unversioned.TypeMeta `json:",inline"`
ObjectMeta `json:"metadata,omitempty"`
ObjectMeta api.ObjectMeta `json:"metadata,omitempty"`
// Spec defines the behavior of a Cluster.
Spec ClusterSpec `json:"spec,omitempty"`

View File

@ -16,19 +16,15 @@ limitations under the License.
package v1alpha1
import (
"k8s.io/kubernetes/pkg/api/unversioned"
)
// Configuration for each component
// Wherever possible, we try to use the types & names in https://github.com/kubernetes/kubernetes/blob/master/pkg/apis/componentconfig/types.go
type KubeletConfig struct {
unversioned.TypeMeta `json:",inline"`
ObjectMeta `json:"metadata,omitempty"`
Spec ClusterSpec `json:"spec,omitempty"`
}
//type KubeletConfig struct {
// unversioned.TypeMeta `json:",inline"`
// ObjectMeta api.ObjectMeta `json:"metadata,omitempty"`
//
// Spec ClusterSpec `json:"spec,omitempty"`
//}
type KubeletConfigSpec struct {
APIServers string `json:"apiServers,omitempty" flag:"api-servers"`

View File

@ -17,12 +17,13 @@ limitations under the License.
package v1alpha1
import (
"k8s.io/kubernetes/pkg/api"
"k8s.io/kubernetes/pkg/api/unversioned"
)
type Federation struct {
unversioned.TypeMeta `json:",inline"`
ObjectMeta `json:"metadata,omitempty"`
ObjectMeta api.ObjectMeta `json:"metadata,omitempty"`
Spec FederationSpec `json:"spec"`
}

View File

@ -1,124 +0,0 @@
/*
Copyright 2016 The Kubernetes Authors.
Licensed 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.
*/
package v1alpha1
import (
"k8s.io/kubernetes/pkg/api"
"k8s.io/kubernetes/pkg/api/unversioned"
"k8s.io/kubernetes/pkg/types"
)
// ObjectMeta is metadata that all persisted resources must have, which includes all objects
// users must create.
type ObjectMeta struct {
// Name is unique within a namespace. Name is required when creating resources, although
// some resources may allow a client to request the generation of an appropriate name
// automatically. Name is primarily intended for creation idempotence and configuration
// definition.
Name string `json:"name,omitempty"`
// GenerateName indicates that the name should be made unique by the server prior to persisting
// it. A non-empty value for the field indicates the name will be made unique (and the name
// returned to the client will be different than the name passed). The value of this field will
// be combined with a unique suffix on the server if the Name field has not been provided.
// The provided value must be valid within the rules for Name, and may be truncated by the length
// of the suffix required to make the value unique on the server.
//
// If this field is specified, and Name is not present, the server will NOT return a 409 if the
// generated name exists - instead, it will either return 201 Created or 500 with Reason
// ServerTimeout indicating a unique name could not be found in the time allotted, and the client
// should retry (optionally after the time indicated in the Retry-After header).
GenerateName string `json:"generateName,omitempty"`
// Namespace defines the space within which name must be unique. An empty namespace is
// equivalent to the "default" namespace, but "default" is the canonical representation.
// Not all objects are required to be scoped to a namespace - the value of this field for
// those objects will be empty.
Namespace string `json:"namespace,omitempty"`
// SelfLink is a URL representing this object.
SelfLink string `json:"selfLink,omitempty"`
// UID is the unique in time and space value for this object. It is typically generated by
// the server on successful creation of a resource and is not allowed to change on PUT
// operations.
UID types.UID `json:"uid,omitempty"`
// An opaque value that represents the version of this resource. May be used for optimistic
// concurrency, change detection, and the watch operation on a resource or set of resources.
// Clients must treat these values as opaque and values may only be valid for a particular
// resource or set of resources. Only servers will generate resource versions.
ResourceVersion string `json:"resourceVersion,omitempty"`
// A sequence number representing a specific generation of the desired state.
// Populated by the system. Read-only.
Generation int64 `json:"generation,omitempty"`
// CreationTimestamp is a timestamp representing the server time when this object was
// created. It is not guaranteed to be set in happens-before order across separate operations.
// Clients may not set this value. It is represented in RFC3339 form and is in UTC.
CreationTimestamp unversioned.Time `json:"creationTimestamp,omitempty"`
// DeletionTimestamp is the time after which this resource will be deleted. This
// field is set by the server when a graceful deletion is requested by the user, and is not
// directly settable by a client. The resource will be deleted (no longer visible from
// resource lists, and not reachable by name) after the time in this field. Once set, this
// value may not be unset or be set further into the future, although it may be shortened
// or the resource may be deleted prior to this time. For example, a user may request that
// a pod is deleted in 30 seconds. The Kubelet will react by sending a graceful termination
// signal to the containers in the pod. Once the resource is deleted in the API, the Kubelet
// will send a hard termination signal to the container.
DeletionTimestamp *unversioned.Time `json:"deletionTimestamp,omitempty"`
// DeletionGracePeriodSeconds records the graceful deletion value set when graceful deletion
// was requested. Represents the most recent grace period, and may only be shortened once set.
DeletionGracePeriodSeconds *int64 `json:"deletionGracePeriodSeconds,omitempty"`
// Labels are key value pairs that may be used to scope and select individual resources.
// Label keys are of the form:
// label-key ::= prefixed-name | name
// prefixed-name ::= prefix '/' name
// prefix ::= DNS_SUBDOMAIN
// name ::= DNS_LABEL
// The prefix is optional. If the prefix is not specified, the key is assumed to be private
// to the user. Other system components that wish to use labels must specify a prefix. The
// "kubernetes.io/" prefix is reserved for use by kubernetes components.
Labels map[string]string `json:"labels,omitempty"`
// Annotations are unstructured key value data stored with a resource that may be set by
// external tooling. They are not queryable and should be preserved when modifying
// objects. Annotation keys have the same formatting restrictions as Label keys. See the
// comments on Labels for details.
Annotations map[string]string `json:"annotations,omitempty"`
// List of objects depended by this object. If ALL objects in the list have
// been deleted, this object will be garbage collected. If this object is managed by a controller,
// then an entry in this list will point to this controller, with the controller field set to true.
// There cannot be more than one managing controller.
OwnerReferences []api.OwnerReference `json:"ownerReferences,omitempty"`
// Must be empty before the object is deleted from the registry. Each entry
// is an identifier for the responsible component that will remove the entry
// from the list. If the deletionTimestamp of the object is non-nil, entries
// in this list can only be removed.
Finalizers []string `json:"finalizers,omitempty"`
// The name of the cluster which the object belongs to.
// This is used to distinguish resources with same name and namespace in different clusters.
// This field is not set anywhere right now and apiserver is going to ignore it if set in create or update request.
ClusterName string `json:"clusterName,omitempty"`
}

View File

@ -17,13 +17,14 @@ limitations under the License.
package v1alpha1
import (
"k8s.io/kubernetes/pkg/api"
"k8s.io/kubernetes/pkg/api/unversioned"
)
// InstanceGroup represents a group of instances (either nodes or masters) with the same configuration
type InstanceGroup struct {
unversioned.TypeMeta `json:",inline"`
ObjectMeta `json:"metadata,omitempty"`
ObjectMeta api.ObjectMeta `json:"metadata,omitempty"`
Spec InstanceGroupSpec `json:"spec,omitempty"`
}

View File

@ -35,20 +35,20 @@ func (c *Cluster) Validate(strict bool) error {
specPath := field.NewPath("Cluster").Child("Spec")
if c.Name == "" {
if c.ObjectMeta.Name == "" {
return field.Required(field.NewPath("Name"), "Cluster Name is required (e.g. --name=mycluster.myzone.com)")
}
{
// Must be a dns name
errs := validation.IsDNS1123Subdomain(c.Name)
errs := validation.IsDNS1123Subdomain(c.ObjectMeta.Name)
if len(errs) != 0 {
return fmt.Errorf("Cluster Name must be a valid DNS name (e.g. --name=mycluster.myzone.com) errors: %s", strings.Join(errs, ", "))
}
if !strings.Contains(c.Name, ".") {
if !strings.Contains(c.ObjectMeta.Name, ".") {
// Tolerate if this is a cluster we are importing for upgrade
if c.Annotations[AnnotationNameManagement] != AnnotationValueManagementImported {
if c.ObjectMeta.Annotations[AnnotationNameManagement] != AnnotationValueManagementImported {
return fmt.Errorf("Cluster Name must be a fully-qualified DNS name (e.g. --name=mycluster.myzone.com)")
}
}

View File

@ -90,11 +90,11 @@ func (r *ClusterVFS) Create(c *api.Cluster) (*api.Cluster, error) {
return nil, err
}
if c.CreationTimestamp.IsZero() {
c.CreationTimestamp = unversioned.NewTime(time.Now().UTC())
if c.ObjectMeta.CreationTimestamp.IsZero() {
c.ObjectMeta.CreationTimestamp = unversioned.NewTime(time.Now().UTC())
}
clusterName := c.Name
clusterName := c.ObjectMeta.Name
if clusterName == "" {
return nil, fmt.Errorf("clusterName is required")
}
@ -104,7 +104,7 @@ func (r *ClusterVFS) Create(c *api.Cluster) (*api.Cluster, error) {
if os.IsExist(err) {
return nil, err
}
return nil, fmt.Errorf("error writing Cluster %q: %v", c.Name, err)
return nil, fmt.Errorf("error writing Cluster %q: %v", c.ObjectMeta.Name, err)
}
return c, nil
@ -116,7 +116,7 @@ func (r *ClusterVFS) Update(c *api.Cluster) (*api.Cluster, error) {
return nil, err
}
clusterName := c.Name
clusterName := c.ObjectMeta.Name
if clusterName == "" {
return nil, fmt.Errorf("clusterName is required")
}
@ -171,11 +171,11 @@ func (r *ClusterVFS) find(clusterName string) (*api.Cluster, error) {
c := o.(*api.Cluster)
if c.Name == "" {
c.Name = clusterName
if c.ObjectMeta.Name == "" {
c.ObjectMeta.Name = clusterName
}
if c.Name != clusterName {
glog.Warningf("Name of cluster does not match: %q vs %q", c.Name, clusterName)
if c.ObjectMeta.Name != clusterName {
glog.Warningf("Name of cluster does not match: %q vs %q", c.ObjectMeta.Name, clusterName)
}
// TODO: Split this out into real version updates / schema changes

View File

@ -1,7 +1,7 @@
{{ range $m := Masters }}
# ASG for master
launchConfiguration/{{ $m.Name }}.masters.{{ ClusterName }}:
launchConfiguration/{{ $m.ObjectMeta.Name }}.masters.{{ ClusterName }}:
sshKey: sshKey/{{ SSHKeyName }}
securityGroups:
- securityGroup/masters.{{ ClusterName }}
@ -14,14 +14,14 @@ launchConfiguration/{{ $m.Name }}.masters.{{ ClusterName }}:
{{ if IsTopologyPrivate }}
associatePublicIP: false
{{ end }}
userData: resources/nodeup.sh {{ $m.Name }}
userData: resources/nodeup.sh {{ $m.ObjectMeta.Name }}
rootVolumeSize: {{ or $m.Spec.RootVolumeSize "20" }}
rootVolumeType: {{ or $m.Spec.RootVolumeType "gp2" }}
{{ if $m.Spec.MaxPrice }}
spotPrice: "{{ $m.Spec.MaxPrice }}"
{{ end }}
autoscalingGroup/{{ $m.Name }}.masters.{{ ClusterName }}:
autoscalingGroup/{{ $m.ObjectMeta.Name }}.masters.{{ ClusterName }}:
minSize: {{ $m.Spec.MinSize }}
maxSize: {{ $m.Spec.MaxSize }}
subnets:
@ -34,7 +34,7 @@ autoscalingGroup/{{ $m.Name }}.masters.{{ ClusterName }}:
{{ end }}
{{ end }}
launchConfiguration: launchConfiguration/{{ $m.Name }}.masters.{{ ClusterName }}
launchConfiguration: launchConfiguration/{{ $m.ObjectMeta.Name }}.masters.{{ ClusterName }}
tags:
{{ range $k, $v := CloudTags $m }}
{{ $k }}: "{{ $v }}"
@ -42,9 +42,9 @@ autoscalingGroup/{{ $m.Name }}.masters.{{ ClusterName }}:
{{ if HasTag "_master_lb" }}
# Attach ASG to ELB
loadBalancerAttachment/masters.{{ $m.Name }}.{{ ClusterName }}:
loadBalancerAttachment/masters.{{ $m.ObjectMeta.Name }}.{{ ClusterName }}:
loadBalancer: loadBalancer/api.{{ ClusterName }}
autoscalingGroup: autoscalingGroup/{{ $m.Name }}.{{ ClusterName }}
autoscalingGroup: autoscalingGroup/{{ $m.ObjectMeta.Name }}.{{ ClusterName }}
{{ end }}
{{ end }}

View File

@ -29,7 +29,7 @@ instance/master.{{ ClusterName }}:
imageId: {{ $.MasterImage }}
instanceType: {{ $.MasterMachineType }}
associatePublicIP: true
userData: resources/nodeup.sh {{ $.Name }}
userData: resources/nodeup.sh {{ $.ObjectMeta.Name }}
blockDeviceMappings:
# Map all the ephemeral devices
{{ range $d := (MachineTypeInfo $.MasterMachineType).EphemeralDevices }}

View File

@ -224,9 +224,9 @@ securityGroupRule/kube-proxy-api-elb:
# Attach each master ASG to the ELB
# ---------------------------------------------------------------
{{ range $m := Masters }}
loadBalancerAttachment/api-elb-attachment.{{ $m.Name }}.{{ ClusterName }}:
loadBalancerAttachment/api-elb-attachment.{{ $m.ObjectMeta.Name }}.{{ ClusterName }}:
loadBalancer: loadBalancer/api.{{ ClusterName }}
autoscalingGroup: autoscalingGroup/{{ $m.Name }}.masters.{{ ClusterName }}
autoscalingGroup: autoscalingGroup/{{ $m.ObjectMeta.Name }}.masters.{{ ClusterName }}
{{ end }}

View File

@ -46,7 +46,7 @@ securityGroupRule/all-node-to-master:
#
# The AutoScaleGroup for the Nodes
# ---------------------------------------------------------------
launchConfiguration/{{ $ig.Name }}.{{ ClusterName }}:
launchConfiguration/{{ $ig.ObjectMeta.Name }}.{{ ClusterName }}:
sshKey: sshKey/{{ SSHKeyName }}
securityGroups:
- securityGroup/nodes.{{ ClusterName }}
@ -54,14 +54,14 @@ launchConfiguration/{{ $ig.Name }}.{{ ClusterName }}:
imageId: {{ $ig.Spec.Image }}
instanceType: {{ $ig.Spec.MachineType }}
associatePublicIP: false
userData: resources/nodeup.sh {{ $ig.Name }}
userData: resources/nodeup.sh {{ $ig.ObjectMeta.Name }}
rootVolumeSize: {{ or $ig.Spec.RootVolumeSize "20" }}
rootVolumeType: {{ or $ig.Spec.RootVolumeType "gp2" }}
{{ if $ig.Spec.MaxPrice }}
spotPrice: "{{ $ig.Spec.MaxPrice }}"
{{ end }}
autoscalingGroup/{{ $ig.Name }}.{{ ClusterName }}:
launchConfiguration: launchConfiguration/{{ $ig.Name }}.{{ ClusterName }}
autoscalingGroup/{{ $ig.ObjectMeta.Name }}.{{ ClusterName }}:
launchConfiguration: launchConfiguration/{{ $ig.ObjectMeta.Name }}.{{ ClusterName }}
minSize: {{ or $ig.Spec.MinSize 2 }}
maxSize: {{ or $ig.Spec.MaxSize 2 }}
subnets:

View File

@ -49,7 +49,7 @@ securityGroupRule/all-node-to-master:
{{ range $ig := NodeSets }}
# LaunchConfiguration & ASG for nodes
launchConfiguration/{{ $ig.Name }}.{{ ClusterName }}:
launchConfiguration/{{ $ig.ObjectMeta.Name }}.{{ ClusterName }}:
sshKey: sshKey/{{ SSHKeyName }}
securityGroups:
- securityGroup/nodes.{{ ClusterName }}
@ -57,15 +57,15 @@ launchConfiguration/{{ $ig.Name }}.{{ ClusterName }}:
imageId: {{ $ig.Spec.Image }}
instanceType: {{ $ig.Spec.MachineType }}
associatePublicIP: {{ WithDefaultBool $ig.Spec.AssociatePublicIP true }}
userData: resources/nodeup.sh {{ $ig.Name }}
userData: resources/nodeup.sh {{ $ig.ObjectMeta.Name }}
rootVolumeSize: {{ or $ig.Spec.RootVolumeSize "20" }}
rootVolumeType: {{ or $ig.Spec.RootVolumeType "gp2" }}
{{ if $ig.Spec.MaxPrice }}
spotPrice: "{{ $ig.Spec.MaxPrice }}"
{{ end }}
autoscalingGroup/{{ $ig.Name }}.{{ ClusterName }}:
launchConfiguration: launchConfiguration/{{ $ig.Name }}.{{ ClusterName }}
autoscalingGroup/{{ $ig.ObjectMeta.Name }}.{{ ClusterName }}:
launchConfiguration: launchConfiguration/{{ $ig.ObjectMeta.Name }}.{{ ClusterName }}
minSize: {{ or $ig.Spec.MinSize 2 }}
maxSize: {{ or $ig.Spec.MaxSize 2 }}
subnets:

View File

@ -89,7 +89,7 @@ func (c *ApplyClusterCmd) Run() error {
}
if c.InstanceGroups == nil {
list, err := c.Clientset.InstanceGroups(c.Cluster.Name).List(k8sapi.ListOptions{})
list, err := c.Clientset.InstanceGroups(c.Cluster.ObjectMeta.Name).List(k8sapi.ListOptions{})
if err != nil {
return err
}
@ -326,7 +326,7 @@ func (c *ApplyClusterCmd) Run() error {
})
if len(sshPublicKeys) == 0 {
return fmt.Errorf("SSH public key must be specified when running with AWS (create with `kops create secret --name %s sshpublickey admin -i ~/.ssh/id_rsa.pub`)", cluster.Name)
return fmt.Errorf("SSH public key must be specified when running with AWS (create with `kops create secret --name %s sshpublickey admin -i ~/.ssh/id_rsa.pub`)", cluster.ObjectMeta.Name)
}
if len(sshPublicKeys) != 1 {
@ -341,7 +341,7 @@ func (c *ApplyClusterCmd) Run() error {
return "", err
}
name := "kubernetes." + cluster.Name + "-" + fingerprint
name := "kubernetes." + cluster.ObjectMeta.Name + "-" + fingerprint
return name, nil
}
}
@ -393,7 +393,7 @@ func (c *ApplyClusterCmd) Run() error {
role := ig.Spec.Role
if role == "" {
return "", fmt.Errorf("cannot determine role for instance group: %v", ig.Name)
return "", fmt.Errorf("cannot determine role for instance group: %v", ig.ObjectMeta.Name)
}
nodeUpTags, err := buildNodeupTags(role, tf.cluster, tf.tags)
@ -408,11 +408,11 @@ func (c *ApplyClusterCmd) Run() error {
config.Assets = c.Assets
config.ClusterName = cluster.Name
config.ClusterName = cluster.ObjectMeta.Name
config.ConfigBase = fi.String(configBase.Path())
config.InstanceGroupName = ig.Name
config.InstanceGroupName = ig.ObjectMeta.Name
var images []*nodeup.Image
@ -556,9 +556,9 @@ func (c *ApplyClusterCmd) Run() error {
}
for _, g := range c.InstanceGroups {
_, err := c.Clientset.InstanceGroups(c.Cluster.Name).Update(g)
_, err := c.Clientset.InstanceGroups(c.Cluster.ObjectMeta.Name).Update(g)
if err != nil {
return fmt.Errorf("error writing InstanceGroup %q to registry: %v", g.Name, err)
return fmt.Errorf("error writing InstanceGroup %q to registry: %v", g.ObjectMeta.Name, err)
}
}
}

View File

@ -39,7 +39,7 @@ func (b *BootstrapChannelBuilder) BuildTasks(l *Loader) error {
return fmt.Errorf("error serializing addons yaml: %v", err)
}
name := b.cluster.Name + "-addons-bootstrap"
name := b.cluster.ObjectMeta.Name + "-addons-bootstrap"
l.tasks[name] = &fitasks.ManagedFile{
Name: fi.String(name),
@ -48,7 +48,7 @@ func (b *BootstrapChannelBuilder) BuildTasks(l *Loader) error {
}
for key, resource := range manifests {
name := b.cluster.Name + "-addons-" + key
name := b.cluster.ObjectMeta.Name + "-addons-" + key
l.tasks[name] = &fitasks.ManagedFile{
Name: fi.String(name),
Location: fi.String(resource),

View File

@ -228,7 +228,7 @@ func (c *populateClusterSpec) run() error {
if err != nil {
return fmt.Errorf("error getting DNS for cloud: %v", err)
}
dnsZone, err := FindDNSHostedZone(dns, cluster.Name)
dnsZone, err := FindDNSHostedZone(dns, cluster.ObjectMeta.Name)
if err != nil {
return fmt.Errorf("Error determining default DNS zone; please specify --dns-zone: %v", err)
}

View File

@ -87,7 +87,7 @@ func PopulateInstanceGroupSpec(cluster *api.Cluster, input *api.InstanceGroup, c
if ig.IsMaster() {
if len(ig.Spec.Zones) == 0 {
return nil, fmt.Errorf("Master InstanceGroup %s did not specify any Zones", ig.Name)
return nil, fmt.Errorf("Master InstanceGroup %s did not specify any Zones", ig.ObjectMeta.Name)
}
} else {
if len(ig.Spec.Zones) == 0 {

View File

@ -28,7 +28,7 @@ import (
func buildMinimalCluster() *api.Cluster {
c := &api.Cluster{}
c.Name = "testcluster.test.com"
c.ObjectMeta.Name = "testcluster.test.com"
c.Spec.KubernetesVersion = "1.4.6"
c.Spec.Zones = []*api.ClusterZoneSpec{
{Name: "us-mock-1a", CIDR: "172.20.1.0/24"},
@ -265,7 +265,7 @@ func TestPopulateCluster_IsolateMastersFalse(t *testing.T) {
func TestPopulateCluster_Name_Required(t *testing.T) {
c := buildMinimalCluster()
c.Name = ""
c.ObjectMeta.Name = ""
expectErrorFromPopulateCluster(t, c, "Name")
}

View File

@ -25,7 +25,7 @@ import (
func buildMinimalNodeInstanceGroup(zones ...string) *api.InstanceGroup {
g := &api.InstanceGroup{}
g.Name = "nodes"
g.ObjectMeta.Name = "nodes"
g.Spec.Role = api.InstanceGroupRoleNode
g.Spec.Zones = zones
@ -34,7 +34,7 @@ func buildMinimalNodeInstanceGroup(zones ...string) *api.InstanceGroup {
func buildMinimalMasterInstanceGroup(zones ...string) *api.InstanceGroup {
g := &api.InstanceGroup{}
g.Name = "master"
g.ObjectMeta.Name = "master"
g.Spec.Role = api.InstanceGroupRoleMaster
g.Spec.Zones = zones
@ -44,7 +44,7 @@ func buildMinimalMasterInstanceGroup(zones ...string) *api.InstanceGroup {
func TestPopulateInstanceGroup_Name_Required(t *testing.T) {
cluster := buildMinimalCluster()
g := buildMinimalNodeInstanceGroup()
g.Name = ""
g.ObjectMeta.Name = ""
channel := &api.Channel{}

View File

@ -117,7 +117,7 @@ func (tf *TemplateFunctions) AddTo(dest template.FuncMap) {
}
dest["ClusterName"] = func() string {
return tf.cluster.Name
return tf.cluster.ObjectMeta.Name
}
dest["HasTag"] = tf.HasTag
@ -231,7 +231,7 @@ func (tf *TemplateFunctions) GetBastionIdleTimeout() (int, error) {
// Will never return a string longer than 32 chars
func (tf *TemplateFunctions) GetELBName32(prefix string) (string, error) {
var returnString string
c := tf.cluster.Name
c := tf.cluster.ObjectMeta.Name
s := strings.Split(c, ".")
if len(s) > 0 {
returnString = fmt.Sprintf("%s-%s", prefix, s[0])
@ -362,7 +362,7 @@ func (tf *TemplateFunctions) CloudTags(ig *api.InstanceGroup) (map[string]string
// GetInstanceGroup returns the instance group with the specified name
func (tf *TemplateFunctions) GetInstanceGroup(name string) (*api.InstanceGroup, error) {
for _, ig := range tf.instanceGroups {
if ig.Name == name {
if ig.ObjectMeta.Name == name {
return ig, nil
}
}

View File

@ -76,7 +76,7 @@ func BuildCloud(cluster *api.Cluster) (fi.Cloud, error) {
return nil, err
}
cloudTags := map[string]string{awsup.TagClusterName: cluster.Name}
cloudTags := map[string]string{awsup.TagClusterName: cluster.ObjectMeta.Name}
awsCloud, err := awsup.NewAWSCloud(region, cloudTags)
if err != nil {

View File

@ -118,19 +118,19 @@ func TestValidateFull_Default_Validates(t *testing.T) {
func TestValidateFull_ClusterName_InvalidDNS_NoDot(t *testing.T) {
c := buildDefaultCluster(t)
c.Name = "test"
c.ObjectMeta.Name = "test"
expectErrorFromValidate(t, c, "DNS name")
}
func TestValidateFull_ClusterName_InvalidDNS_Invalid(t *testing.T) {
c := buildDefaultCluster(t)
c.Name = "test.-"
c.ObjectMeta.Name = "test.-"
expectErrorFromValidate(t, c, "DNS name")
}
func TestValidateFull_ClusterName_Required(t *testing.T) {
c := buildDefaultCluster(t)
c.Name = ""
c.ObjectMeta.Name = ""
expectErrorFromValidate(t, c, "Name")
}
@ -170,9 +170,9 @@ func TestValidate_ClusterName_Import(t *testing.T) {
c := buildDefaultCluster(t)
// When we import a cluster, it likely won't have a valid name until we convert it
c.Annotations = make(map[string]string)
c.Annotations[api.AnnotationNameManagement] = api.AnnotationValueManagementImported
c.Name = "kubernetes"
c.ObjectMeta.Annotations = make(map[string]string)
c.ObjectMeta.Annotations[api.AnnotationNameManagement] = api.AnnotationValueManagementImported
c.ObjectMeta.Name = "kubernetes"
expectNoErrorFromValidate(t, c)
}

View File

@ -94,7 +94,7 @@ func newTemplateFunctions(nodeupConfig *NodeUpConfig, cluster *api.Cluster, inst
// TODO: Remove this once we have a stable release
glog.Warningf("Building a synthetic instance group")
instanceGroup = &api.InstanceGroup{}
instanceGroup.Name = "synthetic"
instanceGroup.ObjectMeta.Name = "synthetic"
if t.IsMaster() {
instanceGroup.Spec.Role = api.InstanceGroupRoleMaster
} else {
@ -150,7 +150,7 @@ func (t *templateFunctions) populate(dest template.FuncMap) {
}
dest["ClusterName"] = func() string {
return t.cluster.Name
return t.cluster.ObjectMeta.Name
}
dest["ProtokubeImage"] = t.ProtokubeImage

View File

@ -72,7 +72,7 @@ func (x *ConvertKubeupCluster) Upgrade() error {
newTags["KubernetesCluster"] = newClusterName
// Build completed cluster (force errors asap)
cluster.Name = newClusterName
cluster.ObjectMeta.Name = newClusterName
newConfigBase, err := x.Clientset.Clusters().(*vfsclientset.ClusterVFS).ConfigBase(newClusterName)
if err != nil {
@ -95,9 +95,9 @@ func (x *ConvertKubeupCluster) Upgrade() error {
return fmt.Errorf("error populating cluster defaults: %v", err)
}
if cluster.Annotations != nil {
if cluster.ObjectMeta.Annotations != nil {
// Remove the management annotation for the new cluster
delete(cluster.Annotations, api.AnnotationNameManagement)
delete(cluster.ObjectMeta.Annotations, api.AnnotationNameManagement)
}
fullCluster, err := cloudup.PopulateClusterSpec(cluster)

View File

@ -32,7 +32,7 @@ type DeleteInstanceGroup struct {
func (c *DeleteInstanceGroup) DeleteInstanceGroup(group *api.InstanceGroup) error {
groups, err := FindCloudInstanceGroups(c.Cloud, c.Cluster, []*api.InstanceGroup{group}, false, nil)
cig := groups[group.Name]
cig := groups[group.ObjectMeta.Name]
if cig == nil {
return fmt.Errorf("InstanceGroup not found in cloud")
}
@ -45,7 +45,7 @@ func (c *DeleteInstanceGroup) DeleteInstanceGroup(group *api.InstanceGroup) erro
return fmt.Errorf("error deleting cloud resources for InstanceGroup: %v", err)
}
err = c.Clientset.InstanceGroups(c.Cluster.Name).Delete(group.Name, nil)
err = c.Clientset.InstanceGroups(c.Cluster.ObjectMeta.Name).Delete(group.ObjectMeta.Name, nil)
if err != nil {
return err
}

View File

@ -52,13 +52,13 @@ func (x *ImportCluster) ImportAWSCluster() error {
var instanceGroups []*api.InstanceGroup
cluster := &api.Cluster{}
cluster.Annotations = make(map[string]string)
cluster.ObjectMeta.Annotations = make(map[string]string)
// This annotation relaxes some validation (e.g. cluster name as full-dns name)
cluster.Annotations[api.AnnotationNameManagement] = api.AnnotationValueManagementImported
cluster.ObjectMeta.Annotations[api.AnnotationNameManagement] = api.AnnotationValueManagementImported
cluster.Spec.CloudProvider = string(fi.CloudProviderAWS)
cluster.Name = clusterName
cluster.ObjectMeta.Name = clusterName
cluster.Spec.KubeControllerManager = &api.KubeControllerManagerConfig{}
@ -185,7 +185,7 @@ func (x *ImportCluster) ImportAWSCluster() error {
return fmt.Errorf("cannot find zone %q for master. Please report this issue", aws.StringValue(masterInstance.Placement.AvailabilityZone))
}
masterGroup.Spec.Zones = []string{masterZone.Name}
masterGroup.Name = "master-" + masterZone.Name
masterGroup.ObjectMeta.Name = "master-" + masterZone.Name
userData, err := GetInstanceUserData(awsCloud, aws.StringValue(masterInstance.InstanceId))
if err != nil {
@ -261,7 +261,7 @@ func (x *ImportCluster) ImportAWSCluster() error {
nodeGroup := &api.InstanceGroup{}
nodeGroup.Spec.Role = api.InstanceGroupRoleNode
nodeGroup.Name = "nodes"
nodeGroup.ObjectMeta.Name = "nodes"
for _, zone := range zones {
nodeGroup.Spec.Zones = append(nodeGroup.Spec.Zones, zone.Name)
}

View File

@ -67,9 +67,9 @@ func FindCloudInstanceGroups(cloud fi.Cloud, cluster *api.Cluster, instancegroup
var asgName string
switch g.Spec.Role {
case api.InstanceGroupRoleMaster:
asgName = g.Name + ".masters." + cluster.Name
asgName = g.ObjectMeta.Name + ".masters." + cluster.ObjectMeta.Name
case api.InstanceGroupRoleNode:
asgName = g.Name + "." + cluster.Name
asgName = g.ObjectMeta.Name + "." + cluster.ObjectMeta.Name
default:
glog.Warningf("Ignoring InstanceGroup of unknown role %q", g.Spec.Role)
continue
@ -89,7 +89,7 @@ func FindCloudInstanceGroups(cloud fi.Cloud, cluster *api.Cluster, instancegroup
continue
}
group := buildCloudInstanceGroup(instancegroup, asg, nodeMap)
groups[instancegroup.Name] = group
groups[instancegroup.ObjectMeta.Name] = group
}
return groups, nil
@ -112,7 +112,7 @@ func (c *RollingUpdateCluster) RollingUpdate(groups map[string]*CloudInstanceGro
case api.InstanceGroupRoleMaster:
masterGroups[k] = group
default:
return fmt.Errorf("unknown group type for group %q", group.InstanceGroup.Name)
return fmt.Errorf("unknown group type for group %q", group.InstanceGroup.ObjectMeta.Name)
}
}