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

Add new API to get cached versions of components on the VHD #4306

Merged
merged 62 commits into from
Apr 26, 2024
Merged
Show file tree
Hide file tree
Changes from 55 commits
Commits
Show all changes
62 commits
Select commit Hold shift + click to select a range
9050abc
feat: adding api to get k8s version in manifest.json
AlisonB319 Mar 29, 2024
99e8198
don't need any inputs
AlisonB319 Mar 29, 2024
87b84cf
Merge branch 'master' into alburgess/ABtoRPns
AlisonB319 Mar 29, 2024
d1b0a60
fix linter
AlisonB319 Mar 29, 2024
e85e450
fix linter
AlisonB319 Mar 29, 2024
9fb7e24
fix formatting
AlisonB319 Mar 29, 2024
af40354
rename to k8versions
AlisonB319 Apr 1, 2024
9a85d8f
use hardcoded path
AlisonB319 Apr 1, 2024
f0a93bf
Merge branch 'master' into alburgess/ABtoRPns
AlisonB319 Apr 1, 2024
91e3bc5
remove blank lines
AlisonB319 Apr 1, 2024
315ee9c
remove blank lines
AlisonB319 Apr 1, 2024
f87e2d5
change up testing
AlisonB319 Apr 1, 2024
233a937
Remove unused util
AlisonB319 Apr 1, 2024
41ff623
reorder
AlisonB319 Apr 1, 2024
dc02986
rename functions
AlisonB319 Apr 17, 2024
10c7ee4
tests not fully operational yet
AlisonB319 Apr 17, 2024
e86c351
merge master and fix conflicts
AlisonB319 Apr 17, 2024
8fd9eb5
unit tests
AlisonB319 Apr 17, 2024
45817c9
fix api server side
AlisonB319 Apr 17, 2024
ccf9bf4
change name again
AlisonB319 Apr 17, 2024
44ef921
fix naming
AlisonB319 Apr 17, 2024
3e0c5e4
remove name component for easier readability
AlisonB319 Apr 17, 2024
bfaf1b3
fix linter
AlisonB319 Apr 17, 2024
841f51b
Merge branch 'master' into alburgess/ABtoRPns
AlisonB319 Apr 17, 2024
31fb1df
cleanup
AlisonB319 Apr 17, 2024
aff3190
rename
AlisonB319 Apr 17, 2024
0bb5cad
change how to remove EOF
AlisonB319 Apr 17, 2024
f43afde
error check
AlisonB319 Apr 17, 2024
1571297
cleanup
AlisonB319 Apr 17, 2024
3bd2a81
reorganize
AlisonB319 Apr 17, 2024
8610a2a
remove changes to SigImageConfig
AlisonB319 Apr 17, 2024
5f13525
Merge branch 'master' into alburgess/ABtoRPns
AlisonB319 Apr 18, 2024
d9f18f3
improve tests
AlisonB319 Apr 19, 2024
90c8966
fix variables for linter
AlisonB319 Apr 19, 2024
b6c6345
Merge branch 'master' into alburgess/ABtoRPns
AlisonB319 Apr 22, 2024
b1383dd
Update pkg/agent/datamodel/sig_config.go
AlisonB319 Apr 23, 2024
5268f0c
Update pkg/agent/datamodel/helper.go
AlisonB319 Apr 23, 2024
d7dc207
Merge branch 'master' into alburgess/ABtoRPns
AlisonB319 Apr 23, 2024
fdc89e2
fix imports
AlisonB319 Apr 23, 2024
d6e8f31
cammel case for json key
AlisonB319 Apr 23, 2024
662a57c
change function name
AlisonB319 Apr 23, 2024
61fd09c
trim suffix
AlisonB319 Apr 23, 2024
57b2b6b
needs to be cap to be exported
AlisonB319 Apr 23, 2024
15801d4
make components a little neater
AlisonB319 Apr 23, 2024
17f56cc
Add downloaded files
AlisonB319 Apr 23, 2024
edde50d
feedback
AlisonB319 Apr 23, 2024
b0d0867
linter
AlisonB319 Apr 23, 2024
95166ac
Re-work manifest
AlisonB319 Apr 24, 2024
7809e72
fix linter
AlisonB319 Apr 24, 2024
11304f1
clarification comment
AlisonB319 Apr 24, 2024
8390ef3
Merge branch 'master' into alburgess/ABtoRPns
AlisonB319 Apr 24, 2024
d3d864f
Merge branch 'master' into alburgess/ABtoRPns
AlisonB319 Apr 25, 2024
d622b24
continue slight reworks
AlisonB319 Apr 25, 2024
525760d
Merge branch 'alburgess/ABtoRPns' of https://github.com/Azure/AgentBa…
AlisonB319 Apr 25, 2024
20e75a9
Merge branch 'master' into alburgess/ABtoRPns
AlisonB319 Apr 25, 2024
6e50921
pr comments
AlisonB319 Apr 25, 2024
c1be03d
fix linter
AlisonB319 Apr 25, 2024
1df434a
small refactor
AlisonB319 Apr 25, 2024
ca9e0f4
help linter out
AlisonB319 Apr 25, 2024
bc5d973
add unit tests for helper functions
AlisonB319 Apr 25, 2024
2e13fb5
have cached be returned as a pointer
AlisonB319 Apr 25, 2024
85d926d
Merge branch 'master' into alburgess/ABtoRPns
AlisonB319 Apr 26, 2024
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
41 changes: 41 additions & 0 deletions apiserver/getcachedvhdimages.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
package apiserver

