Skip to content

Commit 4511a5b

Browse files
Adds process for zero touch registration and functionality to update 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
1 parent 992e941 commit 4511a5b

39 files changed

+2036
-980
lines changed

.env

Lines changed: 0 additions & 8 deletions
This file was deleted.

.gitignore

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,4 +31,5 @@ secrets.txt
3131
__debug_bin1949266242
3232

3333
/zot
34-
/runtime
34+
/runtime
35+
/value

ci/utils.go

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,6 @@ func (m *HarborSatellite) Service(
5858
AsService()
5959
}
6060

61-
6261
// builds given component from source
6362
func (m *HarborSatellite) build(source *dagger.Directory, component string) *dagger.Directory {
6463
fmt.Printf("Building %s\n", component)

cmd/container_runtime/containerd.go

Lines changed: 139 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,139 @@
1+
package runtime
2+
3+
import (
4+
"fmt"
5+
"os"
6+
"path/filepath"
7+
"strings"
8+
9+
"container-registry.com/harbor-satellite/internal/config"
10+
"container-registry.com/harbor-satellite/internal/utils"
11+
"container-registry.com/harbor-satellite/logger"
12+
"container-registry.com/harbor-satellite/registry"
13+
toml "github.com/pelletier/go-toml"
14+
"github.com/rs/zerolog"
15+
"github.com/spf13/cobra"
16+
)
17+
18+
const (
19+
ContainerDCertPath = "/etc/containerd/certs.d"
20+
DefaultGeneratedTomlName = "config.toml"
21+
ContainerdRuntime = "containerd"
22+
DefaultContainerdConfigPath = "/etc/containerd/config.toml"
23+
DefaultConfigVersion = 2
24+
)
25+
26+
var DefaultContainerDGenPath string
27+
28+
func init() {
29+
cwd, err := os.Getwd()
30+
if err != nil {
31+
fmt.Printf("Error getting current working directory: %v\n", err)
32+
DefaultContainerDGenPath = "/runtime/containerd"
33+
if _, err := os.Stat(DefaultContainerDGenPath); os.IsNotExist(err) {
34+
err := os.MkdirAll(DefaultContainerDGenPath, os.ModePerm)
35+
if err != nil {
36+
fmt.Printf("Error creating default directory: %v\n", err)
37+
}
38+
}
39+
} else {
40+
DefaultContainerDGenPath = filepath.Join(cwd, "runtime/containerd")
41+
}
42+
}
43+
44+
func NewContainerdCommand() *cobra.Command {
45+
var generateConfig bool
46+
var defaultZotConfig registry.DefaultZotConfig
47+
var containerdConfigPath string
48+
var containerDCertPath string
49+
50+
containerdCmd := &cobra.Command{
51+
Use: "containerd",
52+
Short: "Creates the config file for the containerd runtime to fetch the images from the local repository",
53+
PersistentPreRunE: func(cmd *cobra.Command, args []string) error {
54+
return SetupContainerRuntimeCommand(cmd, &defaultZotConfig, DefaultContainerDGenPath)
55+
},
56+
RunE: func(cmd *cobra.Command, args []string) error {
57+
log := logger.FromContext(cmd.Context())
58+
sourceRegistry := config.GetSourceRegistryURL()
59+
satelliteHostConfig := NewSatelliteHostConfig(defaultZotConfig.RemoteURL, sourceRegistry)
60+
if generateConfig {
61+
log.Info().Msg("Generating containerd config file for containerd ...")
62+
log.Info().Msgf("Fetching containerd config from path: %s", containerdConfigPath)
63+
err := GenerateContainerdHostConfig(containerDCertPath, DefaultContainerDGenPath, log, *satelliteHostConfig)
64+
if err != nil {
65+
log.Err(err).Msg("Error generating containerd config")
66+
return fmt.Errorf("could not generate containerd config: %w", err)
67+
}
68+
return GenerateContainerdConfig(log, containerdConfigPath, containerDCertPath)
69+
}
70+
return nil
71+
},
72+
}
73+
74+
containerdCmd.Flags().BoolVarP(&generateConfig, "gen", "g", false, "Generate the containerd config file")
75+
containerdCmd.PersistentFlags().StringVarP(&containerdConfigPath, "path", "p", DefaultContainerdConfigPath, "Path to the containerd config file of the container runtime")
76+
containerdCmd.PersistentFlags().StringVarP(&containerDCertPath, "cert-path", "c", ContainerDCertPath, "Path to the containerd cert directory")
77+
containerdCmd.AddCommand(NewReadConfigCommand(ContainerdRuntime))
78+
return containerdCmd
79+
}
80+
81+
// GenerateContainerdConfig generates the containerd config file for the containerd runtime
82+
// It takes the zot config a logger and the containerd config path
83+
// It reads the containerd config file and adds the local registry to the config file
84+
func GenerateContainerdConfig(log *zerolog.Logger, containerdConfigPath, containerdCertPath string) error {
85+
// First Read the present config file at the configPath
86+
data, err := utils.ReadFile(containerdConfigPath, false)
87+
if err != nil {
88+
if os.IsNotExist(err) {
89+
log.Warn().Msg("Config file does not exist, proceeding with default values")
90+
data = []byte{}
91+
} else {
92+
log.Err(err).Msg("Error reading config file")
93+
return fmt.Errorf("could not read config file: %w", err)
94+
}
95+
}
96+
// Now we marshal the data into the containerd config
97+
containerdConfig := &ContainerdConfigToml{}
98+
err = toml.Unmarshal(data, containerdConfig)
99+
if err != nil {
100+
log.Err(err).Msg("Error unmarshalling config")
101+
return fmt.Errorf("could not unmarshal config: %w", err)
102+
}
103+
// Add the certs.d path to the config
104+
if containerdConfig.Plugins.Cri.Registry.ConfigPath == "" {
105+
containerdConfig.Plugins.Cri.Registry.ConfigPath = containerdCertPath
106+
}
107+
// Set default version
108+
if containerdConfig.Version == 0 {
109+
containerdConfig.Version = DefaultConfigVersion
110+
}
111+
// if config disabled plugins container cri then remove it
112+
if len(containerdConfig.DisabledPlugins) > 0 {
113+
filteredPlugins := make([]string, 0, len(containerdConfig.DisabledPlugins))
114+
for _, plugin := range containerdConfig.DisabledPlugins {
115+
if plugin != "cri" {
116+
filteredPlugins = append(filteredPlugins, plugin)
117+
}
118+
}
119+
containerdConfig.DisabledPlugins = filteredPlugins
120+
}
121+
// ToDo: Find a way to remove the unwanted configuration added to the config file while marshalling
122+
pathToWrite := filepath.Join(DefaultContainerDGenPath, DefaultGeneratedTomlName)
123+
log.Info().Msgf("Writing the containerd config to path: %s", pathToWrite)
124+
// Now we write the config to the file
125+
data, err = toml.Marshal(containerdConfig)
126+
dataStr := string(data)
127+
dataStr = strings.Replace(dataStr, "[plugins]\n", "", 1)
128+
data = []byte(dataStr)
129+
if err != nil {
130+
log.Err(err).Msg("Error marshalling config")
131+
return fmt.Errorf("could not marshal config: %w", err)
132+
}
133+
err = utils.WriteFile(pathToWrite, data)
134+
if err != nil {
135+
log.Err(err).Msg("Error writing config to file")
136+
return fmt.Errorf("could not write config to file: %w", err)
137+
}
138+
return nil
139+
}
Lines changed: 169 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,169 @@
1+
package runtime
2+
3+
// ContainerdConfigToml provides containerd configuration data for the server
4+
type ContainerdConfigToml struct {
5+
// Version of the config file
6+
Version int `toml:"version,omitempty"`
7+
// Root is the path to a directory where containerd will store persistent data
8+
Root string `toml:"root,omitempty"`
9+
// State is the path to a directory where containerd will store transient data
10+
State string `toml:"state,omitempty"`
11+
// TempDir is the path to a directory where to place containerd temporary files
12+
TempDir string `toml:"temp,omitempty"`
13+
// PluginDir is the directory for dynamic plugins to be stored
14+
//
15+
// Deprecated: Please use proxy or binary external plugins.
16+
PluginDir string `toml:"plugin_dir,omitempty"`
17+
// GRPC configuration settings
18+
GRPC GRPCConfig `toml:"grpc,omitempty"`
19+
// TTRPC configuration settings
20+
TTRPC TTRPCConfig `toml:"ttrpc,omitempty"`
21+
// Debug and profiling settings
22+
Debug Debug `toml:"debug,omitempty"`
23+
// Metrics and monitoring settings
24+
Metrics MetricsConfig `toml:"metrics,omitempty"`
25+
// DisabledPlugins are IDs of plugins to disable. Disabled plugins won't be
26+
// initialized and started.
27+
// DisabledPlugins must use a fully qualified plugin URI.
28+
DisabledPlugins []string `toml:"disabled_plugins,omitempty"`
29+
// RequiredPlugins are IDs of required plugins. Containerd exits if any
30+
// required plugin doesn't exist or fails to be initialized or started.
31+
// RequiredPlugins must use a fully qualified plugin URI.
32+
RequiredPlugins []string `toml:"required_plugins,omitempty"`
33+
// Plugins provides plugin specific configuration for the initialization of a plugin
34+
Plugins PluginsConfig `toml:"plugins,omitempty"`
35+
// OOMScore adjust the containerd's oom score
36+
OOMScore int `toml:"oom_score,omitempty"`
37+
// Cgroup specifies cgroup information for the containerd daemon process
38+
Cgroup CgroupConfig `toml:"cgroup,omitempty"`
39+
// ProxyPlugins configures plugins which are communicated to over GRPC
40+
ProxyPlugins map[string]ProxyPlugin `toml:"proxy_plugins,omitempty"`
41+
// Timeouts specified as a duration
42+
Timeouts map[string]string `toml:"timeouts,omitempty"`
43+
// Imports are additional file path list to config files that can overwrite main config file fields
44+
Imports []string `toml:"imports,omitempty"`
45+
// StreamProcessors configuration
46+
StreamProcessors map[string]StreamProcessor `toml:"stream_processors,omitempty"`
47+
}
48+
49+
type StreamProcessor struct {
50+
// Accepts specific media-types
51+
Accepts []string `toml:"accepts,omitempty"`
52+
// Returns the media-type
53+
Returns string `toml:"returns,omitempty"`
54+
// Path or name of the binary
55+
Path string `toml:"path"`
56+
// Args to the binary
57+
Args []string `toml:"args,omitempty"`
58+
// Environment variables for the binary
59+
Env []string `toml:"env,omitempty"`
60+
}
61+
62+
type GRPCConfig struct {
63+
Address string `toml:"address"`
64+
TCPAddress string `toml:"tcp_address,omitempty"`
65+
TCPTLSCA string `toml:"tcp_tls_ca,omitempty"`
66+
TCPTLSCert string `toml:"tcp_tls_cert,omitempty"`
67+
TCPTLSKey string `toml:"tcp_tls_key,omitempty"`
68+
UID int `toml:"uid,omitempty"`
69+
GID int `toml:"gid,omitempty"`
70+
MaxRecvMsgSize int `toml:"max_recv_message_size,omitempty"`
71+
MaxSendMsgSize int `toml:"max_send_message_size,omitempty"`
72+
}
73+
74+
// TTRPCConfig provides TTRPC configuration for the socket
75+
type TTRPCConfig struct {
76+
Address string `toml:"address"`
77+
UID int `toml:"uid,omitempty"`
78+
GID int `toml:"gid,omitempty"`
79+
}
80+
81+
// Debug provides debug configuration
82+
type Debug struct {
83+
Address string `toml:"address,omitempty"`
84+
UID int `toml:"uid,omitempty"`
85+
GID int `toml:"gid,omitempty"`
86+
Level string `toml:"level,omitempty"`
87+
// Format represents the logging format. Supported values are 'text' and 'json'.
88+
Format string `toml:"format,omitempty"`
89+
}
90+
91+
// MetricsConfig provides metrics configuration
92+
type MetricsConfig struct {
93+
Address string `toml:"address,omitempty"`
94+
GRPCHistogram bool `toml:"grpc_histogram,omitempty"`
95+
}
96+
97+
// CgroupConfig provides cgroup configuration
98+
type CgroupConfig struct {
99+
Path string `toml:"path,omitempty"`
100+
}
101+
102+
// ProxyPlugin provides a proxy plugin configuration
103+
type ProxyPlugin struct {
104+
Type string `toml:"type"`
105+
Address string `toml:"address"`
106+
Platform string `toml:"platform,omitempty"`
107+
Exports map[string]string `toml:"exports,omitempty"`
108+
Capabilities []string `toml:"capabilities,omitempty"`
109+
}
110+
111+
type PluginsConfig struct {
112+
Cri CriConfig `toml:"io.containerd.grpc.v1.cri,omitempty"`
113+
Cgroups MonitorConfig `toml:"io.containerd.monitor.v1.cgroups,omitempty"`
114+
LinuxRuntime interface{} `toml:"io.containerd.runtime.v1.linux,omitempty"`
115+
Scheduler GCSchedulerConfig `toml:"io.containerd.gc.v1.scheduler,omitempty"`
116+
Bolt interface{} `toml:"io.containerd.metadata.v1.bolt,omitempty"`
117+
Task RuntimeV2TaskConfig `toml:"io.containerd.runtime.v2.task,omitempty"`
118+
Opt interface{} `toml:"io.containerd.internal.v1.opt,omitempty"`
119+
Restart interface{} `toml:"io.containerd.internal.v1.restart,omitempty"`
120+
Tracing interface{} `toml:"io.containerd.internal.v1.tracing,omitempty"`
121+
Otlp interface{} `toml:"io.containerd.tracing.processor.v1.otlp,omitempty"`
122+
Aufs interface{} `toml:"io.containerd.snapshotter.v1.aufs,omitempty"`
123+
Btrfs interface{} `toml:"io.containerd.snapshotter.v1.btrfs,omitempty"`
124+
Devmapper interface{} `toml:"io.containerd.snapshotter.v1.devmapper,omitempty"`
125+
Native interface{} `toml:"io.containerd.snapshotter.v1.native,omitempty"`
126+
Overlayfs interface{} `toml:"io.containerd.snapshotter.v1.overlayfs,omitempty"`
127+
Zfs interface{} `toml:"io.containerd.snapshotter.v1.zfs,omitempty"`
128+
}
129+
130+
type MonitorConfig struct {
131+
NoPrometheus bool `toml:"no_prometheus,omitempty"`
132+
}
133+
134+
type GCSchedulerConfig struct {
135+
PauseThreshold float64 `toml:"pause_threshold,omitempty"`
136+
DeletionThreshold int `toml:"deletion_threshold,omitempty"`
137+
MutationThreshold int `toml:"mutation_threshold,omitempty"`
138+
ScheduleDelay string `toml:"schedule_delay,omitempty"`
139+
StartupDelay string `toml:"startup_delay,omitempty"`
140+
}
141+
142+
type RuntimeV2TaskConfig struct {
143+
Platforms []string `toml:"platforms,omitempty"`
144+
SchedCore bool `toml:"sched_core,omitempty"`
145+
}
146+
147+
type CriConfig struct {
148+
Containerd CriContainerdConfig `toml:"containerd,omitempty"`
149+
Registry RegistryConfig `toml:"registry,omitempty"`
150+
}
151+
152+
type CriContainerdConfig struct {
153+
DefaultRuntimeName string `toml:"default_runtime_name,omitempty"`
154+
Runtimes map[string]RuntimeConfig `toml:"runtimes,omitempty"`
155+
}
156+
157+
type RuntimeConfig struct {
158+
PrivilegedWithoutHostDevices bool `toml:"privileged_without_host_devices,omitempty"`
159+
RuntimeType string `toml:"runtime_type"`
160+
Options RuntimeOptions `toml:"options,omitempty"`
161+
}
162+
163+
type RuntimeOptions struct {
164+
BinaryName string `toml:"BinaryName,omitempty"`
165+
}
166+
167+
type RegistryConfig struct {
168+
ConfigPath string `toml:"config_path,omitempty"`
169+
}

0 commit comments

Comments
 (0)