Skip to content

Commit b050f13

Browse files
vdicephyrog
andauthored
Distro detection parity with containerd-shim-spin's installer (#240)
* implement some basic k8s distro detection * feat(distros): add rke2/k3s setup; call setup func in install Signed-off-by: Vaughn Dice <[email protected]> * feat(node-installer): add k0s support Signed-off-by: Vaughn Dice <[email protected]> * ref(node-installer): rm unused Env param from Restarter Signed-off-by: Vaughn Dice <[email protected]> * feat(node-installer): add DetectDistro tests, testdata Signed-off-by: Vaughn Dice <[email protected]> * ref(node-installer): simplify Restarter to be containerd.Restarter type Signed-off-by: Vaughn Dice <[email protected]> * feat(preset): add preset_test.go Signed-off-by: Vaughn Dice <[email protected]> --------- Signed-off-by: Vaughn Dice <[email protected]> Co-authored-by: Tom Gehrke <[email protected]>
1 parent f6c13b6 commit b050f13

File tree

15 files changed

+474
-8
lines changed

15 files changed

+474
-8
lines changed

cmd/node-installer/detect.go

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
/*
2+
Copyright The SpinKube Authors.
3+
4+
Licensed under the Apache License, Version 2.0 (the "License");
5+
you may not use this file except in compliance with the License.
6+
You may obtain a copy of the License at
7+
8+
http://www.apache.org/licenses/LICENSE-2.0
9+
10+
Unless required by applicable law or agreed to in writing, software
11+
distributed under the License is distributed on an "AS IS" BASIS,
12+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
See the License for the specific language governing permissions and
14+
limitations under the License.
15+
*/
16+
17+
package main
18+
19+
import (
20+
"errors"
21+
"fmt"
22+
"log/slog"
23+
24+
"github.com/spf13/afero"
25+
"github.com/spinkube/runtime-class-manager/internal/preset"
26+
)
27+
28+
var containerdConfigLocations = map[string]preset.Settings{
29+
// Microk8s
30+
"/var/snap/microk8s/current/args/containerd-template.toml": preset.MicroK8s,
31+
// RKE2
32+
"/var/lib/rancher/rke2/agent/etc/containerd/config.toml": preset.RKE2,
33+
// K3s
34+
"/var/lib/rancher/k3s/agent/etc/containerd/config.toml": preset.K3s,
35+
// K0s
36+
"/etc/k0s/containerd.toml": preset.K0s,
37+
// default
38+
"/etc/containerd/config.toml": preset.Default,
39+
}
40+
41+
func DetectDistro(config Config, hostFs afero.Fs) (preset.Settings, error) {
42+
if config.Runtime.ConfigPath != "" {
43+
// containerd config path has been set explicitly
44+
if distro, ok := containerdConfigLocations[config.Runtime.ConfigPath]; ok {
45+
return distro, nil
46+
}
47+
slog.Warn("could not determine distro from containerd config, falling back to defaults", "config", config.Runtime.ConfigPath)
48+
return preset.Default.WithConfigPath(config.Runtime.ConfigPath), nil
49+
}
50+
51+
var errs []error
52+
53+
for loc, distro := range containerdConfigLocations {
54+
_, err := hostFs.Stat(loc)
55+
if err == nil {
56+
// config file found, return corresponding distro settings
57+
return distro, nil
58+
}
59+
errs = append(errs, err)
60+
}
61+
62+
return preset.Settings{}, fmt.Errorf("failed to detect containerd config path: %w", errors.Join(errs...))
63+
}

cmd/node-installer/detect_test.go

