Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

Support for lifecycles #2763

Merged
merged 4 commits into from
Jul 21, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 18 additions & 0 deletions cmd/kops/update_cluster.go
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,8 @@ type UpdateClusterOptions struct {
SSHPublicKey string
MaxTaskDuration time.Duration
CreateKubecfg bool

Phase string
}

func (o *UpdateClusterOptions) InitDefaults() {
Expand Down Expand Up @@ -107,6 +109,7 @@ func NewCmdUpdateCluster(f *util.Factory, out io.Writer) *cobra.Command {
cmd.Flags().StringVar(&options.SSHPublicKey, "ssh-public-key", options.SSHPublicKey, "SSH public key to use (deprecated: use kops create secret instead)")
cmd.Flags().StringVar(&options.OutDir, "out", options.OutDir, "Path to write any local output")
cmd.Flags().BoolVar(&options.CreateKubecfg, "create-kube-config", options.CreateKubecfg, "Will control automatically creating the kube config file on your local filesystem")
cmd.Flags().StringVar(&options.Phase, "phase", options.Phase, "Subset of tasks to run")
Copy link
Contributor

Choose a reason for hiding this comment

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

Should we have this as a list? So I can run "iam,network" for instance?

Copy link
Member Author

Choose a reason for hiding this comment

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

Can you explain the use case? Just convenience?

Copy link
Contributor

Choose a reason for hiding this comment

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

For instance many companies have users that have permissions for iam and network, and another group has perms for ec2 instances. We have many users in this situation. It would be god to provide a user to run a single command to create iam and network.

Copy link
Contributor

Choose a reason for hiding this comment

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

When testing this I am noticing that we are not printing the allowed values for Phase. Can we add to update_cluster.go?

Copy link
Member Author

Choose a reason for hiding this comment

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

We can add those later, let's start trying this out for real and then see whether we need it

return cmd
}

Expand Down Expand Up @@ -172,6 +175,20 @@ func RunUpdateCluster(f *util.Factory, clusterName string, out io.Writer, c *Upd
glog.Infof("Using SSH public key: %v\n", c.SSHPublicKey)
}

var phase cloudup.Phase
Copy link
Contributor

Choose a reason for hiding this comment

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

Should we have the phase options lower, say in create.go? I will probably need kops create -f mycluster.yaml --phase iam.

Copy link
Member Author

Choose a reason for hiding this comment

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

Phase is really only for updating. Today there are some circumstances in which create will do an update (for historical reasons), and you have a PR to tweak that, and the kops-server work may also change that (because in k8s today, creating an object immediately does an update).

I'd prefer to leave our options open unless we know we need it today. Do we need it today?

Copy link
Contributor

Choose a reason for hiding this comment

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

Yes, the majority of user that would be interested in this would be interesting with this with yaml support. We can merge and move lower if you like.

Copy link
Member Author

Choose a reason for hiding this comment

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

Let's get this in and look at the broader role of create vs update as part of the kops-server UX pass

if c.Phase != "" {
switch strings.ToLower(c.Phase) {
case "iam":
phase = cloudup.PhaseIAM
case "network":
phase = cloudup.PhaseNetwork
case "cluster":
phase = cloudup.PhaseCluster
default:
return fmt.Errorf("unknown phase %q", c.Phase)
}
}

var instanceGroups []*kops.InstanceGroup
{
list, err := clientset.InstanceGroupsFor(cluster).List(metav1.ListOptions{})
Expand All @@ -192,6 +209,7 @@ func RunUpdateCluster(f *util.Factory, clusterName string, out io.Writer, c *Upd
DryRun: isDryrun,
MaxTaskDuration: c.MaxTaskDuration,
InstanceGroups: instanceGroups,
Phase: phase,
}

err = applyCmd.Run()
Expand Down
1 change: 1 addition & 0 deletions docs/cli/kops_update_cluster.md
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ kops update cluster
--create-kube-config Will control automatically creating the kube config file on your local filesystem (default true)
--model string Models to apply (separate multiple models with commas) (default "config,proto,cloudup")
--out string Path to write any local output
--phase string Subset of tasks to run
--ssh-public-key string SSH public key to use (deprecated: use kops create secret instead)
--target string Target - direct, terraform, cloudformation (default "direct")
--yes Actually create cloud resources
Expand Down
24 changes: 18 additions & 6 deletions pkg/model/awsmodel/api_loadbalancer.go
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ const LoadBalancerDefaultIdleTimeout = 5 * time.Minute
// APILoadBalancerBuilder builds a LoadBalancer for accessing the API
type APILoadBalancerBuilder struct {
*AWSModelContext
Lifecycle *fi.Lifecycle
}

var _ fi.ModelBuilder = &APILoadBalancerBuilder{}
Expand Down Expand Up @@ -101,7 +102,9 @@ func (b *APILoadBalancerBuilder) Build(c *fi.ModelBuilderContext) error {
}

elb = &awstasks.LoadBalancer{
Name: s("api." + b.ClusterName()),
Name: s("api." + b.ClusterName()),
Lifecycle: b.Lifecycle,

LoadBalancerName: s(loadBalancerName),
SecurityGroups: []*awstasks.SecurityGroup{
b.LinkToELBSecurityGroup("api"),
Expand Down Expand Up @@ -140,7 +143,9 @@ func (b *APILoadBalancerBuilder) Build(c *fi.ModelBuilderContext) error {
// Create security group for API ELB
{
t := &awstasks.SecurityGroup{
Name: s(b.ELBSecurityGroupName("api")),
Name: s(b.ELBSecurityGroupName("api")),
Lifecycle: b.Lifecycle,

VPC: b.LinkToVPC(),
Description: s("Security group for api ELB"),
RemoveExtraRules: []string{"port=443"},
Expand All @@ -151,7 +156,9 @@ func (b *APILoadBalancerBuilder) Build(c *fi.ModelBuilderContext) error {
// Allow traffic from ELB to egress freely
{
t := &awstasks.SecurityGroupRule{
Name: s("api-elb-egress"),
Name: s("api-elb-egress"),
Lifecycle: b.Lifecycle,

SecurityGroup: b.LinkToELBSecurityGroup("api"),
Egress: fi.Bool(true),
CIDR: s("0.0.0.0/0"),
Expand All @@ -163,7 +170,9 @@ func (b *APILoadBalancerBuilder) Build(c *fi.ModelBuilderContext) error {
{
for _, cidr := range b.Cluster.Spec.KubernetesAPIAccess {
t := &awstasks.SecurityGroupRule{
Name: s("https-api-elb-" + cidr),
Name: s("https-api-elb-" + cidr),
Lifecycle: b.Lifecycle,

SecurityGroup: b.LinkToELBSecurityGroup("api"),
CIDR: s(cidr),
FromPort: i64(443),
Expand All @@ -177,7 +186,9 @@ func (b *APILoadBalancerBuilder) Build(c *fi.ModelBuilderContext) error {
// Allow HTTPS to the master instances from the ELB
{
t := &awstasks.SecurityGroupRule{
Name: s("https-elb-to-master"),
Name: s("https-elb-to-master"),
Lifecycle: b.Lifecycle,

SecurityGroup: b.LinkToSecurityGroup(kops.InstanceGroupRoleMaster),
SourceGroup: b.LinkToELBSecurityGroup("api"),
FromPort: i64(443),
Expand All @@ -201,7 +212,8 @@ func (b *APILoadBalancerBuilder) Build(c *fi.ModelBuilderContext) error {

for _, ig := range b.MasterInstanceGroups() {
t := &awstasks.LoadBalancerAttachment{
Name: s("api-" + ig.ObjectMeta.Name),
Name: s("api-" + ig.ObjectMeta.Name),
Lifecycle: b.Lifecycle,

LoadBalancer: b.LinkToELB("api"),
AutoscalingGroup: b.LinkToAutoscalingGroup(ig),
Expand Down
7 changes: 5 additions & 2 deletions pkg/model/awsmodel/autoscalinggroup.go
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ type AutoscalingGroupModelBuilder struct {
*AWSModelContext

BootstrapScript *model.BootstrapScript
Lifecycle *fi.Lifecycle
}

var _ fi.ModelBuilder = &AutoscalingGroupModelBuilder{}
Expand Down Expand Up @@ -67,7 +68,8 @@ func (b *AutoscalingGroupModelBuilder) Build(c *fi.ModelBuilderContext) error {
}

t := &awstasks.LaunchConfiguration{
Name: s(name),
Name: s(name),
Lifecycle: b.Lifecycle,

SecurityGroups: []*awstasks.SecurityGroup{
b.LinkToSecurityGroup(ig.Spec.Role),
Expand Down Expand Up @@ -163,7 +165,8 @@ func (b *AutoscalingGroupModelBuilder) Build(c *fi.ModelBuilderContext) error {
// AutoscalingGroup
{
t := &awstasks.AutoscalingGroup{
Name: s(name),
Name: s(name),
Lifecycle: b.Lifecycle,

LaunchConfiguration: launchConfiguration,
}
Expand Down
45 changes: 34 additions & 11 deletions pkg/model/bastion.go
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ const BastionELBDefaultIdleTimeout = 5 * time.Minute

type BastionModelBuilder struct {
*KopsModelContext
Lifecycle *fi.Lifecycle
}

var _ fi.ModelBuilder = &BastionModelBuilder{}
Expand All @@ -54,7 +55,9 @@ func (b *BastionModelBuilder) Build(c *fi.ModelBuilderContext) error {
// Create security group for bastion instances
{
t := &awstasks.SecurityGroup{
Name: s(b.SecurityGroupName(kops.InstanceGroupRoleBastion)),
Name: s(b.SecurityGroupName(kops.InstanceGroupRoleBastion)),
Lifecycle: b.Lifecycle,

VPC: b.LinkToVPC(),
Description: s("Security group for bastion"),
RemoveExtraRules: []string{"port=22"},
Expand All @@ -65,7 +68,9 @@ func (b *BastionModelBuilder) Build(c *fi.ModelBuilderContext) error {
// Allow traffic from bastion instances to egress freely
{
t := &awstasks.SecurityGroupRule{
Name: s("bastion-egress"),
Name: s("bastion-egress"),
Lifecycle: b.Lifecycle,

SecurityGroup: b.LinkToSecurityGroup(kops.InstanceGroupRoleBastion),
Egress: fi.Bool(true),
CIDR: s("0.0.0.0/0"),
Expand All @@ -77,7 +82,9 @@ func (b *BastionModelBuilder) Build(c *fi.ModelBuilderContext) error {
// TODO: Could we get away without an ELB here? Tricky to fix if dns-controller breaks though...
{
t := &awstasks.SecurityGroupRule{
Name: s("ssh-elb-to-bastion"),
Name: s("ssh-elb-to-bastion"),
Lifecycle: b.Lifecycle,

SecurityGroup: b.LinkToSecurityGroup(kops.InstanceGroupRoleBastion),
SourceGroup: b.LinkToELBSecurityGroup(BastionELBSecurityGroupPrefix),
Protocol: s("tcp"),
Expand All @@ -90,7 +97,9 @@ func (b *BastionModelBuilder) Build(c *fi.ModelBuilderContext) error {
// Allow bastion nodes to SSH to masters
{
t := &awstasks.SecurityGroupRule{
Name: s("bastion-to-master-ssh"),
Name: s("bastion-to-master-ssh"),
Lifecycle: b.Lifecycle,

SecurityGroup: b.LinkToSecurityGroup(kops.InstanceGroupRoleMaster),
SourceGroup: b.LinkToSecurityGroup(kops.InstanceGroupRoleBastion),
Protocol: s("tcp"),
Expand All @@ -103,7 +112,9 @@ func (b *BastionModelBuilder) Build(c *fi.ModelBuilderContext) error {
// Allow bastion nodes to SSH to nodes
{
t := &awstasks.SecurityGroupRule{
Name: s("bastion-to-node-ssh"),
Name: s("bastion-to-node-ssh"),
Lifecycle: b.Lifecycle,

SecurityGroup: b.LinkToSecurityGroup(kops.InstanceGroupRoleNode),
SourceGroup: b.LinkToSecurityGroup(kops.InstanceGroupRoleBastion),
Protocol: s("tcp"),
Expand All @@ -116,7 +127,9 @@ func (b *BastionModelBuilder) Build(c *fi.ModelBuilderContext) error {
// Create security group for bastion ELB
{
t := &awstasks.SecurityGroup{
Name: s(b.ELBSecurityGroupName(BastionELBSecurityGroupPrefix)),
Name: s(b.ELBSecurityGroupName(BastionELBSecurityGroupPrefix)),
Lifecycle: b.Lifecycle,

VPC: b.LinkToVPC(),
Description: s("Security group for bastion ELB"),
RemoveExtraRules: []string{"port=22"},
Expand All @@ -127,7 +140,9 @@ func (b *BastionModelBuilder) Build(c *fi.ModelBuilderContext) error {
// Allow traffic from ELB to egress freely
{
t := &awstasks.SecurityGroupRule{
Name: s("bastion-elb-egress"),
Name: s("bastion-elb-egress"),
Lifecycle: b.Lifecycle,

SecurityGroup: b.LinkToELBSecurityGroup(BastionELBSecurityGroupPrefix),
Egress: fi.Bool(true),
CIDR: s("0.0.0.0/0"),
Expand All @@ -139,7 +154,9 @@ func (b *BastionModelBuilder) Build(c *fi.ModelBuilderContext) error {
// Allow external access to ELB
for _, sshAccess := range b.Cluster.Spec.SSHAccess {
t := &awstasks.SecurityGroupRule{
Name: s("ssh-external-to-bastion-elb-" + sshAccess),
Name: s("ssh-external-to-bastion-elb-" + sshAccess),
Lifecycle: b.Lifecycle,

SecurityGroup: b.LinkToELBSecurityGroup(BastionELBSecurityGroupPrefix),
Protocol: s("tcp"),
FromPort: i64(22),
Expand Down Expand Up @@ -182,7 +199,9 @@ func (b *BastionModelBuilder) Build(c *fi.ModelBuilderContext) error {
}

elb = &awstasks.LoadBalancer{
Name: s("bastion." + b.ClusterName()),
Name: s("bastion." + b.ClusterName()),
Lifecycle: b.Lifecycle,

LoadBalancerName: s(loadBalancerName),
SecurityGroups: []*awstasks.SecurityGroup{
b.LinkToELBSecurityGroup(BastionELBSecurityGroupPrefix),
Expand Down Expand Up @@ -213,7 +232,9 @@ func (b *BastionModelBuilder) Build(c *fi.ModelBuilderContext) error {

// Attach the ELB to the ASG
t := &awstasks.LoadBalancerAttachment{
Name: s("bastion-elb-attachment"),
Name: s("bastion-elb-attachment"),
Lifecycle: b.Lifecycle,

LoadBalancer: elb,
AutoscalingGroup: b.LinkToAutoscalingGroup(ig),
}
Expand All @@ -228,7 +249,9 @@ func (b *BastionModelBuilder) Build(c *fi.ModelBuilderContext) error {
// Here we implement the bastion CNAME logic
// By default bastions will create a CNAME that follows the `bastion-$clustername` formula
t := &awstasks.DNSName{
Name: s(bastionPublicName),
Name: s(bastionPublicName),
Lifecycle: b.Lifecycle,

Zone: b.LinkToDNSZone(),
ResourceType: s("A"),
TargetLoadBalancer: elb,
Expand Down
5 changes: 4 additions & 1 deletion pkg/model/dns.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ import (
// DNSModelBuilder builds DNS related model objects
type DNSModelBuilder struct {
*KopsModelContext
Lifecycle *fi.Lifecycle
}

var _ fi.ModelBuilder = &DNSModelBuilder{}
Expand All @@ -39,7 +40,8 @@ func (b *DNSModelBuilder) ensureDNSZone(c *fi.ModelBuilderContext) error {

// Configuration for a DNS zone
dnsZone := &awstasks.DNSZone{
Name: s(b.NameForDNSZone()),
Name: s(b.NameForDNSZone()),
Lifecycle: b.Lifecycle,
}

topology := b.Cluster.Spec.Topology
Expand Down Expand Up @@ -99,6 +101,7 @@ func (b *DNSModelBuilder) Build(c *fi.ModelBuilderContext) error {

apiDnsName := &awstasks.DNSName{
Name: s(b.Cluster.Spec.MasterPublicName),
Lifecycle: b.Lifecycle,
Zone: b.LinkToDNSZone(),
ResourceType: s("A"),
TargetLoadBalancer: b.LinkToELB("api"),
Expand Down
4 changes: 4 additions & 0 deletions pkg/model/external_access.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ import (
// (SSHAccess, KubernetesAPIAccess)
type ExternalAccessModelBuilder struct {
*KopsModelContext
Lifecycle *fi.Lifecycle
}

var _ fi.ModelBuilder = &ExternalAccessModelBuilder{}
Expand All @@ -50,6 +51,7 @@ func (b *ExternalAccessModelBuilder) Build(c *fi.ModelBuilderContext) error {
for _, sshAccess := range b.Cluster.Spec.SSHAccess {
c.AddTask(&awstasks.SecurityGroupRule{
Name: s("ssh-external-to-master-" + sshAccess),
Lifecycle: b.Lifecycle,
SecurityGroup: b.LinkToSecurityGroup(kops.InstanceGroupRoleMaster),
Protocol: s("tcp"),
FromPort: i64(22),
Expand All @@ -59,6 +61,7 @@ func (b *ExternalAccessModelBuilder) Build(c *fi.ModelBuilderContext) error {

c.AddTask(&awstasks.SecurityGroupRule{
Name: s("ssh-external-to-node-" + sshAccess),
Lifecycle: b.Lifecycle,
SecurityGroup: b.LinkToSecurityGroup(kops.InstanceGroupRoleNode),
Protocol: s("tcp"),
FromPort: i64(22),
Expand All @@ -77,6 +80,7 @@ func (b *ExternalAccessModelBuilder) Build(c *fi.ModelBuilderContext) error {
for _, apiAccess := range b.Cluster.Spec.KubernetesAPIAccess {
t := &awstasks.SecurityGroupRule{
Name: s("https-external-to-master-" + apiAccess),
Lifecycle: b.Lifecycle,
SecurityGroup: b.LinkToSecurityGroup(kops.InstanceGroupRoleMaster),
Protocol: s("tcp"),
FromPort: i64(443),
Expand Down
Loading