-
Notifications
You must be signed in to change notification settings - Fork 136
/
version_image.go
80 lines (64 loc) · 2.24 KB
/
version_image.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
package version
import (
"context"
"fmt"
"github.com/Dynatrace/dynatrace-operator/src/dockerconfig"
"github.com/containers/image/v5/image"
"github.com/containers/image/v5/manifest"
"github.com/containers/image/v5/transports/alltransports"
"github.com/containers/image/v5/types"
)
const (
// VersionLabel is the name of the label used on ActiveGate-provided images.
VersionLabel = "com.dynatrace.build-version"
)
// ImageVersion includes information for a given image. Version can be empty if the corresponding label isn't set.
type ImageVersion struct {
Version string
Hash string
}
// ImageVersionProvider can fetch image information from img
type ImageVersionProvider func(img string, dockerConfig *dockerconfig.DockerConfig) (ImageVersion, error)
var _ ImageVersionProvider = GetImageVersion
// GetImageVersion fetches image information for imageName
func GetImageVersion(imageName string, dockerConfig *dockerconfig.DockerConfig) (ImageVersion, error) {
transportImageName := fmt.Sprintf("docker://%s", imageName)
imageReference, err := alltransports.ParseImageName(transportImageName)
if err != nil {
return ImageVersion{}, err
}
systemContext := dockerconfig.MakeSystemContext(imageReference.DockerReference(), dockerConfig)
imageSource, err := imageReference.NewImageSource(context.TODO(), systemContext)
if err != nil {
return ImageVersion{}, err
}
defer closeImageSource(imageSource)
imageManifest, _, err := imageSource.GetManifest(context.TODO(), nil)
if err != nil {
return ImageVersion{}, err
}
digest, err := manifest.Digest(imageManifest)
if err != nil {
return ImageVersion{}, err
}
sourceImage, err := image.FromUnparsedImage(context.TODO(), systemContext, image.UnparsedInstance(imageSource, nil))
if err != nil {
return ImageVersion{}, err
}
inspectedImage, err := sourceImage.Inspect(context.TODO())
if err != nil {
return ImageVersion{}, err
} else if inspectedImage == nil {
return ImageVersion{}, fmt.Errorf("could not inspect image: '%s'", transportImageName)
}
return ImageVersion{
Hash: digest.Encoded(),
Version: inspectedImage.Labels[VersionLabel], // empty if unset
}, nil
}
func closeImageSource(source types.ImageSource) {
if source != nil {
// Swallow error
_ = source.Close()
}
}