Initial commit
This commit is contained in:
30
internal/podman/models/models.go
Normal file
30
internal/podman/models/models.go
Normal 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"`
|
||||
}
|
42
internal/podman/podman_controller.go
Normal file
42
internal/podman/podman_controller.go
Normal 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)
|
||||
}
|
93
internal/podman/repositories/podman_repository.go
Normal file
93
internal/podman/repositories/podman_repository.go
Normal 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
|
||||
}
|
51
internal/podman/services/podman_service.go
Normal file
51
internal/podman/services/podman_service.go
Normal 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
|
||||
}
|
Reference in New Issue
Block a user