Skip to content

Commit

Permalink
chore(CLI): cache CDK API data in disk (#1529)
Browse files Browse the repository at this point in the history
* chore(CLI): persist CDK API data in disk

* chore(CLI): check catalog.Persist error

* chore: use cli.Cache instead

* chore: only cache components api info

* chore(cli): fetch catalog in command run

* chore(cli): pr suggestion

* chore: pr suggetions

* chore: pr suggetions

* test: add unit test for NewCachedCatalog

* chore: disable TestContainerVulnerabilityCommandScanFailOnSeverity
  • Loading branch information
PengyuanZhao authored Feb 14, 2024
1 parent ff59352 commit e969371
Show file tree
Hide file tree
Showing 11 changed files with 290 additions and 248 deletions.
106 changes: 53 additions & 53 deletions cli/cmd/component.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ import (

const (
componentTypeAnnotation string = "component"
componentsCacheKey string = "components"
)

var (
Expand Down Expand Up @@ -163,14 +164,12 @@ func (c *cliState) IsComponentInstalled(name string) bool {

// Load v1 components
func (c *cliState) LoadComponents() {
components, err := lwcomponent.LocalComponents()
components, err := lwcomponent.LoadLocalComponents()
if err != nil {
c.Log.Debugw("unable to load components", "error", err)
return
}

// @jon-stewart: TODO: load from cached API info

for _, component := range components {
exists := false

Expand All @@ -187,18 +186,8 @@ func (c *cliState) LoadComponents() {
}

version := component.InstalledVersion()
componentDir, err := component.Dir()
if err != nil {
c.Log.Debugw("unable to find component directory", "error", err)
return
}
if devInfo, _ := lwcomponent.NewDevInfo(componentDir); devInfo != nil {
if devVersion, _ := semver.NewVersion(devInfo.Version); devVersion != nil {
version = devVersion
}
}

if version != nil && component.Exec.Executable() {
if version != nil {
componentCmd := &cobra.Command{
Use: component.Name,
Short: component.Description,
Expand All @@ -208,7 +197,7 @@ func (c *cliState) LoadComponents() {
DisableFlagParsing: true,
DisableFlagsInUseLine: true,
RunE: func(cmd *cobra.Command, args []string) error {
return v1ComponentCommand(c, cmd, args)
return v1ComponentCommand(c, cmd)
},
}

Expand All @@ -224,7 +213,7 @@ func startGrpcServer(c *cliState) {
}
}

func v1ComponentCommand(c *cliState, cmd *cobra.Command, args []string) error {
func v1ComponentCommand(c *cliState, cmd *cobra.Command) error {
// Parse component -v/--version flag
versionVal, _ := cmd.Flags().GetBool("version")
if versionVal {
Expand All @@ -234,11 +223,7 @@ func v1ComponentCommand(c *cliState, cmd *cobra.Command, args []string) error {

go startGrpcServer(c)

c.Log.Debugw("running component", "component", cmd.Use,
"args", c.componentParser.componentArgs,
"cli_flags", c.componentParser.cliArgs)

catalog, err := lwcomponent.NewCatalog(cli.LwApi, lwcomponent.NewStageTarGz, false)
catalog, err := LoadCatalog()
if err != nil {
return errors.Wrap(err, "unable to load component Catalog")
}
Expand All @@ -248,6 +233,14 @@ func v1ComponentCommand(c *cliState, cmd *cobra.Command, args []string) error {
return err
}

if !component.Exec.Executable() {
return errors.New("component is not executable")
}

c.Log.Debugw("running component", "component", cmd.Use,
"args", c.componentParser.componentArgs,
"cli_flags", c.componentParser.cliArgs)

// @jon-stewart: TODO: v1 dailyComponentUpdateAvailable

envs := []string{
Expand Down Expand Up @@ -355,12 +348,7 @@ func runComponentsList(_ *cobra.Command, _ []string) (err error) {
}

func listComponents() error {
cli.StartProgress("Loading component Catalog...")

catalog, err := lwcomponent.NewCatalog(cli.LwApi, lwcomponent.NewStageTarGz, true)
defer catalog.Persist()

cli.StopProgress()
catalog, err := LoadCatalog()
if err != nil {
return errors.Wrap(err, "unable to load component Catalog")
}
Expand All @@ -379,8 +367,6 @@ func listComponents() error {

printComponents(catalog.PrintComponents())

cli.OutputHuman("\nComponents version: %s\n", cli.LwComponents.Version)

return nil
}

Expand Down Expand Up @@ -423,12 +409,7 @@ func installComponent(cmd *cobra.Command, args []string) (err error) {
cli.Event.Feature = "install_component"
defer cli.SendHoneyvent()

cli.StartProgress("Loading component Catalog...")

catalog, err := lwcomponent.NewCatalog(cli.LwApi, lwcomponent.NewStageTarGz, false)
defer catalog.Persist()

cli.StopProgress()
catalog, err := LoadCatalog()
if err != nil {
err = errors.Wrap(err, "unable to load component Catalog")
return
Expand Down Expand Up @@ -524,12 +505,7 @@ func showComponent(args []string) error {
componentName string = args[0]
)

cli.StartProgress("Loading components Catalog...")

catalog, err := lwcomponent.NewCatalog(cli.LwApi, lwcomponent.NewStageTarGz, false)
defer catalog.Persist()

cli.StopProgress()
catalog, err := LoadCatalog()
if err != nil {
return errors.Wrap(err, "unable to load component Catalog")
}
Expand Down Expand Up @@ -598,12 +574,7 @@ func updateComponent(args []string) (err error) {
targetVersion *semver.Version
)

cli.StartProgress("Loading components Catalog...")

catalog, err := lwcomponent.NewCatalog(cli.LwApi, lwcomponent.NewStageTarGz, false)
defer catalog.Persist()

cli.StopProgress()
catalog, err := LoadCatalog()
if err != nil {
return errors.Wrap(err, "unable to load component Catalog")
}
Expand Down Expand Up @@ -724,12 +695,7 @@ func deleteComponent(args []string) (err error) {
componentName string = args[0]
)

cli.StartProgress("Loading components Catalog...")

catalog, err := lwcomponent.NewCatalog(cli.LwApi, lwcomponent.NewStageTarGz, false)
defer catalog.Persist()

cli.StopProgress()
catalog, err := LoadCatalog()
if err != nil {
return errors.Wrap(err, "unable to load component Catalog")
}
Expand Down Expand Up @@ -1215,3 +1181,37 @@ func downloadProgress(complete chan int8, path string, sizeB int64) {
time.Sleep(time.Second)
}
}

func LoadCatalog() (*lwcomponent.Catalog, error) {
cli.StartProgress("Loading component catalog...")
defer cli.StopProgress()

var componentsApiInfo map[string]*lwcomponent.ApiInfo

// try to load components Catalog from cache
if !cli.noCache {
expired := cli.ReadCachedAsset(componentsCacheKey, &componentsApiInfo)
if !expired {
cli.Log.Infow("loaded components from cache", "components", componentsApiInfo)
return lwcomponent.NewCachedCatalog(cli.LwApi, lwcomponent.NewStageTarGz, componentsApiInfo)
}
}

// load components Catalog from API
catalog, err := lwcomponent.NewCatalog(cli.LwApi, lwcomponent.NewStageTarGz, true)
if err != nil {
return nil, err
}

componentsApiInfo = make(map[string]*lwcomponent.ApiInfo, len(catalog.Components))

for _, c := range catalog.Components {
if c.ApiInfo != nil {
componentsApiInfo[c.Name] = c.ApiInfo
}
}

cli.WriteAssetToCache(componentsCacheKey, time.Now().Add(time.Hour*12), componentsApiInfo)

return catalog, nil
}
3 changes: 1 addition & 2 deletions cli/cmd/component_dev.go
Original file line number Diff line number Diff line change
Expand Up @@ -92,8 +92,7 @@ func devModeComponent(args []string) error {

cli.StartProgress("Loading components Catalog...")

catalog, err := lwcomponent.NewCatalog(cli.LwApi, lwcomponent.NewStageTarGz, false)
defer catalog.Persist()
catalog, err := LoadCatalog()

cli.StopProgress()
if err != nil {
Expand Down
4 changes: 3 additions & 1 deletion integration/container_vulnerability_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -205,7 +205,9 @@ func TestContainerVulnerabilityCommandScanErrorContainerImageNotFound(t *testing
"EXITCODE is not the expected one")
}

func TestContainerVulnerabilityCommandScanFailOnSeverity(t *testing.T) {
// Disabled due to the api timeout issue
// TODO: re-enable when timeout is fixed
func _TestContainerVulnerabilityCommandScanFailOnSeverity(t *testing.T) {
home := createTOMLConfigFromCIvars()
defer os.RemoveAll(home)
_, err, exitcode := LaceworkCLIWithHome(home,
Expand Down
74 changes: 19 additions & 55 deletions lwcomponent/api_info.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,27 +4,15 @@ import (
"github.com/Masterminds/semver"
)

type ApiInfo interface {
Id() int32

LatestVersion() *semver.Version

AllVersions() []*semver.Version

Deprecated() bool

Size() int64
}

type apiInfo struct {
id int32
name string
version semver.Version
allVersions []*semver.Version
desc string
sizeKB int64
deprecated bool
componentType Type
type ApiInfo struct {
Id int32 `json:"id"`
Name string `json:"name"`
Version *semver.Version `json:"version"`
AllVersions []*semver.Version `json:"allVersions"`
Desc string `json:"desc"`
SizeKB int64 `json:"sizeKB"`
Deprecated bool `json:"deprecated"`
ComponentType Type `json:"componentType"`
}

func NewAPIInfo(
Expand All @@ -36,39 +24,15 @@ func NewAPIInfo(
size int64,
deprecated bool,
componentType Type,
) ApiInfo {
return &apiInfo{
id: id,
name: name,
version: *version,
allVersions: allVersions,
desc: desc,
sizeKB: size,
deprecated: deprecated,
componentType: componentType,
) *ApiInfo {
return &ApiInfo{
Id: id,
Name: name,
Version: version,
AllVersions: allVersions,
Desc: desc,
SizeKB: size,
Deprecated: deprecated,
ComponentType: componentType,
}
}

func (a *apiInfo) Id() int32 {
return a.id
}

// AllVersions implements ApiInfo.
func (a *apiInfo) AllVersions() []*semver.Version {
return a.allVersions
}

// LatestVersion implements ApiInfo.
func (a *apiInfo) LatestVersion() *semver.Version {
return &a.version
}

// Deprecated implements ApiInfo.
func (a *apiInfo) Deprecated() bool {
return a.deprecated
}

// Size implements ApiInfo.
func (a *apiInfo) Size() int64 {
return a.sizeKB
}
4 changes: 2 additions & 2 deletions lwcomponent/api_info_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ func TestApiInfoId(t *testing.T) {

info := lwcomponent.NewAPIInfo(id, "test", version, allVersions, "", 0, false, lwcomponent.BinaryType)

result := info.Id()
result := info.Id
assert.Equal(t, id, result)
}

Expand All @@ -34,6 +34,6 @@ func TestApiInfoLatestVersion(t *testing.T) {

info := lwcomponent.NewAPIInfo(1, "test", version, allVersions, "", 0, false, lwcomponent.BinaryType)

result := info.LatestVersion()
result := info.Version
assert.Equal(t, expectedVer, result.String())
}
Loading

0 comments on commit e969371

Please sign in to comment.