import (
"encoding/json"
"fmt"
"log"
"net/http"

"github.com/Azure/agentbaker/pkg/agent"
)

const (
// RoutePathGetCachedVersionsOnVHD the route path to get cached vhd images.
RoutePathGetCachedVersionsOnVHD string = "/getcachedversionsonvhd"
)

// GetCachedVersionsOnVHD endpoint for getting the current versions of components cached on the vhd.
func (api *APIServer) GetCachedVersionsOnVHD(w http.ResponseWriter, r *http.Request) {
agentBaker, err := agent.NewAgentBaker()
if err != nil {
log.Println(err.Error())
http.Error(w, err.Error(), http.StatusBadRequest)
return
}

cachedOnVHD, err := agentBaker.GetCachedVersionsOnVHD()
if err != nil {
log.Println(err.Error())
http.Error(w, err.Error(), http.StatusBadRequest)
return
}

jsonResponse, err := json.Marshal(cachedOnVHD)
if err != nil {
log.Println(err.Error())
http.Error(w, err.Error(), http.StatusBadRequest)
return
}
w.WriteHeader(http.StatusOK)
fmt.Fprint(w, string(jsonResponse))
}
2 changes: 1 addition & 1 deletion apiserver/getdistrosigimageconfig.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import (
"log"
"net/http"

agent "github.com/Azure/agentbaker/pkg/agent"
"github.com/Azure/agentbaker/pkg/agent"
"github.com/Azure/agentbaker/pkg/agent/datamodel"
)

Expand Down
2 changes: 1 addition & 1 deletion apiserver/getlatestsigimageconfig.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import (
"log"
"net/http"

agent "github.com/Azure/agentbaker/pkg/agent"
"github.com/Azure/agentbaker/pkg/agent"
"github.com/Azure/agentbaker/pkg/agent/datamodel"
)

Expand Down
2 changes: 1 addition & 1 deletion apiserver/getnodebootstrapdata.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import (
"net/http"
"time"

agent "github.com/Azure/agentbaker/pkg/agent"
"github.com/Azure/agentbaker/pkg/agent"
"github.com/Azure/agentbaker/pkg/agent/datamodel"
)

