Skip to content

Commit 3923c22

Browse files
authored
Merge pull request #113 from mjudeikis/mjudeikis/deprecate.fp.url.setting
Deprecate ExternalHostname string in favor of External structure
2 parents 21a6145 + b14dbd3 commit 3923c22

File tree

12 files changed

+143
-10
lines changed

12 files changed

+143
-10
lines changed

config/crd/bases/operator.kcp.io_frontproxies.yaml

Lines changed: 40 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1486,10 +1486,43 @@ spec:
14861486
type: object
14871487
type: object
14881488
type: object
1489+
external:
1490+
description: 'Optional: External configures how this front-proxy should
1491+
be exposed to the outside world. If empty, the RootShard''s external
1492+
hostname will be used only.'
1493+
properties:
1494+
hostname:
1495+
description: |-
1496+
Hostname is the external name of the kcp instance. This should be matched by a DNS
1497+
record pointing to the kcp-front-proxy Service's external IP address.
1498+
type: string
1499+
port:
1500+
format: int32
1501+
type: integer
1502+
privateHostname:
1503+
description: |-
1504+
Optional: PrivateHostname is an optional hostname that should be used to
1505+
access internal front-proxy services, e.g. by other kcp components. This is helpful
1506+
if you don't want to use the public hostname for internal communication, e.g.
1507+
You have a DNS configuration, where DNS is re-encrypted for external access, but
1508+
internal components can access the front-proxy directly. If not set, the value of `hostname` is used.
1509+
type: string
1510+
privatePort:
1511+
description: |-
1512+
Optional: PrivatePort is an optional port that should be used to
1513+
access internal front-proxy services, e.g. by other kcp components. This is helpful
1514+
if you don't want to use the public port for internal communication, e.g.
1515+
because it is firewalled. If not set, the value of `port` is used.
1516+
format: int32
1517+
type: integer
1518+
required:
1519+
- hostname
1520+
- port
1521+
type: object
14891522
externalHostname:
1490-
description: 'Optional: ExternalHostname under which the FrontProxy
1491-
can be reached. If empty, the RootShard''s external hostname will
1492-
be used only.'
1523+
description: |-
1524+
Optional: ExternalHostname under which the FrontProxy can be reached. If empty, the RootShard's external hostname will be used only.
1525+
Deprecated: use spec.External for configuration of external access instead.
14931526
type: string
14941527
image:
14951528
description: 'Optional: Image defines the image to use. Defaults to
@@ -1644,6 +1677,10 @@ spec:
16441677
required:
16451678
- rootShard
16461679
type: object
1680+
x-kubernetes-validations:
1681+
- message: Cannot set both ExternalHostname (deprecated) and External.hostname.
1682+
Use External.hostname only.
1683+
rule: '!(has(self.externalHostname) && has(self.external.hostname))'
16471684
status:
16481685
description: FrontProxyStatus defines the observed state of FrontProxy
16491686
properties:

config/crd/bases/operator.kcp.io_rootshards.yaml

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1662,6 +1662,22 @@ spec:
16621662
port:
16631663
format: int32
16641664
type: integer
1665+
privateHostname:
1666+
description: |-
1667+
Optional: PrivateHostname is an optional hostname that should be used to
1668+
access internal front-proxy services, e.g. by other kcp components. This is helpful
1669+
if you don't want to use the public hostname for internal communication, e.g.
1670+
You have a DNS configuration, where DNS is re-encrypted for external access, but
1671+
internal components can access the front-proxy directly. If not set, the value of `hostname` is used.
1672+
type: string
1673+
privatePort:
1674+
description: |-
1675+
Optional: PrivatePort is an optional port that should be used to
1676+
access internal front-proxy services, e.g. by other kcp components. This is helpful
1677+
if you don't want to use the public port for internal communication, e.g.
1678+
because it is firewalled. If not set, the value of `port` is used.
1679+
format: int32
1680+
type: integer
16651681
required:
16661682
- hostname
16671683
- port

hack/run-e2e-tests.sh

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,7 @@ _build/manager \
9292
-zap-log-level debug \
9393
-zap-encoder console \
9494
-zap-time-encoding iso8601 \
95+
-health-probe-bind-address="" \
9596
>"$DATA_DIR/kcp-operator.log" 2>&1 &
9697
OPERATOR_PID=$!
9798
echo "Running as process $OPERATOR_PID."

