Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 5 additions & 1 deletion api/types/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,11 @@ import (
)

const (
ENV_PLATFORM = "SKUPPER_PLATFORM"
ENV_PLATFORM = "SKUPPER_PLATFORM"
ENV_SYSTEM_AUTO_RELOAD = "SKUPPER_SYSTEM_RELOAD_TYPE"

SystemReloadTypeAuto string = "auto"
SystemReloadTypeManual string = "manual"
)

type ConnectorCreateOptions struct {
Expand Down
5 changes: 5 additions & 0 deletions cmd/system-controller/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,9 @@ import (
"syscall"
"time"

"github.com/skupperproject/skupper/api/types"
"github.com/skupperproject/skupper/internal/nonkube/controller"
"github.com/skupperproject/skupper/internal/utils"
"github.com/skupperproject/skupper/internal/version"
"github.com/skupperproject/skupper/pkg/nonkube/api"
)
Expand All @@ -23,6 +25,9 @@ func main() {
if api.IsRunningInContainer() {
slog.Info("Host path info:", slog.String("path", api.GetHostNamespacesPath()))
}
systemReloadType := utils.DefaultStr(os.Getenv(types.ENV_SYSTEM_AUTO_RELOAD),
types.SystemReloadTypeManual)
slog.Info("System Reload:", slog.String("type", systemReloadType))
if err := os.MkdirAll(namespacesPath, 0755); err != nil {
slog.Error("Error creating skupper namespaces directory", slog.String("path", namespacesPath), slog.Any("error", err))
os.Exit(1)
Expand Down
2 changes: 1 addition & 1 deletion internal/nonkube/bootstrap/bootstrap.go
Original file line number Diff line number Diff line change
Expand Up @@ -109,7 +109,7 @@ func Bootstrap(config *Config) (*api.SiteState, error) {
if err != nil {
return nil, fmt.Errorf("failed to load site state: %v", err)
}
// if sources are being consume from namespace sources, they must be properly set
// if sources are being consumed from namespace sources, they must be properly set
crNamespace := siteState.GetNamespace()
targetNamespace := utils.DefaultStr(config.Namespace, "default")
if config.InputPath == sourcesPath {
Expand Down
3 changes: 3 additions & 0 deletions internal/nonkube/bootstrap/install.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import (
"github.com/skupperproject/skupper/internal/nonkube/bootstrap/controller"
internalclient "github.com/skupperproject/skupper/internal/nonkube/client/compat"
"github.com/skupperproject/skupper/internal/nonkube/common"
"github.com/skupperproject/skupper/internal/utils"
"github.com/skupperproject/skupper/pkg/container"
"github.com/skupperproject/skupper/pkg/nonkube/api"
)
Expand Down Expand Up @@ -75,6 +76,8 @@ func Install(platform string) error {
"CONTAINER_ENDPOINT": config.containerEndpoint,
"SKUPPER_OUTPUT_PATH": config.hostDataHome,
"CONTAINER_ENGINE": config.containerEngine,
"SKUPPER_SYSTEM_RELOAD_TYPE": utils.DefaultStr(os.Getenv(types.ENV_SYSTEM_AUTO_RELOAD),
types.SystemReloadTypeManual),
}

//To mount a volume as a bind, the host path must be specified in the Name field
Expand Down
43 changes: 23 additions & 20 deletions internal/nonkube/bootstrap/teardown.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,20 +22,7 @@ func Teardown(namespace string) error {
if err != nil {
return err
}
if err := removeRouter(namespace, platform); err != nil {
return err
}

if err := removeService(namespace, platform); err != nil {
return err
}

if err := removeDefinition(namespace); err != nil {
return err
}

fmt.Printf("Namespace \"%s\" has been removed\n", namespace)
return nil
return RemoveAll(namespace, platform)

}

Expand All @@ -52,13 +39,10 @@ func removeDefinition(namespace string) error {
func removeRouter(namespace string, platform string) error {

endpoint := os.Getenv("CONTAINER_ENDPOINT")
if endpoint == "" {
endpoint = fmt.Sprintf("unix://%s/podman/podman.sock", api.GetRuntimeDir())
if platform == "docker" {
endpoint = "unix:///run/docker.sock"
}
}

if api.IsRunningInContainer() || endpoint == "" {
endpoint = internalclient.GetDefaultContainerEndpoint()
}
cli, err := internalclient.NewCompatClient(endpoint, "")
if err != nil {
return fmt.Errorf("failed to create container client: %v", err)
Expand Down Expand Up @@ -102,3 +86,22 @@ func removeService(namespace string, platform string) error {

return nil
}

func RemoveAll(namespace string, platform string) error {

if err := removeRouter(namespace, platform); err != nil {
return err
}

if err := removeService(namespace, platform); err != nil {
return err
}

if err := removeDefinition(namespace); err != nil {
return err
}

fmt.Printf("Namespace \"%s\" has been removed\n", namespace)
return nil

}
17 changes: 14 additions & 3 deletions internal/nonkube/client/compat/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import (
"github.com/go-openapi/strfmt"
"github.com/skupperproject/skupper/api/types"
"github.com/skupperproject/skupper/internal/utils"
"github.com/skupperproject/skupper/pkg/nonkube/api"
)

const (
Expand Down Expand Up @@ -157,10 +158,20 @@ func NewCompatClient(endpoint, basePath string) (*CompatClient, error) {
}

func GetDefaultContainerEndpoint() string {
if os.Getenv(types.ENV_PLATFORM) == "docker" {
return "unix:///run/docker.sock"
platform := os.Getenv(types.ENV_PLATFORM)
// the container endpoint is mapped to the podman socket inside the container
if api.IsRunningInContainer() {
if platform == "docker" {
return "unix:///var/run/docker.sock"
}
return "unix:///var/run/podman.sock"
} else {
if platform == "docker" {
return "unix:///run/docker.sock"
}

return fmt.Sprintf("unix://%s/podman/podman.sock", GetRuntimeDir())
}
return fmt.Sprintf("unix://%s/podman/podman.sock", GetRuntimeDir())
}

func GetRuntimeDir() string {
Expand Down
9 changes: 4 additions & 5 deletions internal/nonkube/compat/site_state_renderer.go
Original file line number Diff line number Diff line change
Expand Up @@ -38,12 +38,11 @@ func (s *SiteStateRenderer) Render(loadedSiteState *api.SiteState, reload bool)
}
s.loadedSiteState = loadedSiteState
endpoint := os.Getenv("CONTAINER_ENDPOINT")
if endpoint == "" {
endpoint = fmt.Sprintf("unix://%s/podman/podman.sock", api.GetRuntimeDir())
if s.Platform == "docker" {
endpoint = "unix:///run/docker.sock"
}

if api.IsRunningInContainer() || endpoint == "" {
endpoint = internalclient.GetDefaultContainerEndpoint()
}

s.cli, err = internalclient.NewCompatClient(endpoint, "")
if err != nil {
return fmt.Errorf("failed to create container client: %v", err)
Expand Down
153 changes: 153 additions & 0 deletions internal/nonkube/controller/input_resource_handler.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,153 @@
package controller

import (
"fmt"
"log/slog"
"os"
"strings"
"sync"

"github.com/skupperproject/skupper/api/types"
"github.com/skupperproject/skupper/internal/cmd/skupper/common"
"github.com/skupperproject/skupper/internal/nonkube/bootstrap"
common2 "github.com/skupperproject/skupper/internal/nonkube/common"
"github.com/skupperproject/skupper/internal/utils"
"github.com/skupperproject/skupper/pkg/nonkube/api"
)

// This feature is responsible for handling the creation of input resources and
// execute the start/reload of the site configuration automatically.
type InputResourceHandler struct {
logger *slog.Logger
namespace string
inputPath string
Bootstrap func(config *bootstrap.Config) (*api.SiteState, error)
PostExec func(config *bootstrap.Config, siteState *api.SiteState)
TearDown func(namespace string, platform string) error
ConfigBootstrap bootstrap.Config
lock sync.Mutex
}

type Bootstrap func(config *bootstrap.Config) (*api.SiteState, error)
type PostBootstrap func(config *bootstrap.Config, siteState *api.SiteState)
type TearDown func(namespace string, platform string) error

func NewInputResourceHandler(namespace string, inputPath string, bs Bootstrap, pbs PostBootstrap, td TearDown) *InputResourceHandler {

systemReloadType := utils.DefaultStr(os.Getenv(types.ENV_SYSTEM_AUTO_RELOAD),
types.SystemReloadTypeManual)

if systemReloadType == types.SystemReloadTypeManual {
slog.Default().Debug("Automatic reloading is not configured.")
return nil
}

handler := &InputResourceHandler{
namespace: namespace,
inputPath: inputPath,
}

handler.logger = slog.Default().With("component", "input.resource.handler", "namespace", namespace)

handler.Bootstrap = bs
handler.PostExec = pbs
handler.TearDown = td

var binary string

platform := types.Platform(utils.DefaultStr(os.Getenv("CONTAINER_ENGINE"),
string(types.PlatformPodman)))

// TODO: add support for linux platform
switch common.Platform(platform) {
case common.PlatformDocker:
binary = "docker"
case common.PlatformPodman:
binary = "podman"
case common.PlatformLinux:
handler.logger.Error("Linux platform is not supported yet")
return nil
default:
handler.logger.Error("This platform value is not supported: ", slog.String("platform", string(platform)))
return nil
}

handler.ConfigBootstrap = bootstrap.Config{
Namespace: namespace,
InputPath: inputPath,
Platform: platform,
Binary: binary,
}

return handler
}

func (h *InputResourceHandler) OnCreate(name string) {
h.lock.Lock()
defer h.lock.Unlock()

h.logger.Info(fmt.Sprintf("Resource has been created: %s", name))
err := h.processInputFile()
if err != nil {
h.logger.Error(err.Error())
}
}

// This function does not need to be implemented, given that when a file is updated,
// the event OnCreate is triggered anyway. Having it implemented would cause
// the resources to be reloaded multiple times, stopping and starting a router pod.
// (issue: the router pod is still active while going to be deleted, and the controller
// tries to create a new router pod, failing on this)
func (h *InputResourceHandler) OnUpdate(name string) {}
func (h *InputResourceHandler) OnRemove(name string) {
h.lock.Lock()
defer h.lock.Unlock()

h.logger.Info(fmt.Sprintf("Resource has been deleted: %s", name))

siteStateLoader := &common2.FileSystemSiteStateLoader{
Path: h.ConfigBootstrap.InputPath,
Bundle: h.ConfigBootstrap.IsBundle,
}
siteState, err := siteStateLoader.Load()

//If there is no site configured, the namespace needs to be removed
if err != nil || siteState == nil || siteState.Site == nil {
err = h.tearDownNamespace()
if err != nil {
h.logger.Error(err.Error())
}
return
}

err = h.processInputFile()
if err != nil {
h.logger.Error(err.Error())
}
}
func (h *InputResourceHandler) Filter(name string) bool {
return strings.HasSuffix(name, ".json") || strings.HasSuffix(name, ".yaml") || strings.HasSuffix(name, ".yml")
}

func (h *InputResourceHandler) OnBasePathAdded(basePath string) {}

func (h *InputResourceHandler) processInputFile() error {
siteState, err := h.Bootstrap(&h.ConfigBootstrap)
if err != nil {
return fmt.Errorf("Failed to bootstrap: %s", err)
}

h.PostExec(&h.ConfigBootstrap, siteState)

return nil
}

func (h *InputResourceHandler) tearDownNamespace() error {
h.logger.Info("No site configured, tearing down namespace")
err := h.TearDown(h.namespace, string(h.ConfigBootstrap.Platform))
if err != nil {
return err
}

return nil
}
Loading