diff --git a/pkg/harbourbuild/builder.go b/pkg/harbourbuild/builder.go index cd4c497..dcb4056 100644 --- a/pkg/harbourbuild/builder.go +++ b/pkg/harbourbuild/builder.go @@ -1,14 +1,18 @@ package harbourbuild import ( + "bytes" "context" "fmt" "github.com/docker/docker/api/types" "github.com/docker/docker/client" "github.com/harbourrocks/harbour/pkg/harbourbuild/models" + "github.com/harbourrocks/harbour/pkg/redisconfig" "github.com/jhoonb/archivex" l "github.com/sirupsen/logrus" + "io" "os" + "strings" ) type Builder struct { @@ -17,6 +21,7 @@ type Builder struct { ctx context.Context ctxPath string repoPath string + redisconfig.RedisModel } func NewBuilder(jobChan chan models.BuildJob, ctxPath string, repoPath string) (Builder, error) { @@ -43,33 +48,50 @@ func (b Builder) Start() { } func (b Builder) buildImage(job models.BuildJob) { - l.Trace("Create Build Context") + + redisConfig := b.GetRedisConfig() + redisClient := redisconfig.OpenClient(redisConfig) + redisClient.HSet(job.BuildKey, "build_status", "Running") + buildCtx, err := b.createBuildContext(job.Request.Project) if err != nil { l.WithError(err).Error("Failed to create build context") return } - defer b.cleanUpAfterBuild(buildCtx) - - l.Trace("Create Build Options") opt := types.ImageBuildOptions{ Tags: job.Request.Tags, Dockerfile: job.Request.Dockerfile, } - l.Trace("Build Image") - _, err = b.cli.ImageBuild(b.ctx, buildCtx, opt) + resp, err := b.cli.ImageBuild(b.ctx, buildCtx, opt) if err != nil { l.WithError(err).Error("Failed to build image") return } + + defer b.cleanUpAfterBuild(buildCtx, resp.Body) + + buf := new(bytes.Buffer) + _, err = buf.ReadFrom(resp.Body) + if err != nil { + l.WithError(err).Error("Failed to parse response body") + } + + logs := buf.String() + if strings.Contains(logs, "errorDetail") { + redisClient.HSet(job.BuildKey, "build_status", "Failed", "logs", logs) + return + } + + redisClient.HSet(job.BuildKey, "build_status", "Success", "logs", logs) + l.Trace("Image was built") } -func (b Builder) cleanUpAfterBuild(buildContext *os.File) { - l.Trace("Cleaning up") +func (b Builder) cleanUpAfterBuild(buildContext *os.File, logs io.ReadCloser) { err := buildContext.Close() err = os.Remove(buildContext.Name()) + err = logs.Close() if err != nil { l.WithError(err).Error("Error while cleaning up build context") return @@ -83,7 +105,6 @@ func (b Builder) getProjectPath(project string) (string, error) { } func (b Builder) createBuildContext(project string) (*os.File, error) { - buildContext := fmt.Sprintf(b.ctxPath+"%s.tar", project) projectPath, err := b.getProjectPath(project) if err != nil { diff --git a/pkg/harbourbuild/handler/build.go b/pkg/harbourbuild/handler/build.go index 1a87d9e..d6aaae9 100644 --- a/pkg/harbourbuild/handler/build.go +++ b/pkg/harbourbuild/handler/build.go @@ -2,7 +2,9 @@ package handler import ( "encoding/json" + "github.com/google/uuid" "github.com/harbourrocks/harbour/pkg/harbourbuild/models" + "github.com/harbourrocks/harbour/pkg/harbourbuild/redis" "github.com/harbourrocks/harbour/pkg/httphandler/traits" "github.com/harbourrocks/harbour/pkg/redisconfig" l "github.com/sirupsen/logrus" @@ -23,7 +25,6 @@ func NewBuilderModel(buildChan chan models.BuildJob) BuilderModel { func (b BuilderModel) Handle() { w := b.GetResponse() req := b.GetRequest() - //redisConfig := b.GetRedisConfig() var buildRequest models.BuildRequest decoder := json.NewDecoder(req.Body) err := decoder.Decode(&buildRequest) @@ -33,9 +34,33 @@ func (b BuilderModel) Handle() { return } - b.buildChan <- models.BuildJob{Request: buildRequest} + buildKey, err := b.createBuildEntry(buildRequest) + if err != nil { + l.WithError(err).Error("Failed to save build to redis") + return + } - l.Trace("Build job enqueued") + b.buildChan <- models.BuildJob{Request: buildRequest, BuildKey: buildKey} + l.Trace("Build job enqueued") w.WriteHeader(http.StatusAccepted) } + +func (b BuilderModel) createBuildEntry(request models.BuildRequest) (string, error) { + redisConfig := b.GetRedisConfig() + buildId := uuid.New() + buildKey := redis.BuildAppKey(buildId.String()) + + client := redisconfig.OpenClient(redisConfig) + err := client.HSet(buildKey, + "project", request.Project, + "commit", request.Commit, + "logs", nil, + "repository", request.Project, + "build_status", "Pending").Err() + if err != nil { + return buildKey, err + } + + return buildKey, nil +} diff --git a/pkg/harbourbuild/models/build.go b/pkg/harbourbuild/models/build.go new file mode 100644 index 0000000..4f5a7b4 --- /dev/null +++ b/pkg/harbourbuild/models/build.go @@ -0,0 +1,10 @@ +package models + +type Build struct { + BuildId string + Project string + Commit string + Logs string + Repository string + BuildStatus string +} diff --git a/pkg/harbourbuild/models/buildjob.go b/pkg/harbourbuild/models/buildjob.go index 450d36f..0ce9829 100644 --- a/pkg/harbourbuild/models/buildjob.go +++ b/pkg/harbourbuild/models/buildjob.go @@ -3,5 +3,6 @@ package models // BuildJob represents a job send to the Builder with a channel. // Contains all information required for build a image. type BuildJob struct { - Request BuildRequest + Request BuildRequest + BuildKey string } diff --git a/pkg/harbourbuild/models/buildrequest.go b/pkg/harbourbuild/models/buildrequest.go index d001f58..5a0c9bf 100644 --- a/pkg/harbourbuild/models/buildrequest.go +++ b/pkg/harbourbuild/models/buildrequest.go @@ -4,4 +4,5 @@ type BuildRequest struct { Dockerfile string `json:"dockerfile"` Tags []string `json:"tags"` Project string `json:"project"` + Commit string `json:"commit"` } diff --git a/pkg/harbourbuild/redis/build.go b/pkg/harbourbuild/redis/build.go new file mode 100644 index 0000000..08367c3 --- /dev/null +++ b/pkg/harbourbuild/redis/build.go @@ -0,0 +1,7 @@ +package redis + +import "fmt" + +func BuildAppKey(buildId string) string { + return fmt.Sprintf("BUILD_%s", buildId) +} diff --git a/pkg/harbourbuild/redis/builder.go b/pkg/harbourbuild/redis/builder.go deleted file mode 100644 index bcb7881..0000000 --- a/pkg/harbourbuild/redis/builder.go +++ /dev/null @@ -1,7 +0,0 @@ -package redis - -import "fmt" - -func BuilderAppKey(buildId int) string { - return fmt.Sprintf("BUILD_%d", buildId) -} diff --git a/pkg/harbourbuild/server.go b/pkg/harbourbuild/server.go index bc2ae2f..47bb007 100644 --- a/pkg/harbourbuild/server.go +++ b/pkg/harbourbuild/server.go @@ -21,10 +21,11 @@ func RunBuildServer(o *configuration.Options) error { logrus.Fatal(err) return err } + redisconfig.AddRedis(&builder, o.Redis) builder.Start() logrus.Info("Started Harbour builder ") - http.HandleFunc("/build/test", func(w http.ResponseWriter, r *http.Request) { + http.HandleFunc("/build", func(w http.ResponseWriter, r *http.Request) { logrus.Trace(r) model := handler.NewBuilderModel(buildChan) traits.AddHttp(&model, r, w, o.OIDCConfig)