Initial commit

This commit is contained in:
niku 2023-06-09 11:33:10 +02:00
commit 7c111f97ab
22 changed files with 2221 additions and 0 deletions

44
.air.toml Normal file
View File

@ -0,0 +1,44 @@
root = "."
testdata_dir = "testdata"
tmp_dir = "tmp"
[build]
args_bin = []
bin = "./tmp/main"
cmd = "go build -o ./tmp/main ./cmd/virteen/main.go"
delay = 0
exclude_dir = ["assets", "tmp", "vendor", "testdata"]
exclude_file = []
exclude_regex = ["_test.go"]
exclude_unchanged = false
follow_symlink = false
full_bin = ""
include_dir = []
include_ext = ["go", "tpl", "tmpl", "html"]
include_file = []
kill_delay = "0s"
log = "build-errors.log"
poll = false
poll_interval = 0
rerun = false
rerun_delay = 500
send_interrupt = false
stop_on_error = false
[color]
app = ""
build = "yellow"
main = "magenta"
runner = "green"
watcher = "cyan"
[log]
main_only = false
time = false
[misc]
clean_on_exit = false
[screen]
clear_on_rebuild = false
keep_scroll = true

1
.env.sample Normal file
View File

@ -0,0 +1 @@
JWT_SECRET=

27
.gitignore vendored Normal file
View File

@ -0,0 +1,27 @@
# If you prefer the allow list template instead of the deny list, see community template:
# https://github.com/github/gitignore/blob/main/community/Golang/Go.AllowList.gitignore
#
# Binaries for programs and plugins
*.exe
*.exe~
*.dll
*.so
*.dylib
# Test binary, built with `go test -c`
*.test
# Output of the go coverage tool, specifically when used with LiteIDE
*.out
# Dependency directories (remove the comment below to include it)
# vendor/
# Go workspace file
go.work
# Air
tmp
# secrets
.env

21
LICENSE Normal file
View File

@ -0,0 +1,21 @@
MIT License
Copyright (c) 2023 niku
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

2
README.md Normal file
View File

@ -0,0 +1,2 @@
# virteen
Toy virtualization manager, inspired by Proxmox Virtual Environment.

18
cmd/virteen/main.go Normal file
View File

@ -0,0 +1,18 @@
package main
import (
"log"
"git.cesium.pw/niku/virteen/internal/app"
"github.com/joho/godotenv"
)
func main() {
if err := godotenv.Load(".env"); err != nil {
panic("Error loading .env file")
}
if err := app.Run(); err != nil {
log.Fatal(err)
}
}

149
go.mod Normal file
View File

