Skip to content

Commit e9ec6c5

Browse files
authored
feat(server): update default template to Ubuntu 24.04 (#322)
Also enable metadata service by default when the selected (or default) template requires it.
1 parent e7dd058 commit e9ec6c5

7 files changed

Lines changed: 102 additions & 38 deletions

File tree

CHANGELOG.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,11 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
77

88
## [Unreleased]
99

10+
### Changed
11+
12+
- In `server create` command, use `Ubuntu Server 24.04 LTS (Noble Numbat)` as default value for `--os`. The new default template only supports SSH key based authentication. Use `--ssh-keys` option to provide the keys when creating a server with the default template.
13+
- In `server create` command, enable metadata service by default when the selected (or default) template uses cloud-init (`template_type` is `cloud-init`) and thus requires it.
14+
1015
## [3.9.0] - 2024-07-04
1116

1217
### Added

examples/create_and_ssh_into_a_server.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ In order to be able to connect to the server we are going to create, we will nee
1212

1313
```sh
1414
# Create ssh-key into current working directory
15-
ssh-keygen -t ed25519 -q -f "./id_ed25519" -N ""
15+
ssh-keygen -t ed25519 -q -f "./id_ed25519" -N "" -C "upctl example"
1616
```
1717

1818
Create a server using the above created ssh-key as login method.
@@ -34,7 +34,7 @@ Find the IP address of the created server from the JSON output of `upctl server
3434
ip=$(upctl server show ${prefix}server -o json | jq -r '.networking.interfaces[] | select(.type == "public") | .ip_addresses[0].address')
3535

3636
# Wait for a moment for the ssh server to become available
37-
sleep 15
37+
sleep 30
3838

3939
ssh -i id_ed25519 -o StrictHostKeyChecking=accept-new root@$ip "hostname"
4040
```

examples/possible_exit_codes.md

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ upctl server create
1515
# Error: required flag(s) "hostname", "zone" not set
1616
```
1717

18-
Let's create two server and stop one of those to later see other failing exit codes. These command should succceed, and thus return zero exit code.
18+
Let's create two servers and stop one of those to later see other failing exit codes. This example uses `--type hard` when stopping the servers as the OS might not be completely up and running when the server reaches running state. These command should succeed, and thus return zero exit code.
1919

2020
```sh
2121
# Create ssh-key into current working directory
@@ -24,19 +24,19 @@ ssh-keygen -t ed25519 -q -f "./id_ed25519" -N ""
2424
upctl server create --hostname ${prefix}vm-1 --zone pl-waw1 --ssh-keys ./id_ed25519.pub --wait
2525
upctl server create --hostname ${prefix}vm-2 --zone pl-waw1 --ssh-keys ./id_ed25519.pub --wait
2626

27-
upctl server stop ${prefix}vm-1 --wait
27+
upctl server stop --type hard ${prefix}vm-1 --wait
2828
```
2929

3030
Now let's try to stop both both of the created servers. Exit code will be one, as `${prefix}vm-1` is already stopped and thus cannot be stopped again. `${prefix}vm-2`, though, will be stopped as it was online. Thus one of the two operations failed.
3131

3232
```sh exit_code=1
33-
upctl server stop ${prefix}vm-1 ${prefix}vm-2 --wait
33+
upctl server stop --type hard ${prefix}vm-1 ${prefix}vm-2 --wait
3434
```
3535

3636
If we now try to run above command again, exit code will be two as both of the servers are already stopped. Thus both stop operations failed.
3737

3838
```sh exit_code=2
39-
upctl server stop ${prefix}vm-1 ${prefix}vm-2 --wait
39+
upctl server stop --type hard ${prefix}vm-1 ${prefix}vm-2 --wait
4040
```
4141

4242
Finally, we can cleanup the created resources.

go.mod

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ go 1.21
44

55
require (
66
github.com/UpCloudLtd/progress v1.0.2
7-
github.com/UpCloudLtd/upcloud-go-api/v8 v8.4.0
7+
github.com/UpCloudLtd/upcloud-go-api/v8 v8.6.2
88
github.com/adrg/xdg v0.3.2
99
github.com/asaskevich/govalidator v0.0.0-20210307081110-f21760c49a8d
1010
github.com/gemalto/flume v0.12.0

go.sum

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,8 +17,8 @@ github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym
1717
github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU=
1818
github.com/UpCloudLtd/progress v1.0.2 h1:CTr1bBuFuXop9TEhR1PakbUMPTlUVL7Bgae9JgqXwPg=
1919
github.com/UpCloudLtd/progress v1.0.2/go.mod h1:iGxOnb9HvHW0yrLGUjHr0lxHhn7TehgWwh7a8NqK6iQ=
20-
github.com/UpCloudLtd/upcloud-go-api/v8 v8.4.0 h1:xtc+lscOHhrA4d2N8ifjAOu0zL/d8OXhnFI1w9BIbPg=
21-
github.com/UpCloudLtd/upcloud-go-api/v8 v8.4.0/go.mod h1:/BL9bYxio0GCdotzBvZjkpm1fSDtD0+0z6PtNMew9HU=
20+
github.com/UpCloudLtd/upcloud-go-api/v8 v8.6.2 h1:jmHb2PBA4fbDQRR4WrpD94ncSqQ8EAnzJ7PZS0AmALk=
21+
github.com/UpCloudLtd/upcloud-go-api/v8 v8.6.2/go.mod h1:/BL9bYxio0GCdotzBvZjkpm1fSDtD0+0z6PtNMew9HU=
2222
github.com/adrg/xdg v0.3.2 h1:GUSGQ5pHdev83AYhDSS1A/CX+0JIsxbiWtow2DSA+RU=
2323
github.com/adrg/xdg v0.3.2/go.mod h1:7I2hH/IT30IsupOpKZ5ue7/qNi3CoKzD6tL3HwpaRMQ=
2424
github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=

internal/commands/server/create.go

Lines changed: 21 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -27,14 +27,14 @@ func CreateCommand() commands.Command {
2727
return &createCommand{
2828
BaseCommand: commands.New(
2929
"create",
30-
"Create a server",
31-
"upctl server create --title myapp --zone fi-hel1 --hostname myapp --password-delivery email",
32-
"upctl server create --wait --title myapp --zone fi-hel1 --hostname myapp --password-delivery email",
33-
"upctl server create --title \"My Server\" --zone fi-hel1 --hostname myapp --password-delivery email",
34-
"upctl server create --zone fi-hel1 --hostname myapp --password-delivery email --plan 2xCPU-4GB",
35-
"upctl server create --zone fi-hel1 --hostname myapp --password-delivery email --plan custom --cores 2 --memory 4096",
30+
"Create a new server",
31+
"upctl server create --title myapp --zone fi-hel1 --hostname myapp --ssh-keys ~/.ssh/id_*.pub",
32+
"upctl server create --wait --title myapp --zone fi-hel1 --hostname myapp --ssh-keys ~/.ssh/id_*.pub",
33+
"upctl server create --title \"My Server\" --zone fi-hel1 --hostname myapp --ssh-keys ~/.ssh/id_*.pub",
34+
"upctl server create --zone fi-hel1 --hostname myapp --ssh-keys ~/.ssh/id_*.pub --plan 2xCPU-4GB",
35+
"upctl server create --zone fi-hel1 --hostname myapp --ssh-keys ~/.ssh/id_*.pub --plan custom --cores 2 --memory 4096",
3636
"upctl server create --zone fi-hel1 --hostname myapp --password-delivery email --os \"Debian GNU/Linux 10 (Buster)\" --server-group a4643646-8342-4324-4134-364138712378",
37-
"upctl server create --zone fi-hel1 --hostname myapp --ssh-keys /path/to/publickey --network type=private,network=037a530b-533e-4cef-b6ad-6af8094bb2bc,ip-address=10.0.0.1",
37+
"upctl server create --zone fi-hel1 --hostname myapp --ssh-keys ~/.ssh/id_*.pub --network type=private,network=037a530b-533e-4cef-b6ad-6af8094bb2bc,ip-address=10.0.0.1",
3838
),
3939
}
4040
}
@@ -48,7 +48,7 @@ var defaultCreateParams = &createParams{
4848
},
4949
firewall: false,
5050
metadata: false,
51-
os: "Ubuntu Server 20.04 LTS (Focal Fossa)",
51+
os: "Ubuntu Server 24.04 LTS (Noble Numbat)",
5252
osStorageSize: 0,
5353
sshKeys: nil,
5454
username: "",
@@ -96,6 +96,11 @@ func (s *createParams) processParams(exec commands.Executor) error {
9696
}
9797
}
9898

99+
// Enable metadata service for cloud-init templates. Leave empty for other templates to use value defined by user.
100+
if osStorage.TemplateType == upcloud.StorageTemplateTypeCloudInit {
101+
s.CreateServerRequest.Metadata = upcloud.True
102+
}
103+
99104
s.StorageDevices = append(s.StorageDevices, request.CreateServerStorageDevice{
100105
Action: "clone",
101106
Address: "virtio",
@@ -252,6 +257,10 @@ type createCommand struct {
252257

253258
// InitCommand implements Command.InitCommand
254259
func (s *createCommand) InitCommand() {
260+
s.Cobra().Long = commands.WrapLongDescription(`Create a new server
261+
262+
Note that the default template, Ubuntu Server 24.04 LTS (Noble Numbat), only supports SSH key based authentication. Use ` + "`" + `--ssh-keys` + "`" + ` option to provide the keys when creating a server with the default template. The examples below use public key from the ` + "`" + `~/.ssh` + "`" + ` directory. If you want to use different authentication method, use ` + "`" + `--os` + "`" + ` parameter to specify a different template.`)
263+
255264
fs := &pflag.FlagSet{}
256265
s.params = createParams{CreateServerRequest: request.CreateServerRequest{}}
257266
def := defaultCreateParams
@@ -260,7 +269,7 @@ func (s *createCommand) InitCommand() {
260269
fs.IntVar(&s.params.CoreNumber, "cores", def.CoreNumber, "Number of cores. Only allowed if `plan` option is set to \"custom\".")
261270
config.AddToggleFlag(fs, &s.createPassword, "create-password", def.createPassword, "Create an admin password.")
262271
config.AddEnableOrDisableFlag(fs, &s.firewall, def.firewall, "firewall", "firewall")
263-
config.AddEnableOrDisableFlag(fs, &s.metadata, def.metadata, "metadata", "metadata service")
272+
config.AddEnableOrDisableFlag(fs, &s.metadata, def.metadata, "metadata", "metadata service. The metadata service will be enabled by default, if the selected OS template uses cloud-init and thus requires metadata service")
264273
config.AddEnableOrDisableFlag(fs, &s.remoteAccess, def.remoteAccess, "remote-access", "remote access")
265274
fs.IntVar(&s.params.Host, "host", def.Host, hostDescription)
266275
fs.StringVar(&s.params.Hostname, "hostname", def.Hostname, "Server hostname.")
@@ -335,7 +344,9 @@ func (s *createCommand) ExecuteWithoutArguments(exec commands.Executor) (output.
335344
if s.firewall.Value() {
336345
req.Firewall = "on"
337346
}
338-
req.Metadata = s.metadata.AsUpcloudBoolean()
347+
if req.Metadata.Empty() {
348+
req.Metadata = s.metadata.AsUpcloudBoolean()
349+
}
339350
req.RemoteAccessEnabled = s.remoteAccess.AsUpcloudBoolean()
340351
if s.createPassword.Value() {
341352
req.LoginUser.CreatePassword = "yes"

internal/commands/server/create_test.go

Lines changed: 67 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,6 @@ var (
2020
Title1 = "mock-storage-title1"
2121
Title2 = "mock-storage-title2"
2222
UUID1 = "0127dfd6-3884-4079-a948-3a8881df1a7a"
23-
UUID2 = "012bde1d-f0e7-4bb2-9f4a-74e1f2b49c07"
2423
UUID3 = "012c61a6-b8f0-48c2-a63a-b4bf7d26a655"
2524
PrivateNetworkUUID = "03b5b0a0-ad4c-4817-9632-dafdb3ace5d9"
2625
MockPrivateIPv4 = "10.0.0.1"
@@ -49,15 +48,24 @@ func TestCreateServer(t *testing.T) {
4948
Tier: "maxiops",
5049
}
5150

52-
StorageDef := upcloud.Storage{
53-
UUID: UUID2,
54-
Title: "Ubuntu Server 20.04 LTS (Focal Fossa)",
55-
Access: "private",
56-
State: "online",
57-
Type: "normal",
58-
Zone: "fi-hel1",
59-
Size: 40,
60-
Tier: "maxiops",
51+
StorageUbuntu2004 := upcloud.Storage{
52+
UUID: "01000000-0000-4000-8000-000030200200",
53+
Title: "Ubuntu Server 20.04 LTS (Focal Fossa)",
54+
Access: "public",
55+
State: "online",
56+
Type: "template",
57+
Size: 4,
58+
TemplateType: "native",
59+
}
60+
61+
StorageUbuntu2404 := upcloud.Storage{
62+
UUID: "01000000-0000-4000-8000-000030240200",
63+
Title: "Ubuntu Server 24.04 LTS (Noble Numbat)",
64+
Access: "public",
65+
State: "online",
66+
Type: "template",
67+
Size: 4,
68+
TemplateType: "cloud-init",
6169
}
6270

6371
Storage3 := upcloud.Storage{
@@ -73,7 +81,8 @@ func TestCreateServer(t *testing.T) {
7381
storages := &upcloud.Storages{
7482
Storages: []upcloud.Storage{
7583
Storage1,
76-
StorageDef,
84+
StorageUbuntu2004,
85+
StorageUbuntu2404,
7786
Storage3,
7887
},
7988
}
@@ -88,6 +97,7 @@ func TestCreateServer(t *testing.T) {
8897

8998
serverDetailsStarted := serverDetailsMaint
9099
serverDetailsStarted.State = upcloud.ServerStateStarted
100+
sshKey := "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIHicO0RGJyOSGeMtrmXK1upkkrL5yOrRdjNFl0FLwV00 Example public key"
91101

92102
for _, test := range []struct {
93103
name string
@@ -101,7 +111,7 @@ func TestCreateServer(t *testing.T) {
101111
"--hostname", "example.com",
102112
"--title", "test-server",
103113
"--zone", "uk-lon1",
104-
"--password-delivery", "email",
114+
"--ssh-keys", sshKey,
105115
},
106116
createServerReq: request.CreateServerRequest{
107117
VideoModel: "vga",
@@ -110,12 +120,47 @@ func TestCreateServer(t *testing.T) {
110120
Hostname: "example.com",
111121
Title: "test-server",
112122
Zone: "uk-lon1",
113-
PasswordDelivery: "email",
114-
LoginUser: &request.LoginUser{CreatePassword: "yes"},
123+
Metadata: upcloud.True,
124+
PasswordDelivery: "none",
125+
LoginUser: &request.LoginUser{
126+
CreatePassword: "no",
127+
SSHKeys: []string{sshKey},
128+
},
129+
StorageDevices: request.CreateServerStorageDeviceSlice{request.CreateServerStorageDevice{
130+
Action: "clone",
131+
Address: "virtio",
132+
Storage: StorageUbuntu2404.UUID,
133+
Title: "example.com-OS",
134+
Size: 50,
135+
Type: upcloud.StorageTypeDisk,
136+
}},
137+
},
138+
},
139+
{
140+
name: "use native template",
141+
args: []string{
142+
"--hostname", "example.com",
143+
"--title", "test-server",
144+
"--zone", "uk-lon1",
145+
"--os", "Ubuntu Server 20.04 LTS (Focal Fossa)",
146+
"--ssh-keys", sshKey,
147+
},
148+
createServerReq: request.CreateServerRequest{
149+
VideoModel: "vga",
150+
TimeZone: "UTC",
151+
Plan: "1xCPU-2GB",
152+
Hostname: "example.com",
153+
Title: "test-server",
154+
Zone: "uk-lon1",
155+
PasswordDelivery: "none",
156+
LoginUser: &request.LoginUser{
157+
CreatePassword: "no",
158+
SSHKeys: []string{sshKey},
159+
},
115160
StorageDevices: request.CreateServerStorageDeviceSlice{request.CreateServerStorageDevice{
116161
Action: "clone",
117162
Address: "virtio",
118-
Storage: StorageDef.UUID,
163+
Storage: StorageUbuntu2004.UUID,
119164
Title: "example.com-OS",
120165
Size: 50,
121166
Type: upcloud.StorageTypeDisk,
@@ -202,7 +247,7 @@ func TestCreateServer(t *testing.T) {
202247
StorageDevices: request.CreateServerStorageDeviceSlice{request.CreateServerStorageDevice{
203248
Action: "clone",
204249
Address: "virtio",
205-
Storage: StorageDef.UUID,
250+
Storage: StorageUbuntu2404.UUID,
206251
Title: "example.com-OS",
207252
Size: 10,
208253
Type: upcloud.StorageTypeDisk,
@@ -231,12 +276,13 @@ func TestCreateServer(t *testing.T) {
231276
Hostname: "example.com",
232277
Title: "test-server",
233278
Zone: "uk-lon1",
279+
Metadata: upcloud.True,
234280
PasswordDelivery: "email",
235281
LoginUser: &request.LoginUser{CreatePassword: "yes"},
236282
StorageDevices: request.CreateServerStorageDeviceSlice{request.CreateServerStorageDevice{
237283
Action: "clone",
238284
Address: "virtio",
239-
Storage: StorageDef.UUID,
285+
Storage: StorageUbuntu2404.UUID,
240286
Title: "example.com-OS",
241287
Size: 50,
242288
Type: upcloud.StorageTypeDisk,
@@ -275,14 +321,15 @@ func TestCreateServer(t *testing.T) {
275321
Hostname: "example.com",
276322
Title: "test-server",
277323
Zone: "uk-lon1",
324+
Metadata: upcloud.True,
278325
PasswordDelivery: "email",
279326
LoginUser: &request.LoginUser{CreatePassword: "yes"},
280327
StorageDevices: request.CreateServerStorageDeviceSlice{
281328
request.CreateServerStorageDevice{
282329
Action: "clone",
283330
Address: "virtio",
284331
Encrypted: upcloud.FromBool(true),
285-
Storage: StorageDef.UUID,
332+
Storage: StorageUbuntu2404.UUID,
286333
Title: "example.com-OS",
287334
Size: 50,
288335
Type: upcloud.StorageTypeDisk,
@@ -333,12 +380,13 @@ func TestCreateServer(t *testing.T) {
333380
Hostname: "example.com",
334381
Title: "test-server",
335382
Zone: "uk-lon1",
383+
Metadata: upcloud.True,
336384
PasswordDelivery: "email",
337385
LoginUser: &request.LoginUser{CreatePassword: "yes"},
338386
StorageDevices: request.CreateServerStorageDeviceSlice{request.CreateServerStorageDevice{
339387
Action: "clone",
340388
Address: "virtio",
341-
Storage: StorageDef.UUID,
389+
Storage: StorageUbuntu2404.UUID,
342390
Title: "example.com-OS",
343391
Size: 50,
344392
Type: upcloud.StorageTypeDisk,

0 commit comments

Comments
 (0)