Skip to content

Commit

Permalink
Improve UX around setting Proxy configurations in the spec (#69)
Browse files Browse the repository at this point in the history
  • Loading branch information
Maciek Gołaszewski authored Oct 19, 2024
1 parent 726e58d commit cefee4c
Show file tree
Hide file tree
Showing 12 changed files with 349 additions and 14 deletions.
12 changes: 12 additions & 0 deletions bootstrap/api/v1beta2/ck8sconfig_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,18 @@ type CK8sConfigSpec struct {
// +optional
SnapstoreProxyID string `json:"snapstoreProxyId,omitempty"`

// HTTPSProxy is optional https proxy configuration
// +optional
HTTPSProxy string `json:"httpsProxy,omitempty"`

// HTTPProxy is optional http proxy configuration
// +optional
HTTPProxy string `json:"httpProxy,omitempty"`

// NoProxy is optional no proxy configuration
// +optional
NoProxy string `json:"noProxy,omitempty"`

// Channel is the channel to use for the snap install.
// +optional
Channel string `json:"channel,omitempty"`
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -51,9 +51,6 @@ spec:
items:
type: string
type: array
channel:
description: Channel is the channel to use for the snap install.
type: string
bootstrapConfig:
description: BootstrapConfig is the data to be passed to the bootstrap
script.
Expand Down Expand Up @@ -87,6 +84,9 @@ spec:
- secret
type: object
type: object
channel:
description: Channel is the channel to use for the snap install.
type: string
controlPlane:
description: CK8sControlPlaneConfig is configuration for the control
plane node.
Expand Down Expand Up @@ -201,6 +201,12 @@ spec:
- path
type: object
type: array
httpProxy:
description: HTTPProxy is optional http proxy configuration
type: string
httpsProxy:
description: HTTPSProxy is optional https proxy configuration
type: string
initConfig:
description: CK8sInitConfig is configuration for the initializing
the cluster features.
Expand Down Expand Up @@ -233,6 +239,9 @@ spec:
LocalPath is the path of a local snap file in the workload cluster to use for the snap install.
If Channel or Revision are set, this will be ignored.
type: string
noProxy:
description: NoProxy is optional no proxy configuration
type: string
nodeName:
description: |-
NodeName is the name to use for the kubelet of this node. It is needed for clouds
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -58,9 +58,6 @@ spec:
items:
type: string
type: array
channel:
description: Channel is the channel to use for the snap install.
type: string
bootstrapConfig:
description: BootstrapConfig is the data to be passed to the
bootstrap script.
Expand Down Expand Up @@ -94,6 +91,9 @@ spec:
- secret
type: object
type: object
channel:
description: Channel is the channel to use for the snap install.
type: string
controlPlane:
description: CK8sControlPlaneConfig is configuration for the
control plane node.
Expand Down Expand Up @@ -210,6 +210,12 @@ spec:
- path
type: object
type: array
httpProxy:
description: HTTPProxy is optional http proxy configuration
type: string
httpsProxy:
description: HTTPSProxy is optional https proxy configuration
type: string
initConfig:
description: CK8sInitConfig is configuration for the initializing
the cluster features.
Expand Down Expand Up @@ -242,6 +248,9 @@ spec:
LocalPath is the path of a local snap file in the workload cluster to use for the snap install.
If Channel or Revision are set, this will be ignored.
type: string
noProxy:
description: NoProxy is optional no proxy configuration
type: string
nodeName:
description: |-
NodeName is the name to use for the kubelet of this node. It is needed for clouds
Expand Down
6 changes: 6 additions & 0 deletions bootstrap/controllers/ck8sconfig_controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -378,6 +378,9 @@ func (r *CK8sConfigReconciler) joinWorker(ctx context.Context, scope *Scope) err
ConfigFileContents: string(joinConfig),
MicroclusterAddress: scope.Config.Spec.ControlPlaneConfig.MicroclusterAddress,
MicroclusterPort: microclusterPort,
HTTPProxy: scope.Config.Spec.HTTPProxy,
HTTPSProxy: scope.Config.Spec.HTTPSProxy,
NoProxy: scope.Config.Spec.NoProxy,
AirGapped: scope.Config.Spec.AirGapped,
SnapstoreProxyScheme: scope.Config.Spec.SnapstoreProxyScheme,
SnapstoreProxyDomain: scope.Config.Spec.SnapstoreProxyDomain,
Expand Down Expand Up @@ -693,6 +696,9 @@ func (r *CK8sConfigReconciler) handleClusterNotInitialized(ctx context.Context,
MicroclusterAddress: scope.Config.Spec.ControlPlaneConfig.MicroclusterAddress,
MicroclusterPort: microclusterPort,
NodeName: scope.Config.Spec.NodeName,
HTTPProxy: scope.Config.Spec.HTTPProxy,
HTTPSProxy: scope.Config.Spec.HTTPSProxy,
NoProxy: scope.Config.Spec.NoProxy,
AirGapped: scope.Config.Spec.AirGapped,
SnapstoreProxyScheme: scope.Config.Spec.SnapstoreProxyScheme,
SnapstoreProxyDomain: scope.Config.Spec.SnapstoreProxyDomain,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -246,9 +246,6 @@ spec:
items:
type: string
type: array
channel:
description: Channel is the channel to use for the snap install.
type: string
bootstrapConfig:
description: BootstrapConfig is the data to be passed to the bootstrap
script.
Expand Down Expand Up @@ -282,6 +279,9 @@ spec:
- secret
type: object
type: object
channel:
description: Channel is the channel to use for the snap install.
type: string
controlPlane:
description: CK8sControlPlaneConfig is configuration for the control
plane node.
Expand Down Expand Up @@ -398,6 +398,12 @@ spec:
- path
type: object
type: array
httpProxy:
description: HTTPProxy is optional http proxy configuration
type: string
httpsProxy:
description: HTTPSProxy is optional https proxy configuration
type: string
initConfig:
description: CK8sInitConfig is configuration for the initializing
the cluster features.
Expand Down Expand Up @@ -430,6 +436,9 @@ spec:
LocalPath is the path of a local snap file in the workload cluster to use for the snap install.
If Channel or Revision are set, this will be ignored.
type: string
noProxy:
description: NoProxy is optional no proxy configuration
type: string
nodeName:
description: |-
NodeName is the name to use for the kubelet of this node. It is needed for clouds
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -221,10 +221,6 @@ spec:
items:
type: string
type: array
channel:
description: Channel is the channel to use for the snap
install.
type: string
bootstrapConfig:
description: BootstrapConfig is the data to be passed
to the bootstrap script.
Expand Down Expand Up @@ -258,6 +254,10 @@ spec:
- secret
type: object
type: object
channel:
description: Channel is the channel to use for the snap
install.
type: string
controlPlane:
description: CK8sControlPlaneConfig is configuration for
the control plane node.
Expand Down Expand Up @@ -376,6 +376,12 @@ spec:
- path
type: object
type: array
httpProxy:
description: HTTPProxy is optional http proxy configuration
type: string
httpsProxy:
description: HTTPSProxy is optional https proxy configuration
type: string
initConfig:
description: CK8sInitConfig is configuration for the initializing
the cluster features.
Expand Down Expand Up @@ -408,6 +414,9 @@ spec:
LocalPath is the path of a local snap file in the workload cluster to use for the snap install.
If Channel or Revision are set, this will be ignored.
type: string
noProxy:
description: NoProxy is optional no proxy configuration
type: string
nodeName:
description: |-
NodeName is the name to use for the kubelet of this node. It is needed for clouds
Expand Down
46 changes: 45 additions & 1 deletion pkg/cloudinit/common.go
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,12 @@ type BaseUserData struct {
SnapstoreProxyDomain string
// The snap store proxy ID
SnapstoreProxyID string
// HTTPProxy is http_proxy configuration.
HTTPProxy string
// HTTPSProxy is https_proxy configuration.
HTTPSProxy string
// NoProxy is no_proxy configuration.
NoProxy string
// MicroclusterAddress is the address to use for microcluster.
MicroclusterAddress string
// MicroclusterPort is the port to use for microcluster.
Expand Down Expand Up @@ -95,6 +101,12 @@ func NewBaseCloudConfig(data BaseUserData) (CloudConfig, error) {
config.RunCommands = append(config.RunCommands, "/capi/scripts/configure-snapstore-proxy.sh")
}

// proxy configuration
if proxyConfigFiles := getProxyConfigFiles(data); proxyConfigFiles != nil {
config.WriteFiles = append(config.WriteFiles, proxyConfigFiles...)
config.RunCommands = append(config.RunCommands, "/capi/scripts/configure-proxy.sh")
}

var configFileContents string
if data.BootstrapConfig != "" {
configFileContents = data.BootstrapConfig
Expand Down Expand Up @@ -139,7 +151,6 @@ func NewBaseCloudConfig(data BaseUserData) (CloudConfig, error) {
},
)...,
)

// boot commands
config.BootCommands = data.BootCommands

Expand Down Expand Up @@ -190,3 +201,36 @@ func getSnapstoreProxyConfigFiles(data BaseUserData) []File {

return []File{schemeFile, domainFile, storeIDFile}
}

// getProxyConfigFiles returns the proxy config files.
// Returns slice of files for each proxy parameters are present in data structure with corresponding value
// Nil indicates that no files are returned.
func getProxyConfigFiles(data BaseUserData) []File {
var files []File
if data.HTTPProxy != "" {
files = append(files, File{
Path: "/capi/etc/http-proxy",
Content: data.HTTPProxy,
Permissions: "0400",
Owner: "root:root",
})
}
if data.HTTPSProxy != "" {
files = append(files, File{
Path: "/capi/etc/https-proxy",
Content: data.HTTPSProxy,
Permissions: "0400",
Owner: "root:root",
})
}
if data.NoProxy != "" {
files = append(files, File{
Path: "/capi/etc/no-proxy",
Content: data.NoProxy,
Permissions: "0400",
Owner: "root:root",
})
}

return files
}
69 changes: 69 additions & 0 deletions pkg/cloudinit/controlplane_init_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ import (
. "github.com/onsi/gomega"
format "github.com/onsi/gomega/format"
"github.com/onsi/gomega/gstruct"
"github.com/onsi/gomega/types"

"github.com/canonical/cluster-api-k8s/pkg/cloudinit"
)
Expand Down Expand Up @@ -88,6 +89,7 @@ func TestNewInitControlPlane(t *testing.T) {
HaveField("Path", "/capi/scripts/wait-apiserver-ready.sh"),
HaveField("Path", "/capi/scripts/deploy-manifests.sh"),
HaveField("Path", "/capi/scripts/configure-auth-token.sh"),
HaveField("Path", "/capi/scripts/configure-proxy.sh"),
HaveField("Path", "/capi/scripts/configure-node-token.sh"),
HaveField("Path", "/capi/scripts/create-sentinel-bootstrap.sh"),
HaveField("Path", "/capi/scripts/configure-snapstore-proxy.sh"),
Expand All @@ -105,6 +107,73 @@ func TestNewInitControlPlane(t *testing.T) {
), "Some /capi/scripts files are missing")
}

func TestNewInitControlPlaneWithOptionalProxySettings(t *testing.T) {
g := NewWithT(t)
for _, tc := range []struct {
name string
baseUserData cloudinit.BaseUserData
expectRunCommand bool
expectWriteFiles []types.GomegaMatcher
}{
{
name: "AllProxyFieldsSet",
baseUserData: cloudinit.BaseUserData{
KubernetesVersion: "v1.30.0",
HTTPProxy: "http://proxy.internal",
HTTPSProxy: "https://proxy.internal",
NoProxy: "10.0.0.0/8,10.152.183.1,192.168.0.0/16",
MicroclusterAddress: "10.0.0.0/8",
},
expectRunCommand: true,
expectWriteFiles: []types.GomegaMatcher{
HaveField("Path", "/capi/scripts/configure-proxy.sh"),
HaveField("Path", "/capi/etc/http-proxy"),
HaveField("Path", "/capi/etc/https-proxy"),
HaveField("Path", "/capi/etc/no-proxy"),
},
},
{
name: "HTTPSProxyOnly",
baseUserData: cloudinit.BaseUserData{
KubernetesVersion: "v1.30.0",
HTTPSProxy: "https://proxy.internal",
MicroclusterAddress: "10.0.0.0/8",
},
expectRunCommand: true,
expectWriteFiles: []types.GomegaMatcher{
HaveField("Path", "/capi/scripts/configure-proxy.sh"),
HaveField("Path", "/capi/etc/https-proxy"),
},
},
{
name: "NoProxyFields",
baseUserData: cloudinit.BaseUserData{
KubernetesVersion: "v1.30.0",
MicroclusterAddress: "10.0.0.0/8",
},
expectRunCommand: false,
expectWriteFiles: []types.GomegaMatcher{
HaveField("Path", "/capi/scripts/configure-proxy.sh"),
},
},
} {
t.Run(tc.name, func(t *testing.T) {
config, err := cloudinit.NewInitControlPlane(cloudinit.InitControlPlaneInput{BaseUserData: tc.baseUserData})

g.Expect(err).ToNot(HaveOccurred())
// Verify proxy run command.
if tc.expectRunCommand {
g.Expect(config.RunCommands).To(ContainElement("/capi/scripts/configure-proxy.sh"))
} else {
g.Expect(config.RunCommands).NotTo(ContainElement("/capi/scripts/configure-proxy.sh"))
}
// Verify proxy files present.
g.Expect(config.WriteFiles).To(ContainElements(tc.expectWriteFiles),
"Required files in /capi directory are missing")
})
}
}

func TestUserSuppliedBootstrapConfig(t *testing.T) {
g := NewWithT(t)

Expand Down
Loading

0 comments on commit cefee4c

Please sign in to comment.