Skip to content
This repository has been archived by the owner on Jan 10, 2023. It is now read-only.

Commit

Permalink
Merge pull request #16 from Netflix/fail-on-no-entrypoint
Browse files Browse the repository at this point in the history
Fail on no entrypoint, don't crash
  • Loading branch information
sargun authored Nov 13, 2017
2 parents 29b821d + cf51095 commit 9fa9e62
Show file tree
Hide file tree
Showing 2 changed files with 44 additions and 7 deletions.
16 changes: 16 additions & 0 deletions executor/mock/standalone/standalone_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,10 @@ var (
name: "titusoss/big-image",
tag: "20171025-1508900976",
}
noEntrypoint = testImage{
name: "titusoss/no-entrypoint-test",
tag: "20171109-1510275133",
}
)

// This file still uses log as opposed to using the testing library's built-in logging framework.
Expand All @@ -79,6 +83,7 @@ func TestStandalone(t *testing.T) {
testImageNonExistingDigestFails,
testImagePullError,
testBadEntrypoint,
testNoEntrypoint,
testCanWriteInLogsAndSubDirs,
testShutdown,
testCancelPullBigImage,
Expand Down Expand Up @@ -478,6 +483,17 @@ func testBadEntrypoint(t *testing.T) {
}
}

func testNoEntrypoint(t *testing.T) {
ji := &mock.JobInput{
ImageName: noEntrypoint.name,
Version: noEntrypoint.tag,
}
// We expect this to fail
if mock.RunJobExpectingSuccess(ji, false) {
t.Fail()
}
}

func testCanWriteInLogsAndSubDirs(t *testing.T) {
cmd := `sh -c "mkdir -p /logs/prana && echo begining > /logs/prana/prana.log && ` +
`mv /logs/prana/prana.log /logs/prana/prana-2016.log && echo ending >> /logs/out"`
Expand Down
35 changes: 28 additions & 7 deletions executor/runtime/docker.go
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,9 @@ var (
// and it's a temporary measure during protocol evolution.
var ErrMissingIAMRole = errors.New("IAM Role Missing")

// NoEntrypointError indicates that the Titus job does not have an entrypoint, or command
var NoEntrypointError = &BadEntryPointError{reason: errors.New("Image, and job have no entrypoint, or command")}

// I'm sorry for using regex, it's a simple rule though
// 1. The string must start with a-z, A-Z, or _
// 2. The string MAY contain more characters, in the set a-z, A-Z, 0-9, or _
Expand Down Expand Up @@ -629,6 +632,7 @@ func (r *DockerRuntime) Prepare(parentCtx context.Context, c *Container, binds [
var dockerCfg *container.Config
var hostCfg *container.HostConfig
var size int64
var imageInfo types.ImageInspect

err := r.validateEFSMounts(c)
if err != nil {
Expand All @@ -640,7 +644,18 @@ func (r *DockerRuntime) Prepare(parentCtx context.Context, c *Container, binds [
goto error
}

size = r.reportDockerImageSizeMetric(c, c.QualifiedImageName())
imageInfo, _, err = r.client.ImageInspectWithRaw(ctx, c.QualifiedImageName())
if err != nil {
log.Errorf("Error in inspecting docker image %s: %v", c.QualifiedImageName(), err)
return err
}
size = r.reportDockerImageSizeMetric(c, imageInfo)

// Check if this image (container) has a an entrypoint, or if we
// were passed one
if !r.hasEntrypoint(imageInfo, c) {
return NoEntrypointError
}

dockerCfg, hostCfg, err = r.dockerConfig(c, binds, size)
if err != nil {
Expand Down Expand Up @@ -1471,17 +1486,23 @@ func (r *DockerRuntime) Cleanup(c *Container) error {
}

// reportDockerImageSizeMetric reports a metric that represents the container image's size
func (r *DockerRuntime) reportDockerImageSizeMetric(c *Container, image string) int64 {
imageInfo, _, err := r.client.ImageInspectWithRaw(context.TODO(), image)
if err != nil {
log.Errorf("Error in inspecting docker image %s : %v\n", image, err)
return 0
}
func (r *DockerRuntime) reportDockerImageSizeMetric(c *Container, imageInfo types.ImageInspect) int64 {
// reporting image size in KB
r.metrics.Gauge("titus.executor.dockerImageSize", int(imageInfo.Size/KB), c.ImageTagForMetrics())
return imageInfo.Size
}

func (r *DockerRuntime) hasEntrypoint(imageInfo types.ImageInspect, c *Container) bool {
if entrypoint, err := GetEntrypointFromProto(c.TitusInfo); err != nil {
// If this happens, we return true, because this error will be bubbled up elsewhere
return true
} else if entrypoint != nil {
return true
}

return imageInfo.Config.Entrypoint != nil || imageInfo.Config.Cmd != nil
}

func shouldClose(c io.Closer) {
if err := c.Close(); err != nil {
log.Error("Could not close: ", err)
Expand Down

0 comments on commit 9fa9e62

Please sign in to comment.