internal/controller/kubeconfig/controller.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,7 @@ func (r *KubeconfigReconciler) Reconcile(ctx context.Context, req ctrl.Request)
8383

8484
rootShard := &operatorv1alpha1.RootShard{}
8585
shard := &operatorv1alpha1.Shard{}
86+
var frontProxy operatorv1alpha1.FrontProxy
8687
var caBundle *corev1.Secret
8788

8889
var (
@@ -117,7 +118,6 @@ func (r *KubeconfigReconciler) Reconcile(ctx context.Context, req ctrl.Request)
117118
serverCA = resources.GetRootShardCAName(rootShard, operatorv1alpha1.ServerCA)
118119

119120
case kc.Spec.Target.FrontProxyRef != nil:
120-
var frontProxy operatorv1alpha1.FrontProxy
121121
if err := r.Get(ctx, types.NamespacedName{Name: kc.Spec.Target.FrontProxyRef.Name, Namespace: req.Namespace}, &frontProxy); err != nil {
122122
return ctrl.Result{}, fmt.Errorf("referenced FrontProxy '%s' does not exist", kc.Spec.Target.FrontProxyRef.Name)
123123
}
@@ -166,7 +166,7 @@ func (r *KubeconfigReconciler) Reconcile(ctx context.Context, req ctrl.Request)
166166
return ctrl.Result{RequeueAfter: time.Second * 5}, nil
167167
}
168168

169-
reconciler, err := kubeconfig.KubeconfigSecretReconciler(&kc, rootShard, shard, serverCASecret, clientCertSecret, caBundle)
169+
reconciler, err := kubeconfig.KubeconfigSecretReconciler(&kc, rootShard, shard, frontProxy, serverCASecret, clientCertSecret, caBundle)
170170
if err != nil {
171171
return ctrl.Result{}, err
172172
}

internal/resources/frontproxy/certificates.go

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -83,9 +83,16 @@ func (r *reconciler) serverCertificateReconciler() reconciling.NamedCertificateR
8383
if r.frontProxy != nil {
8484
// only add the external hostname if this is not reconciling the rootshard-internal-only proxy
8585
dnsNames = append(dnsNames, r.rootShard.Spec.External.Hostname)
86+
if r.rootShard.Spec.External.PrivateHostname != "" {
87+
dnsNames = append(dnsNames, r.rootShard.Spec.External.PrivateHostname)
88+
}
8689

90+
// DEPRECATED: keep support for the deprecated ExternalHostname field for now
91+
// to not break existing front-proxy installations.
8792
if r.frontProxy.Spec.ExternalHostname != "" {
8893
dnsNames = append(dnsNames, r.frontProxy.Spec.ExternalHostname)
94+
} else {
95+
dnsNames = append(dnsNames, r.frontProxy.Spec.External.Hostname)
8996
}
9097
}
9198

