Skip to content

Commit

Permalink
Merge pull request #19 from inovex/cloudsYAML
Browse files Browse the repository at this point in the history
feat: switch to config via clouds.yaml to allow e.g. application-credentials
  • Loading branch information
maxbischoff authored Jan 13, 2025
2 parents fb1015d + 6b9bad8 commit e1536ac
Show file tree
Hide file tree
Showing 5 changed files with 35 additions and 79 deletions.
9 changes: 3 additions & 6 deletions .github/workflows/devstack.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,9 @@ name: devstack
on:
pull_request:

env:
OS_CLOUD: devstack-admin-demo

jobs:
external-dns-source-fake:
runs-on: ubuntu-22.04
Expand Down Expand Up @@ -74,17 +77,14 @@ jobs:

- name: Create zones example.com
run: |
source ./devstack/openrc
openstack zone create --email [email protected] example.com.
- name: Wait for zone creation
run: |
source ./devstack/openrc
while [ "$(openstack zone list -f csv | grep PENDING)" != "" ]; do date; openstack zone list -f value; sleep 1; done
- name: Start external-dns-openstack-webhook in background
run: |
source ./devstack/openrc
./build/bin/external-dns-openstack-webhook >/tmp/external-dns-openstack-webhook.log 2>&1 &
- name: Run external-dns
Expand All @@ -96,19 +96,16 @@ jobs:

- name: Wait for PENDING
run: |
source ./devstack/openrc
while [ "$(openstack zone list -f csv | grep PENDING)" != "" ]; do date; openstack zone list -f value; sleep 1; done
- name: Show created entries
run: |
source ./devstack/openrc
echo "Zones:"
openstack zone list -f value
echo "Recordsets:"
openstack recordset list all -f value
- name: Check created entries
run: |
source ./devstack/openrc
if [ $(openstack recordset list all -f value | grep -c " TXT ") -ne 20 ]; then exit 1; fi
if [ $(openstack recordset list all -f value | grep -c " A ") -ne 10 ]; then exit 2; fi
1 change: 1 addition & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ require (
golang.org/x/text v0.21.0 // indirect
google.golang.org/protobuf v1.35.2 // indirect
gopkg.in/inf.v0 v0.9.1 // indirect
gopkg.in/yaml.v2 v2.4.0 // indirect
k8s.io/apimachinery v0.32.0 // indirect
k8s.io/klog/v2 v2.130.1 // indirect
k8s.io/utils v0.0.0-20241104100929-3ea5e8cea738 // indirect
Expand Down
2 changes: 2 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,8 @@ gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntN
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=
gopkg.in/inf.v0 v0.9.1 h1:73M5CoZyi3ZLMOyDlQh031Cx6N9NDJ2Vvfl76EDAgDc=
gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw=
gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=
gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
Expand Down
77 changes: 9 additions & 68 deletions internal/designate/client/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,19 +19,15 @@ package client

import (
"context"
"net"
"net/http"
"os"
"time"

"github.com/gophercloud/gophercloud/v2"
"github.com/gophercloud/gophercloud/v2/openstack"
"github.com/gophercloud/gophercloud/v2/openstack/config"
"github.com/gophercloud/gophercloud/v2/openstack/config/clouds"
"github.com/gophercloud/gophercloud/v2/openstack/dns/v2/recordsets"
"github.com/gophercloud/gophercloud/v2/openstack/dns/v2/zones"
"github.com/gophercloud/gophercloud/v2/pagination"
log "github.com/sirupsen/logrus"

"sigs.k8s.io/external-dns/pkg/tlsutils"
)

// interface between provider and OpenStack DNS API
Expand Down Expand Up @@ -66,81 +62,26 @@ func NewDesignateClient() (DesignateClientInterface, error) {
return &designateClient{serviceClient}, nil
}

// copies environment variables to new names without overwriting existing values
func remapEnv(mapping map[string]string) {
for k, v := range mapping {
currentVal := os.Getenv(k)
newVal := os.Getenv(v)
if currentVal == "" && newVal != "" {
os.Setenv(k, newVal)
}
}
}

// returns OpenStack Keystone authentication settings by obtaining values from standard environment variables.
// also fixes incompatibilities between gophercloud implementation and *-stackrc files that can be downloaded
// from OpenStack dashboard in latest versions
func getAuthSettings() (gophercloud.AuthOptions, error) {
remapEnv(map[string]string{
"OS_TENANT_NAME": "OS_PROJECT_NAME",
"OS_TENANT_ID": "OS_PROJECT_ID",
"OS_DOMAIN_NAME": "OS_USER_DOMAIN_NAME",
"OS_DOMAIN_ID": "OS_USER_DOMAIN_ID",
})

opts, err := openstack.AuthOptionsFromEnv()
if err != nil {
return gophercloud.AuthOptions{}, err
}
opts.AllowReauth = true
return opts, nil
}

// authenticate in OpenStack and obtain Designate service endpoint
func createDesignateServiceClient() (*gophercloud.ServiceClient, error) {
opts, err := getAuthSettings()
if err != nil {
return nil, err
}
log.Infof("Using OpenStack Keystone at %s", opts.IdentityEndpoint)
authProvider, err := openstack.NewClient(opts.IdentityEndpoint)
if err != nil {
return nil, err
}
ctx := context.Background()

tlsConfig, err := tlsutils.CreateTLSConfig("OPENSTACK")
authOptions, endpointOptions, tlsConfig, err := clouds.Parse()
if err != nil {
return nil, err
}

transport := &http.Transport{
Proxy: http.ProxyFromEnvironment,
DialContext: (&net.Dialer{
Timeout: 30 * time.Second,
KeepAlive: 30 * time.Second,
}).DialContext,
MaxIdleConns: 100,
IdleConnTimeout: 90 * time.Second,
TLSHandshakeTimeout: 10 * time.Second,
ExpectContinueTimeout: 1 * time.Second,
TLSClientConfig: tlsConfig,
}
authProvider.HTTPClient.Transport = transport

ctx := context.Background()
if err = openstack.Authenticate(ctx, authProvider, opts); err != nil {
providerClient, err := config.NewProviderClient(ctx, authOptions, config.WithTLSConfig(tlsConfig))
if err != nil {
return nil, err
}
log.Infof("Using OpenStack Keystone at %s", providerClient.IdentityEndpoint)

eo := gophercloud.EndpointOpts{
Region: os.Getenv("OS_REGION_NAME"),
}

client, err := openstack.NewDNSV2(authProvider, eo)
client, err := openstack.NewDNSV2(providerClient, endpointOptions)
if err != nil {
return nil, err
}
log.Infof("Found OpenStack Designate service at %s", client.Endpoint)
log.Infof("Found OpenStack Designate (DNS) service at %s", client.Endpoint)
return client, nil
}

Expand Down
25 changes: 20 additions & 5 deletions internal/designate/provider/provider_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -185,11 +185,26 @@ func TestNewDesignateProvider(t *testing.T) {
t.Fatal(err)
}

os.Setenv("OS_AUTH_URL", ts.URL+"/v3")
os.Setenv("OS_USERNAME", "username")
os.Setenv("OS_PASSWORD", "password")
os.Setenv("OS_USER_DOMAIN_NAME", "Default")
os.Setenv("OPENSTACK_CA_FILE", tmpfile.Name())
tmpcloudsyaml, err := os.CreateTemp("", "clouds.yaml")
if err != nil {
t.Fatal(err)
}
defer os.Remove(tmpcloudsyaml.Name())

tmpcloudsyaml.WriteString(fmt.Sprintf(`
clouds:
unittest:
auth:
auth_url: %s/v3
application_credential_id: fakefake
application_credential_secret: fakefake
region_name: RegionOne
interface: public
auth_type: v3applicationcredential`, ts.URL))

os.Setenv("OS_CLIENT_CONFIG_FILE", tmpcloudsyaml.Name())
os.Setenv("OS_CLOUD", "unittest")
os.Setenv("OS_CACERT", tmpfile.Name())

if _, err := NewDesignateProvider(endpoint.DomainFilter{}, true); err != nil {
t.Fatalf("Failed to initialize Designate provider: %s", err)
Expand Down

0 comments on commit e1536ac

Please sign in to comment.