Skip to content

Commit 3b0c36d

Browse files
committed
Merge pull request #131 from arschles/storage-keys
ref(build.go): pulling slugbuilder storage params out
2 parents 71a09fb + 8e8c0a6 commit 3b0c36d

5 files changed

Lines changed: 191 additions & 36 deletions

File tree

pkg/gitreceive/build.go

Lines changed: 22 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -12,25 +12,13 @@ import (
1212

1313
"github.com/aws/aws-sdk-go/service/s3"
1414
"github.com/deis/builder/pkg"
15+
"github.com/deis/builder/pkg/gitreceive/git"
1516
"github.com/deis/builder/pkg/gitreceive/log"
1617
"github.com/deis/builder/pkg/gitreceive/storage"
1718
"github.com/pborman/uuid"
1819
"gopkg.in/yaml.v2"
1920
)
2021

21-
const (
22-
// this constant represents the length of a shortened git sha - 8 characters long
23-
shortShaIdx = 8
24-
)
25-
26-
type errGitShaTooShort struct {
27-
sha string
28-
}
29-
30-
func (e errGitShaTooShort) Error() string {
31-
return fmt.Sprintf("git sha %s was too short", e.sha)
32-
}
33-
3422
// repoCmd returns exec.Command(first, others...) with its current working directory repoDir
3523
func repoCmd(repoDir, first string, others ...string) *exec.Cmd {
3624
cmd := exec.Command(first, others...)
@@ -53,30 +41,26 @@ func run(cmd *exec.Cmd) error {
5341
return cmd.Run()
5442
}
5543

56-
func build(conf *Config, s3Client *s3.S3, builderKey, gitSha string) error {
44+
func build(conf *Config, s3Client *s3.S3, builderKey, rawGitSha string) error {
5745
repo := conf.Repository
58-
if len(gitSha) <= shortShaIdx {
59-
return errGitShaTooShort{sha: gitSha}
46+
gitSha, err := git.NewSha(rawGitSha)
47+
if err != nil {
48+
return err
6049
}
61-
shortSha := gitSha[0:8]
50+
6251
appName := conf.App()
6352

6453
repoDir := filepath.Join(conf.GitHome, repo)
6554
buildDir := filepath.Join(repoDir, "build")
6655

67-
slugName := fmt.Sprintf("%s:git-%s", appName, shortSha)
56+
slugName := fmt.Sprintf("%s:git-%s", appName, gitSha.Short())
6857
imageName := strings.Replace(slugName, ":", "-", -1)
6958
if err := os.MkdirAll(buildDir, os.ModeDir); err != nil {
7059
return fmt.Errorf("making the build directory %s (%s)", buildDir, err)
7160
}
7261
tmpDir := os.TempDir()
7362

74-
tarObjKey := fmt.Sprintf("home/%s/tar", slugName)
75-
tarURL := fmt.Sprintf("%s/git/%s", s3Client.Endpoint, tarObjKey)
76-
77-
// this is where workflow tells slugrunner to download the slug from, so we have to tell slugbuilder to upload it to here
78-
pushObjKey := fmt.Sprintf("home/%s/push", fmt.Sprintf("%s:git-%s", appName, gitSha))
79-
pushURL := fmt.Sprintf("%s/%s", s3Client.Endpoint, pushObjKey)
63+
slugBuilderInfo := storage.NewSlugBuilderInfo(s3Client.Endpoint, appName, slugName, gitSha)
8064

8165
// Get the application config from the controller, so we can check for a custom buildpack URL
8266
appConf, err := getAppConfig(conf, builderKey, conf.Username, appName)
@@ -94,7 +78,7 @@ func build(conf *Config, s3Client *s3.S3, builderKey, gitSha string) error {
9478

9579
// build a tarball from the new objects
9680
appTgz := fmt.Sprintf("%s.tar.gz", appName)
97-
gitArchiveCmd := repoCmd(repoDir, "git", "archive", "--format=tar.gz", fmt.Sprintf("--output=%s", appTgz), gitSha)
81+
gitArchiveCmd := repoCmd(repoDir, "git", "archive", "--format=tar.gz", fmt.Sprintf("--output=%s", appTgz), gitSha.Full())
9882
gitArchiveCmd.Stdout = os.Stdout
9983
gitArchiveCmd.Stderr = os.Stderr
10084
if err := run(gitArchiveCmd); err != nil {
@@ -153,15 +137,15 @@ func build(conf *Config, s3Client *s3.S3, builderKey, gitSha string) error {
153137
var finalManifest string
154138
uid := uuid.New()[:8]
155139
if usingDockerfile {
156-
buildPodName = fmt.Sprintf("dockerbuild-%s-%s-%s", appName, shortSha, uid)
140+
buildPodName = fmt.Sprintf("dockerbuild-%s-%s-%s", appName, gitSha.Short(), uid)
157141
finalManifest = strings.Replace(string(fileBytes), "repo_name", buildPodName, -1)
158-
finalManifest = strings.Replace(finalManifest, "puturl", pushURL, -1)
159-
finalManifest = strings.Replace(finalManifest, "tar-url", tarURL, -1)
142+
finalManifest = strings.Replace(finalManifest, "puturl", slugBuilderInfo.PushURL(), -1)
143+
finalManifest = strings.Replace(finalManifest, "tar-url", slugBuilderInfo.TarURL(), -1)
160144
} else {
161-
buildPodName = fmt.Sprintf("slugbuild-%s-%s-%s", appName, shortSha, uid)
145+
buildPodName = fmt.Sprintf("slugbuild-%s-%s-%s", appName, gitSha.Short(), uid)
162146
finalManifest = strings.Replace(string(fileBytes), "repo_name", buildPodName, -1)
163-
finalManifest = strings.Replace(finalManifest, "puturl", pushURL, -1)
164-
finalManifest = strings.Replace(finalManifest, "tar-url", tarURL, -1)
147+
finalManifest = strings.Replace(finalManifest, "puturl", slugBuilderInfo.PushURL(), -1)
148+
finalManifest = strings.Replace(finalManifest, "tar-url", slugBuilderInfo.TarURL(), -1)
165149
finalManifest = strings.Replace(finalManifest, "buildurl", buildPackURL, -1)
166150
}
167151

@@ -179,8 +163,10 @@ func build(conf *Config, s3Client *s3.S3, builderKey, gitSha string) error {
179163
if err != nil {
180164
return fmt.Errorf("opening %s for read (%s)", appTgz, err)
181165
}
182-
if err := storage.UploadObject(s3Client, bucketName, tarObjKey, appTgzReader); err != nil {
183-
return fmt.Errorf("uploading %s to %s/%s (%v)", absAppTgz, bucketName, tarObjKey, err)
166+
167+
log.Debug("Uploading tar to %s/%s/%s", s3Client.Endpoint, bucketName, slugBuilderInfo.TarKey())
168+
if err := storage.UploadObject(s3Client, bucketName, slugBuilderInfo.TarKey(), appTgzReader); err != nil {
169+
return fmt.Errorf("uploading %s to %s/%s (%v)", absAppTgz, bucketName, slugBuilderInfo.TarKey(), err)
184170
}
185171

186172
log.Info("Starting build... but first, coffee!")
@@ -233,9 +219,9 @@ func build(conf *Config, s3Client *s3.S3, builderKey, gitSha string) error {
233219
// poll the s3 server to ensure the slug exists
234220
// TODO: time out looking
235221
for {
236-
exists, err := storage.ObjectExists(s3Client, bucketName, pushObjKey)
222+
exists, err := storage.ObjectExists(s3Client, bucketName, slugBuilderInfo.PushKey())
237223
if err != nil {
238-
return fmt.Errorf("Checking if object %s/%s exists (%s)", bucketName, pushObjKey, err)
224+
return fmt.Errorf("Checking if object %s/%s exists (%s)", bucketName, slugBuilderInfo.PushKey(), err)
239225
}
240226
if exists {
241227
break
@@ -247,7 +233,7 @@ func build(conf *Config, s3Client *s3.S3, builderKey, gitSha string) error {
247233
log.Info("Launching...")
248234

249235
buildHook := &pkg.BuildHook{
250-
Sha: gitSha,
236+
Sha: gitSha.Full(),
251237
ReceiveUser: conf.Username,
252238
ReceiveRepo: appName,
253239
Image: appName,

pkg/gitreceive/git/sha.go

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
package git
2+
3+
import (
4+
"fmt"
5+
"regexp"
6+
)
7+
8+
const (
9+
// this constant represents the length of a shortened git sha - 8 characters long
10+
shortShaIdx = 8
11+
)
12+
13+
var shaRegex = regexp.MustCompile(`^[\da-f]{40}$`)
14+
15+
type ErrInvalidGitSha struct {
16+
sha string
17+
}
18+
19+
func (e ErrInvalidGitSha) Error() string {
20+
return fmt.Sprintf("git sha %s was invalid", e.sha)
21+
}
22+
23+
type SHA struct {
24+
full string
25+
short string
26+
}
27+
28+
func NewSha(rawSha string) (*SHA, error) {
29+
if !shaRegex.MatchString(rawSha) {
30+
return nil, ErrInvalidGitSha{sha: rawSha}
31+
}
32+
return &SHA{full: rawSha, short: rawSha[0:8]}, nil
33+
}
34+
35+
func (s SHA) Full() string { return s.full }
36+
func (s SHA) Short() string { return s.short }

pkg/gitreceive/git/sha_test.go

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
package git
2+
3+
import (
4+
"testing"
5+
)
6+
7+
func TestShaTooShort(t *testing.T) {
8+
shaStrs := []string{
9+
"abcdefghij",
10+
"abc",
11+
"",
12+
}
13+
for i, shaStr := range shaStrs {
14+
sha, err := NewSha(shaStr)
15+
if err == nil {
16+
t.Errorf("expected error for sha %s (#%d), got nothing", shaStr, i)
17+
continue
18+
}
19+
if sha != nil {
20+
t.Errorf("expected returned SHA struct to be nil, got %+v instead", *sha)
21+
}
22+
}
23+
}
24+
25+
func TestNewSha(t *testing.T) {
26+
shaStrs := []string{
27+
"71a09fbed590558ff822536584fc77248f070384",
28+
"39d8ef3ea964c98f884a67aecef56b4c8abfc700",
29+
"1b48115b57304d04c8c2e72d62e0a9d1bcd0d48f",
30+
}
31+
for i, shaStr := range shaStrs {
32+
sha, err := NewSha(shaStr)
33+
if err != nil {
34+
t.Errorf("expected no error for sha %s (#%d), got %s", shaStr, i, err)
35+
continue
36+
}
37+
if sha.Full() != shaStr {
38+
t.Errorf("expected full sha string to be %s, got %s", shaStr, sha.Full())
39+
}
40+
if sha.Short() != shaStr[0:8] {
41+
t.Errorf("expected short sha to be first 8 characters of %s, got %s", shaStr, sha.Short())
42+
}
43+
}
44+
}
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
package storage
2+
3+
import (
4+
"fmt"
5+
6+
"github.com/deis/builder/pkg/gitreceive/git"
7+
)
8+
9+
// SlugBuilderInfo contains all of the object storage related information needed to pass to a slug builder
10+
type SlugBuilderInfo struct {
11+
pushKey string
12+
pushURL string
13+
tarKey string
14+
tarURL string
15+
}
16+
17+
// NewSlugBuilderInfo creates and populates a new SlugBuilderInfo based on the given data
18+
func NewSlugBuilderInfo(s3Endpoint, appName, slugName string, gitSha *git.SHA) *SlugBuilderInfo {
19+
tarKey := fmt.Sprintf("home/%s/tar", slugName)
20+
// this is where workflow tells slugrunner to download the slug from, so we have to tell slugbuilder to upload it to here
21+
pushKey := fmt.Sprintf("home/%s:git-%s/push", appName, gitSha.Full())
22+
23+
return &SlugBuilderInfo{
24+
pushKey: pushKey,
25+
pushURL: fmt.Sprintf("%s/git/%s", s3Endpoint, pushKey),
26+
tarKey: tarKey,
27+
tarURL: fmt.Sprintf("%s/git/%s", s3Endpoint, tarKey),
28+
}
29+
}
30+
31+
func (s SlugBuilderInfo) PushKey() string { return s.pushKey }
32+
func (s SlugBuilderInfo) PushURL() string { return s.pushURL }
33+
func (s SlugBuilderInfo) TarKey() string { return s.tarKey }
34+
func (s SlugBuilderInfo) TarURL() string { return s.tarURL }
Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
package storage
2+
3+
import (
4+
"testing"
5+
6+
"github.com/deis/builder/pkg/gitreceive/git"
7+
)
8+
9+
const (
10+
rawSha = "c3b4e4ba8b7267226ff02ad07a3a2cca9c9237de"
11+
s3Endpoint = "http://10.1.2.3:9090"
12+
appName = "myapp"
13+
slugName = "myslug"
14+
)
15+
16+
func TestS3Endpoint(t *testing.T) {
17+
sha, err := git.NewSha(rawSha)
18+
if err != nil {
19+
t.Fatalf("error building git sha (%s)", err)
20+
}
21+
sbi := NewSlugBuilderInfo(s3Endpoint, appName, slugName, sha)
22+
23+
expectedPushURL := s3Endpoint + "/git/" + sbi.PushKey()
24+
if sbi.PushURL() != expectedPushURL {
25+
t.Errorf("push URL %s didn't match expected %s", sbi.PushURL(), expectedPushURL)
26+
}
27+
expectedTarURL := s3Endpoint + "/git/" + sbi.TarKey()
28+
if sbi.TarURL() != expectedTarURL {
29+
t.Errorf("tar URL %s didn't match expected %s", sbi.TarURL(), expectedTarURL)
30+
}
31+
}
32+
33+
func TestPushKey(t *testing.T) {
34+
sha, err := git.NewSha(rawSha)
35+
if err != nil {
36+
t.Fatalf("error building git sha (%s)", err)
37+
}
38+
sbi := NewSlugBuilderInfo(s3Endpoint, appName, slugName, sha)
39+
expectedPushKey := "home/" + appName + ":git-" + sha.Full() + "/push"
40+
if sbi.PushKey() != expectedPushKey {
41+
t.Errorf("push key %s didn't match expected %s", sbi.PushKey(), expectedPushKey)
42+
}
43+
}
44+
45+
func TestTarKey(t *testing.T) {
46+
sha, err := git.NewSha(rawSha)
47+
if err != nil {
48+
t.Fatalf("error building git sha (%s)", err)
49+
}
50+
sbi := NewSlugBuilderInfo(s3Endpoint, appName, slugName, sha)
51+
expectedTarKey := "home/" + slugName + "/tar"
52+
if sbi.TarKey() != expectedTarKey {
53+
t.Errorf("tar key %s didn't match expected %s", sbi.TarKey(), expectedTarKey)
54+
}
55+
}

0 commit comments

Comments
 (0)