@@ -16,14 +16,17 @@ import (
1616 "sort"
1717 "strconv"
1818 "strings"
19+ "net/http"
1920
2021 "cloud.google.com/go/storage"
2122 "github.com/frikky/kin-openapi/openapi3"
23+ docker "github.com/docker/docker/client"
2224
2325 //"github.com/satori/go.uuid"
2426 "gopkg.in/yaml.v2"
2527)
2628
29+ var downloadedImages = []string {}
2730var pythonAllowed = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_"
2831var pythonReplacements = map [string ]string {
2932 "[" : "" ,
@@ -3771,3 +3774,132 @@ func RemoveJsonValues(input []byte, depth int64) ([]byte, string, error) {
37713774
37723775 return input , keyToken , nil
37733776}
3777+
3778+ func DownloadDockerImageBackend (topClient * http.Client , imageName string ) error {
3779+ // Check environment SHUFFLE_AUTO_IMAGE_DOWNLOAD
3780+ if os .Getenv ("SHUFFLE_AUTO_IMAGE_DOWNLOAD" ) == "false" {
3781+ log .Printf ("[DEBUG] SHUFFLE_AUTO_IMAGE_DOWNLOAD is false. Not downloading image %s" , imageName )
3782+ return nil
3783+ }
3784+
3785+ if ArrayContains (downloadedImages , imageName ) && project .Environment == "worker" {
3786+ log .Printf ("[DEBUG] Image %s already downloaded - not re-downloading. This only applies to workers." , imageName )
3787+ return nil
3788+ }
3789+
3790+ baseUrl := os .Getenv ("BASE_URL" )
3791+ log .Printf ("[DEBUG] Trying to download image %s from backend %s as it doesn't exist. All images: %#v" , imageName , baseUrl , downloadedImages )
3792+
3793+ if ! ArrayContains (downloadedImages , imageName ) {
3794+ downloadedImages = append (downloadedImages , imageName )
3795+ }
3796+
3797+ data := fmt .Sprintf (`{"name": "%s"}` , imageName )
3798+ dockerImgUrl := fmt .Sprintf ("%s/api/v1/get_docker_image" , baseUrl )
3799+
3800+ req , err := http .NewRequest (
3801+ "POST" ,
3802+ dockerImgUrl ,
3803+ bytes .NewBuffer ([]byte (data )),
3804+ )
3805+
3806+ // Specific to the worker
3807+ authorization := os .Getenv ("AUTHORIZATION" )
3808+ if len (authorization ) > 0 {
3809+ req .Header .Add ("Authorization" , fmt .Sprintf ("Bearer %s" , authorization ))
3810+ } else {
3811+ // Specific to Orborus auth (org + auth) -> environment auth
3812+ authorization = os .Getenv ("AUTH" )
3813+ if len (authorization ) > 0 {
3814+ log .Printf ("[DEBUG] Found Orborus environment auth - adding to header." )
3815+ req .Header .Add ("Authorization" , fmt .Sprintf ("Bearer %s" , authorization ))
3816+
3817+ org := os .Getenv ("ORG" )
3818+ if len (org ) > 0 {
3819+ req .Header .Add ("Org-Id" , org )
3820+ }
3821+
3822+ } else {
3823+ log .Printf ("[WARNING] No auth found - running backend download without it." )
3824+ }
3825+ }
3826+
3827+ newresp , err := topClient .Do (req )
3828+ if err != nil {
3829+ log .Printf ("[ERROR] Failed download request for %s: %s" , imageName , err )
3830+ return err
3831+ }
3832+
3833+ defer newresp .Body .Close ()
3834+ if newresp .StatusCode != 200 {
3835+ log .Printf ("[ERROR] Docker download for image %s (backend) StatusCode (1): %d" , imageName , newresp .StatusCode )
3836+ return errors .New (fmt .Sprintf ("Failed to get image - status code %d" , newresp .StatusCode ))
3837+ }
3838+
3839+ newImageName := strings .Replace (imageName , "/" , "_" , - 1 )
3840+ newFileName := newImageName + ".tar"
3841+
3842+ tar , err := os .Create (newFileName )
3843+ if err != nil {
3844+ log .Printf ("[WARNING] Failed creating file: %s" , err )
3845+ return err
3846+ }
3847+
3848+ defer tar .Close ()
3849+ _ , err = io .Copy (tar , newresp .Body )
3850+ if err != nil {
3851+ log .Printf ("[WARNING] Failed response body copying: %s" , err )
3852+ return err
3853+ }
3854+ tar .Seek (0 , 0 )
3855+
3856+ dockercli , err := docker .NewEnvClient ()
3857+ if err != nil {
3858+ log .Printf ("[ERROR] Unable to create docker client (3): %s" , err )
3859+ return err
3860+ }
3861+
3862+ defer dockercli .Close ()
3863+
3864+ imageLoadResponse , err := dockercli .ImageLoad (context .Background (), tar , true )
3865+ if err != nil {
3866+ log .Printf ("[ERROR] Error loading images: %s" , err )
3867+ return err
3868+ }
3869+
3870+ defer imageLoadResponse .Body .Close ()
3871+ body , err := ioutil .ReadAll (imageLoadResponse .Body )
3872+ if err != nil {
3873+ log .Printf ("[ERROR] Error reading: %s" , err )
3874+ return err
3875+ }
3876+
3877+ if strings .Contains (string (body ), "no such file" ) {
3878+ return errors .New (string (body ))
3879+ }
3880+
3881+ os .Remove (newFileName )
3882+
3883+ if strings .Contains (strings .ToLower (string (body )), "error" ) {
3884+ log .Printf ("[ERROR] Error loading image %s: %s" , imageName , string (body ))
3885+ return errors .New (string (body ))
3886+ }
3887+
3888+ baseTag := strings .Split (imageName , ":" )
3889+ if len (baseTag ) > 1 {
3890+ tag := baseTag [1 ]
3891+ log .Printf ("[DEBUG] Creating tag copies of downloaded containers from tag %s" , tag )
3892+
3893+ // Remapping
3894+ ctx := context .Background ()
3895+ dockercli .ImageTag (ctx , imageName , fmt .Sprintf ("frikky/shuffle:%s" , tag ))
3896+ dockercli .ImageTag (ctx , imageName , fmt .Sprintf ("registry.hub.docker.com/frikky/shuffle:%s" , tag ))
3897+
3898+ downloadedImages = append (downloadedImages , fmt .Sprintf ("frikky/shuffle:%s" , tag ))
3899+ downloadedImages = append (downloadedImages , fmt .Sprintf ("registry.hub.docker.com/frikky/shuffle:%s" , tag ))
3900+
3901+ }
3902+
3903+ log .Printf ("[INFO] Successfully loaded image %s: %s" , imageName , string (body ))
3904+ return nil
3905+ }
0 commit comments