Initial commit

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

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
}