Expand Down
6 changes: 6 additions & 0 deletions apiserver/routers.go
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,12 @@ func (api *APIServer) NewRouter() *mux.Router {
Name("GetDistroSigImageConfig").
HandlerFunc(api.GetDistroSigImageConfig)

router.
Methods("GET").
Path(RoutePathGetCachedVersionsOnVHD).
Name("GetCachedVersionsOnVHD").
HandlerFunc(api.GetCachedVersionsOnVHD)

router.Methods("GET").Path("/healthz").Name("healthz").HandlerFunc(healthz)

// global timeout and panic handlers.
Expand Down
15 changes: 15 additions & 0 deletions pkg/agent/bakerapi.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ type AgentBaker interface {
GetNodeBootstrapping(ctx context.Context, config *datamodel.NodeBootstrappingConfiguration) (*datamodel.NodeBootstrapping, error)
GetLatestSigImageConfig(sigConfig datamodel.SIGConfig, distro datamodel.Distro, envInfo *datamodel.EnvironmentInfo) (*datamodel.SigImageConfig, error)
GetDistroSigImageConfig(sigConfig datamodel.SIGConfig, envInfo *datamodel.EnvironmentInfo) (map[datamodel.Distro]datamodel.SigImageConfig, error)
GetCachedVersionsOnVHD() (datamodel.CachedOnVHD, error)
}

type agentBakerImpl struct {
Expand Down Expand Up @@ -174,3 +175,17 @@ func findSIGImageConfig(sigConfig datamodel.SIGAzureEnvironmentSpecConfig, distr

return nil
}

func (agentBaker *agentBakerImpl) GetCachedVersionsOnVHD() (datamodel.CachedOnVHD, error) {
cached := datamodel.CachedOnVHD{
CachedFromManifest: datamodel.CachedFromManifest,
CachedFromComponentContainerImages: datamodel.CachedFromComponentContainerImages,
CachedFromComponentDownloadedFiles: datamodel.CachedFromComponentDownloadedFiles,
}

if datamodel.CachedFromManifest == (&datamodel.Manifest{}) || datamodel.CachedFromComponentContainerImages == nil || datamodel.CachedFromComponentDownloadedFiles == nil {
return cached, fmt.Errorf("cached versions are not available")
}

return cached, nil
}
33 changes: 33 additions & 0 deletions pkg/agent/bakerapi_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -523,4 +523,37 @@ var _ = Describe("AgentBaker API implementation tests", func() {
}
})
})

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

cachedOnVHD, err := agentBaker.GetCachedVersionsOnVHD()
Expect(err).NotTo(HaveOccurred())

manifest := datamodel.CacheManifest()
component := datamodel.CacheComponents()

// The indices are hardcoded based on the current components.json.
// Add new components to the bottom of components.json, or update the indices.
pauseIndx := 2
azureCNSIndx := 5
cniPluginIndx := 0
azureCNIIndx := 1

Expect(cachedOnVHD.CachedFromManifest.Runc.Installed["default"]).To(Equal(manifest.Runc.Installed["default"]))
Expect(cachedOnVHD.CachedFromManifest.Runc.Pinned["1804"]).To(Equal(manifest.Runc.Pinned["1804"]))
Expect(cachedOnVHD.CachedFromManifest.Runc.FileName).To(Equal(manifest.Runc.FileName))
Expect(cachedOnVHD.CachedFromManifest.Containerd.Pinned["1804"]).To(Equal(manifest.Containerd.Pinned["1804"]))
Expect(cachedOnVHD.CachedFromManifest.Containerd.Edge).To(Equal(manifest.Containerd.Edge))
Expect(cachedOnVHD.CachedFromManifest.Kubernetes.Versions[0]).To(Equal(manifest.Kubernetes.Versions[0]))
Expect(cachedOnVHD.CachedFromComponentContainerImages["pause"].MultiArchVersions[0]).To(Equal(component.ContainerImages[pauseIndx].MultiArchVersions[0]))
Expect(cachedOnVHD.CachedFromComponentContainerImages["azure-cns"].PrefetchOptimizations[0].Version).To(
Equal(component.ContainerImages[azureCNSIndx].PrefetchOptimizations[0].Version))
Expect(cachedOnVHD.CachedFromComponentContainerImages["azure-cns"].PrefetchOptimizations[0].Binaries[0]).To(Equal("usr/local/bin/azure-cns"))
Expect(cachedOnVHD.CachedFromComponentDownloadedFiles["cni-plugins"].Versions[0]).To(Equal(component.DownloadFiles[cniPluginIndx].Versions[0]))
Expect(cachedOnVHD.CachedFromComponentDownloadedFiles["azure-cni"].Versions[1]).To(Equal(component.DownloadFiles[azureCNIIndx].Versions[1]))
})
})
})
23 changes: 23 additions & 0 deletions pkg/agent/datamodel/helper.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import (
"bufio"
"bytes"
"fmt"
"net/url"
"regexp"
"sort"
"strings"
Expand Down Expand Up @@ -93,3 +94,25 @@ func IndentString(original string, spaces int) string {
}
return out.String()
}

func processContainerImage(downloadURL string) (string, error) {
// example URL "downloadURL": "mcr.microsoft.com/oss/kubernetes/autoscaler/addon-resizer:*",
// getting the data between the last / and the last :
parts := strings.Split(downloadURL, "/")
if len(parts) == 0 || len(parts[len(parts)-1]) == 0 {
return "", fmt.Errorf("container image component URL is not in the expected format: %s", downloadURL)
}
lastPart := parts[len(parts)-1]
component := strings.TrimSuffix(lastPart, ":*")
return component, nil
}

