11package orchestrator
22
33import (
4+ "bytes"
45 "context"
6+ "encoding/json"
57 "os"
8+ "slices"
69 "strings"
710
811 "github.com/arduino/go-paths-helper"
@@ -16,22 +19,31 @@ import (
1619
1720// SystemInit pulls necessary Docker images.
1821func SystemInit (ctx context.Context , pythonImageTag string , staticStore * store.StaticStore ) error {
19- preInstallContainer := []string {
22+ containersToPreinstall := []string {
2023 "ghcr.io/bcmi-labs/arduino/appslab-python-apps-base:" + pythonImageTag ,
2124 }
2225 additionalContainers , err := parseAllModelsRunnerImageTag (staticStore )
2326 if err != nil {
2427 return err
2528 }
26- preInstallContainer = append (preInstallContainer , additionalContainers ... )
29+ containersToPreinstall = append (containersToPreinstall , additionalContainers ... )
30+
31+ pulledImages , err := listImagesAlreadyPulled (ctx )
32+ if err != nil {
33+ return err
34+ }
35+
36+ // Filter out containers alredy pulled
37+ containersToPreinstall = slices .DeleteFunc (containersToPreinstall , func (v string ) bool {
38+ return slices .Contains (pulledImages , v )
39+ })
2740
2841 stdout , _ , err := feedback .DirectStreams ()
2942 if err != nil {
3043 feedback .Fatal (err .Error (), feedback .ErrBadArgument )
3144 return nil
3245 }
33-
34- for _ , container := range preInstallContainer {
46+ for _ , container := range containersToPreinstall {
3547 cmd , err := paths .NewProcess (nil , "docker" , "pull" , container )
3648 if err != nil {
3749 return err
@@ -45,6 +57,45 @@ func SystemInit(ctx context.Context, pythonImageTag string, staticStore *store.S
4557 return nil
4658}
4759
60+ // listImagesAlreadyPulled
61+ func listImagesAlreadyPulled (ctx context.Context ) ([]string , error ) {
62+ cmd , err := paths .NewProcess (nil ,
63+ "docker" , "images" , "--format" , "json" ,
64+ "-f" , "reference=ghcr.io/bcmi-labs/arduino/*" ,
65+ "-f" , "reference=public.ecr.aws/*" ,
66+ )
67+ if err != nil {
68+ return nil , err
69+ }
70+
71+ // Capture the output to check if the image exists
72+ stdout , _ , err := cmd .RunAndCaptureOutput (ctx )
73+ if err != nil {
74+ return nil , err
75+ }
76+
77+ type dockerImage struct {
78+ Repository string `json:"Repository"`
79+ Tag string `json:"Tag"`
80+ }
81+ var resp dockerImage
82+ result := []string {}
83+ for img := range bytes .Lines (stdout ) {
84+ if len (img ) == 0 {
85+ continue
86+ }
87+ if err := json .Unmarshal (img , & resp ); err != nil {
88+ return nil , err
89+ }
90+ if resp .Tag == "<none>" {
91+ continue
92+ }
93+ result = append (result , resp .Repository + ":" + resp .Tag )
94+ }
95+
96+ return result , nil
97+ }
98+
4899func parseAllModelsRunnerImageTag (staticStore * store.StaticStore ) ([]string , error ) {
49100 composePath := staticStore .GetComposeFolder ()
50101 brickNamespace := "arduino"
0 commit comments