@ -0,0 +1,149 @@
module git.cesium.pw/niku/virteen
go 1.19
require (
github.com/containers/common v0.52.0
github.com/containers/podman/v4 v4.5.0
github.com/gofiber/fiber/v2 v2.46.0
github.com/msteinert/pam v1.1.0
github.com/pkg/errors v0.9.1
)
require (
github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1 // indirect
github.com/BurntSushi/toml v1.2.1 // indirect
github.com/MicahParks/keyfunc/v2 v2.1.0 // indirect
github.com/Microsoft/go-winio v0.6.1 // indirect
github.com/Microsoft/hcsshim v0.10.0-rc.8 // indirect
github.com/VividCortex/ewma v1.2.0 // indirect
github.com/acarl005/stripansi v0.0.0-20180116102854-5a71ef0e047d // indirect
github.com/andybalholm/brotli v1.0.5 // indirect
github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2 // indirect
github.com/blang/semver/v4 v4.0.0 // indirect
github.com/chzyer/readline v1.5.1 // indirect
github.com/cilium/ebpf v0.9.1 // indirect
github.com/container-orchestrated-devices/container-device-interface v0.5.4 // indirect
github.com/containerd/cgroups v1.1.0 // indirect
github.com/containerd/containerd v1.7.1 // indirect
github.com/containerd/stargz-snapshotter/estargz v0.14.3 // indirect
github.com/containers/buildah v1.30.0 // indirect
github.com/containers/image/v5 v5.25.0 // indirect
github.com/containers/libtrust v0.0.0-20230121012942-c1716e8a8d01 // indirect
github.com/containers/ocicrypt v1.1.7 // indirect
github.com/containers/psgo v1.8.0 // indirect
github.com/containers/storage v1.46.1 // indirect
github.com/coreos/go-systemd/v22 v22.5.0 // indirect
github.com/cyberphone/json-canonicalization v0.0.0-20220623050100-57a0ce2678a7 // indirect
github.com/cyphar/filepath-securejoin v0.2.3 // indirect
github.com/disiqueira/gotree/v3 v3.0.2 // indirect
github.com/docker/distribution v2.8.1+incompatible // indirect
github.com/docker/docker v23.0.3+incompatible // indirect
github.com/docker/docker-credential-helpers v0.7.0 // indirect
github.com/docker/go-connections v0.4.1-0.20210727194412-58542c764a11 // indirect
github.com/docker/go-units v0.5.0 // indirect
github.com/fsnotify/fsnotify v1.6.0 // indirect
github.com/go-openapi/analysis v0.21.4 // indirect
github.com/go-openapi/errors v0.20.3 // indirect
github.com/go-openapi/jsonpointer v0.19.5 // indirect
github.com/go-openapi/jsonreference v0.20.0 // indirect
github.com/go-openapi/loads v0.21.2 // indirect
github.com/go-openapi/runtime v0.25.0 // indirect
github.com/go-openapi/spec v0.20.8 // indirect
github.com/go-openapi/strfmt v0.21.7 // indirect
github.com/go-openapi/swag v0.22.3 // indirect
github.com/go-openapi/validate v0.22.1 // indirect
github.com/godbus/dbus/v5 v5.1.1-0.20221029134443-4b691ce883d5 // indirect
github.com/gofiber/contrib/jwt v1.0.1 // indirect
github.com/gofiber/jwt/v2 v2.2.7 // indirect
github.com/gogo/protobuf v1.3.2 // indirect
github.com/golang-jwt/jwt v3.2.2+incompatible // indirect
github.com/golang-jwt/jwt/v4 v4.5.0 // indirect
github.com/golang-jwt/jwt/v5 v5.0.0 // indirect
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect
github.com/golang/protobuf v1.5.3 // indirect
github.com/google/go-containerregistry v0.14.0 // indirect
github.com/google/go-intervals v0.0.2 // indirect
github.com/google/uuid v1.3.0 // indirect
github.com/gorilla/mux v1.8.0 // indirect
github.com/gorilla/schema v1.2.0 // indirect
github.com/hashicorp/errwrap v1.1.0 // indirect
github.com/hashicorp/go-multierror v1.1.1 // indirect
github.com/imdario/mergo v0.3.15 // indirect
github.com/jinzhu/copier v0.3.5 // indirect
github.com/joho/godotenv v1.5.1 // indirect
github.com/josharian/intern v1.0.0 // indirect
github.com/json-iterator/go v1.1.12 // indirect
github.com/klauspost/compress v1.16.5 // indirect
github.com/klauspost/pgzip v1.2.6-0.20220930104621-17e8dac29df8 // indirect
github.com/kr/fs v0.1.0 // indirect
github.com/letsencrypt/boulder v0.0.0-20230213213521-fdfea0d469b6 // indirect
github.com/mailru/easyjson v0.7.7 // indirect
github.com/manifoldco/promptui v0.9.0 // indirect
github.com/mattn/go-colorable v0.1.13 // indirect
github.com/mattn/go-isatty v0.0.19 // indirect
github.com/mattn/go-runewidth v0.0.14 // indirect
github.com/mattn/go-shellwords v1.0.12 // indirect
github.com/miekg/pkcs11 v1.1.1 // indirect
github.com/mistifyio/go-zfs/v3 v3.0.0 // indirect
github.com/mitchellh/mapstructure v1.5.0 // indirect
github.com/moby/sys/mountinfo v0.6.2 // indirect
github.com/moby/term v0.0.0-20221120202655-abb19827d345 // indirect
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
github.com/modern-go/reflect2 v1.0.2 // indirect
github.com/nxadm/tail v1.4.8 // indirect
github.com/oklog/ulid v1.3.1 // indirect
github.com/opencontainers/go-digest v1.0.0 // indirect
github.com/opencontainers/image-spec v1.1.0-rc2.0.20221005185240-3a7f492d3f1b // indirect
github.com/opencontainers/runc v1.1.5 // indirect
github.com/opencontainers/runtime-spec v1.1.0-rc.1 // indirect
github.com/opencontainers/runtime-tools v0.9.1-0.20230317050512-e931285f4b69 // indirect
github.com/opencontainers/selinux v1.11.0 // indirect
github.com/ostreedev/ostree-go v0.0.0-20210805093236-719684c64e4f // indirect
github.com/philhofer/fwd v1.1.2 // indirect
github.com/pkg/sftp v1.13.5 // indirect
github.com/proglottis/gpgme v0.1.3 // indirect
github.com/rivo/uniseg v0.4.4 // indirect
github.com/savsgio/dictpool v0.0.0-20221023140959-7bf2e61cea94 // indirect
github.com/savsgio/gotils v0.0.0-20230208104028-c358bd845dee // indirect
github.com/sigstore/fulcio v1.2.0 // indirect
github.com/sigstore/rekor v1.1.0 // indirect
github.com/sigstore/sigstore v1.6.0 // indirect
github.com/sirupsen/logrus v1.9.0 // indirect
github.com/spf13/pflag v1.0.5 // indirect
github.com/stefanberger/go-pkcs11uri v0.0.0-20201008174630-78d3cae3a980 // indirect
github.com/sylabs/sif/v2 v2.11.1 // indirect
github.com/syndtr/gocapability v0.0.0-20200815063812-42c35b437635 // indirect
github.com/tchap/go-patricia/v2 v2.3.1 // indirect
github.com/theupdateframework/go-tuf v0.5.2 // indirect
github.com/tinylib/msgp v1.1.8 // indirect
github.com/titanous/rocacheck v0.0.0-20171023193734-afe73141d399 // indirect
github.com/ulikunitz/xz v0.5.11 // indirect
github.com/valyala/bytebufferpool v1.0.0 // indirect
github.com/valyala/fasthttp v1.47.0 // indirect
github.com/valyala/tcplisten v1.0.0 // indirect
github.com/vbatts/tar-split v0.11.3 // indirect
github.com/vbauerster/mpb/v8 v8.3.0 // indirect
go.etcd.io/bbolt v1.3.7 // indirect
go.mongodb.org/mongo-driver v1.11.3 // indirect
go.mozilla.org/pkcs7 v0.0.0-20210826202110-33d05740a352 // indirect
go.opencensus.io v0.24.0 // indirect
golang.org/x/crypto v0.8.0 // indirect
golang.org/x/exp v0.0.0-20230321023759-10a507213a29 // indirect
golang.org/x/mod v0.9.0 // indirect
golang.org/x/net v0.9.0 // indirect
golang.org/x/sync v0.1.0 // indirect
golang.org/x/sys v0.8.0 // indirect
golang.org/x/term v0.7.0 // indirect
golang.org/x/text v0.9.0 // indirect
golang.org/x/tools v0.7.0 // indirect
google.golang.org/genproto v0.0.0-20230306155012-7f2fa6fef1f4 // indirect
google.golang.org/grpc v1.54.0 // indirect
google.golang.org/protobuf v1.30.0 // indirect
gopkg.in/go-jose/go-jose.v2 v2.6.1 // indirect
gopkg.in/square/go-jose.v2 v2.6.0 // indirect
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 // indirect
gopkg.in/yaml.v2 v2.4.0 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
sigs.k8s.io/yaml v1.3.0 // indirect
)

