Merge pull request #36336 from justinsb/federation_dns_hosted_zone_2

Automatic merge from submit-queue

Federation: allow specification of dns zone by ID
This commit is contained in:
Kubernetes Submit Queue 2016-11-17 00:49:09 -08:00 committed by GitHub
commit 47a431e82f
5 changed files with 60 additions and 13 deletions

View File

@ -190,7 +190,7 @@ func StartControllers(s *options.CMServer, restClientCfg *restclient.Config) err
glog.Infof("Loading client config for service controller %q", servicecontroller.UserAgentName) glog.Infof("Loading client config for service controller %q", servicecontroller.UserAgentName)
scClientset := federationclientset.NewForConfigOrDie(restclient.AddUserAgent(restClientCfg, servicecontroller.UserAgentName)) scClientset := federationclientset.NewForConfigOrDie(restclient.AddUserAgent(restClientCfg, servicecontroller.UserAgentName))
servicecontroller := servicecontroller.New(scClientset, dns, s.FederationName, s.ServiceDnsSuffix, s.ZoneName) servicecontroller := servicecontroller.New(scClientset, dns, s.FederationName, s.ServiceDnsSuffix, s.ZoneName, s.ZoneID)
glog.Infof("Running service controller") glog.Infof("Running service controller")
if err := servicecontroller.Run(s.ConcurrentServiceSyncs, wait.NeverStop); err != nil { if err := servicecontroller.Run(s.ConcurrentServiceSyncs, wait.NeverStop); err != nil {
glog.Errorf("Failed to start service controller: %v", err) glog.Errorf("Failed to start service controller: %v", err)

View File

@ -39,6 +39,8 @@ type ControllerManagerConfiguration struct {
FederationName string `json:"federationName"` FederationName string `json:"federationName"`
// zone name, like example.com. // zone name, like example.com.
ZoneName string `json:"zoneName"` ZoneName string `json:"zoneName"`
// zone ID, for use when zoneName is ambiguous.
ZoneID string `json:"zoneID"`
// ServiceDnsSuffix is the dns suffix to use when publishing federated services. // ServiceDnsSuffix is the dns suffix to use when publishing federated services.
ServiceDnsSuffix string `json:"serviceDnsSuffix"` ServiceDnsSuffix string `json:"serviceDnsSuffix"`
// dnsProvider is the provider for dns services. // dnsProvider is the provider for dns services.
@ -103,6 +105,7 @@ func (s *CMServer) AddFlags(fs *pflag.FlagSet) {
fs.Var(componentconfig.IPVar{Val: &s.Address}, "address", "The IP address to serve on (set to 0.0.0.0 for all interfaces)") fs.Var(componentconfig.IPVar{Val: &s.Address}, "address", "The IP address to serve on (set to 0.0.0.0 for all interfaces)")
fs.StringVar(&s.FederationName, "federation-name", s.FederationName, "Federation name.") fs.StringVar(&s.FederationName, "federation-name", s.FederationName, "Federation name.")
fs.StringVar(&s.ZoneName, "zone-name", s.ZoneName, "Zone name, like example.com.") fs.StringVar(&s.ZoneName, "zone-name", s.ZoneName, "Zone name, like example.com.")
fs.StringVar(&s.ZoneID, "zone-id", s.ZoneID, "Zone ID, needed if the zone name is not unique.")
fs.StringVar(&s.ServiceDnsSuffix, "service-dns-suffix", s.ServiceDnsSuffix, "DNS Suffix to use when publishing federated service names. Defaults to zone-name") fs.StringVar(&s.ServiceDnsSuffix, "service-dns-suffix", s.ServiceDnsSuffix, "DNS Suffix to use when publishing federated service names. Defaults to zone-name")
fs.IntVar(&s.ConcurrentServiceSyncs, "concurrent-service-syncs", s.ConcurrentServiceSyncs, "The number of service syncing operations that will be done concurrently. Larger number = faster endpoint updating, but more CPU (and network) load") fs.IntVar(&s.ConcurrentServiceSyncs, "concurrent-service-syncs", s.ConcurrentServiceSyncs, "The number of service syncing operations that will be done concurrently. Larger number = faster endpoint updating, but more CPU (and network) load")
fs.IntVar(&s.ConcurrentReplicaSetSyncs, "concurrent-replicaset-syncs", s.ConcurrentReplicaSetSyncs, "The number of ReplicaSets syncing operations that will be done concurrently. Larger number = faster endpoint updating, but more CPU (and network) load") fs.IntVar(&s.ConcurrentReplicaSetSyncs, "concurrent-replicaset-syncs", s.ConcurrentReplicaSetSyncs, "The number of ReplicaSets syncing operations that will be done concurrently. Larger number = faster endpoint updating, but more CPU (and network) load")

View File

@ -95,24 +95,55 @@ func (s *ServiceController) getServiceDnsSuffix() (string, error) {
return s.serviceDnsSuffix, nil return s.serviceDnsSuffix, nil
} }
// getDnsZone returns the zone, as identified by zoneName // getDnsZones returns the DNS zones matching dnsZoneName and dnsZoneID (if specified)
func getDnsZone(dnsZoneName string, dnsZonesInterface dnsprovider.Zones) (dnsprovider.Zone, error) { func getDnsZones(dnsZoneName string, dnsZoneID string, dnsZonesInterface dnsprovider.Zones) ([]dnsprovider.Zone, error) {
// TODO: We need query-by-name and query-by-id functions // TODO: We need query-by-name and query-by-id functions
dnsZones, err := dnsZonesInterface.List() dnsZones, err := dnsZonesInterface.List()
if err != nil { if err != nil {
return nil, err return nil, err
} }
var matches []dnsprovider.Zone
findName := strings.TrimSuffix(dnsZoneName, ".") findName := strings.TrimSuffix(dnsZoneName, ".")
for _, dnsZone := range dnsZones { for _, dnsZone := range dnsZones {
if findName != "" { if dnsZoneID != "" {
if strings.TrimSuffix(dnsZone.Name(), ".") == findName { if dnsZoneID != dnsZone.ID() {
return dnsZone, nil continue
} }
} }
if findName != "" {
if strings.TrimSuffix(dnsZone.Name(), ".") != findName {
continue
}
}
matches = append(matches, dnsZone)
} }
return nil, fmt.Errorf("DNS zone %s not found.", dnsZoneName) return matches, nil
}
// getDnsZone returns the DNS zone, as identified by dnsZoneName and dnsZoneID
// This is similar to getDnsZones, but returns an error if there are zero or multiple matching zones.
func getDnsZone(dnsZoneName string, dnsZoneID string, dnsZonesInterface dnsprovider.Zones) (dnsprovider.Zone, error) {
dnsZones, err := getDnsZones(dnsZoneName, dnsZoneID, dnsZonesInterface)
if err != nil {
return nil, err
}
if len(dnsZones) == 1 {
return dnsZones[0], nil
}
name := dnsZoneName
if dnsZoneID != "" {
name += "/" + dnsZoneID
}
if len(dnsZones) == 0 {
return nil, fmt.Errorf("DNS zone %s not found.", name)
} else {
return nil, fmt.Errorf("DNS zone %s is ambiguous (please specify zoneID).", name)
}
} }
/* getRrset is a hack around the fact that dnsprovider.ResourceRecordSets interface does not yet include a Get() method, only a List() method. TODO: Fix that. /* getRrset is a hack around the fact that dnsprovider.ResourceRecordSets interface does not yet include a Get() method, only a List() method. TODO: Fix that.
@ -320,7 +351,7 @@ func (s *ServiceController) ensureDnsRecords(clusterName string, cachedService *
endpoints := [][]string{zoneEndpoints, regionEndpoints, globalEndpoints} endpoints := [][]string{zoneEndpoints, regionEndpoints, globalEndpoints}
dnsZone, err := getDnsZone(s.zoneName, s.dnsZones) dnsZone, err := getDnsZone(s.zoneName, s.zoneID, s.dnsZones)
if err != nil { if err != nil {
return err return err
} }

View File

@ -105,8 +105,9 @@ type ServiceController struct {
federationName string federationName string
// serviceDnsSuffix is the DNS suffix we use when publishing service DNS names // serviceDnsSuffix is the DNS suffix we use when publishing service DNS names
serviceDnsSuffix string serviceDnsSuffix string
// zoneName is used to identify the zone in which to put records // zoneName and zoneID are used to identify the zone in which to put records
zoneName string zoneName string
zoneID string
// each federation should be configured with a single zone (e.g. "mycompany.com") // each federation should be configured with a single zone (e.g. "mycompany.com")
dnsZones dnsprovider.Zones dnsZones dnsprovider.Zones
serviceCache *serviceCache serviceCache *serviceCache
@ -140,7 +141,7 @@ type ServiceController struct {
// (like Kubernetes Services and DNS server records for service discovery) in sync with the registry. // (like Kubernetes Services and DNS server records for service discovery) in sync with the registry.
func New(federationClient fedclientset.Interface, dns dnsprovider.Interface, func New(federationClient fedclientset.Interface, dns dnsprovider.Interface,
federationName, serviceDnsSuffix, zoneName string) *ServiceController { federationName, serviceDnsSuffix, zoneName string, zoneID string) *ServiceController {
broadcaster := record.NewBroadcaster() broadcaster := record.NewBroadcaster()
// federationClient event is not supported yet // federationClient event is not supported yet
// broadcaster.StartRecordingToSink(&unversioned_core.EventSinkImpl{Interface: kubeClient.Core().Events("")}) // broadcaster.StartRecordingToSink(&unversioned_core.EventSinkImpl{Interface: kubeClient.Core().Events("")})
@ -152,6 +153,7 @@ func New(federationClient fedclientset.Interface, dns dnsprovider.Interface,
federationName: federationName, federationName: federationName,
serviceDnsSuffix: serviceDnsSuffix, serviceDnsSuffix: serviceDnsSuffix,
zoneName: zoneName, zoneName: zoneName,
zoneID: zoneID,
serviceCache: &serviceCache{fedServiceMap: make(map[string]*cachedService)}, serviceCache: &serviceCache{fedServiceMap: make(map[string]*cachedService)},
clusterCache: &clusterClientCache{ clusterCache: &clusterClientCache{
rwlock: sync.Mutex{}, rwlock: sync.Mutex{},
@ -279,8 +281,8 @@ func (s *ServiceController) init() error {
if s.federationName == "" { if s.federationName == "" {
return fmt.Errorf("ServiceController should not be run without federationName.") return fmt.Errorf("ServiceController should not be run without federationName.")
} }
if s.zoneName == "" { if s.zoneName == "" && s.zoneID == "" {
return fmt.Errorf("ServiceController should not be run without zoneName.") return fmt.Errorf("ServiceController must be run with either zoneName or zoneID.")
} }
if s.serviceDnsSuffix == "" { if s.serviceDnsSuffix == "" {
// TODO: Is this the right place to do defaulting? // TODO: Is this the right place to do defaulting?
@ -297,7 +299,14 @@ func (s *ServiceController) init() error {
return fmt.Errorf("the dns provider does not support zone enumeration, which is required for creating dns records.") return fmt.Errorf("the dns provider does not support zone enumeration, which is required for creating dns records.")
} }
s.dnsZones = zones s.dnsZones = zones
if _, err := getDnsZone(s.zoneName, s.dnsZones); err != nil { matchingZones, err := getDnsZones(s.zoneName, s.zoneID, s.dnsZones)
if err != nil {
return fmt.Errorf("error querying for DNS zones: %v", err)
}
if len(matchingZones) == 0 {
if s.zoneName == "" {
return fmt.Errorf("ServiceController must be run with zoneName to create zone automatically.")
}
glog.Infof("DNS zone %q not found. Creating DNS zone %q.", s.zoneName, s.zoneName) glog.Infof("DNS zone %q not found. Creating DNS zone %q.", s.zoneName, s.zoneName)
managedZone, err := s.dnsZones.New(s.zoneName) managedZone, err := s.dnsZones.New(s.zoneName)
if err != nil { if err != nil {
@ -310,6 +319,9 @@ func (s *ServiceController) init() error {
glog.Infof("DNS zone %q successfully created. Note that DNS resolution will not work until you have registered this name with "+ glog.Infof("DNS zone %q successfully created. Note that DNS resolution will not work until you have registered this name with "+
"a DNS registrar and they have changed the authoritative name servers for your domain to point to your DNS provider.", zone.Name()) "a DNS registrar and they have changed the authoritative name servers for your domain to point to your DNS provider.", zone.Name())
} }
if len(matchingZones) > 1 {
return fmt.Errorf("Multiple matching DNS zones found for %q; please specify zoneID", s.zoneName)
}
return nil return nil
} }

View File

@ -595,6 +595,7 @@ watch-only
whitelist-override-label whitelist-override-label
windows-line-endings windows-line-endings
www-prefix www-prefix
zone-id
zone-name zone-name
garbage-collector-enabled garbage-collector-enabled
viper-config viper-config