Skip to content

Commit

Permalink
[FAB-3118] pull ccenv image at runtime
Browse files Browse the repository at this point in the history
The current code requires the CORE_CHAINCODE_BUILDER image to
be pre-pulled down from dockerhub or chaincode building will
fail.  This patch adds the docker-client intelligence to
check whether the image is present.  If it finds that it is
not present, it will try to pull the image from dockerhub.

Change-Id: I95b6bcd0f1b1beb2edee7f0b542f90f5fb9eabc7
Signed-off-by: Greg Haskins <gregory.haskins@gmail.com>
  • Loading branch information
ghaskins committed May 22, 2017
1 parent ed41640 commit 980b4b2
Show file tree
Hide file tree
Showing 4 changed files with 73 additions and 3 deletions.
15 changes: 15 additions & 0 deletions core/chaincode/platforms/util/utils.go
Original file line number Diff line number Diff line change
Expand Up @@ -155,6 +155,21 @@ func DockerBuild(opts DockerBuildOptions) error {
}
}

logger.Debugf("Attempting build with image %s", opts.Image)

//-----------------------------------------------------------------------------------
// Ensure the image exists locally, or pull it from a registry if it doesn't
//-----------------------------------------------------------------------------------
_, err = client.InspectImage(opts.Image)
if err != nil {
logger.Debugf("Image %s does not exist locally, attempt pull", opts.Image)

err = client.PullImage(docker.PullImageOptions{Repository: opts.Image}, docker.AuthConfiguration{})
if err != nil {
return fmt.Errorf("Failed to pull %s: %s", opts.Image, err)
}
}

//-----------------------------------------------------------------------------------
// Create an ephemeral container, armed with our Env/Cmd
//-----------------------------------------------------------------------------------
Expand Down
55 changes: 55 additions & 0 deletions core/chaincode/platforms/util/utils_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,16 @@ import (
"testing"
"time"

"archive/tar"
"fmt"
"io"
"os"
"strings"

"github.com/hyperledger/fabric/common/util"
"github.com/hyperledger/fabric/core/config"
cutil "github.com/hyperledger/fabric/core/container/util"
"github.com/spf13/viper"
)

// TestHashContentChange changes a random byte in a content and checks for hash change
Expand Down Expand Up @@ -187,3 +196,49 @@ func TestHashSameDir(t *testing.T) {
t.Error("Hash should be same across multiple downloads")
}
}

func TestDockerPull(t *testing.T) {
codepackage, output := io.Pipe()
go func() {
tw := tar.NewWriter(output)

tw.Close()
output.Close()
}()

binpackage := bytes.NewBuffer(nil)

// Perform a nop operation within a fixed target. We choose 1.0.0-alpha2 because we know it's
// published and available. Ideally we could choose something that we know is both multi-arch
// and ok to delete prior to executing DockerBuild. This would ensure that we exercise the
// image pull logic. However, no suitable target exists that meets all the criteria. Therefore
// we settle on using a known released image. We don't know if the image is already
// downloaded per se, and we don't want to explicitly delete this particular image first since
// it could be in use legitimately elsewhere. Instead, we just know that this should always
// work and call that "close enough".
//
// Future considerations: publish a known dummy image that is multi-arch and free to randomly
// delete, and use that here instead.
err := DockerBuild(DockerBuildOptions{
Image: cutil.ParseDockerfileTemplate("hyperledger/fabric-ccenv:$(ARCH)-1.0.0-alpha2"),
Cmd: "/bin/true",
InputStream: codepackage,
OutputStream: binpackage,
})
if err != nil {
t.Errorf("Error during build: %s", err)
}
}

func TestMain(m *testing.M) {
viper.SetConfigName("core")
viper.SetEnvPrefix("CORE")
config.AddDevConfigPath(nil)
viper.SetEnvKeyReplacer(strings.NewReplacer(".", "_"))
viper.AutomaticEnv()
if err := viper.ReadInConfig(); err != nil {
fmt.Printf("could not read config %s\n", err)
os.Exit(-1)
}
os.Exit(m.Run())
}
4 changes: 2 additions & 2 deletions core/container/util/dockerutil.go
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ func getArch() string {
}
}

func parseDockerfileTemplate(template string) string {
func ParseDockerfileTemplate(template string) string {
r := strings.NewReplacer(
"$(ARCH)", getArch(),
"$(PROJECT_VERSION)", metadata.Version,
Expand All @@ -68,5 +68,5 @@ func parseDockerfileTemplate(template string) string {
}

func GetDockerfileFromConfig(path string) string {
return parseDockerfileTemplate(viper.GetString(path))
return ParseDockerfileTemplate(viper.GetString(path))
}
2 changes: 1 addition & 1 deletion core/container/util/dockerutil_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ import (

func TestUtil_DockerfileTemplateParser(t *testing.T) {
expected := "FROM foo:" + getArch() + "-" + metadata.Version
actual := parseDockerfileTemplate("FROM foo:$(ARCH)-$(PROJECT_VERSION)")
actual := ParseDockerfileTemplate("FROM foo:$(ARCH)-$(PROJECT_VERSION)")
assert.Equal(t, expected, actual, "Error parsing Dockerfile Template. Expected \"%s\", got \"%s\"",
expected, actual)
}
Expand Down

0 comments on commit 980b4b2

Please sign in to comment.