Skip to content

Commit 6b5c5fa

Browse files
committed
node-joiner: allow user to specify sshKey via config file
1 parent 8e548c3 commit 6b5c5fa

File tree

4 files changed

+95
-9
lines changed

4 files changed

+95
-9
lines changed

pkg/asset/agent/joiner/addnodesconfig.go

Lines changed: 24 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,13 +7,13 @@ import (
77
"os"
88
"path/filepath"
99

10-
"github.com/pkg/errors"
1110
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
1211
"k8s.io/apimachinery/pkg/util/validation/field"
1312
"sigs.k8s.io/yaml"
1413

1514
"github.com/openshift/installer/pkg/asset"
1615
"github.com/openshift/installer/pkg/types/agent"
16+
"github.com/openshift/installer/pkg/validate"
1717
)
1818

1919
const (
@@ -37,6 +37,7 @@ type Config struct {
3737
metav1.ObjectMeta `json:"metadata,omitempty"`
3838

3939
CPUArchitecture string `json:"cpuArchitecture,omitempty"`
40+
SSHKey string `json:"sshKey,omitempty"`
4041
Hosts []agent.Host `json:"hosts,omitempty"`
4142
}
4243

@@ -114,10 +115,16 @@ func (a *AddNodesConfig) Load(f asset.FileFetcher) (bool, error) {
114115
}
115116

116117
func (a *AddNodesConfig) finish() error {
117-
if err := a.validateHosts().ToAggregate(); err != nil {
118-
return errors.Wrapf(err, "invalid nodes configuration")
118+
allErrs := field.ErrorList{}
119+
120+
if err := a.validateHosts(); err != nil {
121+
allErrs = append(allErrs, err...)
119122
}
120-
return nil
123+
if err := a.validateSSHKey(); err != nil {
124+
allErrs = append(allErrs, err...)
125+
}
126+
127+
return allErrs.ToAggregate()
121128
}
122129

123130
func (a *AddNodesConfig) validateHosts() field.ErrorList {
@@ -130,3 +137,16 @@ func (a *AddNodesConfig) validateHosts() field.ErrorList {
130137

131138
return allErrs
132139
}
140+
141+
func (a *AddNodesConfig) validateSSHKey() field.ErrorList {
142+
var allErrs field.ErrorList
143+
144+
if a.Config.SSHKey == "" {
145+
return nil
146+
}
147+
148+
if err := validate.SSHPublicKey(a.Config.SSHKey); err != nil {
149+
allErrs = append(allErrs, field.Invalid(field.NewPath("sshKey"), a.Config.SSHKey, err.Error()))
150+
}
151+
return allErrs
152+
}

pkg/asset/agent/joiner/addnodesconfig_test.go

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,26 @@ func TestAddNodesConfig_Load(t *testing.T) {
2727
},
2828
{
2929
name: "empty nodes-config.yaml",
30-
expectedError: "invalid nodes configuration: hosts: Required value: at least one host must be defined",
30+
expectedError: "hosts: Required value: at least one host must be defined",
31+
},
32+
{
33+
name: "ssh key",
34+
nodesConfigData: `hosts:
35+
- hostname: master-0
36+
interfaces:
37+
- name: eth0
38+
macAddress: 00:ef:29:72:b9:771
39+
sshKey: "ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAQEAklOUpkDHrfHY17SbrmTIpNLTGK9Tjom/BWDSUGPl+nafzlHDTYW7hdI4yZ5ew18JH4JW9jbhUFrviQzM7xlELEVf4h9lFX5QVkbPppSwg0cda3Pbv7kOdJ/MTyBlWXFCR+HAo3FXRitBqxiX1nKhXpHAZsMciLq8V6RjsNAQwdsdMFvSlVK/7XAt3FaoJoAsncM1Q9x5+3V0Ww68/eIFmb1zuUFljQJKprrX88XypNDvjYNby6vw/Pb0rwert/EnmZ+AW4OZPnTPI89ZPmVMLuayrD2cE86Z/il8b+gw3r3+1nKatmIkjn2so1d01QraTlMqVSsbxNrRFi9wrf+M7Q=="`,
40+
},
41+
{
42+
name: "invalid ssh key",
43+
nodesConfigData: `hosts:
44+
- hostname: master-0
45+
interfaces:
46+
- name: eth0
47+
macAddress: 00:ef:29:72:b9:771
48+
sshKey: "not a valid ssh key"`,
49+
expectedError: "sshKey: Invalid value: \"not a valid ssh key\": ssh: no key found",
3150
},
3251
}
3352
for _, tc := range cases {

pkg/asset/agent/joiner/clusterinfo.go

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -122,7 +122,7 @@ func (ci *ClusterInfo) Generate(_ context.Context, dependencies asset.Parents) e
122122
return err
123123
}
124124

125-
err = ci.retrieveInstallConfigData()
125+
err = ci.retrieveInstallConfigData(addNodesConfig)
126126
if err != nil {
127127
return err
128128
}
@@ -243,7 +243,7 @@ func (ci *ClusterInfo) retrieveArchitecture(addNodesConfig *AddNodesConfig) erro
243243
return fmt.Errorf("unable to determine target cluster architecture")
244244
}
245245

246-
func (ci *ClusterInfo) retrieveInstallConfigData() error {
246+
func (ci *ClusterInfo) retrieveInstallConfigData(addNodesConfig *AddNodesConfig) error {
247247
clusterConfig, err := ci.Client.CoreV1().ConfigMaps("kube-system").Get(context.Background(), "cluster-config-v1", metav1.GetOptions{})
248248
if err != nil {
249249
if errors.IsNotFound(err) {
@@ -269,6 +269,10 @@ func (ci *ClusterInfo) retrieveInstallConfigData() error {
269269
ci.APIDNSName = fmt.Sprintf("api.%s.%s", ci.ClusterName, installConfig.BaseDomain)
270270
ci.FIPS = installConfig.FIPS
271271

272+
if addNodesConfig.Config.SSHKey != "" {
273+
ci.SSHKey = addNodesConfig.Config.SSHKey
274+
}
275+
272276
return nil
273277
}
274278

pkg/asset/agent/joiner/clusterinfo_test.go

Lines changed: 45 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ func TestClusterInfo_Generate(t *testing.T) {
4949
Version: "4.15.0",
5050
APIDNSName: "api.ostest.test.metalkube.org",
5151
Namespace: "cluster0",
52-
PullSecret: "c3VwZXJzZWNyZXQK",
52+
PullSecret: "c3VwZXJzZWNyZXQK", // notsecret
5353
UserCaBundle: "--- bundle ---",
5454
Architecture: "amd64",
5555
Proxy: &types.Proxy{
@@ -103,7 +103,7 @@ func TestClusterInfo_Generate(t *testing.T) {
103103
Version: "4.15.0",
104104
APIDNSName: "api.ostest.test.metalkube.org",
105105
Namespace: "cluster0",
106-
PullSecret: "c3VwZXJzZWNyZXQK",
106+
PullSecret: "c3VwZXJzZWNyZXQK", // notsecret
107107
UserCaBundle: "--- bundle ---",
108108
Architecture: "arm64",
109109
Proxy: &types.Proxy{
@@ -147,6 +147,49 @@ func TestClusterInfo_Generate(t *testing.T) {
147147
},
148148
expectedError: "Platform: Unsupported value: \"aws\": supported values: \"baremetal\", \"vsphere\", \"none\", \"external\"",
149149
},
150+
{
151+
name: "sshKey from nodes-config.yaml",
152+
workflow: workflow.AgentWorkflowTypeAddNodes,
153+
objs: defaultObjects(),
154+
nodesConfig: AddNodesConfig{
155+
Config: Config{
156+
SSHKey: "ssh-key-from-config",
157+
},
158+
},
159+
expectedClusterInfo: ClusterInfo{
160+
ClusterID: "1b5ba46b-7e56-47b1-a326-a9eebddfb38c",
161+
ClusterName: "ostest",
162+
ReleaseImage: "registry.ci.openshift.org/ocp/release@sha256:65d9b652d0d23084bc45cb66001c22e796d43f5e9e005c2bc2702f94397d596e",
163+
Version: "4.15.0",
164+
APIDNSName: "api.ostest.test.metalkube.org",
165+
Namespace: "cluster0",
166+
PullSecret: "c3VwZXJzZWNyZXQK", // notsecret
167+
UserCaBundle: "--- bundle ---",
168+
Architecture: "amd64",
169+
Proxy: &types.Proxy{
170+
HTTPProxy: "http://proxy",
171+
HTTPSProxy: "https://proxy",
172+
NoProxy: "localhost",
173+
},
174+
ImageDigestSources: []types.ImageDigestSource{
175+
{
176+
Source: "quay.io/openshift-release-dev/ocp-v4.0-art-dev",
177+
Mirrors: []string{
178+
"registry.example.com:5000/ocp4/openshift4",
179+
},
180+
},
181+
},
182+
PlatformType: v1beta1.BareMetalPlatformType,
183+
SSHKey: "ssh-key-from-config",
184+
OSImage: buildStreamData(),
185+
OSImageLocation: "http://my-coreosimage-url/416.94.202402130130-0",
186+
IgnitionEndpointWorker: &models.IgnitionEndpoint{
187+
URL: ptr.To("https://192.168.111.5:22623/config/worker"),
188+
CaCertificate: ptr.To("LS0tL_FakeCertificate_LS0tCg=="),
189+
},
190+
FIPS: true,
191+
},
192+
},
150193
}
151194
for _, tc := range cases {
152195
t.Run(tc.name, func(t *testing.T) {

0 commit comments

Comments
 (0)