Skip to content

Commit f306b22

Browse files
committed
switch to ownedby
1 parent 2ca9055 commit f306b22

File tree

3 files changed

+506
-363
lines changed

3 files changed

+506
-363
lines changed

coredns.go

Lines changed: 65 additions & 76 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ import (
2828
"time"
2929

3030
log "github.com/sirupsen/logrus"
31+
"go.etcd.io/etcd/api/v3/mvccpb"
3132
etcdcv3 "go.etcd.io/etcd/client/v3"
3233
"sigs.k8s.io/external-dns/pkg/tlsutils"
3334

@@ -92,22 +93,19 @@ type Service struct {
9293
// Etcd key where we found this service and ignored from json un-/marshaling
9394
Key string `json:"-"`
9495

95-
// ManagedBy is used to prevent service to be added by different external-dns (only used by external-dns)
96-
ManagedBy string `json:"managedby,omitempty"`
97-
9896
// OwnedBy is used to prevent service to be added by different external-dns (only used by external-dns)
9997
OwnedBy string `json:"ownedby,omitempty"`
10098
}
10199

102100
type etcdClient struct {
103-
client *etcdcv3.Client
104-
managedBy string
105-
ignoreEmptyManagedBy bool
101+
client *etcdcv3.Client
102+
ownerID string
103+
strictlyOwned bool
106104
}
107105

108106
var _ coreDNSClient = etcdClient{}
109107

110-
// GetServices return all Service records stored in etcd stored anywhere under the given key (recursively)
108+
// GetServices GetService return all Service records stored in etcd stored anywhere under the given key (recursively)
111109
func (c etcdClient) GetServices(ctx context.Context, prefix string) ([]*Service, error) {
112110
ctx, cancel := context.WithTimeout(ctx, etcdTimeout)
113111
defer cancel()
@@ -121,32 +119,26 @@ func (c etcdClient) GetServices(ctx context.Context, prefix string) ([]*Service,
121119
var svcs []*Service
122120
bx := make(map[Service]bool)
123121
for _, n := range r.Kvs {
124-
svc := new(Service)
125-
if err := json.Unmarshal(n.Value, svc); err != nil {
126-
return nil, fmt.Errorf("%s: %w", n.Key, err)
122+
svc, err := c.unmarshalService(n)
123+
if err != nil {
124+
return nil, err
125+
}
126+
if c.strictlyOwned && svc.OwnedBy != c.ownerID {
127+
continue
127128
}
128129
b := Service{
129-
Host: svc.Host,
130-
Port: svc.Port,
131-
Priority: svc.Priority,
132-
Weight: svc.Weight,
133-
Text: svc.Text,
134-
Key: string(n.Key),
135-
ManagedBy: svc.ManagedBy,
136-
OwnedBy: svc.OwnedBy,
130+
Host: svc.Host,
131+
Port: svc.Port,
132+
Priority: svc.Priority,
133+
Weight: svc.Weight,
134+
Text: svc.Text,
135+
Key: string(n.Key),
137136
}
138137
if _, ok := bx[b]; ok {
139138
// skip the service if already added to service list.
140139
// the same service might be found in multiple etcd nodes.
141140
continue
142141
}
143-
if c.managedBy != "" {
144-
if c.ignoreEmptyManagedBy && b.ManagedBy != c.managedBy {
145-
continue
146-
} else if !c.ignoreEmptyManagedBy && b.ManagedBy != "" && b.ManagedBy != c.managedBy {
147-
continue
148-
}
149-
}
150142
bx[b] = true
151143

152144
svc.Key = string(n.Key)
@@ -155,7 +147,6 @@ func (c etcdClient) GetServices(ctx context.Context, prefix string) ([]*Service,
155147
}
156148
svcs = append(svcs, svc)
157149
}
158-
159150
return svcs, nil
160151
}
161152

@@ -164,14 +155,23 @@ func (c etcdClient) SaveService(ctx context.Context, service *Service) error {
164155
ctx, cancel := context.WithTimeout(ctx, etcdTimeout)
165156
defer cancel()
166157

167-
if c.managedBy != "" {
168-
service.ManagedBy = c.managedBy
169-
service.OwnedBy = c.managedBy
170-
}
171-
if ownedBy, err := c.IsOwnedBy(ctx, service.Key); err != nil {
172-
return err
173-
} else if !ownedBy {
174-
return fmt.Errorf("key %q is not owned by this service", service.Key)
158+
// check only for empty OwnedBy
159+
if c.strictlyOwned && service.OwnedBy != c.ownerID {
160+
r, err := c.client.Get(ctx, service.Key)
161+
if err != nil {
162+
return fmt.Errorf("etcd get %q: %w", service.Key, err)
163+
}
164+
// Key missing -> treat as owned (safe to create)
165+
if r != nil && len(r.Kvs) != 0 {
166+
svc, err := c.unmarshalService(r.Kvs[0])
167+
if err != nil {
168+
return fmt.Errorf("failed to unmarshal value for key %q: %w", service.Key, err)
169+
}
170+
if svc.OwnedBy != c.ownerID {
171+
return fmt.Errorf("key %q is not owned by this provider", service.Key)
172+
}
173+
}
174+
service.OwnedBy = c.ownerID
175175
}
176176

177177
value, err := json.Marshal(&service)
@@ -185,54 +185,43 @@ func (c etcdClient) SaveService(ctx context.Context, service *Service) error {
185185
return nil
186186
}
187187

188-
func (c etcdClient) IsOwnedBy(ctx context.Context, key string) (bool, error) {
188+
// DeleteService deletes service record from etcd
189+
func (c etcdClient) DeleteService(ctx context.Context, key string) error {
189190
ctx, cancel := context.WithTimeout(ctx, etcdTimeout)
190191
defer cancel()
191192

192-
if c.managedBy == "" {
193-
return true, nil
194-
}
195-
196-
r, err := c.client.Get(ctx, key)
197-
if err != nil {
198-
return false, err
199-
}
200-
if r == nil {
201-
return true, nil
202-
} else if len(r.Kvs) > 1 {
203-
return false, fmt.Errorf("found multiple keys with the same key this service")
204-
} else if len(r.Kvs) == 0 {
205-
return true, nil
206-
}
207-
for _, n := range r.Kvs {
208-
svc := new(Service)
209-
if err := json.Unmarshal(n.Value, svc); err != nil {
210-
return false, fmt.Errorf("%s: %w", n.Key, err)
193+
if c.strictlyOwned {
194+
rs, err := c.client.Get(ctx, key, etcdcv3.WithPrefix())
195+
if err != nil {
196+
return err
211197
}
198+
for _, r := range rs.Kvs {
199+
svc, err := c.unmarshalService(r)
200+
if err != nil {
201+
return err
202+
}
203+
if svc.OwnedBy != c.ownerID {
204+
continue
205+
}
212206

213-
if !c.ignoreEmptyManagedBy && svc.ManagedBy == "" {
214-
return true, nil
215-
}
216-
if svc.ManagedBy == c.managedBy {
217-
return true, nil
207+
_, err = c.client.Delete(ctx, string(r.Key))
208+
if err != nil {
209+
return err
210+
}
218211
}
212+
return err
213+
} else {
214+
_, err := c.client.Delete(ctx, key, etcdcv3.WithPrefix())
215+
return err
219216
}
220-
return false, nil
221217
}
222218

223-
// DeleteService deletes service record from etcd
224-
func (c etcdClient) DeleteService(ctx context.Context, key string) error {
225-
ctx, cancel := context.WithTimeout(ctx, etcdTimeout)
226-
defer cancel()
227-
228-
if owned, err := c.IsOwnedBy(ctx, key); err != nil {
229-
return err
230-
} else if !owned {
231-
return fmt.Errorf("key %q is not owned by this service", key)
219+
func (c etcdClient) unmarshalService(n *mvccpb.KeyValue) (*Service, error) {
220+
svc := new(Service)
221+
if err := json.Unmarshal(n.Value, svc); err != nil {
222+
return nil, fmt.Errorf("failed to unmarshal %q: %w", n.Key, err)
232223
}
233-
234-
_, err := c.client.Delete(ctx, key, etcdcv3.WithPrefix())
235-
return err
224+
return svc, nil
236225
}
237226

238227
// builds etcd client config depending on connection scheme and TLS parameters
@@ -265,7 +254,7 @@ func getETCDConfig() (*etcdcv3.Config, error) {
265254
}
266255

267256
// the newETCDClient is an etcd client constructor
268-
func newETCDClient(managedBy string, ignoreEmptyManagedBy bool) (coreDNSClient, error) {
257+
func newETCDClient(ownerID string, strictlyOwned bool) (coreDNSClient, error) {
269258
cfg, err := getETCDConfig()
270259
if err != nil {
271260
return nil, err
@@ -274,12 +263,12 @@ func newETCDClient(managedBy string, ignoreEmptyManagedBy bool) (coreDNSClient,
274263
if err != nil {
275264
return nil, err
276265
}
277-
return etcdClient{c, managedBy, ignoreEmptyManagedBy}, nil
266+
return etcdClient{c, ownerID, strictlyOwned}, nil
278267
}
279268

280269
// NewCoreDNSProvider is a CoreDNS provider constructor
281-
func NewCoreDNSProvider(config CoreDNSConfig, managedBy string, ignoreEmptyManagedBy, dryRun bool) (provider.Provider, error) {
282-
client, err := newETCDClient(managedBy, ignoreEmptyManagedBy)
270+
func NewCoreDNSProvider(config CoreDNSConfig, ownerID string, strictlyOwned, dryRun bool) (provider.Provider, error) {
271+
client, err := newETCDClient(ownerID, strictlyOwned)
283272
if err != nil {
284273
return nil, err
285274
}

0 commit comments

Comments
 (0)