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

Improve UX around setting Proxy configurations in the spec #69

Merged
merged 13 commits into from
Oct 19, 2024
Merged
Show file tree
Hide file tree
Changes from 9 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
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"`
maci3jka marked this conversation as resolved.
Show resolved Hide resolved

// 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:
maci3jka marked this conversation as resolved.
Show resolved Hide resolved
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
42 changes: 41 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,32 @@ func getSnapstoreProxyConfigFiles(data BaseUserData) []File {

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

// getProxyConfigFiles returns the node proxy config files.
// If the HTTPProxy or HTTPPSProxy is not set, it returns nil.
// Nil indicates that no files are returned.
func getProxyConfigFiles(data BaseUserData) []File {
if data.HTTPProxy == "" && data.HTTPSProxy == "" {
return nil
}
return []File{
maci3jka marked this conversation as resolved.
Show resolved Hide resolved
{
Path: "/capi/etc/http-proxy",
Content: data.HTTPProxy,
Permissions: "0400",
Owner: "root:root",
},
{
Path: "/capi/etc/https-proxy",
Content: data.HTTPSProxy,
Permissions: "0400",
Owner: "root:root",
},
{
Path: "/capi/etc/no-proxy",
Content: data.NoProxy,
Permissions: "0400",
Owner: "root:root",
},
}
}
99 changes: 99 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,103 @@ func TestNewInitControlPlane(t *testing.T) {
), "Some /capi/scripts files are missing")
}

func TestNewInitControlPlaneWithOptionalProxySettings(t *testing.T) {
g := NewWithT(t)
for _, tc := range []struct {
maci3jka marked this conversation as resolved.
Show resolved Hide resolved
name string
baseUserData cloudinit.BaseUserData
expectRunCommand bool
expectWriteFiles []types.GomegaMatcher
}{
{
name: "AllFieldsSet",
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: "HTTPSProxy",
baseUserData: cloudinit.BaseUserData{
KubernetesVersion: "v1.30.0",
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: "HTTPProxy",
baseUserData: cloudinit.BaseUserData{
KubernetesVersion: "v1.30.0",
HTTPProxy: "http://proxy.internal",
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: "NoProxy",
baseUserData: cloudinit.BaseUserData{
KubernetesVersion: "v1.30.0",
NoProxy: "10.0.0.0/8,10.152.183.1,192.168.0.0/16",
MicroclusterAddress: "10.0.0.0/8",
},
expectRunCommand: false,
expectWriteFiles: []types.GomegaMatcher{
HaveField("Path", "/capi/scripts/configure-proxy.sh"),
},
},
{
name: "noFields",
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
Loading