1482
go.sum Normal file

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,22 @@
package api
import (
v1 "git.cesium.pw/niku/virteen/internal/app/api/v1"
"git.cesium.pw/niku/virteen/internal/middleware"
"github.com/gofiber/fiber/v2"
"github.com/gofiber/fiber/v2/middleware/helmet"
)
func ConfigureRoutes(app *fiber.App) error {
api := app.Group("/api")
api.Use(helmet.New())
api.Use(middleware.ErrorHandler())
err := v1.ConfigureRoutes(api)
if err != nil {
return err
}
return nil
}

View File

@ -0,0 +1,9 @@
package v1
import (
"github.com/gofiber/fiber/v2"
)
func Ping(c *fiber.Ctx) error {
return c.SendString("pong")
}

View File

@ -0,0 +1,43 @@
package v1
import (
"git.cesium.pw/niku/virteen/internal/auth"
"git.cesium.pw/niku/virteen/internal/middleware"
"git.cesium.pw/niku/virteen/internal/podman"
"git.cesium.pw/niku/virteen/internal/podman/models"
"git.cesium.pw/niku/virteen/internal/podman/services"
"github.com/gofiber/fiber/v2"
"github.com/gofiber/fiber/v2/middleware/monitor"
"github.com/pkg/errors"
)
func ConfigureRoutes(router fiber.Router) error {
v1 := router.Group("/v1")
ac := auth.NewPamAuthController()
ag := v1.Group("/auth")
ag.Post("/token", ac.GetToken)
v1.Get("/ping", Ping)
v1.Get("/metrics", monitor.New())
v1.Use(middleware.Protected())
var cs models.PodmanService
cs, err := services.NewPodmanContainerService()
if err != nil {
panic(errors.Wrapf(err, "failed to build podman container service"))
}
cc := podman.NewPodmanController(&cs)
cg := v1.Group("/containers")
cg.Get("/", cc.ListContainers)
cg.Post("/", cc.CreateContainer)
ccg := cg.Group("/:name")
ccg.Put("/status", cc.UpdateContainerStatus)
ccg.Delete("/", cc.DeleteContainer)
return nil
}

