Skip to content

Commit

Permalink
Merge pull request #3244 from andrewsykim/dotasks
Browse files Browse the repository at this point in the history
Automatic merge from submit-queue

Implement DigitalOcean Volume FI Task

Implements volume task to create etcd volumes for master nodes.
  • Loading branch information
Kubernetes Submit Queue committed Aug 21, 2017
2 parents 2c8183a + 525fde3 commit d952db7
Show file tree
Hide file tree
Showing 9 changed files with 424 additions and 4 deletions.
1 change: 1 addition & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -137,6 +137,7 @@ codegen: kops-gobindata
PATH=${GOPATH_1ST}/bin:${PATH} go generate k8s.io/kops/upup/pkg/fi/cloudup/awstasks
PATH=${GOPATH_1ST}/bin:${PATH} go generate k8s.io/kops/upup/pkg/fi/cloudup/gcetasks
PATH=${GOPATH_1ST}/bin:${PATH} go generate k8s.io/kops/upup/pkg/fi/assettasks
PATH=${GOPATH_1ST}/bin:${PATH} go generate k8s.io/kops/upup/pkg/fi/cloudup/dotasks
PATH=${GOPATH_1ST}/bin:${PATH} go generate k8s.io/kops/upup/pkg/fi/fitasks

.PHONY: protobuf
Expand Down
1 change: 1 addition & 0 deletions hack/.packages
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,7 @@ k8s.io/kops/upup/pkg/fi/cloudup/awsup
k8s.io/kops/upup/pkg/fi/cloudup/cloudformation
k8s.io/kops/upup/pkg/fi/cloudup/dnstasks
k8s.io/kops/upup/pkg/fi/cloudup/do
k8s.io/kops/upup/pkg/fi/cloudup/dotasks
k8s.io/kops/upup/pkg/fi/cloudup/gce
k8s.io/kops/upup/pkg/fi/cloudup/gcetasks
k8s.io/kops/upup/pkg/fi/cloudup/terraform
Expand Down
14 changes: 14 additions & 0 deletions pkg/model/master_volumes.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ import (
"k8s.io/kops/upup/pkg/fi"
"k8s.io/kops/upup/pkg/fi/cloudup/awstasks"
"k8s.io/kops/upup/pkg/fi/cloudup/awsup"
"k8s.io/kops/upup/pkg/fi/cloudup/dotasks"
"k8s.io/kops/upup/pkg/fi/cloudup/gce"
"k8s.io/kops/upup/pkg/fi/cloudup/gcetasks"
)
Expand Down Expand Up @@ -88,6 +89,8 @@ func (b *MasterVolumeBuilder) Build(c *fi.ModelBuilderContext) error {
switch kops.CloudProviderID(b.Cluster.Spec.CloudProvider) {
case kops.CloudProviderAWS:
b.addAWSVolume(c, name, volumeSize, subnet, etcd, m, allMembers)
case kops.CloudProviderDO:
b.addDOVolume(c, name, volumeSize, subnet, etcd, m, allMembers)
case kops.CloudProviderGCE:
b.addGCEVolume(c, name, volumeSize, subnet, etcd, m, allMembers)
case kops.CloudProviderVSphere:
Expand Down Expand Up @@ -137,6 +140,17 @@ func (b *MasterVolumeBuilder) addAWSVolume(c *fi.ModelBuilderContext, name strin
c.AddTask(t)
}

func (b *MasterVolumeBuilder) addDOVolume(c *fi.ModelBuilderContext, name string, volumeSize int32, subnet *kops.ClusterSubnetSpec, etcd *kops.EtcdClusterSpec, m *kops.EtcdMemberSpec, allMembers []string) {
t := &dotasks.Volume{
Name: s(name),
Lifecycle: b.Lifecycle,
SizeGB: fi.Int64(int64(volumeSize)),
Region: s(subnet.Zone),
}

c.AddTask(t)
}

func (b *MasterVolumeBuilder) addGCEVolume(c *fi.ModelBuilderContext, name string, volumeSize int32, subnet *kops.ClusterSubnetSpec, etcd *kops.EtcdClusterSpec, m *kops.EtcdMemberSpec, allMembers []string) {
volumeType := fi.StringValue(m.VolumeType)
if volumeType == "" {
Expand Down
9 changes: 7 additions & 2 deletions pkg/resources/digitalocean/cloud.go
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ func (t *TokenSource) Token() (*oauth2.Token, error) {

// Cloud exposes all the interfaces required to operate on DigitalOcean resources
type Cloud struct {
client *godo.Client
Client *godo.Client

dns dnsprovider.Interface

Expand All @@ -70,7 +70,7 @@ func NewCloud(region string) (*Cloud, error) {
client := godo.NewClient(oauthClient)

return &Cloud{
client: client,
Client: client,
dns: dns.NewProvider(client),
Region: region,
}, nil
Expand All @@ -86,6 +86,11 @@ func (c *Cloud) DNS() (dnsprovider.Interface, error) {
return c.dns, nil
}

// Volume returns an implementation of godo.StorageService
func (c *Cloud) Volumes() godo.StorageService {
return c.Client.Storage
}

// FindVPCInfo is not implemented, it's only here to satisfy the fi.Cloud interface
func (c *Cloud) FindVPCInfo(id string) (*fi.VPCInfo, error) {
return nil, errors.New("not implemented")
Expand Down
9 changes: 8 additions & 1 deletion upup/pkg/fi/cloudup/apply_cluster.go
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ import (
"k8s.io/kops/upup/pkg/fi/cloudup/awsup"
"k8s.io/kops/upup/pkg/fi/cloudup/cloudformation"
"k8s.io/kops/upup/pkg/fi/cloudup/do"
"k8s.io/kops/upup/pkg/fi/cloudup/dotasks"
"k8s.io/kops/upup/pkg/fi/cloudup/gce"
"k8s.io/kops/upup/pkg/fi/cloudup/gcetasks"
"k8s.io/kops/upup/pkg/fi/cloudup/terraform"
Expand Down Expand Up @@ -335,7 +336,9 @@ func (c *ApplyClusterCmd) Run() error {
}

// this is a no-op for now, add tasks to this list as more DO support is added
l.AddTypes(map[string]interface{}{})
l.AddTypes(map[string]interface{}{
"volume": &dotasks.Volume{},
})
}
case kops.CloudProviderAWS:
{
Expand Down Expand Up @@ -514,6 +517,10 @@ func (c *ApplyClusterCmd) Run() error {
l.Builders = append(l.Builders,
&model.IAMModelBuilder{KopsModelContext: modelContext, Lifecycle: iamLifecycle},
)
case kops.CloudProviderDO:
l.Builders = append(l.Builders,
&model.MasterVolumeBuilder{KopsModelContext: modelContext, Lifecycle: clusterLifecycle},
)

case kops.CloudProviderGCE:
gceModelContext := &gcemodel.GCEModelContext{
Expand Down
135 changes: 135 additions & 0 deletions upup/pkg/fi/cloudup/dotasks/volume.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,135 @@
/*
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 dotasks

import (
"context"

"github.com/digitalocean/godo"

"k8s.io/kops/pkg/resources/digitalocean"
"k8s.io/kops/upup/pkg/fi"
"k8s.io/kops/upup/pkg/fi/cloudup/do"
"k8s.io/kops/upup/pkg/fi/cloudup/terraform"
)

//go:generate fitask -type=Volume
type Volume struct {
Name *string
ID *string
Lifecycle *fi.Lifecycle

SizeGB *int64
Region *string
}

var _ fi.CompareWithID = &Volume{}

func (v *Volume) CompareWithID() *string {
return v.ID
}

func (v *Volume) Find(c *fi.Context) (*Volume, error) {
cloud := c.Cloud.(*digitalocean.Cloud)
volService := cloud.Volumes()

volumes, _, err := volService.ListVolumes(context.TODO(), &godo.ListVolumeParams{
Region: cloud.Region,
Name: fi.StringValue(v.Name),
})
if err != nil {
return nil, err
}

for _, volume := range volumes {
if volume.Name == fi.StringValue(v.Name) {
return &Volume{
Name: fi.String(volume.Name),
ID: fi.String(volume.ID),
Lifecycle: v.Lifecycle,
SizeGB: fi.Int64(volume.SizeGigaBytes),
Region: fi.String(volume.Region.Slug),
}, nil
}
}

// Volume = nil if not found
return nil, nil
}

func (v *Volume) Run(c *fi.Context) error {
return fi.DefaultDeltaRunMethod(v, c)
}

func (_ *Volume) CheckChanges(a, e, changes *Volume) error {
if a != nil {
if changes.Name != nil {
return fi.CannotChangeField("Name")
}
if changes.ID != nil {
return fi.CannotChangeField("ID")
}
if changes.Region != nil {
return fi.CannotChangeField("Region")
}
} else {
if e.Name == nil {
return fi.RequiredField("Name")
}
if e.SizeGB == nil {
return fi.RequiredField("SizeGB")
}
if e.Region == nil {
return fi.RequiredField("Region")
}
}
return nil
}

func (_ *Volume) RenderDO(t *do.DOAPITarget, a, e, changes *Volume) error {
if a != nil {
// in general, we shouldn't need to render changes to a volume
// however there can be cases where we may want to resize or rename.
// consider this in later stages of DO support on kops
return nil
}

volService := t.Cloud.Volumes()
_, _, err := volService.CreateVolume(context.TODO(), &godo.VolumeCreateRequest{
Name: fi.StringValue(e.Name),
Region: fi.StringValue(e.Region),
SizeGigaBytes: fi.Int64Value(e.SizeGB),
})
return err
}

// terraformVolume represents the digitalocean_volume resource in terraform
// https://www.terraform.io/docs/providers/do/r/volume.html
type terraformVolume struct {
Name *string `json:"name"`
SizeGB *int64 `json:"size"`
Region *string `json:"region"`
}

func (_ *Volume) RenderTerraform(t *terraform.TerraformTarget, a, e, changes *Volume) error {
tf := &terraformVolume{
Name: e.Name,
SizeGB: e.SizeGB,
Region: e.Region,
}
return t.RenderResource("digitalocean_volume", *e.Name, tf)
}
70 changes: 70 additions & 0 deletions upup/pkg/fi/cloudup/dotasks/volume_fitask.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading

0 comments on commit d952db7

Please sign in to comment.