Skip to content

Commit

Permalink
feat(server): update default template to Ubuntu 24.04 (#322)
Browse files Browse the repository at this point in the history
Also enable metadata service by default when the selected (or default)
template requires it.
  • Loading branch information
kangasta authored Jul 17, 2024
1 parent e7dd058 commit e9ec6c5
Show file tree
Hide file tree
Showing 7 changed files with 102 additions and 38 deletions.
5 changes: 5 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,11 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

## [Unreleased]

### Changed

- 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.
- 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.

## [3.9.0] - 2024-07-04

### Added
Expand Down
4 changes: 2 additions & 2 deletions examples/create_and_ssh_into_a_server.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ In order to be able to connect to the server we are going to create, we will nee

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

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

# Wait for a moment for the ssh server to become available
sleep 15
sleep 30

ssh -i id_ed25519 -o StrictHostKeyChecking=accept-new root@$ip "hostname"
```
Expand Down
8 changes: 4 additions & 4 deletions examples/possible_exit_codes.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ upctl server create
# Error: required flag(s) "hostname", "zone" not set
```

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.
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.

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

upctl server stop ${prefix}vm-1 --wait
upctl server stop --type hard ${prefix}vm-1 --wait
```

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.

```sh exit_code=1
upctl server stop ${prefix}vm-1 ${prefix}vm-2 --wait
upctl server stop --type hard ${prefix}vm-1 ${prefix}vm-2 --wait
```

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.

```sh exit_code=2
upctl server stop ${prefix}vm-1 ${prefix}vm-2 --wait
upctl server stop --type hard ${prefix}vm-1 ${prefix}vm-2 --wait
```

Finally, we can cleanup the created resources.
Expand Down
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ go 1.21

require (
github.com/UpCloudLtd/progress v1.0.2
github.com/UpCloudLtd/upcloud-go-api/v8 v8.4.0
github.com/UpCloudLtd/upcloud-go-api/v8 v8.6.2
github.com/adrg/xdg v0.3.2
github.com/asaskevich/govalidator v0.0.0-20210307081110-f21760c49a8d
github.com/gemalto/flume v0.12.0
Expand Down
4 changes: 2 additions & 2 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,8 @@ github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym
github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU=
github.com/UpCloudLtd/progress v1.0.2 h1:CTr1bBuFuXop9TEhR1PakbUMPTlUVL7Bgae9JgqXwPg=
github.com/UpCloudLtd/progress v1.0.2/go.mod h1:iGxOnb9HvHW0yrLGUjHr0lxHhn7TehgWwh7a8NqK6iQ=
github.com/UpCloudLtd/upcloud-go-api/v8 v8.4.0 h1:xtc+lscOHhrA4d2N8ifjAOu0zL/d8OXhnFI1w9BIbPg=
github.com/UpCloudLtd/upcloud-go-api/v8 v8.4.0/go.mod h1:/BL9bYxio0GCdotzBvZjkpm1fSDtD0+0z6PtNMew9HU=
github.com/UpCloudLtd/upcloud-go-api/v8 v8.6.2 h1:jmHb2PBA4fbDQRR4WrpD94ncSqQ8EAnzJ7PZS0AmALk=
github.com/UpCloudLtd/upcloud-go-api/v8 v8.6.2/go.mod h1:/BL9bYxio0GCdotzBvZjkpm1fSDtD0+0z6PtNMew9HU=
github.com/adrg/xdg v0.3.2 h1:GUSGQ5pHdev83AYhDSS1A/CX+0JIsxbiWtow2DSA+RU=
github.com/adrg/xdg v0.3.2/go.mod h1:7I2hH/IT30IsupOpKZ5ue7/qNi3CoKzD6tL3HwpaRMQ=
github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
Expand Down
31 changes: 21 additions & 10 deletions internal/commands/server/create.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,14 +27,14 @@ func CreateCommand() commands.Command {
return &createCommand{
BaseCommand: commands.New(
"create",
"Create a server",
"upctl server create --title myapp --zone fi-hel1 --hostname myapp --password-delivery email",
"upctl server create --wait --title myapp --zone fi-hel1 --hostname myapp --password-delivery email",
"upctl server create --title \"My Server\" --zone fi-hel1 --hostname myapp --password-delivery email",
"upctl server create --zone fi-hel1 --hostname myapp --password-delivery email --plan 2xCPU-4GB",
"upctl server create --zone fi-hel1 --hostname myapp --password-delivery email --plan custom --cores 2 --memory 4096",
"Create a new server",
"upctl server create --title myapp --zone fi-hel1 --hostname myapp --ssh-keys ~/.ssh/id_*.pub",
"upctl server create --wait --title myapp --zone fi-hel1 --hostname myapp --ssh-keys ~/.ssh/id_*.pub",
"upctl server create --title \"My Server\" --zone fi-hel1 --hostname myapp --ssh-keys ~/.ssh/id_*.pub",
"upctl server create --zone fi-hel1 --hostname myapp --ssh-keys ~/.ssh/id_*.pub --plan 2xCPU-4GB",
"upctl server create --zone fi-hel1 --hostname myapp --ssh-keys ~/.ssh/id_*.pub --plan custom --cores 2 --memory 4096",
"upctl server create --zone fi-hel1 --hostname myapp --password-delivery email --os \"Debian GNU/Linux 10 (Buster)\" --server-group a4643646-8342-4324-4134-364138712378",
"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",
"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",
),
}
}
Expand All @@ -48,7 +48,7 @@ var defaultCreateParams = &createParams{
},
firewall: false,
metadata: false,
os: "Ubuntu Server 20.04 LTS (Focal Fossa)",
os: "Ubuntu Server 24.04 LTS (Noble Numbat)",
osStorageSize: 0,
sshKeys: nil,
username: "",
Expand Down Expand Up @@ -96,6 +96,11 @@ func (s *createParams) processParams(exec commands.Executor) error {
}
}

// Enable metadata service for cloud-init templates. Leave empty for other templates to use value defined by user.
if osStorage.TemplateType == upcloud.StorageTemplateTypeCloudInit {
s.CreateServerRequest.Metadata = upcloud.True
}

s.StorageDevices = append(s.StorageDevices, request.CreateServerStorageDevice{
Action: "clone",
Address: "virtio",
Expand Down Expand Up @@ -252,6 +257,10 @@ type createCommand struct {

// InitCommand implements Command.InitCommand
func (s *createCommand) InitCommand() {
s.Cobra().Long = commands.WrapLongDescription(`Create a new server
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.`)

fs := &pflag.FlagSet{}
s.params = createParams{CreateServerRequest: request.CreateServerRequest{}}
def := defaultCreateParams
Expand All @@ -260,7 +269,7 @@ func (s *createCommand) InitCommand() {
fs.IntVar(&s.params.CoreNumber, "cores", def.CoreNumber, "Number of cores. Only allowed if `plan` option is set to \"custom\".")
config.AddToggleFlag(fs, &s.createPassword, "create-password", def.createPassword, "Create an admin password.")
config.AddEnableOrDisableFlag(fs, &s.firewall, def.firewall, "firewall", "firewall")
config.AddEnableOrDisableFlag(fs, &s.metadata, def.metadata, "metadata", "metadata service")
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")
config.AddEnableOrDisableFlag(fs, &s.remoteAccess, def.remoteAccess, "remote-access", "remote access")
fs.IntVar(&s.params.Host, "host", def.Host, hostDescription)
fs.StringVar(&s.params.Hostname, "hostname", def.Hostname, "Server hostname.")
Expand Down Expand Up @@ -335,7 +344,9 @@ func (s *createCommand) ExecuteWithoutArguments(exec commands.Executor) (output.
if s.firewall.Value() {
req.Firewall = "on"
}
req.Metadata = s.metadata.AsUpcloudBoolean()
if req.Metadata.Empty() {
req.Metadata = s.metadata.AsUpcloudBoolean()
}
req.RemoteAccessEnabled = s.remoteAccess.AsUpcloudBoolean()
if s.createPassword.Value() {
req.LoginUser.CreatePassword = "yes"
Expand Down
86 changes: 67 additions & 19 deletions internal/commands/server/create_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,6 @@ var (
Title1 = "mock-storage-title1"
Title2 = "mock-storage-title2"
UUID1 = "0127dfd6-3884-4079-a948-3a8881df1a7a"
UUID2 = "012bde1d-f0e7-4bb2-9f4a-74e1f2b49c07"
UUID3 = "012c61a6-b8f0-48c2-a63a-b4bf7d26a655"
PrivateNetworkUUID = "03b5b0a0-ad4c-4817-9632-dafdb3ace5d9"
MockPrivateIPv4 = "10.0.0.1"
Expand Down Expand Up @@ -49,15 +48,24 @@ func TestCreateServer(t *testing.T) {
Tier: "maxiops",
}

StorageDef := upcloud.Storage{
UUID: UUID2,
Title: "Ubuntu Server 20.04 LTS (Focal Fossa)",
Access: "private",
State: "online",
Type: "normal",
Zone: "fi-hel1",
Size: 40,
Tier: "maxiops",
StorageUbuntu2004 := upcloud.Storage{
UUID: "01000000-0000-4000-8000-000030200200",
Title: "Ubuntu Server 20.04 LTS (Focal Fossa)",
Access: "public",
State: "online",
Type: "template",
Size: 4,
TemplateType: "native",
}

StorageUbuntu2404 := upcloud.Storage{
UUID: "01000000-0000-4000-8000-000030240200",
Title: "Ubuntu Server 24.04 LTS (Noble Numbat)",
Access: "public",
State: "online",
Type: "template",
Size: 4,
TemplateType: "cloud-init",
}

Storage3 := upcloud.Storage{
Expand All @@ -73,7 +81,8 @@ func TestCreateServer(t *testing.T) {
storages := &upcloud.Storages{
Storages: []upcloud.Storage{
Storage1,
StorageDef,
StorageUbuntu2004,
StorageUbuntu2404,
Storage3,
},
}
Expand All @@ -88,6 +97,7 @@ func TestCreateServer(t *testing.T) {

serverDetailsStarted := serverDetailsMaint
serverDetailsStarted.State = upcloud.ServerStateStarted
sshKey := "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIHicO0RGJyOSGeMtrmXK1upkkrL5yOrRdjNFl0FLwV00 Example public key"

for _, test := range []struct {
name string
Expand All @@ -101,7 +111,7 @@ func TestCreateServer(t *testing.T) {
"--hostname", "example.com",
"--title", "test-server",
"--zone", "uk-lon1",
"--password-delivery", "email",
"--ssh-keys", sshKey,
},
createServerReq: request.CreateServerRequest{
VideoModel: "vga",
Expand All @@ -110,12 +120,47 @@ func TestCreateServer(t *testing.T) {
Hostname: "example.com",
Title: "test-server",
Zone: "uk-lon1",
PasswordDelivery: "email",
LoginUser: &request.LoginUser{CreatePassword: "yes"},
Metadata: upcloud.True,
PasswordDelivery: "none",
LoginUser: &request.LoginUser{
CreatePassword: "no",
SSHKeys: []string{sshKey},
},
StorageDevices: request.CreateServerStorageDeviceSlice{request.CreateServerStorageDevice{
Action: "clone",
Address: "virtio",
Storage: StorageUbuntu2404.UUID,
Title: "example.com-OS",
Size: 50,
Type: upcloud.StorageTypeDisk,
}},
},
},
{
name: "use native template",
args: []string{
"--hostname", "example.com",
"--title", "test-server",
"--zone", "uk-lon1",
"--os", "Ubuntu Server 20.04 LTS (Focal Fossa)",
"--ssh-keys", sshKey,
},
createServerReq: request.CreateServerRequest{
VideoModel: "vga",
TimeZone: "UTC",
Plan: "1xCPU-2GB",
Hostname: "example.com",
Title: "test-server",
Zone: "uk-lon1",
PasswordDelivery: "none",
LoginUser: &request.LoginUser{
CreatePassword: "no",
SSHKeys: []string{sshKey},
},
StorageDevices: request.CreateServerStorageDeviceSlice{request.CreateServerStorageDevice{
Action: "clone",
Address: "virtio",
Storage: StorageDef.UUID,
Storage: StorageUbuntu2004.UUID,
Title: "example.com-OS",
Size: 50,
Type: upcloud.StorageTypeDisk,
Expand Down Expand Up @@ -202,7 +247,7 @@ func TestCreateServer(t *testing.T) {
StorageDevices: request.CreateServerStorageDeviceSlice{request.CreateServerStorageDevice{
Action: "clone",
Address: "virtio",
Storage: StorageDef.UUID,
Storage: StorageUbuntu2404.UUID,
Title: "example.com-OS",
Size: 10,
Type: upcloud.StorageTypeDisk,
Expand Down Expand Up @@ -231,12 +276,13 @@ func TestCreateServer(t *testing.T) {
Hostname: "example.com",
Title: "test-server",
Zone: "uk-lon1",
Metadata: upcloud.True,
PasswordDelivery: "email",
LoginUser: &request.LoginUser{CreatePassword: "yes"},
StorageDevices: request.CreateServerStorageDeviceSlice{request.CreateServerStorageDevice{
Action: "clone",
Address: "virtio",
Storage: StorageDef.UUID,
Storage: StorageUbuntu2404.UUID,
Title: "example.com-OS",
Size: 50,
Type: upcloud.StorageTypeDisk,
Expand Down Expand Up @@ -275,14 +321,15 @@ func TestCreateServer(t *testing.T) {
Hostname: "example.com",
Title: "test-server",
Zone: "uk-lon1",
Metadata: upcloud.True,
PasswordDelivery: "email",
LoginUser: &request.LoginUser{CreatePassword: "yes"},
StorageDevices: request.CreateServerStorageDeviceSlice{
request.CreateServerStorageDevice{
Action: "clone",
Address: "virtio",
Encrypted: upcloud.FromBool(true),
Storage: StorageDef.UUID,
Storage: StorageUbuntu2404.UUID,
Title: "example.com-OS",
Size: 50,
Type: upcloud.StorageTypeDisk,
Expand Down Expand Up @@ -333,12 +380,13 @@ func TestCreateServer(t *testing.T) {
Hostname: "example.com",
Title: "test-server",
Zone: "uk-lon1",
Metadata: upcloud.True,
PasswordDelivery: "email",
LoginUser: &request.LoginUser{CreatePassword: "yes"},
StorageDevices: request.CreateServerStorageDeviceSlice{request.CreateServerStorageDevice{
Action: "clone",
Address: "virtio",
Storage: StorageDef.UUID,
Storage: StorageUbuntu2404.UUID,
Title: "example.com-OS",
Size: 50,
Type: upcloud.StorageTypeDisk,
Expand Down

0 comments on commit e9ec6c5

Please sign in to comment.