19
internal/app/main.go Normal file
View File

@ -0,0 +1,19 @@
package app
import (
"git.cesium.pw/niku/virteen/internal/app/api"
"github.com/gofiber/fiber/v2"
"github.com/gofiber/fiber/v2/middleware/compress"
"github.com/gofiber/fiber/v2/middleware/logger"
)
func Run() error {
app := fiber.New()
app.Use(logger.New())
app.Use(compress.New())
api.ConfigureRoutes(app)
return app.Listen(":3000")
}

View File

@ -0,0 +1,52 @@
package auth
import (
"fmt"
"os"
"time"
"git.cesium.pw/niku/virteen/internal/auth/services"
"github.com/gofiber/fiber/v2"
"github.com/golang-jwt/jwt"
)
type PamAuthController struct {
pam *services.PamAuthService
}
func NewPamAuthController() *PamAuthController {
return &PamAuthController{
pam: services.NewPamAuthService(),
}
}
type GetTokenBody struct {
User string `json:"user"`
Password string `json:"password"`
}
func (pac *PamAuthController) GetToken(ctx *fiber.Ctx) error {
var body GetTokenBody
if err := ctx.BodyParser(&body); err != nil {
return err
}
isValid := (*pac.pam).IsValidUser(body.User, body.Password)
if isValid == false {
return fmt.Errorf("invalid user or password")
}
claims := jwt.MapClaims{
"name": body.User,
"exp": time.Now().Add(time.Hour * 72).Unix(),
}
token := jwt.NewWithClaims(jwt.SigningMethodHS256, claims)
t, err := token.SignedString([]byte(os.Getenv("JWT_SECRET")))
if err != nil {
return err
}
return ctx.JSON(fiber.Map{"Token": t})
}

View File

@ -0,0 +1,5 @@
package models
type AuthService interface {
IsValidUser(user, password string) bool
}

View File

@ -0,0 +1,31 @@
package repositories
import (
"fmt"
"os"
"github.com/msteinert/pam"
)
type PamRepository struct{}
func NewPamRepository() *PamRepository {
return &PamRepository{}
}
func (pr *PamRepository) IsValidUser(user, password string) bool {
tx, err := pam.StartFunc("virteen", user, func(s pam.Style, msg string) (string, error) {
return password, nil
})
if err != nil {
panic("failed to start PAM transaction")
}
err = tx.Authenticate(pam.Silent)
if err != nil {
fmt.Fprintf(os.Stderr, "authenticate: %s\n", err.Error())
return false
}
return true
}

