Skip to content

Commit

Permalink
bugfix: pull image before run and upgrade (#1419)
Browse files Browse the repository at this point in the history
bugfix: pull image before run and upgrade
  • Loading branch information
wrfly authored and allencloud committed May 29, 2018
1 parent dfdb8fa commit 62055bb
Show file tree
Hide file tree
Showing 5 changed files with 55 additions and 60 deletions.
2 changes: 1 addition & 1 deletion apis/server/image_bridge.go
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ func (s *Server) pullImage(ctx context.Context, rw http.ResponseWriter, req *htt
}
// Error information has be sent to client, so no need call resp.Write
if err := s.ImageMgr.PullImage(ctx, image, &authConfig, rw); err != nil {
logrus.Errorf("failed to pull image %s:%s: %v", image, tag, err)
logrus.Errorf("failed to pull image %s: %v", image, err)
return nil
}
return nil
Expand Down
60 changes: 38 additions & 22 deletions cli/pull.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,13 @@ import (
"encoding/json"
"fmt"
"io"
"net/http"
"os"
"text/tabwriter"
"time"

"github.com/alibaba/pouch/apis/types"
"github.com/alibaba/pouch/client"
"github.com/alibaba/pouch/credential"
"github.com/alibaba/pouch/ctrd"
"github.com/alibaba/pouch/pkg/reference"
Expand Down Expand Up @@ -55,28 +57,7 @@ func (p *PullCommand) addFlags() {

// runPull is the entry of pull command.
func (p *PullCommand) runPull(args []string) error {
namedRef, err := reference.Parse(args[0])
if err != nil {
return fmt.Errorf("failed to pull image: %v", err)
}
namedRef = reference.TrimTagForDigest(reference.WithDefaultTagIfMissing(namedRef))

var name, tag string
if reference.IsNameTagged(namedRef) {
name, tag = namedRef.Name(), namedRef.(reference.Tagged).Tag()
} else {
name = namedRef.String()
}

ctx := context.Background()
apiClient := p.cli.Client()
responseBody, err := apiClient.ImagePull(ctx, name, tag, fetchRegistryAuth(namedRef.Name()))
if err != nil {
return fmt.Errorf("failed to pull image: %v", err)
}
defer responseBody.Close()

return showProgress(responseBody)
return pullMissingImage(context.Background(), p.cli.Client(), args[0], true)
}

func fetchRegistryAuth(serverAddress string) string {
Expand Down Expand Up @@ -228,3 +209,38 @@ IMAGE ID IMAGE NAME SIZE
bbc3a0323522 docker.io/library/busybox:latest 703.14 KB
0153c5db97e5 docker.io/library/redis:alpine 9.63 MB`
}

// pullMissingImage pull the image if it doesn't exist.
// When `force` is true, always pull the latest image instead of
// using the local version
func pullMissingImage(ctx context.Context, apiClient client.CommonAPIClient, image string, force bool) error {
if !force {
_, inspectError := apiClient.ImageInspect(ctx, image)
if inspectError == nil {
return nil
}
if err, ok := inspectError.(client.RespError); !ok {
return inspectError
} else if err.Code() != http.StatusNotFound {
return inspectError
}
}

namedRef, _ := reference.Parse(image)
namedRef = reference.TrimTagForDigest(reference.WithDefaultTagIfMissing(namedRef))

var name, tag string
if reference.IsNameTagged(namedRef) {
name, tag = namedRef.Name(), namedRef.(reference.Tagged).Tag()
} else {
name = namedRef.String()
}

responseBody, err := apiClient.ImagePull(ctx, name, tag, fetchRegistryAuth(namedRef.Name()))
if err != nil {
return fmt.Errorf("failed to pull image: %v", err)
}
defer responseBody.Close()

return showProgress(responseBody)
}
5 changes: 5 additions & 0 deletions cli/run.go
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,11 @@ func (rc *RunCommand) runRun(args []string) error {

ctx := context.Background()
apiClient := rc.cli.Client()

if err := pullMissingImage(ctx, apiClient, config.Image, false); err != nil {
return err
}

result, err := apiClient.ContainerCreate(ctx, config.ContainerConfig, config.HostConfig, config.NetworkingConfig, containerName)
if err != nil {
return fmt.Errorf("failed to run container: %v", err)
Expand Down
43 changes: 6 additions & 37 deletions cli/upgrade.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,6 @@ import (
"context"
"fmt"

"github.com/alibaba/pouch/pkg/errtypes"
"github.com/alibaba/pouch/pkg/reference"

"github.com/spf13/cobra"
)

Expand Down Expand Up @@ -56,46 +53,18 @@ func (ug *UpgradeCommand) runUpgrade(args []string) error {
config.Cmd = args[1:]
}

containerName := ug.name
if containerName == "" {
return fmt.Errorf("failed to upgrade container: must specify container name")
}

ctx := context.Background()
apiClient := ug.cli.Client()

// Check whether the image has been pulled
_, err = apiClient.ImageInspect(ctx, config.Image)
if err != nil && errtypes.IsNotfound(err) {
fmt.Printf("Image %s not found, try to pull it...\n", config.Image)

namedRef, err := reference.Parse(config.Image)
if err != nil {
return fmt.Errorf("failed to pull image: %v", err)
}
namedRef = reference.TrimTagForDigest(reference.WithDefaultTagIfMissing(namedRef))

var name, tag string
if reference.IsNameTagged(namedRef) {
name, tag = namedRef.Name(), namedRef.(reference.Tagged).Tag()
} else {
name = namedRef.String()
}

responseBody, err := apiClient.ImagePull(ctx, name, tag, fetchRegistryAuth(namedRef.Name()))
if err != nil {
return fmt.Errorf("failed to pull image: %v", err)
}
defer responseBody.Close()

if err := showProgress(responseBody); err != nil {
return err
}
} else if err != nil {
if err := pullMissingImage(ctx, apiClient, config.Image, false); err != nil {
return err
}

containerName := ug.name
if containerName == "" {
return fmt.Errorf("failed to upgrade container: must specify container name")
}

// TODO if error is image not found, we can pull image, and retry upgrade
err = apiClient.ContainerUpgrade(ctx, containerName, config.ContainerConfig, config.HostConfig)
if err == nil {
fmt.Println(containerName)
Expand Down
5 changes: 5 additions & 0 deletions client/request.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,11 @@ func (e RespError) Error() string {
return e.msg
}

// Code returns the response code
func (e RespError) Code() int {
return e.code
}

// Response wraps the http.Response and other states.
type Response struct {
StatusCode int
Expand Down

0 comments on commit 62055bb

Please sign in to comment.