Skip to content

Commit 9b294af

Browse files
committed
feat: generate mirrors patch
Upon starting a image cache server, attempt to generate patch for Talos. Signed-off-by: Mateusz Urbanek <mateusz.urbanek@siderolabs.com> (cherry picked from commit f1c04e4)
1 parent 15465f0 commit 9b294af

File tree

2 files changed

+97
-2
lines changed

2 files changed

+97
-2
lines changed

cmd/talosctl/cmd/talos/image.go

Lines changed: 96 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ import (
1212
"io"
1313
"log"
1414
"net"
15+
"net/url"
1516
"os"
1617
"os/signal"
1718
"slices"
@@ -21,6 +22,7 @@ import (
2122

2223
"github.com/blang/semver/v4"
2324
"github.com/dustin/go-humanize"
25+
"github.com/siderolabs/gen/ensure"
2426
"github.com/spf13/cobra"
2527
"github.com/spf13/pflag"
2628
"go.uber.org/zap"
@@ -34,8 +36,11 @@ import (
3436
"github.com/siderolabs/talos/pkg/machinery/api/common"
3537
"github.com/siderolabs/talos/pkg/machinery/api/machine"
3638
"github.com/siderolabs/talos/pkg/machinery/client"
39+
"github.com/siderolabs/talos/pkg/machinery/config/config"
3740
"github.com/siderolabs/talos/pkg/machinery/config/container"
3841
"github.com/siderolabs/talos/pkg/machinery/config/encoder"
42+
"github.com/siderolabs/talos/pkg/machinery/config/types/cri"
43+
"github.com/siderolabs/talos/pkg/machinery/config/types/meta"
3944
"github.com/siderolabs/talos/pkg/machinery/config/types/security"
4045
"github.com/siderolabs/talos/pkg/machinery/config/types/v1alpha1"
4146
"github.com/siderolabs/talos/pkg/machinery/constants"
@@ -443,6 +448,14 @@ var imageCacheServeCmd = &cobra.Command{
443448
return fmt.Errorf("failed to create development logger: %w", err)
444449
}
445450

451+
if err = generateMirrorsConfigPatch(
452+
imageCacheServeCmdFlags.address,
453+
imageCacheServeCmdFlags.mirrors,
454+
imageCacheServeCmdFlags.tlsCertFile != "" && imageCacheServeCmdFlags.tlsKeyFile != "",
455+
); err != nil {
456+
development.Error("failed to generate Talos config patch for registry mirrors", zap.Error(err))
457+
}
458+
446459
it := func(yield func(string) bool) {
447460
for _, root := range []string{imageCacheServeCmdFlags.imageCachePath} {
448461
if !yield(root) {
@@ -462,9 +475,88 @@ var imageCacheServeCmd = &cobra.Command{
462475
},
463476
}
464477

478+
//nolint:gocyclo
479+
func generateMirrorsConfigPatch(addr string, mirrors []string, secure bool) error {
480+
addresses := []string{}
481+
482+
host, port, err := net.SplitHostPort(addr)
483+
if err != nil {
484+
return err
485+
}
486+
487+
if host == "" || host == "0.0.0.0" || host == "[::]" {
488+
// list all IPs for the host
489+
ips, err := net.InterfaceAddrs()
490+
if err != nil {
491+
return err
492+
}
493+
494+
for _, addr := range ips {
495+
if ipnet, ok := addr.(*net.IPNet); ok {
496+
if ipnet.IP.IsLoopback() {
497+
continue
498+
}
499+
500+
addresses = append(addresses, net.JoinHostPort(ipnet.IP.String(), port))
501+
}
502+
503+
if ipa, ok := addr.(*net.IPAddr); ok {
504+
if ipa.IP.IsLoopback() {
505+
continue
506+
}
507+
508+
addresses = append(addresses, net.JoinHostPort(ipa.IP.String(), port))
509+
}
510+
}
511+
} else {
512+
addresses = []string{net.JoinHostPort(host, port)}
513+
}
514+
515+
if port == "0" {
516+
return nil // we do not generate patch for dynamic ports
517+
}
518+
519+
patches := make([]config.Document, 0, len(mirrors))
520+
521+
prefix := "http://"
522+
if secure {
523+
prefix = "https://"
524+
}
525+
526+
for _, mirror := range mirrors {
527+
patch := cri.NewRegistryMirrorConfigV1Alpha1(mirror)
528+
patch.RegistryEndpoints = []cri.RegistryEndpoint{}
529+
530+
for _, endpoint := range addresses {
531+
patch.RegistryEndpoints = append(patch.RegistryEndpoints, cri.RegistryEndpoint{
532+
EndpointURL: meta.URL{URL: ensure.Value(url.Parse(prefix + endpoint))},
533+
})
534+
}
535+
536+
patches = append(patches, patch)
537+
}
538+
539+
ctr, err := container.New(patches...)
540+
if err != nil {
541+
return err
542+
}
543+
544+
patchBytes, err := ctr.EncodeBytes(encoder.WithComments(encoder.CommentsDisabled))
545+
if err != nil {
546+
return err
547+
}
548+
549+
const patchFile = "image-cache-mirrors-patch.yaml"
550+
551+
log.Printf("writing config patch to %s", patchFile)
552+
553+
return os.WriteFile(patchFile, patchBytes, 0o644)
554+
}
555+
465556
var imageCacheServeCmdFlags struct {
466557
imageCachePath string
467558
address string
559+
mirrors []string
468560
tlsCertFile string
469561
tlsKeyFile string
470562
}
@@ -485,7 +577,7 @@ var imageCacheCertGenCmd = &cobra.Command{
485577
return nil
486578
}
487579

488-
if err = generateConfigPatch(caPEM); err != nil {
580+
if err = generateCAConfigPatch(caPEM); err != nil {
489581
return err
490582
}
491583

@@ -505,7 +597,7 @@ var imageCacheCertGenCmd = &cobra.Command{
505597
},
506598
}
507599

508-
func generateConfigPatch(caPEM []byte) error {
600+
func generateCAConfigPatch(caPEM []byte) error {
509601
patch := security.NewTrustedRootsConfigV1Alpha1()
510602
patch.MetaName = "image-cache-ca"
511603
patch.Certificates = string(caPEM)
@@ -562,6 +654,8 @@ func init() {
562654
imageCacheServeCmd.PersistentFlags().StringVar(&imageCacheServeCmdFlags.imageCachePath, "image-cache-path", "", "directory to save the image cache in flat format")
563655
imageCacheServeCmd.MarkPersistentFlagRequired("image-cache-path") //nolint:errcheck
564656
imageCacheServeCmd.PersistentFlags().StringVar(&imageCacheServeCmdFlags.address, "address", constants.RegistrydListenAddress, "address to serve the registry on")
657+
imageCacheServeCmd.PersistentFlags().StringSliceVar(&imageCacheServeCmdFlags.mirrors, "mirror", []string{"docker.io", "ghcr.io", "registry.k8s.io"},
658+
"list of registry mirrors to add to the Talos config patch")
565659
imageCacheServeCmd.PersistentFlags().StringVar(&imageCacheServeCmdFlags.tlsCertFile, "tls-cert-file", "", "TLS certificate file to use for serving")
566660
imageCacheServeCmd.PersistentFlags().StringVar(&imageCacheServeCmdFlags.tlsKeyFile, "tls-key-file", "", "TLS key file to use for serving")
567661

website/content/v1.12/reference/cli.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1961,6 +1961,7 @@ talosctl image cache-serve [flags]
19611961
--address string address to serve the registry on (default "127.0.0.1:3172")
19621962
-h, --help help for cache-serve
19631963
--image-cache-path string directory to save the image cache in flat format
1964+
--mirror strings list of registry mirrors to add to the Talos config patch (default [docker.io,ghcr.io,registry.k8s.io])
19641965
--tls-cert-file string TLS certificate file to use for serving
19651966
--tls-key-file string TLS key file to use for serving
19661967
```

0 commit comments

Comments
 (0)