Skip to content

Commit

Permalink
Merge pull request #394 from travis-ci/meat-gce-hostname
Browse files Browse the repository at this point in the history
Consistently construct GCE and Docker hostnames
  • Loading branch information
meatballhat authored Oct 17, 2017
2 parents cdce890 + 8201fbb commit 4628313
Show file tree
Hide file tree
Showing 5 changed files with 72 additions and 69 deletions.
33 changes: 1 addition & 32 deletions backend/docker.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,6 @@ import (
docker "github.com/docker/docker/client"
"github.com/docker/go-connections/tlsconfig"
humanize "github.com/dustin/go-humanize"
"github.com/pborman/uuid"

"github.com/pkg/errors"
"github.com/sirupsen/logrus"
Expand Down Expand Up @@ -348,7 +347,7 @@ func (p *dockerProvider) Start(ctx gocontext.Context, startAttributes *StartAttr
imageName = p.dockerImageNameForID(ctx, imageID)
}

containerName := containerNameFromContext(ctx)
containerName := hostnameFromContext(ctx)

dockerConfig := &dockercontainer.Config{
Cmd: p.runCmd,
Expand Down Expand Up @@ -705,33 +704,3 @@ func findDockerImageByTag(searchTags []string, images []dockertypes.ImageSummary

return "", fmt.Errorf("failed to find matching docker image tag")
}

func containerNameFromContext(ctx gocontext.Context) string {
randName := fmt.Sprintf("travis-job-unk-unk-%s", uuid.NewRandom())
jobID, ok := context.JobIDFromContext(ctx)
if !ok {
return randName
}

repoName, ok := context.RepositoryFromContext(ctx)
if !ok {
return randName
}

nameParts := []string{"travis-job"}
for _, part := range strings.Split(repoName, "/") {
cleanedPart := containerNamePartDisallowed.ReplaceAllString(part, "-")
// NOTE: the part limit of 14 is meant to ensure a maximum hostname of
// 64 characters, given:
// travis-job.{part}.{part}.{job-id}.travisci.net
// ^---11----^^--15-^^--15-^^--11---^^---12-----^
// therefore:
// 11 + 15 + 15 + 11 + 12 = 64
if len(cleanedPart) > 14 {
cleanedPart = cleanedPart[0:14]
}
nameParts = append(nameParts, cleanedPart)
}

return strings.Join(append(nameParts, fmt.Sprintf("%v", jobID)), "-")
}
26 changes: 0 additions & 26 deletions backend/docker_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ import (
gocontext "context"
"encoding/json"
"fmt"
"math/rand"
"net/http"
"net/http/httptest"
"strings"
Expand All @@ -19,7 +18,6 @@ import (
dockercontainer "github.com/docker/docker/api/types/container"
"github.com/stretchr/testify/assert"
"github.com/travis-ci/worker/config"
"github.com/travis-ci/worker/context"
)

var (
Expand Down Expand Up @@ -582,27 +580,3 @@ func TestDockerInstance_ID(t *testing.T) {
instance.container = nil
assert.Equal(t, "{unidentified}", instance.ID())
}

func TestDocker_containerNameFromContext(t *testing.T) {
jobID := rand.Uint64()

for _, tc := range []struct{ r, n string }{
{
r: "friendly/fribble",
n: fmt.Sprintf("travis-job-friendly-fribble-%v", jobID),
},
{
r: "very-SiLlY.nAmE.wat/por-cu-pine",
n: fmt.Sprintf("travis-job-very-SiLlY-nAm-por-cu-pine-%v", jobID),
},
} {
ctx := context.FromRepository(context.FromJobID(gocontext.TODO(), jobID), tc.r)
assert.Equal(t, tc.n, containerNameFromContext(ctx))
}

randName := containerNameFromContext(gocontext.TODO())
randParts := strings.Split(randName, "-")
assert.Len(t, randParts, 9)
assert.Equal(t, "unk", randParts[2])
assert.Equal(t, "unk", randParts[3])
}
7 changes: 3 additions & 4 deletions backend/gce.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,6 @@ import (

"github.com/cenk/backoff"
"github.com/mitchellh/multistep"
"github.com/pborman/uuid"
"github.com/pkg/errors"
"github.com/sirupsen/logrus"
"github.com/travis-ci/worker/config"
Expand Down Expand Up @@ -702,7 +701,7 @@ func (p *gceProvider) stepRenderScript(c *gceStartContext) multistep.StepAction
}

func (p *gceProvider) stepInsertInstance(c *gceStartContext) multistep.StepAction {
inst := p.buildInstance(c.startAttributes, c.image.SelfLink, c.script)
inst := p.buildInstance(c.ctx, c.startAttributes, c.image.SelfLink, c.script)

context.LoggerFromContext(c.ctx).WithFields(logrus.Fields{
"self": "backend/gce_provider",
Expand Down Expand Up @@ -863,7 +862,7 @@ func buildGCEImageSelector(selectorType string, cfg *config.ProviderConfig) (ima
}
}

func (p *gceProvider) buildInstance(startAttributes *StartAttributes, imageLink, startupScript string) *compute.Instance {
func (p *gceProvider) buildInstance(ctx gocontext.Context, startAttributes *StartAttributes, imageLink, startupScript string) *compute.Instance {
var machineType *compute.MachineType
switch startAttributes.VMType {
case "premium":
Expand Down Expand Up @@ -915,7 +914,7 @@ func (p *gceProvider) buildInstance(startAttributes *StartAttributes, imageLink,
Preemptible: p.ic.Preemptible,
},
MachineType: machineType.SelfLink,
Name: fmt.Sprintf("testing-gce-%s", uuid.NewRandom()),
Name: hostnameFromContext(ctx),
Metadata: &compute.Metadata{
Items: []*compute.MetadataItems{
&compute.MetadataItems{
Expand Down
45 changes: 39 additions & 6 deletions backend/package.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,11 +29,14 @@ New providers should call Register in init() to register the alias it should be
package backend

import (
"context"
gocontext "context"
"fmt"
"io"
"strings"
"time"

"github.com/pborman/uuid"
"github.com/travis-ci/worker/context"
)

var (
Expand All @@ -55,25 +58,25 @@ var (
type Provider interface {
// Setup performs whatever is necessary in order to be ready to start
// instances.
Setup(context.Context) error
Setup(gocontext.Context) error

// Start starts an instance. It shouldn't return until the instance is
// ready to call UploadScript on (this may, for example, mean that it
// waits for SSH connections to be possible).
Start(context.Context, *StartAttributes) (Instance, error)
Start(gocontext.Context, *StartAttributes) (Instance, error)
}

// An Instance is something that can run a build script.
type Instance interface {
// UploadScript uploads the given script to the instance. The script is
// a bash script with a shebang (#!/bin/bash) line. Note that this
// method should not be called multiple times.
UploadScript(context.Context, []byte) error
UploadScript(gocontext.Context, []byte) error

// RunScript runs the build script that was uploaded with the
// UploadScript method.
RunScript(context.Context, io.Writer) (*RunResult, error)
Stop(context.Context) error
RunScript(gocontext.Context, io.Writer) (*RunResult, error)
Stop(gocontext.Context) error

// ID is used when identifying the instance in logs and such
ID() string
Expand Down Expand Up @@ -119,3 +122,33 @@ func str2map(s string) map[string]string {

return ret
}

func hostnameFromContext(ctx gocontext.Context) string {
randName := fmt.Sprintf("travis-job-unk-unk-%s", uuid.NewRandom())
jobID, ok := context.JobIDFromContext(ctx)
if !ok {
return randName
}

repoName, ok := context.RepositoryFromContext(ctx)
if !ok {
return randName
}

nameParts := []string{"travis-job"}
for _, part := range strings.Split(repoName, "/") {
cleanedPart := containerNamePartDisallowed.ReplaceAllString(part, "-")
// NOTE: the part limit of 14 is meant to ensure a maximum hostname of
// 64 characters, given:
// travis-job-{part}-{part}-{job-id}.travisci.net
// ^---11----^^--15-^^--15-^^--11---^^---12-----^
// therefore:
// 11 + 15 + 15 + 11 + 12 = 64
if len(cleanedPart) > 14 {
cleanedPart = cleanedPart[0:14]
}
nameParts = append(nameParts, cleanedPart)
}

return strings.Join(append(nameParts, fmt.Sprintf("%v", jobID)), "-")
}
30 changes: 29 additions & 1 deletion backend/package_test.go
Original file line number Diff line number Diff line change
@@ -1,11 +1,15 @@
package backend

import (
gocontext "context"
"fmt"
"math/rand"
"net/http"
"strings"
"testing"

"github.com/stretchr/testify/assert"
"github.com/travis-ci/worker/context"
)

type recordingHTTPTransport struct {
Expand All @@ -17,7 +21,7 @@ func (t *recordingHTTPTransport) RoundTrip(req *http.Request) (*http.Response, e
return nil, fmt.Errorf("recording HTTP transport impl")
}

func TestAsBool(t *testing.T) {
func Test_asBool(t *testing.T) {
for s, b := range map[string]bool{
"yes": true,
"on": true,
Expand All @@ -36,3 +40,27 @@ func TestAsBool(t *testing.T) {
assert.Equal(t, b, asBool(s))
}
}

func Test_hostnameFromContext(t *testing.T) {
jobID := rand.Uint64()

for _, tc := range []struct{ r, n string }{
{
r: "friendly/fribble",
n: fmt.Sprintf("travis-job-friendly-fribble-%v", jobID),
},
{
r: "very-SiLlY.nAmE.wat/por-cu-pine",
n: fmt.Sprintf("travis-job-very-SiLlY-nAm-por-cu-pine-%v", jobID),
},
} {
ctx := context.FromRepository(context.FromJobID(gocontext.TODO(), jobID), tc.r)
assert.Equal(t, tc.n, hostnameFromContext(ctx))
}

randName := hostnameFromContext(gocontext.TODO())
randParts := strings.Split(randName, "-")
assert.Len(t, randParts, 9)
assert.Equal(t, "unk", randParts[2])
assert.Equal(t, "unk", randParts[3])
}

0 comments on commit 4628313

Please sign in to comment.