Skip to content

Commit

Permalink
Adds process for zero touch registration and functionality to update …
Browse files Browse the repository at this point in the history
…processes and configs (#64)

* adding state artifact fetcher to fetch the state from harbor

* completing the url fetcher

* adding schedulers and process to satellite

* adding simple notifier to fetch state process

* added description to the scheduler

* coderabbit fixes and changes to fetcher and schedulers

* adding new format of the state file

* adding config to process new state artifact file

* coderabbit review

* added ./zot to gitignore

* fixing the replication process

* fixing the replication and deletion process

* fixing paning while removing the null tags

* using repository name instead of the image name while uploading the image to the zot

* adding container runtime config

* containerd function and changing the harbor satellite to a cobra cli application

* generating config file for containerd

* adding better logging

* fix

* adding config generation for containerd

* fixing host gen file

* generating the config for the containerd fixes

* fixes

* coderabbit fixes

* fixes

* adding config command for crio

* moving from toml config to json config

* making config.json work with the replicator

* avoid printing confedential information in log

* coderabbit fixes

* fixing startup

* fixing panic error in generating container runtime config

* changing config structuring

* adding event driven architecture changes

* adds config fetch process architecture, registration process and state update process

* adds docker compose and satellite registers different processes

* minor fixes

* handelling config error

* code rabbit fixes

* dagger version

* enhancing the config

* otel version fix

* replication fix

* adds unwanted binary files to gitignore

* configurable cron schedule, local registry auth and fixing memory leaks

* fixing merge conflicts

* panic fix

* pr reviews
  • Loading branch information
Mehul-Kumar-27 authored Dec 3, 2024
1 parent 992e941 commit 4511a5b
Show file tree
Hide file tree
Showing 39 changed files with 2,036 additions and 980 deletions.
8 changes: 0 additions & 8 deletions .env

This file was deleted.

3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -31,4 +31,5 @@ secrets.txt
__debug_bin1949266242

/zot
/runtime
/runtime
/value
1 change: 0 additions & 1 deletion ci/utils.go
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,6 @@ func (m *HarborSatellite) Service(
AsService()
}


// builds given component from source
func (m *HarborSatellite) build(source *dagger.Directory, component string) *dagger.Directory {
fmt.Printf("Building %s\n", component)
Expand Down
139 changes: 139 additions & 0 deletions cmd/container_runtime/containerd.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,139 @@
package runtime

import (
"fmt"
"os"
"path/filepath"
"strings"

"container-registry.com/harbor-satellite/internal/config"
"container-registry.com/harbor-satellite/internal/utils"
"container-registry.com/harbor-satellite/logger"
"container-registry.com/harbor-satellite/registry"
toml "github.com/pelletier/go-toml"
"github.com/rs/zerolog"
"github.com/spf13/cobra"
)

const (
ContainerDCertPath = "/etc/containerd/certs.d"
DefaultGeneratedTomlName = "config.toml"
ContainerdRuntime = "containerd"
DefaultContainerdConfigPath = "/etc/containerd/config.toml"
DefaultConfigVersion = 2
)

var DefaultContainerDGenPath string

func init() {
cwd, err := os.Getwd()
if err != nil {
fmt.Printf("Error getting current working directory: %v\n", err)
DefaultContainerDGenPath = "/runtime/containerd"
if _, err := os.Stat(DefaultContainerDGenPath); os.IsNotExist(err) {
err := os.MkdirAll(DefaultContainerDGenPath, os.ModePerm)
if err != nil {
fmt.Printf("Error creating default directory: %v\n", err)
}
}
} else {
DefaultContainerDGenPath = filepath.Join(cwd, "runtime/containerd")
}
}

func NewContainerdCommand() *cobra.Command {
var generateConfig bool
var defaultZotConfig registry.DefaultZotConfig
var containerdConfigPath string
var containerDCertPath string

containerdCmd := &cobra.Command{
Use: "containerd",
Short: "Creates the config file for the containerd runtime to fetch the images from the local repository",
PersistentPreRunE: func(cmd *cobra.Command, args []string) error {
return SetupContainerRuntimeCommand(cmd, &defaultZotConfig, DefaultContainerDGenPath)
},
RunE: func(cmd *cobra.Command, args []string) error {
log := logger.FromContext(cmd.Context())
sourceRegistry := config.GetSourceRegistryURL()
satelliteHostConfig := NewSatelliteHostConfig(defaultZotConfig.RemoteURL, sourceRegistry)
if generateConfig {
log.Info().Msg("Generating containerd config file for containerd ...")
log.Info().Msgf("Fetching containerd config from path: %s", containerdConfigPath)
err := GenerateContainerdHostConfig(containerDCertPath, DefaultContainerDGenPath, log, *satelliteHostConfig)
if err != nil {
log.Err(err).Msg("Error generating containerd config")
return fmt.Errorf("could not generate containerd config: %w", err)
}
return GenerateContainerdConfig(log, containerdConfigPath, containerDCertPath)
}
return nil
},
}

containerdCmd.Flags().BoolVarP(&generateConfig, "gen", "g", false, "Generate the containerd config file")
containerdCmd.PersistentFlags().StringVarP(&containerdConfigPath, "path", "p", DefaultContainerdConfigPath, "Path to the containerd config file of the container runtime")
containerdCmd.PersistentFlags().StringVarP(&containerDCertPath, "cert-path", "c", ContainerDCertPath, "Path to the containerd cert directory")
containerdCmd.AddCommand(NewReadConfigCommand(ContainerdRuntime))
return containerdCmd
}

// GenerateContainerdConfig generates the containerd config file for the containerd runtime
// It takes the zot config a logger and the containerd config path
// It reads the containerd config file and adds the local registry to the config file
func GenerateContainerdConfig(log *zerolog.Logger, containerdConfigPath, containerdCertPath string) error {
// First Read the present config file at the configPath
data, err := utils.ReadFile(containerdConfigPath, false)
if err != nil {
if os.IsNotExist(err) {
log.Warn().Msg("Config file does not exist, proceeding with default values")
data = []byte{}
} else {
log.Err(err).Msg("Error reading config file")
return fmt.Errorf("could not read config file: %w", err)
}
}
// Now we marshal the data into the containerd config
containerdConfig := &ContainerdConfigToml{}
err = toml.Unmarshal(data, containerdConfig)
if err != nil {
log.Err(err).Msg("Error unmarshalling config")
return fmt.Errorf("could not unmarshal config: %w", err)
}
// Add the certs.d path to the config
if containerdConfig.Plugins.Cri.Registry.ConfigPath == "" {
containerdConfig.Plugins.Cri.Registry.ConfigPath = containerdCertPath
}
// Set default version
if containerdConfig.Version == 0 {
containerdConfig.Version = DefaultConfigVersion
}
// if config disabled plugins container cri then remove it
if len(containerdConfig.DisabledPlugins) > 0 {
filteredPlugins := make([]string, 0, len(containerdConfig.DisabledPlugins))
for _, plugin := range containerdConfig.DisabledPlugins {
if plugin != "cri" {
filteredPlugins = append(filteredPlugins, plugin)
}
}
containerdConfig.DisabledPlugins = filteredPlugins
}
// ToDo: Find a way to remove the unwanted configuration added to the config file while marshalling
pathToWrite := filepath.Join(DefaultContainerDGenPath, DefaultGeneratedTomlName)
log.Info().Msgf("Writing the containerd config to path: %s", pathToWrite)
// Now we write the config to the file
data, err = toml.Marshal(containerdConfig)
dataStr := string(data)
dataStr = strings.Replace(dataStr, "[plugins]\n", "", 1)
data = []byte(dataStr)
if err != nil {
log.Err(err).Msg("Error marshalling config")
return fmt.Errorf("could not marshal config: %w", err)
}
err = utils.WriteFile(pathToWrite, data)
if err != nil {
log.Err(err).Msg("Error writing config to file")
return fmt.Errorf("could not write config to file: %w", err)
}
return nil
}
169 changes: 169 additions & 0 deletions cmd/container_runtime/containerd_config.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,169 @@
package runtime

// ContainerdConfigToml provides containerd configuration data for the server
type ContainerdConfigToml struct {
// Version of the config file
Version int `toml:"version,omitempty"`
// Root is the path to a directory where containerd will store persistent data
Root string `toml:"root,omitempty"`
// State is the path to a directory where containerd will store transient data
State string `toml:"state,omitempty"`
// TempDir is the path to a directory where to place containerd temporary files
TempDir string `toml:"temp,omitempty"`
// PluginDir is the directory for dynamic plugins to be stored
//
// Deprecated: Please use proxy or binary external plugins.
PluginDir string `toml:"plugin_dir,omitempty"`
// GRPC configuration settings
GRPC GRPCConfig `toml:"grpc,omitempty"`
// TTRPC configuration settings
TTRPC TTRPCConfig `toml:"ttrpc,omitempty"`
// Debug and profiling settings
Debug Debug `toml:"debug,omitempty"`
// Metrics and monitoring settings
Metrics MetricsConfig `toml:"metrics,omitempty"`
// DisabledPlugins are IDs of plugins to disable. Disabled plugins won't be
// initialized and started.
// DisabledPlugins must use a fully qualified plugin URI.
DisabledPlugins []string `toml:"disabled_plugins,omitempty"`
// RequiredPlugins are IDs of required plugins. Containerd exits if any
// required plugin doesn't exist or fails to be initialized or started.
// RequiredPlugins must use a fully qualified plugin URI.
RequiredPlugins []string `toml:"required_plugins,omitempty"`
// Plugins provides plugin specific configuration for the initialization of a plugin
Plugins PluginsConfig `toml:"plugins,omitempty"`
// OOMScore adjust the containerd's oom score
OOMScore int `toml:"oom_score,omitempty"`
// Cgroup specifies cgroup information for the containerd daemon process
Cgroup CgroupConfig `toml:"cgroup,omitempty"`
// ProxyPlugins configures plugins which are communicated to over GRPC
ProxyPlugins map[string]ProxyPlugin `toml:"proxy_plugins,omitempty"`
// Timeouts specified as a duration
Timeouts map[string]string `toml:"timeouts,omitempty"`
// Imports are additional file path list to config files that can overwrite main config file fields
Imports []string `toml:"imports,omitempty"`
// StreamProcessors configuration
StreamProcessors map[string]StreamProcessor `toml:"stream_processors,omitempty"`
}

type StreamProcessor struct {
// Accepts specific media-types
Accepts []string `toml:"accepts,omitempty"`
// Returns the media-type
Returns string `toml:"returns,omitempty"`
// Path or name of the binary
Path string `toml:"path"`
// Args to the binary
Args []string `toml:"args,omitempty"`
// Environment variables for the binary
Env []string `toml:"env,omitempty"`
}

type GRPCConfig struct {
Address string `toml:"address"`
TCPAddress string `toml:"tcp_address,omitempty"`
TCPTLSCA string `toml:"tcp_tls_ca,omitempty"`
TCPTLSCert string `toml:"tcp_tls_cert,omitempty"`
TCPTLSKey string `toml:"tcp_tls_key,omitempty"`
UID int `toml:"uid,omitempty"`
GID int `toml:"gid,omitempty"`
MaxRecvMsgSize int `toml:"max_recv_message_size,omitempty"`
MaxSendMsgSize int `toml:"max_send_message_size,omitempty"`
}

// TTRPCConfig provides TTRPC configuration for the socket
type TTRPCConfig struct {
Address string `toml:"address"`
UID int `toml:"uid,omitempty"`
GID int `toml:"gid,omitempty"`
}

// Debug provides debug configuration
type Debug struct {
Address string `toml:"address,omitempty"`
UID int `toml:"uid,omitempty"`
GID int `toml:"gid,omitempty"`
Level string `toml:"level,omitempty"`
// Format represents the logging format. Supported values are 'text' and 'json'.
Format string `toml:"format,omitempty"`
}

// MetricsConfig provides metrics configuration
type MetricsConfig struct {
Address string `toml:"address,omitempty"`
GRPCHistogram bool `toml:"grpc_histogram,omitempty"`
}

// CgroupConfig provides cgroup configuration
type CgroupConfig struct {
Path string `toml:"path,omitempty"`
}

// ProxyPlugin provides a proxy plugin configuration
type ProxyPlugin struct {
Type string `toml:"type"`
Address string `toml:"address"`
Platform string `toml:"platform,omitempty"`
Exports map[string]string `toml:"exports,omitempty"`
Capabilities []string `toml:"capabilities,omitempty"`
}

type PluginsConfig struct {
Cri CriConfig `toml:"io.containerd.grpc.v1.cri,omitempty"`
Cgroups MonitorConfig `toml:"io.containerd.monitor.v1.cgroups,omitempty"`
LinuxRuntime interface{} `toml:"io.containerd.runtime.v1.linux,omitempty"`
Scheduler GCSchedulerConfig `toml:"io.containerd.gc.v1.scheduler,omitempty"`
Bolt interface{} `toml:"io.containerd.metadata.v1.bolt,omitempty"`
Task RuntimeV2TaskConfig `toml:"io.containerd.runtime.v2.task,omitempty"`
Opt interface{} `toml:"io.containerd.internal.v1.opt,omitempty"`
Restart interface{} `toml:"io.containerd.internal.v1.restart,omitempty"`
Tracing interface{} `toml:"io.containerd.internal.v1.tracing,omitempty"`
Otlp interface{} `toml:"io.containerd.tracing.processor.v1.otlp,omitempty"`
Aufs interface{} `toml:"io.containerd.snapshotter.v1.aufs,omitempty"`
Btrfs interface{} `toml:"io.containerd.snapshotter.v1.btrfs,omitempty"`
Devmapper interface{} `toml:"io.containerd.snapshotter.v1.devmapper,omitempty"`
Native interface{} `toml:"io.containerd.snapshotter.v1.native,omitempty"`
Overlayfs interface{} `toml:"io.containerd.snapshotter.v1.overlayfs,omitempty"`
Zfs interface{} `toml:"io.containerd.snapshotter.v1.zfs,omitempty"`
}

type MonitorConfig struct {
NoPrometheus bool `toml:"no_prometheus,omitempty"`
}

type GCSchedulerConfig struct {
PauseThreshold float64 `toml:"pause_threshold,omitempty"`
DeletionThreshold int `toml:"deletion_threshold,omitempty"`
MutationThreshold int `toml:"mutation_threshold,omitempty"`
ScheduleDelay string `toml:"schedule_delay,omitempty"`
StartupDelay string `toml:"startup_delay,omitempty"`
}

type RuntimeV2TaskConfig struct {
Platforms []string `toml:"platforms,omitempty"`
SchedCore bool `toml:"sched_core,omitempty"`
}

type CriConfig struct {
Containerd CriContainerdConfig `toml:"containerd,omitempty"`
Registry RegistryConfig `toml:"registry,omitempty"`
}

type CriContainerdConfig struct {
DefaultRuntimeName string `toml:"default_runtime_name,omitempty"`
Runtimes map[string]RuntimeConfig `toml:"runtimes,omitempty"`
}

type RuntimeConfig struct {
PrivilegedWithoutHostDevices bool `toml:"privileged_without_host_devices,omitempty"`
RuntimeType string `toml:"runtime_type"`
Options RuntimeOptions `toml:"options,omitempty"`
}

type RuntimeOptions struct {
BinaryName string `toml:"BinaryName,omitempty"`
}

type RegistryConfig struct {
ConfigPath string `toml:"config_path,omitempty"`
}
Loading

0 comments on commit 4511a5b

Please sign in to comment.