internal/resources/kubeconfig/secret.go

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@ func KubeconfigSecretReconciler(
4141
kubeconfig *operatorv1alpha1.Kubeconfig,
4242
rootShard *operatorv1alpha1.RootShard,
4343
shard *operatorv1alpha1.Shard,
44+
frontProxy operatorv1alpha1.FrontProxy,
4445
caSecret *corev1.Secret,
4546
certSecret *corev1.Secret,
4647
caBundle *corev1.Secret, // can be nil
@@ -120,7 +121,15 @@ func KubeconfigSecretReconciler(
120121
panic("RootShard must be provided when kubeconfig targets a FrontProxy.")
121122
}
122123

123-
serverURL := fmt.Sprintf("https://%s:6443", rootShard.Spec.External.Hostname)
124+
var serverURL string
125+
// New flow:
126+
if frontProxy.Spec.External.Hostname != "" {
127+
serverURL = fmt.Sprintf("https://%s:%d", frontProxy.Spec.External.Hostname, frontProxy.Spec.External.Port)
128+
} else {
129+
// Old flow:
130+
serverURL = fmt.Sprintf("https://%s:%d", rootShard.Spec.External.Hostname, rootShard.Spec.External.Port)
131+
}
132+
124133
defaultURL, err := url.JoinPath(serverURL, "clusters", "root")
125134
if err != nil {
126135
return nil, err

internal/resources/rootshard/kubeconfigs.go

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -101,7 +101,7 @@ func ExternalLogicalClusterAdminKubeconfigReconciler(rootShard *operatorv1alpha1
101101
Clusters: map[string]*clientcmdapi.Cluster{
102102
serverName: {
103103
// This has to point to a front-proxy, not the root shard itself.
104-
Server: fmt.Sprintf("https://%s:%d", rootShard.Spec.External.Hostname, rootShard.Spec.External.Port),
104+
// Server is populated from the external hostname and port below.
105105
// CertificateAuthority will be populated below, depending on whether CABundle is specified or not.
106106
},
107107
},
@@ -120,6 +120,16 @@ func ExternalLogicalClusterAdminKubeconfigReconciler(rootShard *operatorv1alpha1
120120
CurrentContext: contextName,
121121
}
122122

123+
if rootShard.Spec.External.PrivateHostname != "" {
124+
port := rootShard.Spec.External.Port
125+
if rootShard.Spec.External.PrivatePort != nil {
126+
port = *rootShard.Spec.External.PrivatePort
127+
}
128+
config.Clusters[serverName].Server = fmt.Sprintf("https://%s:%d", rootShard.Spec.External.PrivateHostname, port)
129+
} else {
130+
config.Clusters[serverName].Server = fmt.Sprintf("https://%s:%d", rootShard.Spec.External.Hostname, rootShard.Spec.External.Port)
131+
}
132+
123133
if rootShard.Spec.CABundleSecretRef == nil {
124134
config.Clusters[serverName].CertificateAuthority = getCAMountPath(operatorv1alpha1.ServerCA) + "/tls.crt"
125135
} else {

sdk/apis/operator/v1alpha1/frontproxy_types.go

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ import (
2222
)
2323

2424
// FrontProxySpec defines the desired state of FrontProxy.
25+
// +kubebuilder:validation:XValidation:rule="!(has(self.externalHostname) && has(self.external.hostname))",message="Cannot set both ExternalHostname (deprecated) and External.hostname. Use External.hostname only."
2526
type FrontProxySpec struct {
2627
// RootShard configures the kcp root shard that this front-proxy instance should connect to.
2728
RootShard RootShardConfig `json:"rootShard"`
@@ -38,8 +39,12 @@ type FrontProxySpec struct {
3839
// Optional: Image defines the image to use. Defaults to the latest versioned image during the release of kcp-operator.
3940
Image *ImageSpec `json:"image,omitempty"`
4041
// Optional: ExternalHostname under which the FrontProxy can be reached. If empty, the RootShard's external hostname will be used only.
42+
// Deprecated: use spec.External for configuration of external access instead.
4143
ExternalHostname string `json:"externalHostname,omitempty"`
4244

45+
// Optional: External configures how this front-proxy should be exposed to the outside world. If empty, the RootShard's external hostname will be used only.
46+
External ExternalConfig `json:"external,omitempty"`
47+
4348
// Optional: ServiceTemplate configures the Kubernetes Service created for this front-proxy instance.
4449
ServiceTemplate *ServiceTemplate `json:"serviceTemplate,omitempty"`
4550

sdk/apis/operator/v1alpha1/rootshard_types.go

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,21 @@ type ExternalConfig struct {
6666
// record pointing to the kcp-front-proxy Service's external IP address.
6767
Hostname string `json:"hostname"`
6868
Port uint32 `json:"port"`
69+
70+
// Optional: PrivateHostname is an optional hostname that should be used to
71+
// access internal front-proxy services, e.g. by other kcp components. This is helpful
72+
// if you don't want to use the public hostname for internal communication, e.g.
73+
// You have a DNS configuration, where DNS is re-encrypted for external access, but
74+
// internal components can access the front-proxy directly. If not set, the value of `hostname` is used.
75+
// +optional
76+
PrivateHostname string `json:"privateHostname,omitempty"`
77+
78+
// Optional: PrivatePort is an optional port that should be used to
79+
// access internal front-proxy services, e.g. by other kcp components. This is helpful
80+
// if you don't want to use the public port for internal communication, e.g.
81+
// because it is firewalled. If not set, the value of `port` is used.
82+
// +optional
83+
PrivatePort *uint32 `json:"privatePort,omitempty"`
6984
}
7085

7186
// Certificates configures how certificates for kcp should be created.

sdk/apis/operator/v1alpha1/zz_generated.deepcopy.go

Lines changed: 7 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)