github.com/Racer159/jackal@v0.32.7-0.20240401174413-0bd2339e4f2e/src/internal/packager/images/push.go (about) 1 // SPDX-License-Identifier: Apache-2.0 2 // SPDX-FileCopyrightText: 2021-Present The Jackal Authors 3 4 // Package images provides functions for building and pushing images. 5 package images 6 7 import ( 8 "fmt" 9 "net/http" 10 "time" 11 12 "github.com/Racer159/jackal/src/config" 13 "github.com/Racer159/jackal/src/pkg/cluster" 14 "github.com/Racer159/jackal/src/pkg/k8s" 15 "github.com/Racer159/jackal/src/pkg/message" 16 "github.com/Racer159/jackal/src/pkg/transform" 17 "github.com/Racer159/jackal/src/pkg/utils" 18 "github.com/defenseunicorns/pkg/helpers" 19 "github.com/google/go-containerregistry/pkg/crane" 20 "github.com/google/go-containerregistry/pkg/logs" 21 v1 "github.com/google/go-containerregistry/pkg/v1" 22 ) 23 24 // PushToJackalRegistry pushes a provided image into the configured Jackal registry 25 // This function will optionally shorten the image name while appending a checksum of the original image name. 26 func (i *ImageConfig) PushToJackalRegistry() error { 27 message.Debug("images.PushToJackalRegistry()") 28 29 logs.Warn.SetOutput(&message.DebugWriter{}) 30 logs.Progress.SetOutput(&message.DebugWriter{}) 31 32 refInfoToImage := map[transform.Image]v1.Image{} 33 var totalSize int64 34 // Build an image list from the references 35 for _, refInfo := range i.ImageList { 36 img, err := utils.LoadOCIImage(i.ImagesPath, refInfo) 37 if err != nil { 38 return err 39 } 40 refInfoToImage[refInfo] = img 41 imgSize, err := calcImgSize(img) 42 if err != nil { 43 return err 44 } 45 totalSize += imgSize 46 } 47 48 // If this is not a no checksum image push we will be pushing two images (the second will go faster as it checks the same layers) 49 if !i.NoChecksum { 50 totalSize = totalSize * 2 51 } 52 53 httpTransport := http.DefaultTransport.(*http.Transport).Clone() 54 httpTransport.TLSClientConfig.InsecureSkipVerify = i.Insecure 55 // TODO (@WSTARR) This is set to match the TLSHandshakeTimeout to potentially mitigate effects of https://github.com/Racer159/jackal/issues/1444 56 httpTransport.ResponseHeaderTimeout = 10 * time.Second 57 progressBar := message.NewProgressBar(totalSize, fmt.Sprintf("Pushing %d images to the jackal registry", len(i.ImageList))) 58 defer progressBar.Stop() 59 craneTransport := helpers.NewTransport(httpTransport, progressBar) 60 61 pushOptions := config.GetCraneOptions(i.Insecure, i.Architectures...) 62 pushOptions = append(pushOptions, config.GetCraneAuthOption(i.RegInfo.PushUsername, i.RegInfo.PushPassword)) 63 pushOptions = append(pushOptions, crane.WithTransport(craneTransport)) 64 65 var ( 66 err error 67 tunnel *k8s.Tunnel 68 registryURL string 69 ) 70 71 registryURL = i.RegInfo.Address 72 73 c, _ := cluster.NewCluster() 74 if c != nil { 75 registryURL, tunnel, err = c.ConnectToJackalRegistryEndpoint(i.RegInfo) 76 if err != nil { 77 return err 78 } 79 } 80 81 if tunnel != nil { 82 defer tunnel.Close() 83 } 84 85 pushImage := func(img v1.Image, name string) error { 86 if tunnel != nil { 87 return tunnel.Wrap(func() error { return crane.Push(img, name, pushOptions...) }) 88 } 89 90 return crane.Push(img, name, pushOptions...) 91 } 92 93 for refInfo, img := range refInfoToImage { 94 refTruncated := message.Truncate(refInfo.Reference, 55, true) 95 progressBar.UpdateTitle(fmt.Sprintf("Pushing %s", refTruncated)) 96 97 // If this is not a no checksum image push it for use with the Jackal agent 98 if !i.NoChecksum { 99 offlineNameCRC, err := transform.ImageTransformHost(registryURL, refInfo.Reference) 100 if err != nil { 101 return err 102 } 103 104 message.Debugf("crane.Push() %s:%s -> %s)", i.ImagesPath, refInfo.Reference, offlineNameCRC) 105 106 err = pushImage(img, offlineNameCRC) 107 if err != nil { 108 return err 109 } 110 } 111 112 // To allow for other non-jackal workloads to easily see the images upload a non-checksum version 113 // (this may result in collisions but this is acceptable for this use case) 114 offlineName, err := transform.ImageTransformHostWithoutChecksum(registryURL, refInfo.Reference) 115 if err != nil { 116 return err 117 } 118 119 message.Debugf("crane.Push() %s:%s -> %s)", i.ImagesPath, refInfo.Reference, offlineName) 120 121 err = pushImage(img, offlineName) 122 if err != nil { 123 return err 124 } 125 } 126 127 progressBar.Successf("Pushed %d images to the jackal registry", len(i.ImageList)) 128 129 return nil 130 } 131 132 func calcImgSize(img v1.Image) (int64, error) { 133 size, err := img.Size() 134 if err != nil { 135 return size, err 136 } 137 138 layers, err := img.Layers() 139 if err != nil { 140 return size, err 141 } 142 143 for _, layer := range layers { 144 ls, err := layer.Size() 145 if err != nil { 146 return size, err 147 } 148 size += ls 149 } 150 151 return size, nil 152 }