Lines changed: 188 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,188 @@
1+
/*
2+
Copyright The SpinKube Authors.
3+
4+
Licensed under the Apache License, Version 2.0 (the "License");
5+
you may not use this file except in compliance with the License.
6+
You may obtain a copy of the License at
7+
8+
http://www.apache.org/licenses/LICENSE-2.0
9+
10+
Unless required by applicable law or agreed to in writing, software
11+
distributed under the License is distributed on an "AS IS" BASIS,
12+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
See the License for the specific language governing permissions and
14+
limitations under the License.
15+
*/
16+
17+
package main_test
18+
19+
import (
20+
"reflect"
21+
"testing"
22+
23+
"github.com/spf13/afero"
24+
main "github.com/spinkube/runtime-class-manager/cmd/node-installer"
25+
"github.com/spinkube/runtime-class-manager/internal/preset"
26+
tests "github.com/spinkube/runtime-class-manager/tests/node-installer"
27+
"github.com/stretchr/testify/require"
28+
)
29+
30+
func Test_DetectDistro(t *testing.T) {
31+
type args struct {
32+
config main.Config
33+
hostFs afero.Fs
34+
}
35+
tests := []struct {
36+
name string
37+
args args
38+
wantErr bool
39+
wantPreset preset.Settings
40+
}{
41+
{
42+
"config_override",
43+
args{
44+
main.Config{
45+
struct {
46+
Name string
47+
ConfigPath string
48+
}{"containerd", preset.MicroK8s.ConfigPath},
49+
struct {
50+
Path string
51+
AssetPath string
52+
}{"/opt/kwasm", "/assets"},
53+
struct{ RootPath string }{""},
54+
},
55+
tests.FixtureFs("../../testdata/node-installer/distros/default"),
56+
},
57+
false,
58+
preset.MicroK8s,
59+
},
60+
{
61+
"config_not_found_fallback_default",
62+
args{
63+
main.Config{
64+
struct {
65+
Name string
66+
ConfigPath string
67+
}{"containerd", "/etc/containerd/not_found.toml"},
68+
struct {
69+
Path string
70+
AssetPath string
71+
}{"/opt/kwasm", "/assets"},
72+
struct{ RootPath string }{""},
73+
},
74+
tests.FixtureFs("../../testdata/node-installer/distros/default"),
75+
},
76+
false,
77+
preset.Default.WithConfigPath("/etc/containerd/not_found.toml"),
78+
},
79+
{
80+
"unsupported",
81+
args{
82+
main.Config{
83+
struct {
84+
Name string
85+
ConfigPath string
86+
}{"containerd", ""},
87+
struct {
88+
Path string
89+
AssetPath string
90+
}{"/opt/kwasm", "/assets"},
91+
struct{ RootPath string }{""},
92+
},
93+
tests.FixtureFs("../../testdata/node-installer/distros/unsupported"),
94+
},
95+
true,
96+
preset.Default,
97+
},
98+
{
99+
"microk8s",
100+
args{
101+
main.Config{
102+
struct {
103+
Name string
104+
ConfigPath string
105+
}{"containerd", ""},
106+
struct {
107+
Path string
108+
AssetPath string
109+
}{"/opt/kwasm", "/assets"},
110+
struct{ RootPath string }{""},
111+
},
112+
tests.FixtureFs("../../testdata/node-installer/distros/microk8s"),
113+
},
114+
false,
115+
preset.MicroK8s,
116+
},
117+
{
118+
"k0s",
119+
args{
120+
main.Config{
121+
struct {
122+
Name string
123+
ConfigPath string
124+
}{"containerd", ""},
125+
struct {
126+
Path string
127+
AssetPath string
128+
}{"/opt/kwasm", "/assets"},
129+
struct{ RootPath string }{""},
130+
},
131+
tests.FixtureFs("../../testdata/node-installer/distros/k0s"),
132+
},
133+
false,
134+
preset.K0s,
135+
},
136+
{
137+
"k3s",
138+
args{
139+
main.Config{
140+
struct {
141+
Name string
142+
ConfigPath string
143+
}{"containerd", ""},
144+
struct {
145+
Path string
146+
AssetPath string
147+
}{"/opt/kwasm", "/assets"},
148+
struct{ RootPath string }{""},
149+
},
150+
tests.FixtureFs("../../testdata/node-installer/distros/k3s"),
151+
},
152+
false,
153+
preset.K3s,
154+
},
155+
{
156+
"rke2",
157+
args{
158+
main.Config{
159+
struct {
160+
Name string
161+
ConfigPath string
162+
}{"containerd", ""},
163+
struct {
164+
Path string
165+
AssetPath string
166+
}{"/opt/kwasm", "/assets"},
167+
struct{ RootPath string }{""},
168+
},
169+
tests.FixtureFs("../../testdata/node-installer/distros/rke2"),
170+
},
171+
false,
172+
preset.RKE2,
173+
},
174+
}
175+
for _, tt := range tests {
176+
t.Run(tt.name, func(t *testing.T) {
177+
preset, err := main.DetectDistro(tt.args.config, tt.args.hostFs)
178+
if tt.wantErr {
179+
require.Error(t, err)
180+
} else {
181+
require.NoError(t, err)
182+
require.Equal(t, tt.wantPreset.ConfigPath, preset.ConfigPath)
183+
require.Equal(t, reflect.ValueOf(tt.wantPreset.Setup), reflect.ValueOf(preset.Setup))
184+
require.Equal(t, reflect.ValueOf(tt.wantPreset.Restarter), reflect.ValueOf(preset.Restarter))
185+
}
186+
})
187+
}
188+
}

