Skip to content

Commit efba629

Browse files
authored
feat: go-resty component download (#1466)
1 parent 4790d27 commit efba629

37 files changed

+6123
-108
lines changed

cli/cmd/component.go

Lines changed: 100 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -402,9 +402,10 @@ func runComponentsInstall(cmd *cobra.Command, args []string) (err error) {
402402

403403
func installComponent(cmd *cobra.Command, args []string) (err error) {
404404
var (
405-
componentName string = args[0]
406-
params map[string]interface{} = make(map[string]interface{})
407-
start time.Time
405+
componentName string = args[0]
406+
downloadComplete = make(chan int8)
407+
params map[string]interface{} = make(map[string]interface{})
408+
start time.Time
408409
)
409410

410411
cli.Event.Component = componentName
@@ -433,12 +434,18 @@ func installComponent(cmd *cobra.Command, args []string) (err error) {
433434

434435
start = time.Now()
435436

436-
stageClose, err := catalog.Stage(component, versionArg)
437+
progressClosure := func(path string, sizeB int64) {
438+
downloadProgress(downloadComplete, path, sizeB)
439+
}
440+
441+
stageClose, err := catalog.Stage(component, versionArg, progressClosure)
437442
if err != nil {
438443
return
439444
}
440445
defer stageClose()
441446

447+
downloadComplete <- 0
448+
442449
params["stage_duration_ms"] = time.Since(start).Milliseconds()
443450
cli.Event.FeatureData = params
444451

@@ -568,10 +575,11 @@ func runComponentsUpdate(_ *cobra.Command, args []string) (err error) {
568575

569576
func updateComponent(args []string) (err error) {
570577
var (
571-
componentName string = args[0]
572-
params map[string]interface{} = make(map[string]interface{})
573-
start time.Time
574-
targetVersion *semver.Version
578+
componentName string = args[0]
579+
downloadComplete = make(chan int8)
580+
params map[string]interface{} = make(map[string]interface{})
581+
start time.Time
582+
targetVersion *semver.Version
575583
)
576584

577585
cli.StartProgress("Loading components Catalog...")
@@ -619,12 +627,18 @@ func updateComponent(args []string) (err error) {
619627

620628
start = time.Now()
621629

622-
stageClose, err := catalog.Stage(component, versionArg)
630+
progressClosure := func(path string, sizeB int64) {
631+
downloadProgress(downloadComplete, path, sizeB)
632+
}
633+
634+
stageClose, err := catalog.Stage(component, versionArg, progressClosure)
623635
if err != nil {
624636
return
625637
}
626638
defer stageClose()
627639

640+
downloadComplete <- 0
641+
628642
params["stage_duration_ms"] = time.Since(start).Milliseconds()
629643
cli.Event.FeatureData = params
630644

@@ -873,10 +887,11 @@ func componentsToTable() [][]string {
873887

874888
func prototypeRunComponentsInstall(cmd *cobra.Command, args []string) (err error) {
875889
var (
876-
componentName string = args[0]
877-
version string = versionArg
878-
params map[string]interface{} = make(map[string]interface{})
879-
start time.Time
890+
componentName string = args[0]
891+
downloadComplete = make(chan int8)
892+
version string = versionArg
893+
params map[string]interface{} = make(map[string]interface{})
894+
start time.Time
880895
)
881896

882897
cli.Event.Component = componentName
@@ -906,13 +921,20 @@ func prototypeRunComponentsInstall(cmd *cobra.Command, args []string) (err error
906921

907922
start = time.Now()
908923

924+
progressClosure := func(path string, sizeB int64) {
925+
downloadProgress(downloadComplete, path, sizeB)
926+
}
927+
909928
cli.StartProgress(fmt.Sprintf("Installing component %s...", component.Name))
910-
err = cli.LwComponents.Install(component, version)
929+
err = cli.LwComponents.Install(component, version, progressClosure)
911930
cli.StopProgress()
912931
if err != nil {
913932
err = errors.Wrap(err, "unable to install component")
914933
return
915934
}
935+
936+
downloadComplete <- 0
937+
916938
cli.OutputChecklist(successIcon, "Component %s installed\n", color.HiYellowString(component.Name))
917939

918940
params["install_duration_ms"] = time.Since(start).Milliseconds()
@@ -999,13 +1021,22 @@ func prototypeRunComponentsUpdate(args []string) (err error) {
9991021
return nil
10001022
}
10011023

1024+
downloadComplete := make(chan int8)
1025+
1026+
progressClosure := func(path string, sizeB int64) {
1027+
downloadProgress(downloadComplete, path, sizeB)
1028+
}
1029+
10021030
cli.StartProgress(fmt.Sprintf("Updating component %s to version %s...", component.Name, &updateTo))
1003-
err = cli.LwComponents.Install(component, updateTo.String())
1031+
err = cli.LwComponents.Install(component, updateTo.String(), progressClosure)
10041032
cli.StopProgress()
10051033
if err != nil {
10061034
err = errors.Wrap(err, "unable to update component")
10071035
return
10081036
}
1037+
1038+
downloadComplete <- 0
1039+
10091040
cli.OutputChecklist(successIcon, "Component %s updated to %s\n",
10101041
color.HiYellowString(component.Name),
10111042
color.HiCyanString(fmt.Sprintf("v%s", updateTo.String())))
@@ -1103,3 +1134,57 @@ func prototypeRunComponentsDelete(args []string) (err error) {
11031134
cli.OutputHuman("Reach out to us at %s\n", color.HiCyanString("[email protected]"))
11041135
return
11051136
}
1137+
1138+
func downloadProgress(complete chan int8, path string, sizeB int64) {
1139+
file, err := os.Open(path)
1140+
if err != nil {
1141+
cli.Log.Errorf("Failed to open component file: %s", err.Error())
1142+
return
1143+
}
1144+
defer file.Close()
1145+
1146+
var (
1147+
previous float64 = 0
1148+
stop bool = false
1149+
)
1150+
1151+
spinnerSuffix := cli.spinner.Suffix
1152+
1153+
for !stop {
1154+
select {
1155+
case <-complete:
1156+
stop = true
1157+
default:
1158+
info, err := file.Stat()
1159+
if err != nil {
1160+
cli.Log.Errorf("Failed to stat component file: %s", err.Error())
1161+
return
1162+
}
1163+
1164+
size := info.Size()
1165+
if size == 0 {
1166+
size = 1
1167+
}
1168+
1169+
if sizeB == 0 {
1170+
mb := float64(size) / (1 << 20)
1171+
1172+
if mb > previous {
1173+
cli.spinner.Suffix = fmt.Sprintf("%s Downloaded: %.0fmb", spinnerSuffix, mb)
1174+
1175+
previous = mb
1176+
}
1177+
} else {
1178+
percent := float64(size) / float64(sizeB) * 100
1179+
1180+
if percent > previous {
1181+
cli.spinner.Suffix = fmt.Sprintf("%s Downloaded: %.0f%s", spinnerSuffix, percent, "%")
1182+
1183+
previous = percent
1184+
}
1185+
}
1186+
}
1187+
1188+
time.Sleep(time.Second)
1189+
}
1190+
}

go.mod

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,7 @@ require (
5858
github.com/aws/smithy-go v1.13.5
5959
github.com/gabriel-vasile/mimetype v1.4.2
6060
github.com/go-git/go-git/v5 v5.5.2
61+
github.com/go-resty/resty/v2 v2.10.0
6162
github.com/google/uuid v1.3.0
6263
github.com/hashicorp/consul/sdk v0.13.1
6364
github.com/mattn/go-isatty v0.0.18

go.sum

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -202,6 +202,8 @@ github.com/go-git/go-git/v5 v5.5.2/go.mod h1:BE5hUJ5yaV2YMxhmaP4l6RBQ08kMxKSPD4B
202202
github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU=
203203
github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8=
204204
github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8=
205+
github.com/go-resty/resty/v2 v2.10.0 h1:Qla4W/+TMmv0fOeeRqzEpXPLfTUnR5HZ1+lGs+CkiCo=
206+
github.com/go-resty/resty/v2 v2.10.0/go.mod h1:iiP/OpA0CkcL3IGt1O0+/SIItFUbkkyw5BGXiVdTu+A=
205207
github.com/go-test/deep v1.0.3 h1:ZrJSEWsXzPOxaZnFteGEfooLba+ju3FYIbOrS+rQd68=
206208
github.com/go-test/deep v1.0.3/go.mod h1:wGDj63lr65AM2AQyKZd/NYHGb0R+1RLqB8NKt3aSFNA=
207209
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
@@ -569,6 +571,8 @@ golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qx
569571
golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
570572
golang.org/x/net v0.0.0-20220826154423-83b083e8dc8b/go.mod h1:YDH+HFinaLZZlnHAfSS6ZXJJ9M9t4Dl22yv3iI2vPwk=
571573
golang.org/x/net v0.2.0/go.mod h1:KqCZLdyyvdV855qA2rE3GC2aiw5xGR5TEjj8smXukLY=
574+
golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
575+
golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg=
572576
golang.org/x/net v0.17.0 h1:pVaXccu2ozPjCXewfr1S7xza/zcXTity9cCdXQYSjIM=
573577
golang.org/x/net v0.17.0/go.mod h1:NxSsAGuq816PNPmqtQdLE42eU2Fs7NoRIZrHJAlaCOE=
574578
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
@@ -593,6 +597,7 @@ golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJ
593597
golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
594598
golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
595599
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
600+
golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
596601
golang.org/x/sync v0.3.0 h1:ftCYgMx6zT/asHUrPw8BLLscYtGznsLAnjq5RH9P66E=
597602
golang.org/x/sync v0.3.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y=
598603
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
@@ -651,7 +656,9 @@ golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBc
651656
golang.org/x/sys v0.0.0-20220825204002-c680a09ffe64/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
652657
golang.org/x/sys v0.2.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
653658
golang.org/x/sys v0.3.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
659+
golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
654660
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
661+
golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
655662
golang.org/x/sys v0.13.0 h1:Af8nKPmuFypiUBjVoU9V20FiaFXOcuZI21p0ycVYYGE=
656663
golang.org/x/sys v0.13.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
657664
golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw=
@@ -660,6 +667,8 @@ golang.org/x/term v0.0.0-20210503060354-a79de5458b56/go.mod h1:tfny5GFUkzUvx4ps4
660667
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
661668
golang.org/x/term v0.0.0-20220722155259-a9ba230a4035/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
662669
golang.org/x/term v0.2.0/go.mod h1:TVmDHMZPmdnySmBfhjOoOdhjzdE1h4u1VwSiw2l1Nuc=
670+
golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k=
671+
golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo=
663672
golang.org/x/term v0.13.0 h1:bb+I9cTfFazGW51MZqBVmZy7+JEJMouUHTUSKVQLBek=
664673
golang.org/x/term v0.13.0/go.mod h1:LTmsnFJwVN6bCy1rVCoS+qHT1HhALEFxKncY3WNNh4U=
665674
golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
@@ -672,11 +681,15 @@ golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
672681
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
673682
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
674683
golang.org/x/text v0.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
684+
golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
685+
golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8=
675686
golang.org/x/text v0.13.0 h1:ablQoSUd0tRdKxZewP80B+BaqeKJuVhuRxj/dkrun3k=
676687
golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE=
677688
golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
678689
golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
679690
golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
691+
golang.org/x/time v0.3.0 h1:rg5rLMjNzMS1RkNLzCG38eapWhnYLFYXDXj2gOlr8j4=
692+
golang.org/x/time v0.3.0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
680693
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
681694
golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
682695
golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY=

lwcomponent/api_info.go

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,8 @@ type ApiInfo interface {
1212
AllVersions() []*semver.Version
1313

1414
Deprecated() bool
15+
16+
Size() int64
1517
}
1618

1719
type apiInfo struct {
@@ -65,3 +67,8 @@ func (a *apiInfo) LatestVersion() *semver.Version {
6567
func (a *apiInfo) Deprecated() bool {
6668
return a.deprecated
6769
}
70+
71+
// Size implements ApiInfo.
72+
func (a *apiInfo) Size() int64 {
73+
return a.sizeKB
74+
}

lwcomponent/catalog.go

Lines changed: 13 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -73,11 +73,11 @@ func (c *Catalog) GetComponent(name string) (*CDKComponent, error) {
7373
}
7474

7575
func (c *Catalog) ListComponentVersions(component *CDKComponent) (versions []*semver.Version) {
76-
if component.apiInfo == nil {
76+
if component.ApiInfo == nil {
7777
return
7878
}
7979

80-
versions = component.apiInfo.AllVersions()
80+
versions = component.ApiInfo.AllVersions()
8181

8282
return
8383
}
@@ -92,26 +92,29 @@ func (c *Catalog) PrintComponents() [][]string {
9292
return result
9393
}
9494

95-
func (c *Catalog) Stage(component *CDKComponent, version string) (stageClose func(), err error) {
95+
func (c *Catalog) Stage(
96+
component *CDKComponent,
97+
version string,
98+
progressClosure func(filepath string, sizeB int64)) (stageClose func(), err error) {
9699
var (
97100
semv *semver.Version
98101
)
99102

100103
stageClose = func() {}
101104

102105
if version == "" {
103-
semv = component.apiInfo.LatestVersion()
106+
semv = component.ApiInfo.LatestVersion()
104107
} else {
105108
semv, err = semver.NewVersion(version)
106109
if err != nil {
107110
return
108111
}
109112
}
110113

111-
if component.hostInfo != nil {
114+
if component.HostInfo != nil {
112115
var installedVersion *semver.Version
113116

114-
installedVersion, err = component.hostInfo.Version()
117+
installedVersion, err = component.HostInfo.Version()
115118
if err != nil {
116119
return
117120
}
@@ -123,7 +126,7 @@ func (c *Catalog) Stage(component *CDKComponent, version string) (stageClose fun
123126
}
124127

125128
response, err := c.client.V2.Components.FetchComponentArtifact(
126-
component.apiInfo.Id(),
129+
component.ApiInfo.Id(),
127130
operatingSystem,
128131
architecture,
129132
semv.String())
@@ -141,12 +144,12 @@ func (c *Catalog) Stage(component *CDKComponent, version string) (stageClose fun
141144
component.InstallMessage = data.InstallMessage
142145
component.UpdateMessage = data.UpdateMessage
143146

144-
stage, err := c.stageConstructor(component.Name, data.ArtifactUrl)
147+
stage, err := c.stageConstructor(component.Name, data.ArtifactUrl, data.Size)
145148
if err != nil {
146149
return
147150
}
148151

149-
if err = stage.Download(); err != nil {
152+
if err = stage.Download(progressClosure); err != nil {
150153
stage.Close()
151154
return
152155
}
@@ -206,7 +209,7 @@ func (c *Catalog) Install(component *CDKComponent) (err error) {
206209
return
207210
}
208211

209-
component.hostInfo = NewHostInfo(componentDir)
212+
component.HostInfo = NewHostInfo(componentDir)
210213

211214
return
212215
}

0 commit comments

Comments
 (0)