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

Move DNS records from base_domain to cluster_domain #1169

Merged
merged 6 commits into from
Feb 16, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 5 additions & 3 deletions data/data/aws/main.tf
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
locals {
private_zone_id = "${aws_route53_zone.int.zone_id}"

cluster_domain = "${var.cluster_name}.${var.base_domain}"

tags = "${merge(map(
"openshiftClusterID", "${var.cluster_id}"
), var.aws_extra_tags)}"
Expand Down Expand Up @@ -92,20 +94,20 @@ resource "aws_route53_record" "etcd_a_nodes" {
type = "A"
ttl = "60"
zone_id = "${local.private_zone_id}"
name = "${var.cluster_name}-etcd-${count.index}"
name = "etcd-${count.index}.${local.cluster_domain}"
records = ["${module.masters.ip_addresses[count.index]}"]
}

resource "aws_route53_record" "etcd_cluster" {
type = "SRV"
ttl = "60"
zone_id = "${local.private_zone_id}"
name = "_etcd-server-ssl._tcp.${var.cluster_name}"
name = "_etcd-server-ssl._tcp"
records = ["${formatlist("0 10 2380 %s", aws_route53_record.etcd_a_nodes.*.fqdn)}"]
}

resource "aws_route53_zone" "int" {
name = "${var.base_domain}"
name = "${local.cluster_domain}"
force_destroy = true

vpc {
Expand Down
6 changes: 4 additions & 2 deletions data/data/aws/route53/base.tf
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,13 @@ locals {
public_zone_id = "${data.aws_route53_zone.base.zone_id}"

zone_id = "${var.private_zone_id}"

cluster_domain = "${var.cluster_name}.${var.base_domain}"
Copy link
Member

Choose a reason for hiding this comment

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

This package could be adjusted to take the unsplit cluster domain if we replaced this with Go logic to snip subdomains off the full cluster name until we found a public zone. Or we could restructure the install-config to make the public zone's domain part of the AWS-specific platform configuration. Both of those are probably more work than we want to sink into initial exploration, but I thought I'd file a note to track future polish possibilities ;).

}

resource "aws_route53_record" "api_external" {
zone_id = "${local.public_zone_id}"
name = "${var.cluster_name}-api.${var.base_domain}"
name = "api.${local.cluster_domain}"
type = "A"

alias {
Expand All @@ -22,7 +24,7 @@ resource "aws_route53_record" "api_external" {

resource "aws_route53_record" "api_internal" {
zone_id = "${var.private_zone_id}"
name = "${var.cluster_name}-api.${var.base_domain}"
name = "api.${local.cluster_domain}"
type = "A"

alias {
Expand Down
4 changes: 3 additions & 1 deletion data/data/aws/vpc/vpc.tf
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
locals {
new_private_cidr_range = "${cidrsubnet(data.aws_vpc.cluster_vpc.cidr_block,1,1)}"
new_public_cidr_range = "${cidrsubnet(data.aws_vpc.cluster_vpc.cidr_block,1,0)}"

cluster_domain = "${var.cluster_name}.${var.base_domain}"
Copy link
Member

Choose a reason for hiding this comment

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

This module could be adjusted to take the unsplit cluster domain and use it where it currently uses var.cluster_name in tag values and resource names. That would address #762, although we might have to use the length-limited cluster ID for the load-balancer names or somehow introduce uniqueness there. I've just filed #1170 making cluster-names in metadata.json libvirt-specific, so this resource naming is the last #762 blocker.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

#762 @blrm was looking at finding the resources that would conflict if we try to use same cluster name for same base domain. I remember him mentioning that it was more than this module.

@blrm do you have some notes/finding that can provide more details on what might collide in #762 😇

Copy link
Member

Choose a reason for hiding this comment

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

@blrm was looking at finding the resources that would conflict if we try to use same cluster name for same base domain.

I'd guess:

$ git describe
unreleased-master-177-g4907cba
$ git grep ' name *= .*cluster_name' data/data/aws | cat
data/data/aws/bootstrap/main.tf:  name = "${var.cluster_name}-bootstrap-profile"
data/data/aws/bootstrap/main.tf:  name  = "${var.cluster_name}-bootstrap-role"
data/data/aws/bootstrap/main.tf:  name  = "${var.cluster_name}-bootstrap-policy"
data/data/aws/iam/main.tf:  name = "${var.cluster_name}-worker-profile"
data/data/aws/iam/main.tf:  name  = "${var.cluster_name}-worker-role"
data/data/aws/iam/main.tf:  name  = "${var.cluster_name}_worker_policy"
data/data/aws/main.tf:  name    = "${var.cluster_name}-etcd-${count.index}"
data/data/aws/main.tf:  name    = "_etcd-server-ssl._tcp.${var.cluster_name}"
data/data/aws/master/main.tf:  name = "${var.cluster_name}-master-profile"
data/data/aws/master/main.tf:  name  = "${var.cluster_name}-master-role"
data/data/aws/master/main.tf:  name  = "${var.cluster_name}_master_policy"
data/data/aws/route53/base.tf:  name    = "${var.cluster_name}-api.${var.base_domain}"
data/data/aws/route53/base.tf:  name    = "${var.cluster_name}-api.${var.base_domain}"
data/data/aws/vpc/master-elb.tf:  name                             = "${var.cluster_name}-int"
data/data/aws/vpc/master-elb.tf:  name                             = "${var.cluster_name}-ext"
data/data/aws/vpc/master-elb.tf:  name     = "${var.cluster_name}-api-int"
data/data/aws/vpc/master-elb.tf:  name     = "${var.cluster_name}-api-ext"
data/data/aws/vpc/master-elb.tf:  name     = "${var.cluster_name}-services"

but I don't see a problem with removing those in stages.

}

resource "aws_vpc" "new_vpc" {
Expand All @@ -9,7 +11,7 @@ resource "aws_vpc" "new_vpc" {
enable_dns_support = true

tags = "${merge(map(
"Name", "${var.cluster_name}.${var.base_domain}",
"Name", "${local.cluster_domain}",
), var.tags)}"
}

Expand Down
16 changes: 10 additions & 6 deletions data/data/libvirt/main.tf
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
locals {
cluster_domain = "${var.cluster_name}.${var.base_domain}"
}

provider "libvirt" {
uri = "${var.libvirt_uri}"
}
Expand Down Expand Up @@ -36,7 +40,7 @@ resource "libvirt_network" "net" {
mode = "nat"
bridge = "${var.libvirt_network_if}"

domain = "${var.base_domain}"
domain = "${local.cluster_domain}"

addresses = [
"${var.machine_cidr}",
Expand Down Expand Up @@ -92,27 +96,27 @@ resource "libvirt_domain" "master" {
data "libvirt_network_dns_host_template" "bootstrap" {
count = "${var.bootstrap_dns ? 1 : 0}"
ip = "${var.libvirt_bootstrap_ip}"
hostname = "${var.cluster_name}-api"
hostname = "api.${local.cluster_domain}"
}

data "libvirt_network_dns_host_template" "masters" {
count = "${var.master_count}"
ip = "${var.libvirt_master_ips[count.index]}"
hostname = "${var.cluster_name}-api"
hostname = "api.${local.cluster_domain}"
}

data "libvirt_network_dns_host_template" "etcds" {
count = "${var.master_count}"
ip = "${var.libvirt_master_ips[count.index]}"
hostname = "${var.cluster_name}-etcd-${count.index}"
hostname = "etcd-${count.index}.${local.cluster_domain}"
}

data "libvirt_network_dns_srv_template" "etcd_cluster" {
count = "${var.master_count}"
service = "etcd-server-ssl"
protocol = "tcp"
domain = "${var.cluster_name}.${var.base_domain}"
domain = "${local.cluster_domain}"
port = 2380
weight = 10
target = "${var.cluster_name}-etcd-${count.index}.${var.base_domain}"
target = "etcd-${count.index}.${local.cluster_domain}"
}
6 changes: 5 additions & 1 deletion data/data/openstack/main.tf
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
locals {
cluster_domain = "${var.cluster_name}.${var.base_domain}"
}

provider "openstack" {
auth_url = "${var.openstack_credentials_auth_url}"
cert = "${var.openstack_credentials_cert}"
Expand Down Expand Up @@ -81,7 +85,7 @@ module "topology" {
}

resource "openstack_objectstorage_container_v1" "container" {
name = "${lower(var.cluster_name)}.${var.base_domain}"
name = "${local.cluster_domain}"

metadata = "${merge(map(
"Name", "${var.cluster_name}-ignition-master",
Expand Down
18 changes: 9 additions & 9 deletions data/data/openstack/service/main.tf
Original file line number Diff line number Diff line change
Expand Up @@ -134,19 +134,19 @@ data "ignition_file" "corefile" {
errors
reload 10s

${length(var.lb_floating_ip) == 0 ? "" : " file /etc/coredns/db.${var.cluster_domain} ${var.cluster_name}-api.${var.cluster_domain} {\n }\n"}
${length(var.lb_floating_ip) == 0 ? "" : " file /etc/coredns/db.${var.cluster_domain} api.${var.cluster_domain} {\n }\n"}


file /etc/coredns/db.${var.cluster_domain} _etcd-server-ssl._tcp.${var.cluster_name}.${var.cluster_domain} {
file /etc/coredns/db.${var.cluster_domain} _etcd-server-ssl._tcp.${var.cluster_domain} {
}

${replace(join("\n", formatlist(" file /etc/coredns/db.${var.cluster_domain} ${var.cluster_name}-etcd-%s.${var.cluster_domain} {\n upstream /etc/resolv.conf\n }\n", var.master_port_names)), "master-port-", "")}
${replace(join("\n", formatlist(" file /etc/coredns/db.${var.cluster_domain} etcd-%s.${var.cluster_domain} {\n upstream /etc/resolv.conf\n }\n", var.master_port_names)), "master-port-", "")}

forward . /etc/resolv.conf {
}
}

${var.cluster_name}.${var.cluster_domain} {
${var.cluster_domain} {
log
errors
reload 10s
Expand All @@ -168,20 +168,20 @@ data "ignition_file" "coredb" {
content {
content = <<EOF
$ORIGIN ${var.cluster_domain}.
@ 3600 IN SOA host-${var.cluster_name}.${var.cluster_domain}. hostmaster (
@ 3600 IN SOA host.${var.cluster_domain}. hostmaster (
2017042752 ; serial
7200 ; refresh (2 hours)
3600 ; retry (1 hour)
1209600 ; expire (2 weeks)
3600 ; minimum (1 hour)
)

${length(var.lb_floating_ip) == 0 ? "" : "${var.cluster_name}-api IN A ${var.lb_floating_ip}"}
${length(var.lb_floating_ip) == 0 ? "" : "*.apps.${var.cluster_name} IN A ${var.lb_floating_ip}"}
${length(var.lb_floating_ip) == 0 ? "" : "api IN A ${var.lb_floating_ip}"}
${length(var.lb_floating_ip) == 0 ? "" : "*.apps IN A ${var.lb_floating_ip}"}

${replace(join("\n", formatlist("${var.cluster_name}-etcd-%s IN CNAME ${var.cluster_name}-master-%s", var.master_port_names, var.master_port_names)), "master-port-", "")}
${replace(join("\n", formatlist("etcd-%s IN CNAME master-%s", var.master_port_names, var.master_port_names)), "master-port-", "")}

${replace(join("\n", formatlist("_etcd-server-ssl._tcp.${var.cluster_name} 8640 IN SRV 0 10 2380 ${var.cluster_name}-etcd-%s.${var.cluster_domain}.", var.master_port_names)), "master-port-", "")}
${replace(join("\n", formatlist("_etcd-server-ssl._tcp.${var.cluster_domain} 8640 IN SRV 0 10 2380 etcd-%s.${var.cluster_domain}.", var.master_port_names)), "master-port-", "")}
EOF
}
}
Expand Down
2 changes: 1 addition & 1 deletion data/data/openstack/service/variables.tf
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ variable "cluster_id" {

variable "cluster_domain" {
type = "string"
description = "The domain name of the cluster."
description = "The domain name of the cluster. All DNS records must be under this domain."
}

variable "ignition" {
Expand Down
2 changes: 1 addition & 1 deletion pkg/asset/ignition/bootstrap/bootstrap.go
Original file line number Diff line number Diff line change
Expand Up @@ -142,7 +142,7 @@ func (a *Bootstrap) Files() []*asset.File {
func (a *Bootstrap) getTemplateData(installConfig *types.InstallConfig) (*bootstrapTemplateData, error) {
etcdEndpoints := make([]string, *installConfig.ControlPlane.Replicas)
for i := range etcdEndpoints {
etcdEndpoints[i] = fmt.Sprintf("https://%s-etcd-%d.%s:2379", installConfig.ObjectMeta.Name, i, installConfig.BaseDomain)
etcdEndpoints[i] = fmt.Sprintf("https://etcd-%d.%s:2379", i, installConfig.ClusterDomain())
}

releaseImage := defaultReleaseImage
Expand Down
2 changes: 1 addition & 1 deletion pkg/asset/ignition/machine/node.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ func pointerIgnitionConfig(installConfig *types.InstallConfig, rootCA []byte, ro
Source: func() *url.URL {
return &url.URL{
Scheme: "https",
Host: fmt.Sprintf("%s-api.%s:22623", installConfig.ObjectMeta.Name, installConfig.BaseDomain),
Host: fmt.Sprintf("api.%s:22623", installConfig.ClusterDomain()),
Path: fmt.Sprintf("/config/%s", role),
}
}().String(),
Expand Down
2 changes: 1 addition & 1 deletion pkg/asset/kubeconfig/kubeconfig.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ func (k *kubeconfig) generate(
{
Name: installConfig.ObjectMeta.Name,
Cluster: clientcmd.Cluster{
Server: fmt.Sprintf("https://%s-api.%s:6443", installConfig.ObjectMeta.Name, installConfig.BaseDomain),
Server: fmt.Sprintf("https://api.%s:6443", installConfig.ClusterDomain()),
CertificateAuthorityData: []byte(rootCA.Cert()),
},
},
Expand Down
4 changes: 2 additions & 2 deletions pkg/asset/kubeconfig/kubeconfig_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ func TestKubeconfigGenerate(t *testing.T) {
expectedData: []byte(`clusters:
- cluster:
certificate-authority-data: VEhJUyBJUyBST09UIENBIENFUlQgREFUQQ==
server: https://test-cluster-name-api.test.example.com:6443
server: https://api.test-cluster-name.test.example.com:6443
name: test-cluster-name
contexts:
- context:
Expand All @@ -86,7 +86,7 @@ users:
expectedData: []byte(`clusters:
- cluster:
certificate-authority-data: VEhJUyBJUyBST09UIENBIENFUlQgREFUQQ==
server: https://test-cluster-name-api.test.example.com:6443
server: https://api.test-cluster-name.test.example.com:6443
name: test-cluster-name
contexts:
- context:
Expand Down
2 changes: 1 addition & 1 deletion pkg/asset/manifests/dns.go
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ func (d *DNS) Generate(dependencies asset.Parents) error {
// not namespaced
},
Spec: configv1.DNSSpec{
BaseDomain: installConfig.Config.BaseDomain,
BaseDomain: installConfig.Config.ClusterDomain(),
Copy link
Contributor

@ironcladlou ironcladlou Feb 7, 2019

Choose a reason for hiding this comment

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

Do we instead need to change DNSSpec like:

type DNSSpec struct {
  BaseDomain string `json:"baseDomain"`
  ClusterDomain string `json:"clusterDomain"`
}

Otherwise downstream consumers (e.g. the ingress operator's DNS manager) are left to guess the public zone.

Copy link
Contributor Author

@abhinavdahiya abhinavdahiya Feb 7, 2019

Choose a reason for hiding this comment

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

Do we instead need to change DNSSpec like:

type DNSSpec struct {
  BaseDomain string `json:"baseDomain"`
  ClusterDomain string `json:"clusterDomain"`
}

I think the Basedomain field correctly represents what is required.
from the doc

	// baseDomain is the base domain of the cluster. All managed DNS records will
	// be sub-domains of this base.
	//
	// For example, given the base domain `openshift.example.com`, an API server
	// DNS record may be created for `cluster-api.openshift.example.com`.

Otherwise downstream consumers (e.g. the ingress operator's DNS manager) are left to guess the public zone.

while the Ingress spec only specifies the domain used for routes
from the doc

	// domain is used to generate a default host name for a route when the
	// route's host name is empty.  The generated host name will follow this
	// pattern: "<route-name>.<route-namespace>.<domain>".

but does not specify how/where to realize that information for ingress's DNS manager.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

So what if we extend the DNSSpec to

type DNSSpec struct {
  BaseDomain string `json:"baseDomain"`
  PublicZone *DNSZone `json:"publicZone"`
  PrivateZone *DNSZone `json:"privateZone"`
}

// DNSZone describes a dns zone for a provider.
// A zone can be identified by an identifier or tags.
type DNSZone struct {
  // id is the identifier that can be used to find the dns zone
  // +optional
  ID *string `json:"id"`
  // tags is a map of tags that can be used to query the dns zone
  // +optional
  Tags map[string]string `json:"tags"`
}

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Copy link
Contributor

Choose a reason for hiding this comment

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

Order of operations to get ingress-operator updated and get installer tests passing might be:

  1. Merge config/v1: add public and private zones to DNSSpec api#202 to add the zone IDs
  2. PR to installer to populate the zone IDs (no change to DNS.Spec.BaseDomain)
  3. PR to ingress-operator to redo the DNS management in terms of the new API from config/v1: add public and private zones to DNSSpec api#202, this eliminates ingress-operator's usage of DNS.Spec.BaseDomain entirely)

Then installer PRs which want to change the meaning of DNS.Spec.BaseDomain are okay (although if no other operators are consuming it, maybe it needs removed, or at least moved to DNS.Status.BaseDomain?)

Copy link
Contributor

Choose a reason for hiding this comment

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

},
}

Expand Down
2 changes: 1 addition & 1 deletion pkg/asset/manifests/ingress.go
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ func (ing *Ingress) Generate(dependencies asset.Parents) error {
// not namespaced
},
Spec: configv1.IngressSpec{
Domain: fmt.Sprintf("apps.%s.%s", installConfig.Config.ObjectMeta.Name, installConfig.Config.BaseDomain),
Domain: fmt.Sprintf("apps.%s", installConfig.Config.ClusterDomain()),
},
}

Expand Down
4 changes: 2 additions & 2 deletions pkg/asset/manifests/operators.go
Original file line number Diff line number Diff line change
Expand Up @@ -142,7 +142,7 @@ func (m *Manifests) generateBootKubeManifests(dependencies asset.Parents) []*ass

etcdEndpointHostnames := make([]string, *installConfig.Config.ControlPlane.Replicas)
for i := range etcdEndpointHostnames {
etcdEndpointHostnames[i] = fmt.Sprintf("%s-etcd-%d", installConfig.Config.ObjectMeta.Name, i)
etcdEndpointHostnames[i] = fmt.Sprintf("etcd-%d", i)
}

templateData := &bootkubeTemplateData{
Expand All @@ -158,7 +158,7 @@ func (m *Manifests) generateBootKubeManifests(dependencies asset.Parents) []*ass
RootCaCert: string(rootCA.Cert()),
CVOClusterID: clusterID.ClusterID,
EtcdEndpointHostnames: etcdEndpointHostnames,
EtcdEndpointDNSSuffix: installConfig.Config.BaseDomain,
EtcdEndpointDNSSuffix: installConfig.Config.ClusterDomain(),
}

kubeCloudConfig := &bootkube.KubeCloudConfig{}
Expand Down
4 changes: 2 additions & 2 deletions pkg/asset/manifests/utils.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,9 +34,9 @@ func configMap(namespace, name string, data genericData) *configurationObject {
}

func getAPIServerURL(ic *types.InstallConfig) string {
return fmt.Sprintf("https://%s-api.%s:6443", ic.ObjectMeta.Name, ic.BaseDomain)
return fmt.Sprintf("https://api.%s:6443", ic.ClusterDomain())
}

func getEtcdDiscoveryDomain(ic *types.InstallConfig) string {
return fmt.Sprintf("%s.%s", ic.ObjectMeta.Name, ic.BaseDomain)
return ic.ClusterDomain()
}
2 changes: 1 addition & 1 deletion pkg/asset/tls/helper.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ func assetFilePath(filename string) string {
}

func apiAddress(cfg *types.InstallConfig) string {
return fmt.Sprintf("%s-api.%s", cfg.ObjectMeta.Name, cfg.BaseDomain)
return fmt.Sprintf("api.%s", cfg.ClusterDomain())
}

func cidrhost(network net.IPNet, hostNum int) (string, error) {
Expand Down
39 changes: 32 additions & 7 deletions pkg/destroy/aws/aws.go
Original file line number Diff line number Diff line change
Expand Up @@ -348,21 +348,47 @@ func getSharedHostedZone(client *route53.Route53, privateID string, logger logru
logger.WithField("hosted zone", privateName).Warn("could not determine whether hosted zone is private")
}

domain := privateName
parents := []string{domain}
for {
idx := strings.Index(domain, ".")
if idx == -1 {
break
}
if len(domain[idx+1:]) > 0 {
parents = append(parents, domain[idx+1:])
}
domain = domain[idx+1:]
}

for _, p := range parents {
sZone, err := findPublicRoute53(client, p, logger)
if err != nil {
return "", err
}
if sZone != "" {
return sZone, nil
}
}
return "", nil
}

// findPublicRoute53 finds a public route53 zone matching the dnsName.
// It returns "", when no public route53 zone could be found.
func findPublicRoute53(client *route53.Route53, dnsName string, logger logrus.FieldLogger) (string, error) {
request := &route53.ListHostedZonesByNameInput{
DNSName: aws.String(privateName),
DNSName: aws.String(dnsName),
}
for i := 0; true; i++ {
logger.Debugf("listing AWS hosted zones (page %d)", i)
logger.Debugf("listing AWS hosted zones %q (page %d)", dnsName, i)
list, err := client.ListHostedZonesByName(request)
if err != nil {
return "", err
}

for _, zone := range list.HostedZones {
if *zone.Id == privateID {
continue
}
if *zone.Name != privateName {
if *zone.Name != dnsName {
// No name after this can match dnsName
return "", nil
}
if zone.Config == nil || zone.Config.PrivateZone == nil {
Expand All @@ -381,7 +407,6 @@ func getSharedHostedZone(client *route53.Route53, privateID string, logger logru

break
}

return "", nil
}

Expand Down
7 changes: 7 additions & 0 deletions pkg/types/installconfig.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
package types

import (
"fmt"

"github.com/openshift/installer/pkg/ipnet"
"github.com/openshift/installer/pkg/types/aws"
"github.com/openshift/installer/pkg/types/libvirt"
Expand Down Expand Up @@ -64,6 +66,11 @@ type InstallConfig struct {
PullSecret string `json:"pullSecret"`
}

// ClusterDomain returns the DNS domain that all records for a cluster must belong to.
func (c *InstallConfig) ClusterDomain() string {
return fmt.Sprintf("%s.%s", c.ObjectMeta.Name, c.BaseDomain)
}

// Platform is the configuration for the specific platform upon which to perform
// the installation. Only one of the platform configuration should be set.
type Platform struct {
Expand Down