openstack designate dns provider

This commit is contained in:
Jon Perritt 2018-09-10 13:27:34 -05:00 committed by Derek Lemon -T (delemon - AEROTEK INC at Cisco)
parent 9573ed45c0
commit 83365a992a
8 changed files with 512 additions and 0 deletions

View File

@ -0,0 +1,27 @@
load("@io_bazel_rules_go//go:def.bzl", "go_library")
go_library(
name = "go_default_library",
srcs = [
"designate.go",
"interface.go",
"rrchangeset.go",
"rrset.go",
"rrsets.go",
"zone.go",
"zones.go",
],
importpath = "k8s.io/kops/dnsprovider/pkg/dnsprovider/providers/openstack/designate",
visibility = ["//visibility:public"],
deps = [
"//dnsprovider/pkg/dnsprovider:go_default_library",
"//dnsprovider/pkg/dnsprovider/rrstype:go_default_library",
"//util/pkg/vfs:go_default_library",
"//vendor/github.com/golang/glog:go_default_library",
"//vendor/github.com/gophercloud/gophercloud:go_default_library",
"//vendor/github.com/gophercloud/gophercloud/openstack:go_default_library",
"//vendor/github.com/gophercloud/gophercloud/openstack/dns/v2/recordsets:go_default_library",
"//vendor/github.com/gophercloud/gophercloud/openstack/dns/v2/zones:go_default_library",
"//vendor/github.com/gophercloud/gophercloud/pagination:go_default_library",
],
)

View File

@ -0,0 +1,67 @@
package designate
import (
"crypto/tls"
"fmt"
"io"
"net/http"
"github.com/golang/glog"
"github.com/gophercloud/gophercloud/openstack"
"k8s.io/kops/dnsprovider/pkg/dnsprovider"
"k8s.io/kops/util/pkg/vfs"
)
const (
// ProviderName is the name of this DNS provider
ProviderName = "openstack-designate"
)
func init() {
dnsprovider.RegisterDnsProvider(ProviderName, func(config io.Reader) (dnsprovider.Interface, error) {
return newDesignate(config)
})
}
func newDesignate(_ io.Reader) (*Interface, error) {
oc := vfs.OpenstackConfig{}
ao, err := oc.GetCredential()
if err != nil {
return nil, err
}
/*
pc, err := openstack.AuthenticatedClient(ao)
if err != nil {
return nil, fmt.Errorf("error building openstack authenticated client: %v", err)
}*/
provider, err := openstack.NewClient(ao.IdentityEndpoint)
if err != nil {
return nil, fmt.Errorf("error building openstack provider client: %v", err)
}
tlsconfig := &tls.Config{}
tlsconfig.InsecureSkipVerify = true
transport := &http.Transport{TLSClientConfig: tlsconfig}
provider.HTTPClient = http.Client{
Transport: transport,
}
glog.V(2).Info("authenticating to keystone")
err = openstack.Authenticate(provider, ao)
if err != nil {
return nil, fmt.Errorf("error building openstack authenticated client: %v", err)
}
endpointOpt, err := oc.GetServiceConfig("Designate")
if err != nil {
return nil, err
}
sc, err := openstack.NewDNSV2(provider, endpointOpt)
if err != nil {
}
return New(sc), nil
}

View File

@ -0,0 +1,22 @@
package designate
import (
"github.com/gophercloud/gophercloud"
"k8s.io/kops/dnsprovider/pkg/dnsprovider"
)
var _ dnsprovider.Interface = Interface{}
type Interface struct {
sc *gophercloud.ServiceClient
}
// New builds an Interface, with a specified Designate implementation.
// This is useful for testing purposes, but also if we want an instance with custom OpenStack options.
func New(sc *gophercloud.ServiceClient) *Interface {
return &Interface{sc}
}
func (i Interface) Zones() (zones dnsprovider.Zones, supported bool) {
return Zones{&i}, true
}

View File

