Skip to content

Commit 7e6a246

Browse files
committed
Adds basic implementation for Systemd and adds systemd support for kraft run cmd
Signed-off-by: MdSahil-oss <mohdssahil1@gmail.com>
1 parent cd82032 commit 7e6a246

File tree

6 files changed

+282
-47
lines changed

6 files changed

+282
-47
lines changed

go.mod

+1-1
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ require (
3939
github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510
4040
github.com/google/uuid v1.6.0
4141
github.com/henvic/httpretty v0.1.3
42+
github.com/kardianos/service v1.2.2
4243
github.com/kubescape/go-git-url v0.0.30
4344
github.com/mattn/go-colorable v0.1.13
4445
github.com/mattn/go-isatty v0.0.20
@@ -167,7 +168,6 @@ require (
167168
github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 // indirect
168169
github.com/josharian/intern v1.0.0 // indirect
169170
github.com/json-iterator/go v1.1.12 // indirect
170-
github.com/kardianos/service v1.2.2 // indirect
171171
github.com/kevinburke/ssh_config v1.2.0 // indirect
172172
github.com/klauspost/compress v1.17.4 // indirect
173173
github.com/lucasb-eyer/go-colorful v1.2.0 // indirect

internal/cli/kraft/run/run.go

+67-3
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,12 @@ import (
88
"context"
99
"errors"
1010
"fmt"
11+
"os"
12+
"path/filepath"
13+
"strings"
1114

1215
"github.com/MakeNowJust/heredoc"
16+
"github.com/kardianos/service"
1317
"github.com/sirupsen/logrus"
1418
"github.com/spf13/cobra"
1519
corev1 "k8s.io/api/core/v1"
@@ -19,11 +23,14 @@ import (
1923
machineapi "kraftkit.sh/api/machine/v1alpha1"
2024
"kraftkit.sh/cmdfactory"
2125
"kraftkit.sh/config"
26+
"kraftkit.sh/internal/cli/kraft/remove"
2227
"kraftkit.sh/internal/cli/kraft/start"
28+
"kraftkit.sh/internal/cli/kraft/stop"
2329
"kraftkit.sh/internal/set"
2430
"kraftkit.sh/iostreams"
2531
"kraftkit.sh/log"
2632
mplatform "kraftkit.sh/machine/platform"
33+
"kraftkit.sh/machine/platform/systemd"
2734
"kraftkit.sh/packmanager"
2835
"kraftkit.sh/tui/selection"
2936
ukarch "kraftkit.sh/unikraft/arch"
@@ -51,6 +58,7 @@ type RunOptions struct {
5158
Rootfs string `long:"rootfs" usage:"Specify a path to use as root file system (can be volume or initramfs)"`
5259
RunAs string `long:"as" usage:"Force a specific runner"`
5360
Runtime string `long:"runtime" short:"r" usage:"Set an alternative unikernel runtime"`
61+
Systemd bool `long:"systemd" usage:"runs unikernel as systemd process"`
5462
Target string `long:"target" short:"t" usage:"Explicitly use the defined project target"`
5563
Volumes []string `long:"volume" short:"v" usage:"Bind a volume to the instance"`
5664
WithKernelDbg bool `long:"symbolic" usage:"Use the debuggable (symbolic) unikernel"`
@@ -376,15 +384,71 @@ func (opts *RunOptions) Run(ctx context.Context, args []string) error {
376384
return err
377385
}
378386

379-
if opts.NoStart {
387+
if opts.NoStart && !opts.Systemd {
380388
// Output the name of the instance such that it can be piped
381389
fmt.Fprintf(iostreams.G(ctx).Out, "%s\n", machine.Name)
382390
return nil
383391
}
384392

385-
return start.Start(ctx, &start.StartOptions{
386-
Detach: opts.Detach,
393+
err = start.Start(ctx, &start.StartOptions{
394+
Detach: opts.Systemd || opts.Detach,
387395
Platform: opts.platform.String(),
388396
Remove: opts.Remove,
389397
}, machine.Name)
398+
399+
// Installs systemd serivce that runs a new unikernel instance on each start.
400+
if err == nil && opts.Systemd {
401+
// Stops & removes the created testing instance if that is still runnning & present.
402+
if err = stop.Stop(ctx, &stop.StopOptions{Platform: opts.platform.String()}, machine.Name); err != nil {
403+
log.G(ctx).Debugf("instance %s was already stopped", machine.Name)
404+
}
405+
if err = remove.Remove(ctx, &remove.RemoveOptions{Platform: opts.platform.String()}, machine.Name); err != nil {
406+
log.G(ctx).Errorf("could not remove %s", machine.Name)
407+
}
408+
409+
opts.Name = machine.Name
410+
opts.Remove = true
411+
sysdArgs := []string{"run"}
412+
sysdArgs = append(sysdArgs, opts.GetArgs()...)
413+
414+
if len(args) > 0 {
415+
if strings.HasPrefix(args[0], ".") {
416+
pwd, err := os.Getwd()
417+
if err != nil {
418+
return err
419+
}
420+
args[0] = filepath.Join(pwd, args[0])
421+
}
422+
sysdArgs = append(sysdArgs, args[0])
423+
} else {
424+
sysdArgs = append(sysdArgs, opts.workdir)
425+
}
426+
427+
svcConfig, err := systemd.NewMachineV1alpha1ServiceSystemdWrapper(
428+
ctx,
429+
systemd.WithName(machine.Name),
430+
systemd.WithDescription("created by Kraftkit"),
431+
systemd.WithArguments(sysdArgs),
432+
systemd.WithOptions(service.KeyValue{
433+
"Restart": "never",
434+
}),
435+
)
436+
if err != nil {
437+
return err
438+
}
439+
440+
machine, err = svcConfig.Create(ctx, machine)
441+
if err != nil {
442+
return err
443+
}
444+
log.G(ctx).Infof("created a systemd process named %s ", svcConfig.Name)
445+
446+
_, err = svcConfig.Start(ctx, machine)
447+
if err != nil {
448+
return err
449+
}
450+
log.G(ctx).Infof("started running %s as systemd process", svcConfig.Name)
451+
}
452+
453+
return err
390454
}

internal/cli/kraft/run/utils.go

+63
Original file line numberDiff line numberDiff line change
@@ -459,3 +459,66 @@ func (opts *RunOptions) parseEnvs(_ context.Context, machine *machineapi.Machine
459459

460460
return nil
461461
}
462+
463+
// GetArgs returns all the arguments of run command as an array of strings.
464+
func (opts *RunOptions) GetArgs() []string {
465+
args := []string{}
466+
if opts.Detach {
467+
args = append(args, "--detach")
468+
}
469+
if opts.DisableAccel {
470+
args = append(args, "--disable-acceleration")
471+
}
472+
if opts.PrefixName {
473+
args = append(args, "--prefix-name")
474+
}
475+
if opts.WithKernelDbg {
476+
args = append(args, "--symbolic")
477+
}
478+
if opts.Remove {
479+
args = append(args, "--rm")
480+
}
481+
if len(opts.Name) > 0 {
482+
args = append(args, "--name", opts.Name)
483+
}
484+
if len(opts.Architecture) > 0 {
485+
args = append(args, "--arch", opts.Architecture)
486+
}
487+
if len(opts.RunAs) > 0 {
488+
args = append(args, "--as", opts.RunAs)
489+
}
490+
if len(opts.KernelArgs) > 0 {
491+
args = append(args, "--kernel-arg", strings.Join(opts.KernelArgs, " "))
492+
}
493+
if len(opts.Kraftfile) > 0 {
494+
args = append(args, "--kraftfile", opts.Kraftfile)
495+
}
496+
if len(opts.MacAddress) > 0 {
497+
args = append(args, "--mac", opts.MacAddress)
498+
}
499+
if len(opts.Memory) > 0 {
500+
args = append(args, "--memory", opts.Memory)
501+
}
502+
if len(opts.Networks) > 0 {
503+
args = append(args, "--network", strings.Join(opts.Networks, " "))
504+
}
505+
if len(opts.Platform) > 0 {
506+
args = append(args, "--plat", opts.Platform)
507+
}
508+
if len(opts.Ports) > 0 {
509+
args = append(args, "--port", strings.Join(opts.Ports, " "))
510+
}
511+
if len(opts.Prefix) > 0 {
512+
args = append(args, "--prefix", opts.Prefix)
513+
}
514+
if len(opts.Rootfs) > 0 {
515+
args = append(args, "--rootfs", opts.Rootfs)
516+
}
517+
if len(opts.Target) > 0 {
518+
args = append(args, "--target ", opts.Target)
519+
}
520+
if len(opts.Volumes) > 0 {
521+
args = append(args, "--volume", strings.Join(opts.Volumes, " "))
522+
}
523+
return args
524+
}

machine/platform/systemd/manage.go

+4-1
Original file line numberDiff line numberDiff line change
@@ -9,9 +9,12 @@ func (p *startStop) Start(s service.Service) error {
99
go p.run()
1010
return nil
1111
}
12-
func (p *startStop) run() {
12+
13+
func (p *startStop) run() error {
1314
// Do work here
15+
return nil
1416
}
17+
1518
func (p *startStop) Stop(s service.Service) error {
1619
// Stop should not block. Return with a few seconds.
1720
return nil

machine/platform/systemd/options.go

+26-10
Original file line numberDiff line numberDiff line change
@@ -4,42 +4,58 @@ import "github.com/kardianos/service"
44

55
type ServiceConfigOption func(*ServiceConfig) error
66

7-
// WithName sets the name of the systemd process.
7+
// WithName sets the name of systemd service.
88
func WithName(name string) ServiceConfigOption {
99
return func(config *ServiceConfig) error {
10-
config.name = name
10+
config.Name = name
1111
return nil
1212
}
1313
}
1414

15-
// WithDisplayName sets the display-name of the systemd process.
15+
// WithDisplayName sets the display-name of systemd service.
1616
func WithDisplayName(dName string) ServiceConfigOption {
1717
return func(config *ServiceConfig) error {
18-
config.displayName = dName
18+
config.DisplayName = dName
1919
return nil
2020
}
2121
}
2222

23-
// WithDescription sets the description of the systemd process.
23+
// WithDescription sets the description/heading of systemd service.
2424
func WithDescription(desc string) ServiceConfigOption {
2525
return func(config *ServiceConfig) error {
26-
config.description = desc
26+
config.Description = desc
2727
return nil
2828
}
2929
}
3030

31-
// WithDependencies sets the dependencies of the systemd process.
31+
// WithDependencies sets the dependencies of systemd service.
3232
func WithDependencies(deps []string) ServiceConfigOption {
3333
return func(config *ServiceConfig) error {
34-
config.dependencies = deps
34+
config.Dependencies = deps
3535
return nil
3636
}
3737
}
3838

39-
// WithOptions sets the options of the systemd process.
39+
// WithEnvVars sets the environment variables for systemd service.
40+
func WithEnvVars(envVars map[string]string) ServiceConfigOption {
41+
return func(config *ServiceConfig) error {
42+
config.EnvVars = envVars
43+
return nil
44+
}
45+
}
46+
47+
// WithArguments sets the arguments to the command executed by systemd service.
48+
func WithArguments(args []string) ServiceConfigOption {
49+
return func(config *ServiceConfig) error {
50+
config.Arguments = args
51+
return nil
52+
}
53+
}
54+
55+
// WithOptions sets the options of systemd service.
4056
func WithOptions(opts service.KeyValue) ServiceConfigOption {
4157
return func(config *ServiceConfig) error {
42-
config.option = opts
58+
config.Option = opts
4359
return nil
4460
}
4561
}

0 commit comments

Comments
 (0)