View File

@ -0,0 +1,17 @@
package services
import "git.cesium.pw/niku/virteen/internal/auth/repositories"
type PamAuthService struct {
pam *repositories.PamRepository
}
func NewPamAuthService() *PamAuthService {
return &PamAuthService{
pam: repositories.NewPamRepository(),
}
}
func (pas PamAuthService) IsValidUser(user, password string) bool {
return pas.pam.IsValidUser(user, password)
}

View File

@ -0,0 +1,20 @@
package middleware
import (
"os"
jwtware "github.com/gofiber/contrib/jwt"
"github.com/gofiber/fiber/v2"
)
func errorHandler(c *fiber.Ctx, err error) error {
c.Status(401)
return err
}
func Protected() fiber.Handler {
return jwtware.New(jwtware.Config{
SigningKey: jwtware.SigningKey{Key: []byte(os.Getenv("JWT_SECRET"))},
ErrorHandler: errorHandler,
})
}

View File

@ -0,0 +1,43 @@
package middleware
import (
"fmt"
"github.com/gofiber/fiber/v2"
)
type ProblemDetails struct {
Type string
Title string
Status int
Detail string
}
func ErrorHandler() fiber.Handler {
return func(c *fiber.Ctx) error {
defer func() {
if r := recover(); r != nil {
status := fiber.StatusInternalServerError
c.Status(status).JSON(ProblemDetails{
Type: fmt.Sprintf("https://httpstatuses.io/%d", status),
Title: "Internal Server Error",
Status: status,
Detail: fmt.Sprint(r),
})
}
}()
err := c.Next()
if err != nil {
status := c.Response().StatusCode()
c.JSON(ProblemDetails{
Type: fmt.Sprintf("https://httpstatuses.io/%d", status),
Title: err.Error(),
Status: status,
Detail: "No further details available",
})
}
return nil
}
}

View File

@ -0,0 +1,30 @@
package models
import (
"github.com/containers/podman/v4/pkg/domain/entities"
)
type ContainerStatus int
const (
StopContainer ContainerStatus = iota
StartContainer
RestartContainer
)
type PodmanService interface {
List() ([]entities.ListContainer, error)
Create(ContainerBlueprint) error
Delete(string) error
UpdateStatus(string, string) error
}
type PortMapping struct {
ContainerPort uint16 `json:"containerPort"`
HostPort uint16 `json:"hostPort"`
}
type ContainerBlueprint struct {
Image string `json:"image"`
PortMapping []PortMapping `json:"portMapping"`
}

View File

@ -0,0 +1,42 @@
package podman
import (
"git.cesium.pw/niku/virteen/internal/podman/models"
"github.com/gofiber/fiber/v2"
)
type PodmanController struct {
containerService *models.PodmanService
}
func NewPodmanController(cs *models.PodmanService) *PodmanController {
return &PodmanController{containerService: cs}
}
func (cc *PodmanController) ListContainers(ctx *fiber.Ctx) error {
containerList, err := (*cc.containerService).List()
if err != nil {
return err
}
return ctx.JSON(containerList)
}
func (cc *PodmanController) CreateContainer(ctx *fiber.Ctx) error {
var blueprint models.ContainerBlueprint
if err := ctx.BodyParser(&blueprint); err != nil {
return err
}
return (*cc.containerService).Create(blueprint)
}
func (cc *PodmanController) UpdateContainerStatus(ctx *fiber.Ctx) error {
name := ctx.Params("name")
state := ctx.Query("state")
return (*cc.containerService).UpdateStatus(name, state)
}
func (cc *PodmanController) DeleteContainer(ctx *fiber.Ctx) error {
name := ctx.Params("name")
return (*cc.containerService).Delete(name)
}

View File