@ -0,0 +1,136 @@
/*
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 designate
import (
"fmt"
"github.com/gophercloud/gophercloud/openstack/dns/v2/recordsets"
"k8s.io/kops/dnsprovider/pkg/dnsprovider"
)
var _ dnsprovider.ResourceRecordChangeset = &ResourceRecordChangeset{}
type ResourceRecordChangeset struct {
zone *Zone
rrsets *ResourceRecordSets
additions []dnsprovider.ResourceRecordSet
removals []dnsprovider.ResourceRecordSet
upserts []dnsprovider.ResourceRecordSet
}
func (c *ResourceRecordChangeset) Add(rrset dnsprovider.ResourceRecordSet) dnsprovider.ResourceRecordChangeset {
c.additions = append(c.additions, rrset)
return c
}
func (c *ResourceRecordChangeset) Remove(rrset dnsprovider.ResourceRecordSet) dnsprovider.ResourceRecordChangeset {
c.removals = append(c.removals, rrset)
return c
}
func (c *ResourceRecordChangeset) Upsert(rrset dnsprovider.ResourceRecordSet) dnsprovider.ResourceRecordChangeset {
c.upserts = append(c.upserts, rrset)
return c
}
func (c *ResourceRecordChangeset) Apply() error {
zoneID := c.zone.impl.ID
for _, removal := range c.removals {
rrID, err := c.nameToID(removal.Name())
if err != nil {
}
err = recordsets.Delete(c.zone.zones.iface.sc, zoneID, rrID).ExtractErr()
if err != nil {
}
}
for _, addition := range c.additions {
opts := recordsets.CreateOpts{
Name: addition.Name(),
TTL: int(addition.Ttl()),
Type: string(addition.Type()),
Records: addition.Rrdatas(),
}
_, err := recordsets.Create(c.zone.zones.iface.sc, zoneID, opts).Extract()
if err != nil {
}
}
for _, upsert := range c.upserts {
rrID, err := c.nameToID(upsert.Name())
if err != nil {
}
uopts := recordsets.UpdateOpts{
TTL: int(upsert.Ttl()),
Records: upsert.Rrdatas(),
}
_, err = recordsets.Update(c.zone.zones.iface.sc, zoneID, rrID, uopts).Extract()
if err != nil {
copts := recordsets.CreateOpts{
Name: upsert.Name(),
TTL: int(upsert.Ttl()),
Type: string(upsert.Type()),
Records: upsert.Rrdatas(),
}
_, err := recordsets.Create(c.zone.zones.iface.sc, zoneID, copts).Extract()
if err != nil {
}
}
}
return nil
}
func (c *ResourceRecordChangeset) IsEmpty() bool {
return len(c.removals) == 0 && len(c.additions) == 0 && len(c.upserts) == 0
}
// ResourceRecordSets returns the parent ResourceRecordSets
func (c *ResourceRecordChangeset) ResourceRecordSets() dnsprovider.ResourceRecordSets {
return c.rrsets
}
func (c *ResourceRecordChangeset) nameToID(name string) (string, error) {
opts := recordsets.ListOpts{
Name: name,
}
allPages, err := recordsets.ListByZone(c.zone.zones.iface.sc, c.zone.impl.ID, opts).AllPages()
if err != nil {
}
rrs, err := recordsets.ExtractRecordSets(allPages)
if err != nil {
}
switch len(rrs) {
case 0:
return "", fmt.Errorf("couldn't find recordset with name: %s, expected 1", name)
case 1:
return rrs[0].ID, nil
default:
return "", fmt.Errorf("found multiple recordsets with name: %s, expected 1", name)
}
}

View File

@ -0,0 +1,47 @@
/*
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 designate
import (
"k8s.io/kops/dnsprovider/pkg/dnsprovider"
"k8s.io/kops/dnsprovider/pkg/dnsprovider/rrstype"
"github.com/gophercloud/gophercloud/openstack/dns/v2/recordsets"
)
var _ dnsprovider.ResourceRecordSet = ResourceRecordSet{}
type ResourceRecordSet struct {
impl *recordsets.RecordSet
rrsets *ResourceRecordSets
}
func (rrset ResourceRecordSet) Name() string {
return rrset.impl.Name
}
func (rrset ResourceRecordSet) Rrdatas() []string {
return rrset.impl.Records
}
func (rrset ResourceRecordSet) Ttl() int64 {
return int64(rrset.impl.TTL)
}
func (rrset ResourceRecordSet) Type() rrstype.RrsType {
return rrstype.RrsType(rrset.impl.Type)
}

View File

@ -0,0 +1,99 @@
/*
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 designate
import (
"github.com/gophercloud/gophercloud/openstack/dns/v2/recordsets"
"github.com/gophercloud/gophercloud/pagination"
"k8s.io/kops/dnsprovider/pkg/dnsprovider"
"k8s.io/kops/dnsprovider/pkg/dnsprovider/rrstype"
)
var _ dnsprovider.ResourceRecordSets = ResourceRecordSets{}
type ResourceRecordSets struct {
zone *Zone
}
func (rrsets ResourceRecordSets) List() ([]dnsprovider.ResourceRecordSet, error) {
var list []dnsprovider.ResourceRecordSet
err := recordsets.ListByZone(rrsets.zone.zones.iface.sc, rrsets.zone.impl.ID, nil).EachPage(func(page pagination.Page) (bool, error) {
rrs, err := recordsets.ExtractRecordSets(page)
if err != nil {
return false, err
}
for _, rr := range rrs {
list = append(list, &ResourceRecordSet{&rr, &rrsets})
}
return true, nil
})
return list, err
}
func (rrsets ResourceRecordSets) Get(name string) ([]dnsprovider.ResourceRecordSet, error) {
// This list implementation is very similar to the one implemented in
// the List() method above, but it restricts the retrieved list to
// the records whose name match the given `name`.
opts := &recordsets.ListOpts{
Name: name,
}
var list []dnsprovider.ResourceRecordSet
err := recordsets.ListByZone(rrsets.zone.zones.iface.sc, rrsets.zone.impl.ID, opts).EachPage(func(page pagination.Page) (bool, error) {
rrs, err := recordsets.ExtractRecordSets(page)
if err != nil {
return false, err
}
for _, rr := range rrs {
list = append(list, &ResourceRecordSet{&rr, &rrsets})
}
return true, nil
})
if err != nil {
return nil, err
}
return list, nil
}
func (rrsets ResourceRecordSets) StartChangeset() dnsprovider.ResourceRecordChangeset {
return &ResourceRecordChangeset{
zone: rrsets.zone,
rrsets: &rrsets,
}
}
func (rrsets ResourceRecordSets) New(name string, rrdatas []string, ttl int64, rrstype rrstype.RrsType) dnsprovider.ResourceRecordSet {
rrs := &recordsets.RecordSet{
Name: name,
Type: string(rrstype),
TTL: int(ttl),
}
for _, rrdata := range rrdatas {
rrs.Records = append(rrs.Records, string(rrdata))
}
return ResourceRecordSet{
rrs,
&rrsets,
}
}
// Zone returns the parent zone
func (rrset ResourceRecordSets) Zone() dnsprovider.Zone {
return rrset.zone
}

View File

@ -0,0 +1,42 @@
/*
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 designate
import (
"k8s.io/kops/dnsprovider/pkg/dnsprovider"
"github.com/gophercloud/gophercloud/openstack/dns/v2/zones"
)
var _ dnsprovider.Zone = &Zone{}
type Zone struct {
impl zones.Zone
zones *Zones
}
func (z *Zone) Name() string {
return z.impl.Name
}
func (z *Zone) ID() string {
return z.impl.ID
}
func (z *Zone) ResourceRecordSets() (dnsprovider.ResourceRecordSets, bool) {
return &ResourceRecordSets{z}, true
}

View File

@ -0,0 +1,72 @@
/*
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 designate
import (
"github.com/gophercloud/gophercloud/openstack/dns/v2/zones"
"k8s.io/kops/dnsprovider/pkg/dnsprovider"
)
var _ dnsprovider.Zones = Zones{}
type Zones struct {
iface *Interface
}
func (kzs Zones) List() ([]dnsprovider.Zone, error) {
var zoneList []dnsprovider.Zone
allPages, err := zones.List(kzs.iface.sc, nil).AllPages()
if err != nil {
return zoneList, err
}
zs, err := zones.ExtractZones(allPages)
if err != nil {
return zoneList, err
}
for _, z := range zs {
kz := &Zone{
impl: z,
zones: &kzs,
}
zoneList = append(zoneList, kz)
}
return zoneList, nil
}
func (kzs Zones) Add(zone dnsprovider.Zone) (dnsprovider.Zone, error) {
opts := &zones.CreateOpts{Name: zone.Name()}
z, err := zones.Create(kzs.iface.sc, opts).Extract()
if err != nil {
return nil, err
}
return &Zone{
impl: *z,
zones: &kzs,
}, nil
}
func (kzs Zones) Remove(zone dnsprovider.Zone) error {
_, err := zones.Delete(kzs.iface.sc, zone.ID()).Extract()
return err
}
func (kzs Zones) New(name string) (dnsprovider.Zone, error) {
zone := zones.Zone{Name: name}
return &Zone{zone, &kzs}, nil
}