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

Fail on no entrypoint, don't crash #16

Merged
merged 2 commits into from
Nov 13, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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