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

digitalocean support -- dns provider #2864

Merged
merged 5 commits into from
Jul 15, 2017

Conversation

andrewsykim
Copy link
Member

@andrewsykim andrewsykim commented Jul 5, 2017

Initial support for DO on kops, this includes init code for DO Cloud and DNS provider.

Related:
#2150

TODO:

  • comments (the dns provider interface is kinda confusing)
  • wrap calls to DO API into methods with error handling

@k8s-ci-robot k8s-ci-robot added the cncf-cla: yes Indicates the PR's author has signed the CNCF CLA. label Jul 5, 2017
@andrewsykim
Copy link
Member Author

/retest

@andrewsykim andrewsykim force-pushed the digitalocean branch 4 times, most recently from df40822 to e760014 Compare July 11, 2017 01:44
@andrewsykim andrewsykim changed the title [WIP] digitalocean support -- dns provider digitalocean support -- dns provider Jul 11, 2017
@andrewsykim
Copy link
Member Author

/assign @chrislovecnm @justinsb

@chrislovecnm
Copy link
Contributor

@joonas any idea who can do a PR review of the new code that we are bringing in for DO support with kops?

Copy link
Contributor

@chrislovecnm chrislovecnm left a comment

Choose a reason for hiding this comment

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

Exciting stuff btw. Lots of questions - mostly around how you are handling the HTTP API calls.

General questions. Should we put this behind a feature flag? I know this is just the start of support, but should you just include a small document of what has been done, and update that doc with each PR?

tags map[string]string
}

func NewCloud() (*Cloud, error) {
Copy link
Contributor

Choose a reason for hiding this comment

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

Code level comments, please.


// List returns a list of all dns zones
func (z *zones) List() ([]dnsprovider.Zone, error) {
domains, err := listDomains(z.client)
Copy link
Contributor

Choose a reason for hiding this comment

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

We filter calls like these with AWS. Are we able to filter with DO?

Copy link
Member Author

Choose a reason for hiding this comment

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

For certain resources you can, for example you can get droplets by tag, but for domains I don't think so.

Copy link
Member Author

Choose a reason for hiding this comment

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

In this case, you don't want to filter List() anyways since zones.List() is actually supposed to return all the zones registered under the cloud provider.

Copy link
Member Author

Choose a reason for hiding this comment

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

zone represents just 1 of the zones (aka domains, this interface is really confusing IMO)

}

oauthClient := oauth2.NewClient(oauth2.NoContext, tokenSource)
client := godo.NewClient(oauthClient)
Copy link
Contributor

Choose a reason for hiding this comment

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

Can we check that the client is valid? I am surprised that this does not return error handling.

Copy link
Member Author

Choose a reason for hiding this comment

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

The godo client is pretty straight forward since it only needs to initialize a http client so there's really no errors to return. See implementation here: https://github.com/digitalocean/godo/blob/master/godo.go#L150-L179


// List returns a list of dnsprovider.ResourceRecordSet
func (r *resourceRecordSets) List() ([]dnsprovider.ResourceRecordSet, error) {
records, err := getRecords(r.client, r.zone.Name())
Copy link
Contributor

Choose a reason for hiding this comment

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

Same question about filtering. This may return ALOT of records on big accounts. Can we paginate or filter?

Copy link
Member Author

Choose a reason for hiding this comment

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

There's no way to filter records iirc, but for the case where there's a lot of records, you can paginate. This is definitely something I'd want to address before DO support goes beta, for now I think this will be okay. (I'll leave a note though)

}

// New returns an implementation of dnsprovider.ResourceRecordSet
func (r *resourceRecordSets) New(name string, rrdatas []string, ttl int64, rrstype rrstype.RrsType) dnsprovider.ResourceRecordSet {
Copy link
Contributor

Choose a reason for hiding this comment

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

You are not doing much error handling with values that are not defined. Which values are mandatory?

Copy link
Member Author

Choose a reason for hiding this comment

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

I believe all the values are required, I would return an err in this function, but I'm using the dnsprovider interface https://github.com/kubernetes/kubernetes/blob/master/federation/pkg/dnsprovider/dns.go#L63

// TODO (andrewsykim): pagination in ListOptions
domains, resp, err := c.Domains.List(context.TODO(), &godo.ListOptions{})
if err != nil {
return nil, err
Copy link
Contributor

Choose a reason for hiding this comment

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

fmt.Errorf on this please, with resp code and error.

return nil, err
}

if resp.StatusCode != 200 {
Copy link
Contributor

Choose a reason for hiding this comment

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

I am wondering if this is unreachable. Will you get an err from the API if the HTTP status is not 200?

Copy link
Member Author

Choose a reason for hiding this comment

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

If I'm not mistaken, the err returned from godo will still be nil if the API returns a 4XX or 5XX. The above err may not be nil if there's a connection timeout or some client side validation failed.

}

// deleteDomain deletes a domain given its name
func deleteDomain(c *godo.Client, name string) error {
Copy link
Contributor

Choose a reason for hiding this comment

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

Again same pattern for HTTP / API handling. Looks like some sort of interface would be appropriate.

Copy link
Member Author

Choose a reason for hiding this comment

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

See comment here

return fmt.Errorf("error applying changeset: %v", err)
}

if resp.StatusCode != http.StatusOK {
Copy link
Contributor

Choose a reason for hiding this comment

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

need to use the status code everywhere, mostly you have 200.

@@ -0,0 +1,489 @@
/*
Copy link
Contributor

Choose a reason for hiding this comment

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

Nice!

@andrewsykim
Copy link
Member Author

andrewsykim commented Jul 13, 2017

@chrislovecnm added the feature gate here #2929

re: documentation, I was hoping to use this issue for task tracking/updates but I can open up a doc in another PR if you think that's best :)

for _, record := range r.additions {
recordCreateRequest := &godo.DomainRecordEditRequest{
Name: record.Name(),
Data: record.Rrdatas()[0],
Copy link
Member

Choose a reason for hiding this comment

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

FYI I do think we use multiple RRDatas (e.g. HA) but I guess we'll see :-)

Copy link
Member

@justinsb justinsb left a comment

Choose a reason for hiding this comment

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

LGTM

@justinsb
Copy link
Member

LGTM, and all feature-flagged anyway.

At some stage we probably want to adopt external-dns, but I really like the idea of putting the dns provider code into our codebase rather than putting it into core. Makes it easier both to develop the dnsprovider, fix any bugs we find, and maybe move to external-dns at some stage in the future. 👍

@justinsb justinsb merged commit 3139e89 into kubernetes:master Jul 15, 2017
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
cncf-cla: yes Indicates the PR's author has signed the CNCF CLA.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants