Skip to content

Commit

Permalink
fix: component download AWS XML error
Browse files Browse the repository at this point in the history
  • Loading branch information
jon-stewart committed Mar 1, 2024
1 parent 523eb64 commit 2c17d96
Show file tree
Hide file tree
Showing 5 changed files with 133 additions and 13 deletions.
8 changes: 5 additions & 3 deletions cli/cmd/component.go
Original file line number Diff line number Diff line change
Expand Up @@ -443,10 +443,11 @@ func installComponent(args []string) (err error) {
}

stageClose, err := catalog.Stage(component, versionArg, progressClosure)
defer stageClose()
if err != nil {
cli.StopProgress()
return
}
defer stageClose()

downloadComplete <- 0

Expand Down Expand Up @@ -631,10 +632,11 @@ func updateComponent(args []string) (err error) {
}

stageClose, err := catalog.Stage(component, versionArg, progressClosure)
defer stageClose()
if err != nil {
cli.StopProgress()
return
}
defer stageClose()

downloadComplete <- 0

Expand Down Expand Up @@ -879,7 +881,7 @@ func componentsToTable() [][]string {
return out
}

func prototypeRunComponentsInstall(cmd *cobra.Command, args []string) (err error) {
func prototypeRunComponentsInstall(_ *cobra.Command, args []string) (err error) {
var (
componentName string = args[0]
downloadComplete = make(chan int8)
Expand Down
29 changes: 29 additions & 0 deletions lwcomponent/catalog.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package lwcomponent

import (
"encoding/xml"
"fmt"
"os"
"path/filepath"
Expand Down Expand Up @@ -155,6 +156,11 @@ func (c *Catalog) Stage(
return
}

err = parseAWSXMLError(filepath.Join(stage.Directory(), stage.Filename()))
if err != nil {
return
}

if err = stage.Unpack(); err != nil {
stage.Close()
return
Expand Down Expand Up @@ -444,3 +450,26 @@ func componentDirectory(componentName string) (string, error) {

return filepath.Join(dir, componentName), nil
}

type awsXMLError struct {
xml.Name
Code string `xml:"Code"`
Message string `xml:"Message"`
}

func parseAWSXMLError(path string) error {
data, err := os.ReadFile(path)
if err != nil {
return err
}

xmlError := &awsXMLError{}
err = xml.Unmarshal(data, xmlError)
if err != nil {
return nil
}

log.Error(string(data))

return errors.Errorf("Code: %s. Message: %s", xmlError.Code, xmlError.Message)
}
97 changes: 90 additions & 7 deletions lwcomponent/catalog_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -549,13 +549,57 @@ func TestCatalogStage(t *testing.T) {
fmt.Fprint(w, generateComponentsResponse(prefix, apiComponentCount))
})

url := "s3-download"

fakeServer.MockAPI(url, func(w http.ResponseWriter, r *http.Request) {
dir, _ := os.MkdirTemp("", "cdk-component-stage-tar-gz-")

path := MakeGzip(name, MakeTar(name, "1.0.0", dir, "component", "sig"))

data, err := os.ReadFile(path)
if err != nil {
panic(err)
}

w.Write(data)
})

XMLUrl := "s3-error"

fakeServer.MockAPI(XMLUrl, func(w http.ResponseWriter, r *http.Request) {
data := []byte(`<?xml version="1.0" encoding="UTF-8"?>
<Error><Code>PermanentRedirect</Code>
<Message>The bucket you are attempting to access must be addressed using the specified endpoint.
Please send all future requests to this endpoint.</Message>
<Endpoint>lw-cdk-store.s3-us-west-2.amazonaws.com</Endpoint>
<Bucket>lw-cdk-store</Bucket><RequestId>VFXE02WRA7339CW6</RequestId><HostId></HostId></Error>`)
w.Write(data)
})

EOFUrl := "eof"

fakeServer.MockAPI(EOFUrl, func(w http.ResponseWriter, r *http.Request) {
data := []byte("")
w.Write(data)
})

fakeServer.MockAPI("Components/Artifact/1", func(w http.ResponseWriter, r *http.Request) {
assert.Equal(t, "GET", r.Method, "Components API only accepts HTTP GET")

if r.URL.Query().Get("version") != version {
http.Error(w, "component version not found", http.StatusNotFound)
} else {
fmt.Fprint(w, generateFetchResponse(1, name, version, ""))
l := r.URL.Query().Get("version")
switch l {
case "1.0.0":
{
fmt.Fprint(w, generateFetchResponse(1, name, version, fmt.Sprintf("%s/api/v2/%s", fakeServer.URL(), url)))
}
case "3.0.1":
{
fmt.Fprint(w, generateFetchResponse(1, name, version, fmt.Sprintf("%s/api/v2/%s", fakeServer.URL(), EOFUrl)))
}
case "5.4.3":
{
fmt.Fprint(w, generateFetchResponse(1, name, version, fmt.Sprintf("%s/api/v2/%s", fakeServer.URL(), XMLUrl)))
}
}
})

Expand All @@ -575,7 +619,7 @@ func TestCatalogStage(t *testing.T) {
api.WithURL(fakeServer.URL()),
)

catalog, err := lwcomponent.NewCatalog(client, newTestStage)
catalog, err := lwcomponent.NewCatalog(client, lwcomponent.NewStageTarGz)
assert.NotNil(t, catalog)
assert.Nil(t, err)

Expand All @@ -589,6 +633,29 @@ func TestCatalogStage(t *testing.T) {
defer stageClose()
})

// @jon-stewart: TODO GROW-2765
// t.Run("EOF Error", func(t *testing.T) {
// component, err := catalog.GetComponent(name)
// assert.NotNil(t, component)
// assert.Nil(t, err)

// stageClose, err := catalog.Stage(component, "3.0.1", ProgressClosure)
// assert.NotNil(t, err)
// defer stageClose()
// })

t.Run("AWS XML Error", func(t *testing.T) {
component, err := catalog.GetComponent(name)
assert.NotNil(t, component)
assert.Nil(t, err)

stageClose, err := catalog.Stage(component, "5.4.3", ProgressClosure)
assert.NotNil(t, err)
assert.Contains(t, err.Error(), "PermanentRedirect")

defer stageClose()
})

t.Run("already installed", func(t *testing.T) {
CreateLocalComponent(name, version, false)

Expand Down Expand Up @@ -646,8 +713,19 @@ func (t *testStage) Directory() string {
return t.dir
}

// Filename implements lwcomponent.Stager.
func (t *testStage) Filename() string {
return "newTestStageFile"
}

// Download implements lwcomponent.Stager.
func (*testStage) Download(func(string, int64)) error {
func (t *testStage) Download(func(string, int64)) error {
file, err := os.Create(filepath.Join(t.dir, t.Filename()))
if err != nil {
log.Fatal(err)
}
defer file.Close()

return nil
}

Expand Down Expand Up @@ -678,7 +756,12 @@ func (*testStage) Validate() error {
}

func newTestStage(name, artifactUrl string, size int64) (stage lwcomponent.Stager, err error) {
stage = &testStage{}
dir, err := os.MkdirTemp("", "newTestStage")
if err != nil {
panic(err)
}

stage = &testStage{dir: dir}

return
}
Expand Down
6 changes: 6 additions & 0 deletions lwcomponent/staging.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,8 @@ type Stager interface {

Download(progressClosure func(filepath string, sizeB int64)) error

Filename() string

Signature() (sig []byte, err error)

Unpack() error
Expand Down Expand Up @@ -87,6 +89,10 @@ func (s *stageTarGz) Directory() string {
return s.dir
}

func (s *stageTarGz) Filename() string {
return filepath.Base(s.artifactUrl.Path)
}

func (s *stageTarGz) Download(progressClosure func(filepath string, sizeB int64)) (err error) {
fileName := filepath.Base(s.artifactUrl.Path)

Expand Down
6 changes: 3 additions & 3 deletions lwcomponent/staging_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -103,12 +103,12 @@ func TestStagingTarGzUnpack(t *testing.T) {
assert.NotNil(t, stage)
defer stage.Close()

makeGzip(name, makeTar(name, "1.1.1", stage.Directory(), componentData, sigData))
MakeGzip(name, MakeTar(name, "1.1.1", stage.Directory(), componentData, sigData))

stage.Unpack()
}

func makeTar(name string, version string, dir string, data string, sig string) string {
func MakeTar(name string, version string, dir string, data string, sig string) string {
tarname := fmt.Sprintf("%s.tar", name)
path := filepath.Join(dir, tarname)

Expand Down Expand Up @@ -147,7 +147,7 @@ func makeTar(name string, version string, dir string, data string, sig string) s
return path
}

func makeGzip(name, path string) string {
func MakeGzip(name, path string) string {
reader, err := os.Open(path)
if err != nil {
panic(err)
Expand Down

0 comments on commit 2c17d96

Please sign in to comment.