Skip to content

Commit ee8a45f

Browse files
committed
support users field of cloud-config
1 parent f9d3ec2 commit ee8a45f

File tree

7 files changed

+211
-32
lines changed

7 files changed

+211
-32
lines changed

api/v1beta1/cloudinit_types.go

Lines changed: 29 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,10 @@ package v1beta1
33
// CloudInit is passed to disk directly as raw yaml file
44
// not via Proxmox API so you can configure more detailed configs
55
type CloudInit struct {
6-
User *User `json:"user,omitempty"`
6+
UserData *UserData `json:"user,omitempty"`
77
}
88

9-
type User struct {
9+
type UserData struct {
1010
BootCmd []string `yaml:"bootcmd,omitempty" json:"bootcmd,omitempty"`
1111
CACerts CACert `yaml:"ca_certs,omitempty" json:"ca_certs,omitempty"`
1212
ChPasswd ChPasswd `yaml:"chpasswd,omitempty" json:"chpasswd,omitempty"`
@@ -23,7 +23,7 @@ type User struct {
2323
SSHKeys SSHKeys `yaml:"ssh_keys,omitempty" json:"ssh_keys,omitempty"`
2424
SSHPWAuth bool `yaml:"ssh_pwauth,omitempty" json:"ssh_pwauth,omitempty"`
2525
User string `yaml:"user,omitempty" json:"user,omitempty"`
26-
Users []string `yaml:"users,omitempty" json:"-"`
26+
Users []User `yaml:"users,omitempty" json:"users,omitempty"`
2727
WriteFiles []WriteFiles `yaml:"write_files,omitempty" json:"writeFiles,omitempty"`
2828
}
2929

@@ -49,6 +49,32 @@ type SSHKeys struct {
4949
EDSCAPublic string `yaml:"ecdsa_public,omitempty" json:"ecdsa_public,omitempty"`
5050
}
5151

52+
type User struct {
53+
Name string `yaml:"name" json:"name"`
54+
// +kubebuilder:validation:Pattern:="^/d{4}-(0[1-9]|1[012])-(0[1-9]|[12][0-9]|3[01])$"
55+
ExpireDate string `yaml:"expiredate,omitempty" json:"expiredate,omitempty"`
56+
GECOS string `yaml:"gecos,omitempty" json:"gecos,omitempty"`
57+
// +kubebuilder:validation:Pattern:=^/.+
58+
HomeDir string `yaml:"homedir,omitempty" json:"homedir,omitempty"`
59+
PrimaryGroup string `yaml:"primary_group,omitempty" json:"primary_group,omitempty"`
60+
Groups []string `yaml:"groups,omitempty" json:"groups,omitempty"`
61+
SELinuxUser string `yaml:"selinux_user,omitempty" json:"selinux_user,omitempty"`
62+
LockPasswd bool `yaml:"lock_passwd,omitempty" json:"lock_passwd,omitempty"`
63+
// +kubebuilder:validation:Minimum:=0
64+
Inactive int `yaml:"inactive,omitempty" json:"inactive,omitempty"`
65+
Passwd string `yaml:"passwd,omitempty" json:"passwd,omitempty"`
66+
NoCreateHome bool `yaml:"no_create_home,omitempty" json:"no_create_home,omitempty"`
67+
NoUserGroup bool `yaml:"no_user_group,omitempty" json:"no_user_group,omitempty"`
68+
NoLogInit bool `yaml:"no_log_init,omitempty" json:"no_log_init,omitempty"`
69+
SSHImportID []string `yaml:"ssh_import_id,omitempty" json:"ssh_import_id,omitempty"`
70+
SSHAuthorizedKeys []string `yaml:"ssh_authorized_keys,omitempty" json:"ssh_authorized_keys,omitempty"`
71+
SSHRedirectUser bool `yaml:"ssh_redirect_user,omitempty" json:"ssh_redirect_user,omitempty"`
72+
Sudo []string `yaml:"sudo,omitempty" json:"sudo,omitempty"`
73+
System bool `yaml:"system,omitempty" json:"system,omitempty"`
74+
SnapUser string `yaml:"snapuser,omitempty" json:"snapuser,omitempty"`
75+
Shell string `yaml:"shell,omitempty" json:"shell,omitempty"`
76+
}
77+
5278
type WriteFiles struct {
5379
Encoding string `yaml:"encoding,omitempty" json:"encoding,omitempty"`
5480
Path string `yaml:"path,omitempty" json:"path,omitempty"`

api/v1beta1/zz_generated.deepcopy.go

Lines changed: 45 additions & 8 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

cloud/cloudinit/user.go

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -9,23 +9,23 @@ import (
99
infrav1 "github.com/sp-yduck/cluster-api-provider-proxmox/api/v1beta1"
1010
)
1111

12-
func ParseUser(content string) (*infrav1.User, error) {
13-
var config *infrav1.User
12+
func ParseUserData(content string) (*infrav1.UserData, error) {
13+
var config *infrav1.UserData
1414
if err := yaml.Unmarshal([]byte(content), &config); err != nil {
1515
return nil, err
1616
}
1717
return config, nil
1818
}
1919

20-
func GenerateUserYaml(config infrav1.User) (string, error) {
20+
func GenerateUserDataYaml(config infrav1.UserData) (string, error) {
2121
b, err := yaml.Marshal(&config)
2222
if err != nil {
2323
return "", err
2424
}
2525
return fmt.Sprintf("#cloud-config\n%s", string(b)), nil
2626
}
2727

28-
func MergeUsers(a, b *infrav1.User) (*infrav1.User, error) {
28+
func MergeUserDatas(a, b *infrav1.UserData) (*infrav1.UserData, error) {
2929
if err := mergo.Merge(a, b, mergo.WithAppendSlice); err != nil {
3030
return nil, err
3131
}

cloud/cloudinit/user_test.go

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ runcmd:
2222
- "chmod +x /usr/local/bin/kubectl"
2323
- "reboot now"
2424
`
25-
_, err := cloudinit.ParseUser(testYaml)
25+
_, err := cloudinit.ParseUserData(testYaml)
2626
if err != nil {
2727
t.Errorf("failed to parse user: %v", err)
2828
}
@@ -35,7 +35,7 @@ owner: root:root
3535
content: |
3636
asdfasdfasdf
3737
`
38-
user, err := cloudinit.ParseUser(testYaml)
38+
user, err := cloudinit.ParseUserData(testYaml)
3939
if err == nil {
4040
t.Errorf("should returns an error. user=%v", *user)
4141
}
@@ -56,31 +56,31 @@ runcmd:
5656
- "reboot now"
5757
`
5858

59-
uc, err := cloudinit.ParseUser(testYaml)
59+
uc, err := cloudinit.ParseUserData(testYaml)
6060
if err != nil {
6161
t.Fatalf("failed to parse user: %v", err)
6262
}
6363

64-
_, err = cloudinit.GenerateUserYaml(*uc)
64+
_, err = cloudinit.GenerateUserDataYaml(*uc)
6565
if err != nil {
6666
t.Fatalf("generate : %v", err)
6767
}
6868
}
6969

7070
func TestMergeUsers(t *testing.T) {
71-
a := infrav1.User{
71+
a := infrav1.UserData{
7272
User: "override-user",
7373
RunCmd: []string{"command A", "command B"},
7474
}
75-
b := infrav1.User{
75+
b := infrav1.UserData{
7676
User: "test-user",
7777
RunCmd: []string{"command C"},
7878
}
79-
expected := infrav1.User{
79+
expected := infrav1.UserData{
8080
User: "override-user",
8181
RunCmd: []string{"command A", "command B", "command C"},
8282
}
83-
c, err := cloudinit.MergeUsers(&a, &b)
83+
c, err := cloudinit.MergeUserDatas(&a, &b)
8484
if err != nil {
8585
t.Errorf("failed to merge cloud init user data: %v", err)
8686
}

cloud/services/compute/instance/cloudinit.go

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ func (s *Service) reconcileCloudInit(ctx context.Context) error {
2020
log := log.FromContext(ctx)
2121
log.Info("Reconciling cloud init")
2222

23-
// user
23+
// user-data
2424
if err := s.reconcileCloudInitUser(ctx); err != nil {
2525
return err
2626
}
@@ -55,18 +55,18 @@ func (s *Service) reconcileCloudInitUser(ctx context.Context) error {
5555
log.Error(err, "Error getting bootstrap data for machine")
5656
return errors.Wrap(err, "failed to retrieve bootstrap data")
5757
}
58-
bootstrapConfig, err := cloudinit.ParseUser(bootstrap)
58+
bootstrapConfig, err := cloudinit.ParseUserData(bootstrap)
5959
if err != nil {
6060
return err
6161
}
6262

6363
vmName := s.scope.Name()
64-
cloudConfig, err := mergeUserDatas(bootstrapConfig, baseUserData(vmName), s.scope.GetCloudInit().User)
64+
cloudConfig, err := mergeUserDatas(bootstrapConfig, baseUserData(vmName), s.scope.GetCloudInit().UserData)
6565
if err != nil {
6666
return err
6767
}
6868

69-
configYaml, err := cloudinit.GenerateUserYaml(*cloudConfig)
69+
configYaml, err := cloudinit.GenerateUserDataYaml(*cloudConfig)
7070
if err != nil {
7171
return err
7272
}
@@ -87,15 +87,15 @@ func (s *Service) reconcileCloudInitUser(ctx context.Context) error {
8787

8888
// a and b must not be nil
8989
// only c can be nil
90-
func mergeUserDatas(a, b, c *infrav1.User) (*infrav1.User, error) {
90+
func mergeUserDatas(a, b, c *infrav1.UserData) (*infrav1.UserData, error) {
9191
var err error
9292
if c != nil {
93-
c, err = cloudinit.MergeUsers(c, b)
93+
c, err = cloudinit.MergeUserDatas(c, b)
9494
if err != nil {
9595
return nil, err
9696
}
9797
}
98-
c, err = cloudinit.MergeUsers(c, a)
98+
c, err = cloudinit.MergeUserDatas(c, a)
9999
if err != nil {
100100
return nil, err
101101
}
@@ -106,8 +106,8 @@ func userSnippetPath(vmName string) string {
106106
return fmt.Sprintf(userSnippetPathFormat, vmName)
107107
}
108108

109-
func baseUserData(vmName string) *infrav1.User {
110-
return &infrav1.User{
109+
func baseUserData(vmName string) *infrav1.UserData {
110+
return &infrav1.UserData{
111111
HostName: vmName,
112112
Packages: []string{"qemu-guest-agent"},
113113
RunCmd: []string{"systemctl start qemu-guest-agent"},

config/crd/bases/infrastructure.cluster.x-k8s.io_proxmoxmachines.yaml

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -129,6 +129,64 @@ spec:
129129
type: boolean
130130
user:
131131
type: string
132+
users:
133+
items:
134+
properties:
135+
expiredate:
136+
pattern: ^/d{4}-(0[1-9]|1[012])-(0[1-9]|[12][0-9]|3[01])$
137+
type: string
138+
gecos:
139+
type: string
140+
groups:
141+
items:
142+
type: string
143+
type: array
144+
homedir:
145+
pattern: ^/.+
146+
type: string
147+
inactive:
148+
minimum: 0
149+
type: integer
150+
lock_passwd:
151+
type: boolean
152+
name:
153+
type: string
154+
no_create_home:
155+
type: boolean
156+
no_log_init:
157+
type: boolean
158+
no_user_group:
159+
type: boolean
160+
passwd:
161+
type: string
162+
primary_group:
163+
type: string
164+
selinux_user:
165+
type: string
166+
shell:
167+
type: string
168+
snapuser:
169+
type: string
170+
ssh_authorized_keys:
171+
items:
172+
type: string
173+
type: array
174+
ssh_import_id:
175+
items:
176+
type: string
177+
type: array
178+
ssh_redirect_user:
179+
type: boolean
180+
sudo:
181+
items:
182+
type: string
183+
type: array
184+
system:
185+
type: boolean
186+
required:
187+
- name
188+
type: object
189+
type: array
132190
writeFiles:
133191
items:
134192
properties:

0 commit comments

Comments
 (0)