Skip to content

Commit a1c4d12

Browse files
author
Aaron Schlesinger
committed
fix(*): creating and using interfaces for system tasks
Everywhere they’re used can (and will in a subsequent commit) now be unit tested
1 parent 6955570 commit a1c4d12

8 files changed

Lines changed: 112 additions & 21 deletions

File tree

boot.go

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ import (
1414
"github.com/deis/builder/pkg/gitreceive/storage"
1515
"github.com/deis/builder/pkg/healthsrv"
1616
"github.com/deis/builder/pkg/sshd"
17+
"github.com/deis/builder/pkg/sys"
1718
pkglog "github.com/deis/pkg/log"
1819
kcl "k8s.io/kubernetes/pkg/client/unversioned"
1920
)
@@ -48,10 +49,12 @@ func main() {
4849
pkglog.Err("getting config for %s [%s]", serverConfAppName, err)
4950
os.Exit(1)
5051
}
52+
env := sys.RealEnv()
53+
fs := sys.RealFS()
5154
pushLock := sshd.NewInMemoryRepositoryLock()
5255
circ := sshd.NewCircuit()
5356

54-
s3Client, err := storage.GetClient(cnf.HealthSrvTestStorageRegion)
57+
s3Client, err := storage.GetClient(cnf.HealthSrvTestStorageRegion, fs, env)
5558
if err != nil {
5659
log.Printf("Error getting s3 client (%s)", err)
5760
os.Exit(1)
@@ -106,8 +109,10 @@ func main() {
106109
os.Exit(1)
107110
}
108111
cnf.CheckDurations()
112+
fs := sys.RealFS()
113+
env := sys.RealEnv()
109114

110-
if err := gitreceive.Run(cnf); err != nil {
115+
if err := gitreceive.Run(cnf, fs, env); err != nil {
111116
log.Printf("Error running git receive hook [%s]", err)
112117
os.Exit(1)
113118
}

pkg/gitreceive/build.go

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ import (
1515
"github.com/deis/builder/pkg"
1616
"github.com/deis/builder/pkg/gitreceive/git"
1717
"github.com/deis/builder/pkg/gitreceive/storage"
18+
"github.com/deis/builder/pkg/sys"
1819
"github.com/deis/pkg/log"
1920
"gopkg.in/yaml.v2"
2021

@@ -41,7 +42,7 @@ func run(cmd *exec.Cmd) error {
4142
return cmd.Run()
4243
}
4344

44-
func build(conf *Config, s3Client *s3.S3, kubeClient *client.Client, builderKey, rawGitSha string) error {
45+
func build(conf *Config, s3Client *s3.S3, kubeClient *client.Client, env sys.Env, fs sys.FS, builderKey, rawGitSha string) error {
4546
repo := conf.Repository
4647
gitSha, err := git.NewSha(rawGitSha)
4748
if err != nil {
@@ -125,7 +126,7 @@ func build(conf *Config, s3Client *s3.S3, kubeClient *client.Client, builderKey,
125126
return fmt.Errorf("uploading %s to %s/%s (%v)", absAppTgz, conf.Bucket, slugBuilderInfo.TarKey(), err)
126127
}
127128

128-
creds := storage.CredsOK()
129+
creds := storage.CredsOK(fs)
129130

130131
var pod *api.Pod
131132
var buildPodName string

pkg/gitreceive/run.go

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import (
77
"strings"
88

99
"github.com/deis/builder/pkg/gitreceive/storage"
10+
"github.com/deis/builder/pkg/sys"
1011
"github.com/deis/pkg/log"
1112

1213
builderconf "github.com/deis/builder/pkg/conf"
@@ -22,15 +23,15 @@ func readLine(line string) (string, string, string, error) {
2223
return spl[0], spl[1], spl[2], nil
2324
}
2425

25-
func Run(conf *Config) error {
26+
func Run(conf *Config, fs sys.FS, env sys.Env) error {
2627
log.Debug("Running git hook")
2728

2829
builderKey, err := builderconf.GetBuilderKey()
2930
if err != nil {
3031
return err
3132
}
3233

33-
s3Client, err := storage.GetClient(conf.StorageRegion)
34+
s3Client, err := storage.GetClient(conf.StorageRegion, fs, env)
3435
if err != nil {
3536
return fmt.Errorf("configuring S3 client (%s)", err)
3637
}
@@ -56,7 +57,7 @@ func Run(conf *Config) error {
5657
}
5758
// if we're processing a receive-pack on an existing repo, run a build
5859
if strings.HasPrefix(conf.SSHOriginalCommand, "git-receive-pack") {
59-
if err := build(conf, s3Client, kubeClient, builderKey, newRev); err != nil {
60+
if err := build(conf, s3Client, kubeClient, env, fs, builderKey, newRev); err != nil {
6061
return err
6162
}
6263
}

pkg/gitreceive/storage/auth.go

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,11 @@ package storage
22

33
import (
44
"fmt"
5-
"io/ioutil"
65
"os"
76
"strings"
87

98
"github.com/aws/aws-sdk-go/aws/credentials"
9+
"github.com/deis/builder/pkg/sys"
1010
)
1111

1212
const (
@@ -24,9 +24,9 @@ var (
2424
// if a key exists but not a secret, or vice-versa, returns an error.
2525
// if both don't exist returns emptyAuth.
2626
// otherwise returns a valid auth
27-
func getAuth() (*credentials.Credentials, error) {
28-
accessKeyIDBytes, accessKeyErr := ioutil.ReadFile(accessKeyIDFile)
29-
accessSecretKeyBytes, accessSecretKeyErr := ioutil.ReadFile(accessSecretKeyFile)
27+
func getAuth(fs sys.FS) (*credentials.Credentials, error) {
28+
accessKeyIDBytes, accessKeyErr := fs.ReadFile(accessKeyIDFile)
29+
accessSecretKeyBytes, accessSecretKeyErr := fs.ReadFile(accessSecretKeyFile)
3030
if accessKeyErr == os.ErrNotExist && accessSecretKeyErr == os.ErrNotExist {
3131
return emptyAuth, nil
3232
}
@@ -43,8 +43,8 @@ func getAuth() (*credentials.Credentials, error) {
4343
}
4444

4545
// CredsOK checks if the required credentials to make a request exist
46-
func CredsOK() bool {
47-
cred, err := getAuth()
46+
func CredsOK(fs sys.FS) bool {
47+
cred, err := getAuth(fs)
4848
if err != nil {
4949
return false
5050
}

pkg/gitreceive/storage/client.go

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,16 +4,17 @@ import (
44
"github.com/aws/aws-sdk-go/aws"
55
"github.com/aws/aws-sdk-go/aws/session"
66
"github.com/aws/aws-sdk-go/service/s3"
7+
"github.com/deis/builder/pkg/sys"
78
)
89

910
// GetClient returns a S3 API compatible storage client
10-
func GetClient(regionStr string) (*s3.S3, error) {
11-
auth, err := getAuth()
11+
func GetClient(regionStr string, fs sys.FS, env sys.Env) (*s3.S3, error) {
12+
auth, err := getAuth(fs)
1213
if err != nil {
1314
return nil, err
1415
}
1516

16-
endpoint, err := getEndpoint()
17+
endpoint, err := getEndpoint(env)
1718
if err != nil {
1819
return nil, err
1920
}

pkg/gitreceive/storage/endpoint.go

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,8 @@ package storage
22

33
import (
44
"fmt"
5-
"os"
5+
6+
"github.com/deis/builder/pkg/sys"
67
)
78

89
const (
@@ -20,10 +21,10 @@ var (
2021
)
2122
)
2223

23-
func getEndpoint() (string, error) {
24-
mHost := os.Getenv(minioHostEnvVar)
25-
mPort := os.Getenv(minioPortEnvVar)
26-
S3EP := os.Getenv(outsideStorageEndpoint)
24+
func getEndpoint(env sys.Env) (string, error) {
25+
mHost := env.Get(minioHostEnvVar)
26+
mPort := env.Get(minioPortEnvVar)
27+
S3EP := env.Get(outsideStorageEndpoint)
2728
if S3EP != "" {
2829
return S3EP, nil
2930
} else if mHost != "" && mPort != "" {

pkg/sys/env.go

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
package sys
2+
3+
import (
4+
"os"
5+
)
6+
7+
// Env is an interface to a set of environment variables
8+
type Env interface {
9+
// Get gets the environment variable of the given name
10+
Get(name string) string
11+
}
12+
13+
type realEnv struct{}
14+
15+
func (r realEnv) Get(name string) string {
16+
return os.Getenv(name)
17+
}
18+
19+
func RealEnv() Env {
20+
return realEnv{}
21+
}
22+
23+
type FakeEnv struct {
24+
Envs map[string]string
25+
}
26+
27+
func NewFakeEnv() *FakeEnv {
28+
return &FakeEnv{Envs: make(map[string]string)}
29+
}
30+
31+
func (f *FakeEnv) Get(name string) string {
32+
return f.Envs[name]
33+
}

pkg/sys/fs.go

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
package sys
2+
3+
import (
4+
"fmt"
5+
"io/ioutil"
6+
)
7+
8+
// FS is the interface to a file system
9+
type FS interface {
10+
// ReadAll gets the contents of filename, or an error if the file didn't exist or there was an error reading it
11+
ReadFile(filename string) ([]byte, error)
12+
}
13+
14+
// RealFS returns an FS object that interacts with the real local filesystem
15+
func RealFS() FS {
16+
return &realFS{}
17+
}
18+
19+
type realFS struct{}
20+
21+
func (r *realFS) ReadFile(name string) ([]byte, error) {
22+
return ioutil.ReadFile(name)
23+
}
24+
25+
// FakeFileNotFound is the error returned by FakeFS when a requested file isn't found
26+
type FakeFileNotFound struct {
27+
Filename string
28+
}
29+
30+
// Error is the error interface implementation
31+
func (f FakeFileNotFound) Error() string {
32+
return fmt.Sprintf("Fake file %s not found", f.Filename)
33+
}
34+
35+
type FakeFS struct {
36+
Files map[string][]byte
37+
}
38+
39+
func NewFakeFS() *FakeFS {
40+
return &FakeFS{Files: make(map[string][]byte)}
41+
}
42+
43+
func (f *FakeFS) ReadFile(name string) ([]byte, error) {
44+
b, ok := f.Files[name]
45+
if !ok {
46+
return nil, FakeFileNotFound{Filename: name}
47+
}
48+
return b, nil
49+
}

0 commit comments

Comments
 (0)