Skip to content

Commit

Permalink
adding config command for crio
Browse files Browse the repository at this point in the history
  • Loading branch information
Mehul-Kumar-27 committed Nov 4, 2024
1 parent 771a6e3 commit 0dc1160
Show file tree
Hide file tree
Showing 5 changed files with 234 additions and 34 deletions.
45 changes: 12 additions & 33 deletions cmd/container_runtime/containerd.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,20 +29,21 @@ type ContainerdController interface {
Generate(ctx context.Context, configPath string, log *zerolog.Logger) error
}

var DefaultGenPath string
var DefaultContainerDGenPath string

func init() {
cwd, err := os.Getwd()
if err != nil {
fmt.Printf("Error getting current working directory: %v\n", err)
if _, err := os.Stat(DefaultGenPath); os.IsNotExist(err) {
err := os.MkdirAll(DefaultGenPath, os.ModePerm)
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 {
DefaultGenPath = filepath.Join(cwd, "runtime/containerd")
DefaultContainerDGenPath = filepath.Join(cwd, "runtime/containerd")
}
}

Expand All @@ -56,43 +57,21 @@ func NewContainerdCommand() *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 {
var err error
utils.SetupContextForCommand(cmd)
config.InitConfig()
log := logger.FromContext(cmd.Context())
if config.GetOwnRegistry() {
log.Info().Msg("Using own registry for config generation")
address, err := utils.ValidateRegistryAddress(config.GetOwnRegistryAdr(), config.GetOwnRegistryPort())
if err != nil {
log.Err(err).Msg("Error validating registry address")
return err
}
log.Info().Msgf("Registry address validated: %s", address)
defaultZotConfig.HTTP.Address = config.GetOwnRegistryAdr()
defaultZotConfig.HTTP.Port = config.GetOwnRegistryPort()
} else {
log.Info().Msg("Using default registry for config generation")
defaultZotConfig, err = registry.ReadConfig(config.GetZotConfigPath())
if err != nil || defaultZotConfig == nil {
return fmt.Errorf("could not read config: %w", err)
}
log.Info().Msgf("Default config read successfully: %v", defaultZotConfig.HTTP.Address+":"+defaultZotConfig.HTTP.Port)
}
return utils.CreateRuntimeDirectory(DefaultGenPath)
return SetupContainerRuntimeCommand(cmd, &defaultZotConfig, DefaultContainerDGenPath)
},
RunE: func(cmd *cobra.Command, args []string) error {
log := logger.FromContext(cmd.Context())
sourceRegistry := config.GetRemoteRegistryURL()
satelliteHostConfig := NewSatelliteHostConfig(defaultZotConfig.GetLocalRegistryURL(), sourceRegistry)
if generateConfig {
log.Info().Msg("Generating containerd config file for containerd ...")
log.Info().Msgf("Fetching containerd config from path path: %s", containerdConfigPath)
err := GenerateContainerdHostConfig(containerDCertPath, DefaultGenPath, log, *satelliteHostConfig)
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 GenerateConfig(defaultZotConfig, log, containerdConfigPath, containerDCertPath)
return GenerateContainerdConfig(defaultZotConfig, log, containerdConfigPath, containerDCertPath)
}
return nil
},
Expand All @@ -105,10 +84,10 @@ func NewContainerdCommand() *cobra.Command {
return containerdCmd
}

// GenerateConfig generates the containerd config file for the containerd runtime
// 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 GenerateConfig(defaultZotConfig *registry.DefaultZotConfig, log *zerolog.Logger, containerdConfigPath, containerdCertPath string) error {
func GenerateContainerdConfig(defaultZotConfig *registry.DefaultZotConfig, 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 {
Expand Down Expand Up @@ -141,7 +120,7 @@ func GenerateConfig(defaultZotConfig *registry.DefaultZotConfig, log *zerolog.Lo
containerdConfig.DisabledPlugins = filteredPlugins
}
// ToDo: Find a way to remove the unwanted configuration added to the config file while marshalling
pathToWrite := filepath.Join(DefaultGenPath, DefaultGeneratedTomlName)
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)
Expand Down
169 changes: 169 additions & 0 deletions cmd/container_runtime/crio.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,169 @@
package runtime

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

"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"
"github.com/pelletier/go-toml/v2"
"github.com/rs/zerolog"
"github.com/spf13/cobra"
)

const (
DefaultCrioRegistryConfigPath = "/etc/containers/registries.conf.d/crio.conf"
)

var DefaultCrioGenPath string

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

func NewCrioCommand() *cobra.Command {
var defaultZotConfig *registry.DefaultZotConfig
var generateConfig bool
var crioConfigPath string

crioCmd := &cobra.Command{
Use: "crio",
Short: "Creates the config file for the crio runtime to fetch the images from the local repository",
PersistentPreRunE: func(cmd *cobra.Command, args []string) error {
return SetupContainerRuntimeCommand(cmd, &defaultZotConfig, DefaultCrioGenPath)
},
RunE: func(cmd *cobra.Command, args []string) error {
log := logger.FromContext(cmd.Context())
if generateConfig {
log.Info().Msg("Generating the config file for crio ...")
log.Info().Msgf("Fetching crio registry config file form path: %s", crioConfigPath)
// Generate the config file
err := GenerateCrioRegistryConfig(defaultZotConfig, crioConfigPath, log)
if err != nil {
log.Err(err).Msg("Error generating crio registry config")
return err
}
}
return nil
},
}
crioCmd.Flags().BoolVarP(&generateConfig, "gen", "g", false, "Generate the config file")
crioCmd.PersistentFlags().StringVarP(&crioConfigPath, "config", "c", DefaultCrioRegistryConfigPath, "Path to the crio registry config file")
return crioCmd
}

func GenerateCrioRegistryConfig(defaultZotConfig *registry.DefaultZotConfig, crioConfigPath string, log *zerolog.Logger) error {
// Read the current crio registry config file
data, err := utils.ReadFile(crioConfigPath, false)
if err != nil {
return fmt.Errorf("could not read crio registry config file: %w", err)
}
var crioRegistryConfig CriORegistryConfig
err = toml.Unmarshal(data, &crioRegistryConfig)
if err != nil {
log.Err(err).Msg("Error unmarshalling crio registry config")
return fmt.Errorf("could not unmarshal crio registry config: %w", err)
}
// Update the crio registry config file
// - Add the local registry to the unqualified search registries if not already present
var found bool = false
var localRegistry string = utils.FormatRegistryURL(defaultZotConfig.GetLocalRegistryURL())
for _, registry := range crioRegistryConfig.UnqualifiedSearchRegistries {
if registry == localRegistry {
found = true
break
}
}
if !found {
crioRegistryConfig.UnqualifiedSearchRegistries = append(crioRegistryConfig.UnqualifiedSearchRegistries, localRegistry)
}
// Now range over the registries and find if there is a registry with the prefix satellite
// If there is a registry with the prefix satellite, update the location to the local registry
found = false
for _, registries := range crioRegistryConfig.Registries {
if registries.Prefix == "satellite" {
found = true
if registries.Location == "" {
registries.Location = DockerURL
}
// Add the local registry to the first position in the mirrors
mirror := Mirror{
Location: localRegistry,
Insecure: config.UseUnsecure(),
}
registries.Mirrors = append([]Mirror{mirror}, registries.Mirrors...)
}
}
if !found {
// Add the satellite registry to the registries
registry := Registry{
Prefix: "satellite",
Location: DockerURL,
Mirrors: []Mirror{
{
Location: localRegistry,
Insecure: config.UseUnsecure(),
},
},
}
crioRegistryConfig.Registries = append(crioRegistryConfig.Registries, registry)
}
// Now marshal the updated crio registry config
updatedData, err := toml.Marshal(crioRegistryConfig)
if err != nil {
log.Err(err).Msg("Error marshalling crio registry config")
return fmt.Errorf("could not marshal crio registry config: %w", err)
}
// Write the updated crio registry config to the file
pathToWrite := filepath.Join(DefaultCrioGenPath, "crio.conf")
log.Info().Msgf("Writing the crio registry config to path: %s", pathToWrite)
err = utils.WriteFile(pathToWrite, updatedData)
if err != nil {
log.Err(err).Msg("Error writing crio registry config")
return fmt.Errorf("could not write crio registry config: %w", err)
}
log.Info().Msg("Successfully wrote the crio registry config")
return nil
}

func SetupContainerRuntimeCommand(cmd *cobra.Command, defaultZotConfig **registry.DefaultZotConfig, defaultGenPath string) error {
var err error
utils.SetupContextForCommand(cmd)
config.InitConfig()
log := logger.FromContext(cmd.Context())

if config.GetOwnRegistry() {
log.Info().Msg("Using own registry for config generation")
address, err := utils.ValidateRegistryAddress(config.GetOwnRegistryAdr(), config.GetOwnRegistryPort())
if err != nil {
log.Err(err).Msg("Error validating registry address")
return err
}
log.Info().Msgf("Registry address validated: %s", address)
(*defaultZotConfig).HTTP.Address = config.GetOwnRegistryAdr()
(*defaultZotConfig).HTTP.Port = config.GetOwnRegistryPort()
} else {
log.Info().Msg("Using default registry for config generation")
*defaultZotConfig, err = registry.ReadConfig(config.GetZotConfigPath())
if err != nil || *defaultZotConfig == nil {
return fmt.Errorf("could not read config: %w", err)
}
log.Info().Msgf("Default config read successfully: %v", (*defaultZotConfig).HTTP.Address+":"+(*defaultZotConfig).HTTP.Port)
}
return utils.CreateRuntimeDirectory(defaultGenPath)
}
51 changes: 51 additions & 0 deletions cmd/container_runtime/crio_config.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
package runtime

// CriORegistryConfig represents the overall configuration for container image registries.
type CriORegistryConfig struct {
// UnqualifiedSearchRegistries is an array of host[:port] registries to try
// when pulling an unqualified image, in the specified order.
UnqualifiedSearchRegistries []string `toml:"unqualified-search-registries,omitempty"`

// Registries is a list of registry configurations, each defining the behavior for a specific prefix or namespace.
Registries []Registry `toml:"registry,omitempty"`
}

// Registry represents a specific registry configuration.
type Registry struct {
// Prefix is used to choose the relevant [[registry]] TOML table.
// Only the table with the longest match for the input image name
// (considering namespace/repo/tag/digest separators) is used.
// If this field is missing, it defaults to the value of Location.
// Example: "example.com/foo"
Prefix string `toml:"prefix,omitempty"`

// Insecure allows unencrypted HTTP as well as TLS connections with untrusted certificates
// if set to true. This should only be enabled for trusted registries to avoid security risks.
Insecure bool `toml:"insecure,omitempty"`

// Blocked, if set to true, prevents pulling images with matching names from this registry.
// This can be used to blacklist certain registries.
Blocked bool `toml:"blocked,omitempty"`

// Location specifies the physical location of the "prefix"-rooted namespace.
// By default, this is equal to "prefix". It can be empty for wildcarded prefixes (e.g., "*.example.com"),
// in which case the input reference is used as-is without modification.
// Example: "internal-registry-for-example.com/bar"
Location string `toml:"location,omitempty"`

// Mirrors is an array of potential mirror locations for the "prefix"-rooted namespace.
// Mirrors are attempted in the specified order; the first reachable mirror containing the image
// is used. If no mirror has the image, the primary location or the unmodified user-specified reference is tried last.
Mirrors []Mirror `toml:"mirror,omitempty"`
}

// Mirror represents a mirror registry configuration.
type Mirror struct {
// Location specifies the address of the mirror. The mirror will be used if it contains the image.
// Example: "example-mirror-0.local/mirror-for-foo"
Location string `toml:"location,omitempty"`

// Insecure allows access to the mirror over unencrypted HTTP or with untrusted TLS certificates
// if set to true. This should be used cautiously.
Insecure bool `toml:"insecure,omitempty"`
}
2 changes: 1 addition & 1 deletion cmd/container_runtime/host.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ const (
SatelliteConfigPath = "satellite"
HostToml = "host_gen.toml"
DefaultTomlConfigPath = "_default"
DockerURL = "https://registry-1.docker.io"
DockerURL = "docker.io"
)

type ContainerdHostConfig struct {
Expand Down
1 change: 1 addition & 0 deletions cmd/root.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ func NewRootCommand() *cobra.Command {
},
}
rootCmd.AddCommand(runtime.NewContainerdCommand())
rootCmd.AddCommand(runtime.NewCrioCommand())
return rootCmd
}

Expand Down

0 comments on commit 0dc1160

Please sign in to comment.