Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: expand GetLatestSigImageConfig to include cached VHD data #4267

Closed
wants to merge 19 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions pkg/agent/bakerapi.go
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,10 @@ func (agentBaker *agentBakerImpl) GetLatestSigImageConfig(sigConfig datamodel.SI
sigImageConfig.Version = imageVersion
}
}

sigImageConfig.CachedFromManifest = datamodel.CachedFromManifest
sigImageConfig.CachedFromComponsents = datamodel.CachedFromComponsents

return sigImageConfig, nil
}

Expand Down
23 changes: 23 additions & 0 deletions pkg/agent/bakerapi_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,9 @@ var _ = Describe("AgentBaker API implementation tests", func() {
)

BeforeEach(func() {
datamodel.CacheManifest()
datamodel.CacheComponents()

toggles = agenttoggles.New()

cs = &datamodel.ContainerService{
Expand Down Expand Up @@ -312,6 +315,26 @@ var _ = Describe("AgentBaker API implementation tests", func() {
Expect(sigImageConfig.Version).To(Equal("2021.11.06"))
})

It("should return cached VHD data", func() {
agentBaker, err := NewAgentBaker()
Expect(err).NotTo(HaveOccurred())
agentBaker = agentBaker.WithToggles(toggles)

sigImageConfig, err := agentBaker.GetLatestSigImageConfig(config.SIGConfig, datamodel.AKSUbuntu1604, &datamodel.EnvironmentInfo{
SubscriptionID: config.SubscriptionID,
TenantID: config.TenantID,
Region: cs.Location,
})
Expect(err).NotTo(HaveOccurred())

Expect(sigImageConfig.CachedFromManifest["runc"].Installed["default"]).To(Equal("1.1.12"))
Expect(sigImageConfig.CachedFromManifest["containerd"].Pinned["1804"]).To(Equal("1.7.1-1"))
Expect(sigImageConfig.CachedFromManifest["containerd"].Edge).To(Equal("1.7.15-1"))
Expect(sigImageConfig.CachedFromComponsents["pause"].MultiArchVersions[0]).To(Equal("3.6"))
Expect(sigImageConfig.CachedFromComponsents["azure-cns"].PrefetchOptimizations.Version).To(Equal("v1.5.23"))
Expect(sigImageConfig.CachedFromComponsents["azure-cns"].PrefetchOptimizations.Binaries[0]).To(Equal("usr/local/bin/azure-cns"))
})

It("should return correct value for existing distro when linux node image version override is provided", func() {
toggles.Maps = map[string]agenttoggles.MapToggle{
"linux-node-image-version": func(entity *agenttoggles.Entity) map[string]string {
Expand Down
21 changes: 21 additions & 0 deletions pkg/agent/datamodel/helper.go
Original file line number Diff line number Diff line change
Expand Up @@ -98,3 +98,24 @@ func IndentString(original string, spaces int) string {
}
return out.String()
}

func trimEOF(data []byte) []byte {
eofIndex := bytes.LastIndex(data, []byte("#EOF"))
if eofIndex != -1 { // #EOF found
newlineIndex := bytes.LastIndex(data[:eofIndex], []byte("\n"))
if newlineIndex != -1 {
return data[:newlineIndex]
}
}
return data
}

func processDownloadURL(downloadURL string) string {
// example URL "downloadURL": "mcr.microsoft.com/oss/kubernetes/autoscaler/addon-resizer:*",
// getting the data between the last / and the last :
parts := strings.Split(downloadURL, "/")
lastPart := parts[len(parts)-1]
component := strings.Split(lastPart, ":")
componentName := component[0]
return componentName
}
26 changes: 26 additions & 0 deletions pkg/agent/datamodel/helper_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -346,3 +346,29 @@ func TestIndentString(t *testing.T) {
})
}
}

func TestTrimEOF(t *testing.T) {
tests := []struct {
name string
input []byte
expected string
}{
{
name: "Should remove #EOF at the end of a file",
input: []byte(`"versions":["1.26.6","1.26.10","1.26.12","1.27.3","1.27.7","1.27.9","1.28.1","1.28.3","1.28.5","1.29.0","1.29.2"]},"_template":{"fileName":"","downloadLocation":"","downloadURL":"","versions":[]}}` + "\n#EOF"), //nolint:lll
expected: `"versions":["1.26.6","1.26.10","1.26.12","1.27.3","1.27.7","1.27.9","1.28.1","1.28.3","1.28.5","1.29.0","1.29.2"]},"_template":{"fileName":"","downloadLocation":"","downloadURL":"","versions":[]}}`, //nolint:lll
},
}

for _, test := range tests {
test := test
t.Run(test.name, func(t *testing.T) {
t.Parallel()
got := trimEOF(test.input)
diff := cmp.Diff(test.expected, string(got))
if diff != "" {
t.Fatalf(diff)
}
})
}
}
150 changes: 147 additions & 3 deletions pkg/agent/datamodel/sig_config.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,9 @@ import (
_ "embed"
"encoding/json"
"fmt"
"os"
"path"
"runtime"
"strings"
)

Expand All @@ -12,6 +15,30 @@ const (
AzurePublicCloudSigSubscription string = "109a5e88-712a-48ae-9078-9ca8b3c81345" // AKS VHD
)

//nolint:gochecknoglobals
var (
CachedFromComponsents = make(map[string]ProcessedComponents)
CachedFromManifest = make(map[string]ProcessedManifest)
)

//nolint:gochecknoinits
func init() {
CacheManifest()
CacheComponents()
}

func CacheManifest() {
_, filename, _, _ := runtime.Caller(0)
manifestFilePath := "../../../parts/linux/cloud-init/artifacts/manifest.json"
getCachedK8sVersionFromManifest(path.Join(path.Dir(filename), manifestFilePath))
}

func CacheComponents() {
_, filename, _, _ := runtime.Caller(0)
componentsFilePath := "../../../vhdbuilder/packer/components.json"
getCachedComponentsFromComponents(path.Join(path.Dir(filename), componentsFilePath))
}

// SIGAzureEnvironmentSpecConfig is the overall configuration differences in different cloud environments.
/* TODO(tonyxu) merge this with AzureEnvironmentSpecConfig from aks-engine(pkg/api/azenvtypes.go) once
it's moved into AKS RP. */
Expand Down Expand Up @@ -273,8 +300,6 @@ func (d Distro) IsWindowsDistro() bool {
}

// SigImageConfigTemplate represents the SIG image configuration template.
//
//nolint:musttag // tags can be added if deemed necessary
type SigImageConfigTemplate struct {
ResourceGroup string
Gallery string
Expand All @@ -285,7 +310,9 @@ type SigImageConfigTemplate struct {
// SigImageConfig represents the SIG image configuration.
type SigImageConfig struct {
SigImageConfigTemplate
SubscriptionID string
SubscriptionID string
CachedFromManifest map[string]ProcessedManifest
CachedFromComponsents map[string]ProcessedComponents
}

// WithOptions converts a SigImageConfigTemplate to SigImageConfig instance via function opts.
Expand Down Expand Up @@ -875,3 +902,120 @@ func withSubscription(subscriptionID string) SigImageConfigOpt {
c.SubscriptionID = subscriptionID
}
}

type Manifest struct {
Containerd struct {
Edge string `json:"edge"`
Versions []string `json:"versions"`
Pinned map[string]string `json:"pinned"`
} `json:"containerd"`
Runc struct {
Versions []string `json:"versions"`
Pinned map[string]string `json:"pinned"`
Installed map[string]string `json:"installed"`
} `json:"runc"`
NvidiaContainerRuntime struct {
Versions []string `json:"versions"`
} `json:"nvidia-container-runtime"`
NvidiaDrivers struct {
Versions []string `json:"versions"`
} `json:"nvidia-drivers"`
Kubernetes struct {
Versions []string `json:"versions"`
} `json:"kubernetes"`
}

type ProcessedManifest struct {
Name string
Versions []string
Pinned map[string]string
Edge string
Installed map[string]string
}

func getCachedK8sVersionFromManifest(manifestFilePath string) {
data, err := os.ReadFile(manifestFilePath)
if err != nil {
panic(err)
}
data = trimEOF(data)
var manifest Manifest
if err = json.Unmarshal(data, &manifest); err != nil {
panic(err)
}

CachedFromManifest["kubernetes"] = ProcessedManifest{
Name: "kubernetes",
Versions: manifest.Kubernetes.Versions,
}
CachedFromManifest["runc"] = ProcessedManifest{
Name: "runc",
Versions: manifest.Runc.Versions,
Pinned: manifest.Runc.Pinned,
Installed: manifest.Runc.Installed,
}
CachedFromManifest["containerd"] = ProcessedManifest{
Name: "containerd",
Versions: manifest.Containerd.Versions,
Pinned: manifest.Containerd.Pinned,
Edge: manifest.Containerd.Edge,
}
CachedFromManifest["nvidia-container-runtime"] = ProcessedManifest{
Name: "nvidia-container-runtime",
Versions: manifest.NvidiaContainerRuntime.Versions,
}
CachedFromManifest["nvidia-drivers"] = ProcessedManifest{
Name: "nvidia-drivers",
Versions: manifest.NvidiaDrivers.Versions,
}
}

type Components struct {
ContainerImages []struct {
DownloadURL string `json:"downloadURL"`
Amd64OnlyVersions []string `json:"amd64OnlyVersions"`
MultiArchVersions []string `json:"multiArchVersions"`
PrefetchOptimizations []struct {
Version string `json:"version"`
Binaries []string `json:"binaries"`
} `json:"prefetchOptimizations"`
} `json:"ContainerImages"`
}
type PrefetchOptimizations struct {
Version string
Binaries []string
}

type ProcessedComponents struct {
Name string
MultiArchVersions []string
Amd64OnlyVersions []string
PrefetchOptimizations PrefetchOptimizations
}

func getCachedComponentsFromComponents(componentsFilePath string) {
data, err := os.ReadFile(componentsFilePath)
if err != nil {
panic(err)
}
var components Components
if err = json.Unmarshal(data, &components); err != nil {
panic(err)
}

for _, image := range components.ContainerImages {
componentName := processDownloadURL(image.DownloadURL)
processed := ProcessedComponents{
Name: componentName,
MultiArchVersions: image.MultiArchVersions,
Amd64OnlyVersions: image.Amd64OnlyVersions,
}
if len(image.PrefetchOptimizations) > 0 {
processed.PrefetchOptimizations = PrefetchOptimizations{
Version: image.PrefetchOptimizations[0].Version,
Binaries: image.PrefetchOptimizations[0].Binaries,
}
}
CachedFromComponsents[componentName] = processed
}
}
6 changes: 0 additions & 6 deletions pkg/agent/datamodel/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -1620,8 +1620,6 @@ type K8sComponents struct {

// GetLatestSigImageConfigRequest describes the input for a GetLatestSigImageConfig HTTP request.
// This is mostly a wrapper over existing types so RP doesn't have to manually construct JSON.
//
//nolint:musttag // tags can be added if deemed necessary
type GetLatestSigImageConfigRequest struct {
SIGConfig SIGConfig
SubscriptionID string
Expand All @@ -1631,8 +1629,6 @@ type GetLatestSigImageConfigRequest struct {
}

// NodeBootstrappingConfiguration represents configurations for node bootstrapping.
//
//nolint:musttag // tags can be added if deemed necessary
type NodeBootstrappingConfiguration struct {
ContainerService *ContainerService
CloudSpecConfig *AzureEnvironmentSpecConfig
Expand Down Expand Up @@ -1695,8 +1691,6 @@ const (
)

// NodeBootstrapping represents the custom data, CSE, and OS image info needed for node bootstrapping.
//
//nolint:musttag // tags can be added if deemed necessary
type NodeBootstrapping struct {
CustomData string
CSE string
Expand Down
1 change: 0 additions & 1 deletion pkg/agent/utils_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -725,5 +725,4 @@ var _ = Describe("Test removeComments", func() {
result := removeComments(input)
Expect(string(result)).To(Equal(expected))
})

})
Loading