func processDownloadFile(downloadURL string) (string, error) {
// example URL "downloadURL": "https://acs-mirror.azureedge.net/cni-plugins/v*/binaries",
url, err := url.Parse(downloadURL) // /cni-plugins/v*/binaries
if err != nil {
return "", fmt.Errorf("download file image URL is not in the expected format: %s", downloadURL)
}
urlSplit := strings.Split(url.Path, "/") // ["", cni-plugins, v*, binaries]
return urlSplit[1], nil
}
136 changes: 134 additions & 2 deletions pkg/agent/datamodel/sig_config.go
Original file line number Diff line number Diff line change
@@ -1,9 +1,13 @@
package datamodel

import (
"bytes"
_ "embed"
"encoding/json"
"fmt"
"os"
"path"
"runtime"
"strings"
)

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

//nolint:gochecknoglobals
var (
CachedFromComponentContainerImages = make(map[string]ContainerImage)
CachedFromComponentDownloadedFiles = make(map[string]DownloadFiles)
CachedFromManifest = &Manifest{}
)

//nolint:gochecknoinits
func init() {
manifest := CacheManifest()
processManifest(manifest)

components := CacheComponents()
processComponents(components)
}

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

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

func processManifest(manifest Manifest) {
CachedFromManifest.Kubernetes = manifest.Kubernetes
CachedFromManifest.Runc = manifest.Runc
CachedFromManifest.Containerd = manifest.Containerd
CachedFromManifest.NvidiaContainerRuntime = manifest.NvidiaContainerRuntime
CachedFromManifest.NvidiaDrivers = manifest.NvidiaDrivers
}

func processComponents(components Components) {
for _, image := range components.ContainerImages {
componentName, err := processContainerImage(image.DownloadURL)
if err != nil {
panic(err)
}
CachedFromComponentContainerImages[componentName] = image
}
for _, file := range components.DownloadFiles {
componetName, err := processDownloadFile(file.DownloadURL)
if err != nil {
panic(err)
}
CachedFromComponentDownloadedFiles[componetName] = file
}
}

func getCachedVersionsFromManifestJSON(manifestFilePath string) Manifest {
data, err := os.ReadFile(manifestFilePath)
if err != nil {
panic(err)
}
data = bytes.ReplaceAll(data, []byte("#EOF"), []byte(""))
var manifest Manifest
if err = json.Unmarshal(data, &manifest); err != nil {
panic(err)
}
return manifest
}

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

type CachedOnVHD struct {
CachedFromManifest *Manifest `json:"cached_from_manifest"`
CachedFromComponentContainerImages map[string]ContainerImage `json:"cached_from_component_container_images"`
CachedFromComponentDownloadedFiles map[string]DownloadFiles `json:"cached_from_component_downloaded_files"`
}

type Dependency struct {
FileName string `json:"fileName"`
DownloadLocation string `json:"downloadLocation"`
DownloadURL string `json:"downloadURL"`
Versions []string `json:"versions"`
Installed map[string]string `json:"installed"`
Pinned map[string]string `json:"pinned"`
Edge string `json:"edge"`
}

type Manifest struct {
Containerd Dependency `json:"containerd"`
Runc Dependency `json:"runc"`
NvidiaContainerRuntime Dependency `json:"nvidia-container-runtime"`
NvidiaDrivers Dependency `json:"nvidia-drivers"`
Kubernetes Dependency `json:"kubernetes"`
}

type Versions struct {
Versions []string `json:"versions"`
}

type Components struct {
ContainerImages []ContainerImage `json:"containerImages"`
DownloadFiles []DownloadFiles `json:"downloadFiles"`
}

type ContainerImage struct {
DownloadURL string `json:"downloadURL"`
MultiArchVersions []string `json:"multiArchVersions"`
Amd64OnlyVersions []string `json:"amd64OnlyVersions"`
PrefetchOptimizations []PrefetchOptimization `json:"prefetchOptimizations"`
}

type PrefetchOptimization struct {
Version string `json:"version"`
Binaries []string `json:"binaries"`
}

type DownloadFiles struct {
FileName string `json:"fileName"`
DownloadLocation string `json:"downloadLocation"`
DownloadURL string `json:"downloadURL"`
Versions []string `json:"versions"`
}

// 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 @@ -278,8 +412,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 Down
6 changes: 0 additions & 6 deletions pkg/agent/datamodel/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -1638,8 +1638,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 @@ -1649,8 +1647,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 @@ -1713,8 +1709,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
Loading