@ -0,0 +1,93 @@
package repositories
import (
"context"
"git.cesium.pw/niku/virteen/internal/podman/models"
"github.com/containers/common/libnetwork/types"
"github.com/containers/podman/v4/pkg/bindings"
"github.com/containers/podman/v4/pkg/bindings/containers"
"github.com/containers/podman/v4/pkg/bindings/images"
"github.com/containers/podman/v4/pkg/domain/entities"
"github.com/containers/podman/v4/pkg/specgen"
"github.com/pkg/errors"
)
func newPodmanContext() (context.Context, error) {
conn, err := bindings.NewConnection(context.Background(), "unix:///run/user/1000/podman/podman.sock")
if err != nil {
return nil, err
}
return conn, nil
}
type PodmanRepository struct {
ctx context.Context
}
func (pcs *PodmanRepository) ListContainers() ([]entities.ListContainer, error) {
return containers.List(pcs.ctx, &containers.ListOptions{})
}
func (pcs *PodmanRepository) CreateContainer(bp models.ContainerBlueprint) error {
pullQuiet := true
_, err := images.Pull(pcs.ctx, bp.Image, &images.PullOptions{Quiet: &pullQuiet})
if err != nil {
return errors.Wrapf(err, "failed to pull image")
}
s := specgen.NewSpecGenerator("nginx", false)
portMapping := make([]types.PortMapping, len(bp.PortMapping))
for i, pm := range bp.PortMapping {
portMapping[i] = types.PortMapping{ContainerPort: pm.ContainerPort, HostPort: pm.HostPort}
}
s.ContainerNetworkConfig.PortMappings = append(s.ContainerNetworkConfig.PortMappings, portMapping...)
createResponse, err := containers.CreateWithSpec(pcs.ctx, s, nil)
if err != nil {
return errors.Wrapf(err, "failed to create spec")
}
if err := containers.Start(pcs.ctx, createResponse.ID, nil); err != nil {
return errors.Wrapf(err, "failed to start container")
}
return nil
}
func (pcs *PodmanRepository) UpdateContainerStatus(name string, state models.ContainerStatus) error {
switch state {
case models.StopContainer:
return containers.Stop(pcs.ctx, name, nil)
case models.StartContainer:
return containers.Start(pcs.ctx, name, nil)
case models.RestartContainer:
return containers.Restart(pcs.ctx, name, nil)
default:
return nil
}
}
func (pcs *PodmanRepository) DeleteContainer(name string) error {
err := pcs.UpdateContainerStatus(name, models.StopContainer)
if err != nil {
return err
}
_, err = containers.Remove(pcs.ctx, name, nil)
if err != nil {
return err
}
return err
}
func NewPodmanRepository() (*PodmanRepository, error) {
ctx, err := newPodmanContext()
if err != nil {
return nil, err
}
return &PodmanRepository{ctx: ctx}, nil
}

View File

@ -0,0 +1,51 @@
package services
import (
"fmt"
"git.cesium.pw/niku/virteen/internal/podman/models"
"git.cesium.pw/niku/virteen/internal/podman/repositories"
"github.com/containers/podman/v4/pkg/domain/entities"
)
type PodmanContainerService struct {
podman *repositories.PodmanRepository
}
func (pcs *PodmanContainerService) List() ([]entities.ListContainer, error) {
return pcs.podman.ListContainers()
}
func (pcs *PodmanContainerService) Create(blueprint models.ContainerBlueprint) error {
return pcs.podman.CreateContainer(blueprint)
}
func (pcs *PodmanContainerService) Delete(name string) error {
return pcs.podman.DeleteContainer(name)
}
func (pcs *PodmanContainerService) UpdateStatus(name, status string) error {
var state models.ContainerStatus
if status == "started" {
state = models.StartContainer
} else if status == "stopped" {
state = models.StopContainer
} else if status == "restarting" {
state = models.RestartContainer
} else {
return fmt.Errorf("invalid state, should be started, stopped or restarting")
}
return pcs.podman.UpdateContainerStatus(name, state)
}
func NewPodmanContainerService() (*PodmanContainerService, error) {
podmanRepo, err := repositories.NewPodmanRepository()
if err != nil {
return nil, err
}
return &PodmanContainerService{
podman: podmanRepo,
}, nil
}