Skip to content

Commit 349849c

Browse files
committed
Use embedded hashes for our well-known assets
Rather than downloading the hash every time, we can record the hashes for our well-known assets and bake them into the kOps binary. If the hash is not baked in, we will continue to fall-back to downloading it, this is important for new k8s versions, or where the user specifies a version of one of our well-known assets (such as containerd).
1 parent 311a1fa commit 349849c

17 files changed

+197
-475
lines changed

cmd/kops/get_assets.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -132,7 +132,7 @@ func RunGetAssets(ctx context.Context, f *util.Factory, out io.Writer, options *
132132
file := File{
133133
Canonical: fileAsset.CanonicalURL.String(),
134134
Download: fileAsset.DownloadURL.String(),
135-
SHA: fileAsset.SHAValue,
135+
SHA: fileAsset.SHAValue.Hex(),
136136
}
137137
if !seen[file.Canonical] {
138138
result.Files = append(result.Files, &file)

pkg/assets/builder.go

+30-44
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ import (
3232
"k8s.io/klog/v2"
3333
"k8s.io/kops/pkg/apis/kops"
3434
"k8s.io/kops/pkg/apis/kops/util"
35+
"k8s.io/kops/pkg/assets/assetdata"
3536
"k8s.io/kops/pkg/featureflag"
3637
"k8s.io/kops/pkg/kubemanifest"
3738
"k8s.io/kops/pkg/values"
@@ -97,7 +98,7 @@ type FileAsset struct {
9798
// CanonicalURL is the canonical location of the asset, for example as distributed by the kops project
9899
CanonicalURL *url.URL
99100
// SHAValue is the SHA hash of the FileAsset.
100-
SHAValue string
101+
SHAValue *hashing.Hash
101102
}
102103

103104
// NewAssetBuilder creates a new AssetBuilder.
@@ -235,70 +236,45 @@ func (a *AssetBuilder) RemapImage(image string) (string, error) {
235236
return image + "@" + digest, nil
236237
}
237238

238-
// RemapFileAndSHA returns a remapped URL for the file, if AssetsLocation is defined.
239-
// It also returns the SHA hash of the file.
240-
func (a *AssetBuilder) RemapFileAndSHA(fileURL *url.URL) (*url.URL, *hashing.Hash, error) {
241-
if fileURL == nil {
242-
return nil, nil, fmt.Errorf("unable to remap a nil URL")
239+
// RemapFile returns a remapped URL for the file, if AssetsLocation is defined.
240+
// It also returns the SHA hash of the file; which is knownHash is provided,
241+
// and otherwise will be found via download.
242+
func (a *AssetBuilder) RemapFile(canonicalURL *url.URL, knownHash *hashing.Hash) (*FileAsset, error) {
243+
if canonicalURL == nil {
244+
return nil, fmt.Errorf("unable to remap a nil URL")
243245
}
244246

245247
fileAsset := &FileAsset{
246-
DownloadURL: fileURL,
247-
CanonicalURL: fileURL,
248+
DownloadURL: canonicalURL,
249+
CanonicalURL: canonicalURL,
248250
}
249251

250252
if a.AssetsLocation != nil && a.AssetsLocation.FileRepository != nil {
251-
252-
normalizedFile, err := a.remapURL(fileURL)
253+
normalizedFile, err := a.remapURL(canonicalURL)
253254
if err != nil {
254-
return nil, nil, err
255+
return nil, err
255256
}
256257

257-
if fileURL.Host != normalizedFile.Host {
258+
if canonicalURL.Host != normalizedFile.Host {
258259
fileAsset.DownloadURL = normalizedFile
259260
klog.V(4).Infof("adding remapped file: %q", fileAsset.DownloadURL.String())
260261
}
261262
}
262263

263-
h, err := a.findHash(fileAsset)
264-
if err != nil {
265-
return nil, nil, err
266-
}
267-
fileAsset.SHAValue = h.Hex()
268-
269-
klog.V(8).Infof("adding file: %+v", fileAsset)
270-
a.FileAssets = append(a.FileAssets, fileAsset)
271-
272-
return fileAsset.DownloadURL, h, nil
273-
}
274-
275-
// RemapFileAndSHAValue returns a remapped URL for the file without a SHA file in object storage, if AssetsLocation is defined.
276-
func (a *AssetBuilder) RemapFileAndSHAValue(fileURL *url.URL, shaValue string) (*url.URL, error) {
277-
if fileURL == nil {
278-
return nil, fmt.Errorf("unable to remap a nil URL")
279-
}
280-
281-
fileAsset := &FileAsset{
282-
DownloadURL: fileURL,
283-
CanonicalURL: fileURL,
284-
SHAValue: shaValue,
285-
}
286-
287-
if a.AssetsLocation != nil && a.AssetsLocation.FileRepository != nil {
288-
normalizedFile, err := a.remapURL(fileURL)
264+
if knownHash == nil {
265+
h, err := a.findHash(fileAsset)
289266
if err != nil {
290267
return nil, err
291268
}
292-
if fileURL.Host != normalizedFile.Host {
293-
fileAsset.DownloadURL = normalizedFile
294-
klog.V(4).Infof("adding remapped file: %q", fileAsset.DownloadURL.String())
295-
}
269+
knownHash = h
296270
}
297271

272+
fileAsset.SHAValue = knownHash
273+
298274
klog.V(8).Infof("adding file: %+v", fileAsset)
299275
a.FileAssets = append(a.FileAssets, fileAsset)
300276

301-
return fileAsset.DownloadURL, nil
277+
return fileAsset, nil
302278
}
303279

304280
// FindHash returns the hash value of a FileAsset.
@@ -324,6 +300,16 @@ func (a *AssetBuilder) findHash(file *FileAsset) (*hashing.Hash, error) {
324300
return nil, fmt.Errorf("file url is not defined")
325301
}
326302

303+
knownHash, found, err := assetdata.GetHash(file.CanonicalURL)
304+
if err != nil {
305+
return nil, err
306+
}
307+
if found {
308+
return knownHash, nil
309+
}
310+
311+
klog.Infof("asset %q is not well-known, downloading hash", file.CanonicalURL)
312+
327313
// We now prefer sha256 hashes
328314
for backoffSteps := 1; backoffSteps <= 3; backoffSteps++ {
329315
// We try first with a short backoff, so we don't
@@ -338,7 +324,7 @@ func (a *AssetBuilder) findHash(file *FileAsset) (*hashing.Hash, error) {
338324
for _, ext := range []string{".sha256", ".sha256sum"} {
339325
for _, mirror := range FindURLMirrors(u.String()) {
340326
hashURL := mirror + ext
341-
klog.V(3).Infof("Trying to read hash fie: %q", hashURL)
327+
klog.V(3).Infof("Trying to read hash file: %q", hashURL)
342328
b, err := a.vfsContext.ReadFile(hashURL, vfs.WithBackoff(backoff))
343329
if err != nil {
344330
// Try to log without being too alarming - issue #7550

pkg/assets/copy.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@ func Copy(imageAssets []*ImageAsset, fileAssets []*FileAsset, vfsContext *vfs.VF
5656
Name: fileAsset.CanonicalURL.String(),
5757
TargetFile: fileAsset.DownloadURL.String(),
5858
SourceFile: fileAsset.CanonicalURL.String(),
59-
SHA: fileAsset.SHAValue,
59+
SHA: fileAsset.SHAValue.Hex(),
6060
VFSContext: vfsContext,
6161
Cluster: cluster,
6262
}

pkg/assets/mirrored_asset.go

+5-4
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,6 @@ limitations under the License.
1717
package assets
1818

1919
import (
20-
"net/url"
2120
"strings"
2221

2322
"k8s.io/klog/v2"
@@ -30,12 +29,14 @@ type MirroredAsset struct {
3029
}
3130

3231
// BuildMirroredAsset checks to see if this is a file under the standard base location, and if so constructs some mirror locations
33-
func BuildMirroredAsset(u *url.URL, hash *hashing.Hash) *MirroredAsset {
32+
func BuildMirroredAsset(asset *FileAsset) *MirroredAsset {
33+
u := asset.DownloadURL
34+
3435
a := &MirroredAsset{
35-
Hash: hash,
36+
Hash: asset.SHAValue,
3637
}
3738

38-
if hash == nil {
39+
if asset.SHAValue == nil {
3940
klog.Warningf("not using mirrors for asset %s as it does not have a known hash", u)
4041
a.Locations = []string{u.String()}
4142
} else {

pkg/nodemodel/fileassets.go

+30-22
Original file line numberDiff line numberDiff line change
@@ -75,11 +75,11 @@ func (c *FileAssets) AddFileAssets(assetBuilder *assets.AssetBuilder) error {
7575
}
7676
k.Path = path.Join(k.Path, an)
7777

78-
u, hash, err := assetBuilder.RemapFileAndSHA(k)
78+
asset, err := buildMirroredAsset(assetBuilder, k)
7979
if err != nil {
8080
return err
8181
}
82-
c.Assets[arch] = append(c.Assets[arch], assets.BuildMirroredAsset(u, hash))
82+
c.Assets[arch] = append(c.Assets[arch], asset)
8383
}
8484

8585
kubernetesVersion, _ := util.ParseKubernetesVersion(c.Cluster.Spec.KubernetesVersion)
@@ -106,70 +106,69 @@ func (c *FileAssets) AddFileAssets(assetBuilder *assets.AssetBuilder) error {
106106
if err != nil {
107107
return fmt.Errorf("unable to parse auth-provider-gcp binary asset hash %q: %v", hashes[arch], err)
108108
}
109-
u, err := assetBuilder.RemapFileAndSHAValue(k, hashes[arch])
109+
asset, err := assetBuilder.RemapFile(k, hash)
110110
if err != nil {
111111
return err
112112
}
113113

114-
c.Assets[arch] = append(c.Assets[arch], assets.BuildMirroredAsset(u, hash))
114+
c.Assets[arch] = append(c.Assets[arch], assets.BuildMirroredAsset(asset))
115115
case kops.CloudProviderAWS:
116116
binaryLocation := c.Cluster.Spec.CloudProvider.AWS.BinariesLocation
117117
if binaryLocation == nil {
118118
binaryLocation = fi.PtrTo("https://artifacts.k8s.io/binaries/cloud-provider-aws/v1.27.1")
119119
}
120120

121-
k, err := url.Parse(fmt.Sprintf("%s/linux/%s/ecr-credential-provider-linux-%s", *binaryLocation, arch, arch))
121+
u, err := url.Parse(fmt.Sprintf("%s/linux/%s/ecr-credential-provider-linux-%s", *binaryLocation, arch, arch))
122122
if err != nil {
123123
return err
124124
}
125-
u, hash, err := assetBuilder.RemapFileAndSHA(k)
125+
asset, err := buildMirroredAsset(assetBuilder, u)
126126
if err != nil {
127127
return err
128128
}
129-
130-
c.Assets[arch] = append(c.Assets[arch], assets.BuildMirroredAsset(u, hash))
129+
c.Assets[arch] = append(c.Assets[arch], asset)
131130
}
132131
}
133132

134133
{
135-
cniAsset, cniAssetHash, err := wellknownassets.FindCNIAssets(c.Cluster, assetBuilder, arch)
134+
cniAsset, err := wellknownassets.FindCNIAssets(c.Cluster, assetBuilder, arch)
136135
if err != nil {
137136
return err
138137
}
139-
c.Assets[arch] = append(c.Assets[arch], assets.BuildMirroredAsset(cniAsset, cniAssetHash))
138+
c.Assets[arch] = append(c.Assets[arch], assets.BuildMirroredAsset(cniAsset))
140139
}
141140

142141
if c.Cluster.Spec.Containerd == nil || !c.Cluster.Spec.Containerd.SkipInstall {
143-
containerdAssetUrl, containerdAssetHash, err := wellknownassets.FindContainerdAsset(c.Cluster, assetBuilder, arch)
142+
containerdAsset, err := wellknownassets.FindContainerdAsset(c.Cluster, assetBuilder, arch)
144143
if err != nil {
145144
return err
146145
}
147-
if containerdAssetUrl != nil && containerdAssetHash != nil {
148-
c.Assets[arch] = append(c.Assets[arch], assets.BuildMirroredAsset(containerdAssetUrl, containerdAssetHash))
146+
if containerdAsset != nil {
147+
c.Assets[arch] = append(c.Assets[arch], assets.BuildMirroredAsset(containerdAsset))
149148
}
150149

151-
runcAssetUrl, runcAssetHash, err := wellknownassets.FindRuncAsset(c.Cluster, assetBuilder, arch)
150+
runcAsset, err := wellknownassets.FindRuncAsset(c.Cluster, assetBuilder, arch)
152151
if err != nil {
153152
return err
154153
}
155-
if runcAssetUrl != nil && runcAssetHash != nil {
156-
c.Assets[arch] = append(c.Assets[arch], assets.BuildMirroredAsset(runcAssetUrl, runcAssetHash))
154+
if runcAsset != nil {
155+
c.Assets[arch] = append(c.Assets[arch], assets.BuildMirroredAsset(runcAsset))
157156
}
158-
nerdctlAssetUrl, nerdctlAssetHash, err := wellknownassets.FindNerdctlAsset(c.Cluster, assetBuilder, arch)
157+
nerdctlAsset, err := wellknownassets.FindNerdctlAsset(c.Cluster, assetBuilder, arch)
159158
if err != nil {
160159
return err
161160
}
162-
if nerdctlAssetUrl != nil && nerdctlAssetHash != nil {
163-
c.Assets[arch] = append(c.Assets[arch], assets.BuildMirroredAsset(nerdctlAssetUrl, nerdctlAssetHash))
161+
if nerdctlAsset != nil {
162+
c.Assets[arch] = append(c.Assets[arch], assets.BuildMirroredAsset(nerdctlAsset))
164163
}
165164
}
166165

167-
crictlAssetUrl, crictlAssetHash, err := wellknownassets.FindCrictlAsset(c.Cluster, assetBuilder, arch)
166+
crictlAsset, err := wellknownassets.FindCrictlAsset(c.Cluster, assetBuilder, arch)
168167
if err != nil {
169168
return err
170169
}
171-
if crictlAssetUrl != nil && crictlAssetHash != nil {
172-
c.Assets[arch] = append(c.Assets[arch], assets.BuildMirroredAsset(crictlAssetUrl, crictlAssetHash))
170+
if crictlAsset != nil {
171+
c.Assets[arch] = append(c.Assets[arch], assets.BuildMirroredAsset(crictlAsset))
173172
}
174173

175174
asset, err := wellknownassets.NodeUpAsset(assetBuilder, arch)
@@ -193,3 +192,12 @@ func needsMounterAsset(c *kops.Cluster) bool {
193192
return false
194193
}
195194
}
195+
196+
func buildMirroredAsset(assetBuilder *assets.AssetBuilder, canonicalURL *url.URL) (*assets.MirroredAsset, error) {
197+
asset, err := assetBuilder.RemapFile(canonicalURL, nil)
198+
if err != nil {
199+
return nil, err
200+
}
201+
mirroredAsset := assets.BuildMirroredAsset(asset)
202+
return mirroredAsset, nil
203+
}

pkg/nodemodel/nodeupconfigbuilder.go

+9-9
Original file line numberDiff line numberDiff line change
@@ -117,14 +117,14 @@ func NewNodeUpConfigBuilder(cluster *kops.Cluster, assetBuilder *assets.AssetBui
117117

118118
baseURL.Path = path.Join(baseURL.Path, "/bin/linux", string(arch), component+".tar")
119119

120-
u, hash, err := assetBuilder.RemapFileAndSHA(baseURL)
120+
asset, err := assetBuilder.RemapFile(baseURL, nil)
121121
if err != nil {
122122
return nil, err
123123
}
124124

125125
image := &nodeup.Image{
126-
Sources: []string{u.String()},
127-
Hash: hash.Hex(),
126+
Sources: []string{asset.DownloadURL.String()},
127+
Hash: asset.SHAValue.Hex(),
128128
}
129129
images[role][arch] = append(images[role][arch], image)
130130
}
@@ -143,14 +143,14 @@ func NewNodeUpConfigBuilder(cluster *kops.Cluster, assetBuilder *assets.AssetBui
143143

144144
baseURL.Path = path.Join(baseURL.Path, "/images/"+name+"-"+string(arch)+".tar.gz")
145145

146-
u, hash, err := assetBuilder.RemapFileAndSHA(baseURL)
146+
asset, err := assetBuilder.RemapFile(baseURL, nil)
147147
if err != nil {
148148
return nil, err
149149
}
150150

151151
image := &nodeup.Image{
152-
Sources: []string{u.String()},
153-
Hash: hash.Hex(),
152+
Sources: []string{asset.DownloadURL.String()},
153+
Hash: asset.SHAValue.Hex(),
154154
}
155155
images[role][arch] = append(images[role][arch], image)
156156
}
@@ -166,14 +166,14 @@ func NewNodeUpConfigBuilder(cluster *kops.Cluster, assetBuilder *assets.AssetBui
166166

167167
baseURL.Path = path.Join(baseURL.Path, "/images/"+name+"-"+string(arch)+".tar.gz")
168168

169-
u, hash, err := assetBuilder.RemapFileAndSHA(baseURL)
169+
asset, err := assetBuilder.RemapFile(baseURL, nil)
170170
if err != nil {
171171
return nil, err
172172
}
173173

174174
image := &nodeup.Image{
175-
Sources: []string{u.String()},
176-
Hash: hash.Hex(),
175+
Sources: []string{asset.DownloadURL.String()},
176+
Hash: asset.SHAValue.Hex(),
177177
}
178178
images[role][arch] = append(images[role][arch], image)
179179
}

0 commit comments

Comments
 (0)