cmd/node-installer/install.go

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ import (
2626
"github.com/spf13/afero"
2727
"github.com/spf13/cobra"
2828
"github.com/spinkube/runtime-class-manager/internal/containerd"
29+
"github.com/spinkube/runtime-class-manager/internal/preset"
2930
"github.com/spinkube/runtime-class-manager/internal/shim"
3031
)
3132

@@ -36,9 +37,20 @@ var installCmd = &cobra.Command{
3637
Run: func(_ *cobra.Command, _ []string) {
3738
rootFs := afero.NewOsFs()
3839
hostFs := afero.NewBasePathFs(rootFs, config.Host.RootPath)
39-
restarter := containerd.NewRestarter()
4040

41-
if err := RunInstall(config, rootFs, hostFs, restarter); err != nil {
41+
distro, err := DetectDistro(config, hostFs)
42+
if err != nil {
43+
slog.Error("failed to detect containerd config", "error", err)
44+
os.Exit(1)
45+
}
46+
47+
config.Runtime.ConfigPath = distro.ConfigPath
48+
if err = distro.Setup(preset.Env{ConfigPath: distro.ConfigPath, HostFs: hostFs}); err != nil {
49+
slog.Error("failed to run distro setup", "error", err)
50+
os.Exit(1)
51+
}
52+
53+
if err := RunInstall(config, rootFs, hostFs, distro.Restarter); err != nil {
4254
slog.Error("failed to install", "error", err)
4355
os.Exit(1)
4456
}

cmd/node-installer/root.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@ func Execute() {
5151

5252
func init() {
5353
rootCmd.PersistentFlags().StringVarP(&config.Runtime.Name, "runtime", "r", "containerd", "Set the container runtime to configure (containerd, cri-o)")
54-
rootCmd.PersistentFlags().StringVarP(&config.Runtime.ConfigPath, "runtime-config", "c", "/etc/containerd/config.toml", "Path to the runtime config file")
54+
rootCmd.PersistentFlags().StringVarP(&config.Runtime.ConfigPath, "runtime-config", "c", "", "Path to the runtime config file. Will try to autodetect if left empty")
5555
rootCmd.PersistentFlags().StringVarP(&config.Kwasm.Path, "kwasm-path", "k", "/opt/kwasm", "Working directory for kwasm on the host")
5656
rootCmd.PersistentFlags().StringVarP(&config.Host.RootPath, "host-root", "H", "/", "Path to the host root path")
5757
}

cmd/node-installer/uninstall.go

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -36,13 +36,18 @@ var uninstallCmd = &cobra.Command{
3636
Run: func(_ *cobra.Command, _ []string) {
3737
rootFs := afero.NewOsFs()
3838
hostFs := afero.NewBasePathFs(rootFs, config.Host.RootPath)
39-
restarter := containerd.NewRestarter()
4039

41-
if err := RunUninstall(config, rootFs, hostFs, restarter); err != nil {
42-
slog.Error("failed to uninstall shim", "error", err)
40+
distro, err := DetectDistro(config, hostFs)
41+
if err != nil {
42+
slog.Error("failed to detect containerd config", "error", err)
43+
os.Exit(1)
44+
}
45+
46+
config.Runtime.ConfigPath = distro.ConfigPath
4347

44-
// Exiting with 0 to prevent Kubernetes Jobs from running repetitively
45-
os.Exit(0)
48+
if err := RunUninstall(config, rootFs, hostFs, distro.Restarter); err != nil {
49+
slog.Error("failed to uninstall", "error", err)
50+
os.Exit(1)
4651
}
4752
},
4853
}

0 commit comments

Comments
 (0)