Skip to content

Commit c095b98

Browse files
authored
Merge pull request #362 from xiaods/dev
update cmds
2 parents 28b0b25 + d4f87f7 commit c095b98

File tree

8 files changed

+346
-219
lines changed

8 files changed

+346
-219
lines changed

cmd/cert/main.go

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,17 +5,18 @@ import (
55
"errors"
66
"os"
77

8-
"github.com/sirupsen/logrus"
9-
"github.com/urfave/cli"
108
"github.com/xiaods/k8e/pkg/cli/cert"
119
"github.com/xiaods/k8e/pkg/cli/cmds"
1210
"github.com/xiaods/k8e/pkg/configfilearg"
11+
"github.com/sirupsen/logrus"
12+
"github.com/urfave/cli"
1313
)
1414

1515
func main() {
1616
app := cmds.NewApp()
1717
app.Commands = []cli.Command{
1818
cmds.NewCertCommands(
19+
cert.Check,
1920
cert.Rotate,
2021
cert.RotateCA,
2122
),
@@ -24,4 +25,4 @@ func main() {
2425
if err := app.Run(configfilearg.MustParse(os.Args)); err != nil && !errors.Is(err, context.Canceled) {
2526
logrus.Fatal(err)
2627
}
27-
}
28+
}

cmd/k8e/main.go

Lines changed: 114 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -4,14 +4,15 @@ import (
44
"bytes"
55
"context"
66
"io"
7+
"io/fs"
78
"os"
89
"os/exec"
910
"path/filepath"
1011
"strconv"
1112
"strings"
1213

1314
"github.com/pkg/errors"
14-
"github.com/rancher/wrangler/pkg/resolvehome"
15+
"github.com/rancher/wrangler/v3/pkg/resolvehome"
1516
"github.com/sirupsen/logrus"
1617
"github.com/spf13/pflag"
1718
"github.com/urfave/cli"
@@ -29,6 +30,10 @@ var criDefaultConfigPath = "/etc/crictl.yaml"
2930

3031
// main entrypoint for the k8e multicall binary
3132
func main() {
33+
if findDebug(os.Args) {
34+
logrus.SetLevel(logrus.DebugLevel)
35+
}
36+
3237
dataDir := findDataDir(os.Args)
3338

3439
// Handle direct invocation via symlink alias (multicall binary behavior)
@@ -51,33 +56,32 @@ func main() {
5156
cmds.NewCRICTL(externalCLIAction("crictl", dataDir)),
5257
cmds.NewCtrCommand(externalCLIAction("ctr", dataDir)),
5358
cmds.NewCheckConfigCommand(externalCLIAction("check-config", dataDir)),
54-
cmds.NewInitOSConfigCommand(externalCLIAction("init-os-config", dataDir)),
5559
cmds.NewTokenCommands(
5660
tokenCommand,
5761
tokenCommand,
5862
tokenCommand,
5963
tokenCommand,
6064
tokenCommand,
6165
),
62-
cmds.NewEtcdSnapshotCommand(etcdsnapshotCommand,
63-
cmds.NewEtcdSnapshotSubcommands(
64-
etcdsnapshotCommand,
65-
etcdsnapshotCommand,
66-
etcdsnapshotCommand,
67-
etcdsnapshotCommand),
66+
cmds.NewEtcdSnapshotCommands(
67+
etcdsnapshotCommand,
68+
etcdsnapshotCommand,
69+
etcdsnapshotCommand,
70+
etcdsnapshotCommand,
6871
),
69-
cmds.NewSecretsEncryptCommand(secretsencryptCommand,
70-
cmds.NewSecretsEncryptSubcommands(
71-
secretsencryptCommand,
72-
secretsencryptCommand,
73-
secretsencryptCommand,
74-
secretsencryptCommand,
75-
secretsencryptCommand,
76-
secretsencryptCommand),
72+
cmds.NewSecretsEncryptCommands(
73+
secretsencryptCommand,
74+
secretsencryptCommand,
75+
secretsencryptCommand,
76+
secretsencryptCommand,
77+
secretsencryptCommand,
78+
secretsencryptCommand,
79+
secretsencryptCommand,
7780
),
7881
cmds.NewCertCommands(
7982
certCommand,
8083
certCommand,
84+
certCommand,
8185
),
8286
cmds.NewCompletionCommand(internalCLIAction(version.Program+"-completion", dataDir, os.Args)),
8387
}
@@ -87,11 +91,32 @@ func main() {
8791
}
8892
}
8993

90-
// findDataDir reads data-dir settings from the CLI args and config file.
94+
// findDebug reads debug settings from the environment, CLI args, and config file.
95+
func findDebug(args []string) bool {
96+
debug, _ := strconv.ParseBool(os.Getenv(version.ProgramUpper + "_DEBUG"))
97+
if debug {
98+
return debug
99+
}
100+
fs := pflag.NewFlagSet("debug-set", pflag.ContinueOnError)
101+
fs.ParseErrorsWhitelist.UnknownFlags = true
102+
fs.SetOutput(io.Discard)
103+
fs.BoolVarP(&debug, "debug", "", false, "(logging) Turn on debug logs")
104+
fs.Parse(args)
105+
if debug {
106+
return debug
107+
}
108+
debug, _ = strconv.ParseBool(configfilearg.MustFindString(args, "debug"))
109+
return debug
110+
}
111+
112+
// findDataDir reads data-dir settings from the environment, CLI args, and config file.
91113
// If not found, the default will be used, which varies depending on whether
92114
// k8e is being run as root or not.
93115
func findDataDir(args []string) string {
94-
var dataDir string
116+
dataDir := os.Getenv(version.ProgramUpper + "_DATA_DIR")
117+
if dataDir != "" {
118+
return dataDir
119+
}
95120
fs := pflag.NewFlagSet("data-dir-set", pflag.ContinueOnError)
96121
fs.ParseErrorsWhitelist.UnknownFlags = true
97122
fs.SetOutput(io.Discard)
@@ -161,7 +186,7 @@ func externalCLI(cli, dataDir string, args []string) error {
161186
return stageAndRun(dataDir, cli, append([]string{cli}, args...), false)
162187
}
163188

164-
// internalCLIAction returns a function that will call a k8e internal command, be used as the Action of a cli.Command.
189+
// internalCLIAction returns a function that will call a K8e internal command, be used as the Action of a cli.Command.
165190
func internalCLIAction(cmd, dataDir string, args []string) func(ctx *cli.Context) error {
166191
return func(ctx *cli.Context) error {
167192
// We don't want the Info logs seen when printing the autocomplete script
@@ -185,16 +210,24 @@ func stageAndRun(dataDir, cmd string, args []string, calledAsInternal bool) erro
185210
}
186211
logrus.Debugf("Asset dir %s", dir)
187212

188-
var pathEnv string
213+
pathList := []string{
214+
filepath.Clean(filepath.Join(dir, "..", "cni")),
215+
filepath.Join(dir, "bin"),
216+
}
189217
if findPreferBundledBin(args) {
190-
pathEnv = filepath.Join(dir, "bin") + string(os.PathListSeparator) + filepath.Join(dir, "bin/aux") + string(os.PathListSeparator) + os.Getenv("PATH")
218+
pathList = append(
219+
pathList,
220+
filepath.Join(dir, "bin", "aux"),
221+
os.Getenv("PATH"),
222+
)
191223
} else {
192-
pathEnv = filepath.Join(dir, "bin") + string(os.PathListSeparator) + os.Getenv("PATH") + string(os.PathListSeparator) + filepath.Join(dir, "bin/aux")
193-
}
194-
if err := os.Setenv("PATH", pathEnv); err != nil {
195-
return err
224+
pathList = append(
225+
pathList,
226+
os.Getenv("PATH"),
227+
filepath.Join(dir, "bin", "aux"),
228+
)
196229
}
197-
if err := os.Setenv(version.ProgramUpper+"_DATA_DIR", dir); err != nil {
230+
if err := os.Setenv("PATH", strings.Join(pathList, string(os.PathListSeparator))); err != nil {
198231
return err
199232
}
200233

@@ -269,6 +302,53 @@ func extract(dataDir string) (string, error) {
269302
return "", err
270303
}
271304

305+
// Create a stable CNI bin dir and place it first in the path so that users have a
306+
// consistent location to drop their own CNI plugin binaries.
307+
cniPath := filepath.Join(dataDir, "data", "cni")
308+
cniBin := filepath.Join(dir, "bin", "cni")
309+
if err := os.MkdirAll(cniPath, 0755); err != nil {
310+
return "", err
311+
}
312+
// Create symlink that points at the cni multicall binary itself
313+
logrus.Debugf("Creating symlink %s -> %s", filepath.Join(cniPath, "cni"), cniBin)
314+
os.Remove(filepath.Join(cniPath, "cni"))
315+
if err := os.Symlink(cniBin, filepath.Join(cniPath, "cni")); err != nil {
316+
return "", err
317+
}
318+
319+
// Find symlinks that point to the cni multicall binary, and clone them in the stable CNI bin dir.
320+
// Non-symlink plugins in the stable CNI bin dir will not be overwritten, to allow users to replace our
321+
// CNI plugins with their own versions if they want. Note that the cni multicall binary itself is always
322+
// symlinked into the stable bin dir and should not be replaced.
323+
ents, err := os.ReadDir(filepath.Join(tempDest, "bin"))
324+
if err != nil {
325+
return "", err
326+
}
327+
for _, ent := range ents {
328+
if info, err := ent.Info(); err == nil && info.Mode()&fs.ModeSymlink != 0 {
329+
if target, err := os.Readlink(filepath.Join(tempDest, "bin", ent.Name())); err == nil && target == "cni" {
330+
src := filepath.Join(cniPath, ent.Name())
331+
// Check if plugin already exists in stable CNI bin dir
332+
if info, err := os.Lstat(src); err == nil {
333+
if info.Mode()&fs.ModeSymlink != 0 {
334+
// Exists and is a symlink, remove it so we can create a new symlink for the new bin.
335+
os.Remove(src)
336+
} else {
337+
// Not a symlink, leave it alone
338+
logrus.Debugf("Not replacing non-symlink CNI plugin %s with mode %O", src, info.Mode())
339+
continue
340+
}
341+
}
342+
logrus.Debugf("Creating symlink %s -> %s", src, cniBin)
343+
if err := os.Symlink(cniBin, src); err != nil {
344+
return "", err
345+
}
346+
}
347+
}
348+
}
349+
350+
// Rotate 'current' symlink into 'previous', and create a new 'current' that points
351+
// at the new directory.
272352
currentSymLink := filepath.Join(dataDir, "data", "current")
273353
previousSymLink := filepath.Join(dataDir, "data", "previous")
274354
if _, err := os.Lstat(currentSymLink); err == nil {
@@ -279,7 +359,14 @@ func extract(dataDir string) (string, error) {
279359
if err := os.Symlink(dir, currentSymLink); err != nil {
280360
return "", err
281361
}
282-
return dir, os.Rename(tempDest, dir)
362+
363+
// Rename the new directory into place after updating symlinks, so that the k8e binary check at the start
364+
// of this function only succeeds if everything else has been completed successfully.
365+
if err := os.Rename(tempDest, dir); err != nil {
366+
return "", err
367+
}
368+
369+
return dir, nil
283370
}
284371

285372
// findCriConfig returns the path to crictl.yaml

pkg/cli/cmds/agent.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,8 @@ import (
44
"os"
55
"path/filepath"
66

7-
"github.com/xiaods/k8e/pkg/version"
87
"github.com/urfave/cli"
8+
"github.com/xiaods/k8e/pkg/version"
99
)
1010

1111
type Agent struct {

pkg/cli/cmds/certs.go

Lines changed: 11 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -23,23 +23,19 @@ var (
2323
DataDirFlag,
2424
&cli.StringSliceFlag{
2525
Name: "service,s",
26-
Usage: "List of services to rotate certificates for. Options include (admin, api-server, controller-manager, scheduler, " + version.Program + "-controller, " + version.Program + "-server, cloud-controller, etcd, auth-proxy, kubelet)",
26+
Usage: "List of services to manage certificates for. Options include (admin, api-server, controller-manager, scheduler, supervisor, " + version.Program + "-controller, " + version.Program + "-server, cloud-controller, etcd, auth-proxy, kubelet, kube-proxy)",
2727
Value: &ServicesList,
2828
},
2929
}
3030
CertRotateCACommandFlags = []cli.Flag{
31+
DataDirFlag,
3132
cli.StringFlag{
3233
Name: "server,s",
3334
Usage: "(cluster) Server to connect to",
3435
EnvVar: version.ProgramUpper + "_URL",
3536
Value: "https://127.0.0.1:6443",
3637
Destination: &ServerConfig.ServerURL,
3738
},
38-
cli.StringFlag{
39-
Name: "data-dir,d",
40-
Usage: "(data) Folder to hold state default /var/lib/" + version.Program + " or ${HOME}/." + version.Program + " if not root",
41-
Destination: &ServerConfig.DataDir,
42-
},
4339
cli.StringFlag{
4440
Name: "path",
4541
Usage: "Path to directory containing new CA certificates",
@@ -54,13 +50,21 @@ var (
5450
}
5551
)
5652

57-
func NewCertCommands(rotate, rotateCA func(ctx *cli.Context) error) cli.Command {
53+
func NewCertCommands(check, rotate, rotateCA func(ctx *cli.Context) error) cli.Command {
5854
return cli.Command{
5955
Name: CertCommand,
6056
Usage: "Manage K8e certificates",
6157
SkipFlagParsing: false,
6258
SkipArgReorder: true,
6359
Subcommands: []cli.Command{
60+
{
61+
Name: "check",
62+
Usage: "Check " + version.Program + " component certificates on disk",
63+
SkipFlagParsing: false,
64+
SkipArgReorder: true,
65+
Action: check,
66+
Flags: CertRotateCommandFlags,
67+
},
6468
{
6569
Name: "rotate",
6670
Usage: "Rotate " + version.Program + " component certificates on disk",

0 commit comments

Comments
 (0)