Skip to content

Commit 068c8af

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 6504a5f commit 068c8af

File tree

6 files changed

+283
-47
lines changed

6 files changed

+283
-47
lines changed

go.mod

+1-1
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ require (
3737
github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510
3838
github.com/google/uuid v1.6.0
3939
github.com/henvic/httpretty v0.1.3
40+
github.com/kardianos/service v1.2.2
4041
github.com/kubescape/go-git-url v0.0.30
4142
github.com/mattn/go-colorable v0.1.13
4243
github.com/mattn/go-isatty v0.0.20
@@ -160,7 +161,6 @@ require (
160161
github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 // indirect
161162
github.com/josharian/intern v1.0.0 // indirect
162163
github.com/json-iterator/go v1.1.12 // indirect
163-
github.com/kardianos/service v1.2.2 // indirect
164164
github.com/kevinburke/ssh_config v1.2.0 // indirect
165165
github.com/klauspost/compress v1.17.4 // indirect
166166
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"
@@ -49,6 +56,7 @@ type RunOptions struct {
4956
Remove bool `long:"rm" usage:"Automatically remove the unikernel when it shutsdown"`
5057
Rootfs string `long:"rootfs" usage:"Specify a path to use as root file system (can be volume or initramfs)"`
5158
RunAs string `long:"as" usage:"Force a specific runner"`
59+
Systemd bool `long:"systemd" usage:"runs unikernel as systemd process"`
5260
Target string `long:"target" short:"t" usage:"Explicitly use the defined project target"`
5361
Volumes []string `long:"volume" short:"v" usage:"Bind a volume to the instance"`
5462
WithKernelDbg bool `long:"symbolic" usage:"Use the debuggable (symbolic) unikernel"`
@@ -374,15 +382,71 @@ func (opts *RunOptions) Run(ctx context.Context, args []string) error {
374382
return err
375383
}
376384

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

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

internal/cli/kraft/run/utils.go

+64
Original file line numberDiff line numberDiff line change
@@ -360,3 +360,67 @@ func (opts *RunOptions) prepareRootfs(ctx context.Context, machine *machineapi.M
360360

361361
return treemodel.Start()
362362
}
363+
364+
// GetArgs returns all the arguments of run command as an array of strings.
365+
func (opts *RunOptions) GetArgs() []string {
366+
367+
args := []string{}
368+
if opts.Detach {
369+
args = append(args, "--detach")
370+
}
371+
if opts.DisableAccel {
372+
args = append(args, "--disable-acceleration")
373+
}
374+
if opts.PrefixName {
375+
args = append(args, "--prefix-name")
376+
}
377+
if opts.WithKernelDbg {
378+
args = append(args, "--symbolic")
379+
}
380+
if opts.Remove {
381+
args = append(args, "--rm")
382+
}
383+
if len(opts.Name) > 0 {
384+
args = append(args, "--name", opts.Name)
385+
}
386+
if len(opts.Architecture) > 0 {
387+
args = append(args, "--arch", opts.Architecture)
388+
}
389+
if len(opts.RunAs) > 0 {
390+
args = append(args, "--as", opts.RunAs)
391+
}
392+
if len(opts.KernelArgs) > 0 {
393+
args = append(args, "--kernel-arg", strings.Join(opts.KernelArgs, " "))
394+
}
395+
if len(opts.Kraftfile) > 0 {
396+
args = append(args, "--kraftfile", opts.Kraftfile)
397+
}
398+
if len(opts.MacAddress) > 0 {
399+
args = append(args, "--mac", opts.MacAddress)
400+
}
401+
if len(opts.Memory) > 0 {
402+
args = append(args, "--memory", opts.Memory)
403+
}
404+
if len(opts.Networks) > 0 {
405+
args = append(args, "--network", strings.Join(opts.Networks, " "))
406+
}
407+
if len(opts.Platform) > 0 {
408+
args = append(args, "--plat", opts.Platform)
409+
}
410+
if len(opts.Ports) > 0 {
411+
args = append(args, "--port", strings.Join(opts.Ports, " "))
412+
}
413+
if len(opts.Prefix) > 0 {
414+
args = append(args, "--prefix", opts.Prefix)
415+
}
416+
if len(opts.Rootfs) > 0 {
417+
args = append(args, "--rootfs", opts.Rootfs)
418+
}
419+
if len(opts.Target) > 0 {
420+
args = append(args, "--target ", opts.Target)
421+
}
422+
if len(opts.Volumes) > 0 {
423+
args = append(args, "--volume", strings.Join(opts.Volumes, " "))
424+
}
425+
return args
426+
}

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)