1
0
Fork 0
mirror of https://github.com/imjasonh/kontain.me synced 2026-07-16 20:34:22 +00:00

write build logs to GCS

This commit is contained in:
Jason Hall 2019-05-16 09:07:59 -04:00
parent 8bc4369596
commit 15431a2bc2
30 changed files with 43 additions and 9604 deletions

View file

@ -33,7 +33,8 @@ more).
Uploading tarball of [.] to [gs://my-project_cloudbuild/source/1557981306.47-9ee5987ef42e4dc988d7dcd4a4dc0bdc.tgz]
Created [https://api-an3qnndwmq-uc.a.run.app/v1/projects/my-project/builds/a33da1cc-8e3c-4579-92cd-d7bab749ba22].
Logs are available in the Cloud Console.
... snip ...
ID CREATE_TIME DURATION SOURCE IMAGES STATUS
a33da1cc-8e3c-4579-92cd-d7bab749ba22 2019-05-16T04:35:07+00:00 1M6S gs://my-project_cloudbuild/source/1557981306.47-9ee5987ef42e4dc988d7dcd4a4dc0bdc.tgz gcr.io/my-project/built SUCCESS
```
@ -65,13 +66,21 @@ statusDetail: ''
## Known differences / NYEs
- [ ] Builds are performed entirely in the context of the
`projects.builds.create` request, not by polling a long-running operation.
The `--async` flag has no effect.
- [ ] Build operations (source pulls and image pushes) are authorized using the
- Builds are performed entirely in the context of the `projects.builds.create`
request, not by polling a long-running operation. The `--async` flag has no
effect.
- Build operations (source pulls and image pushes) are authorized using the
end-user credentials, not the project's builder service account.
- [ ] Build logs are not yet written to Cloud Storage, so they're not available
via `gcloud`.
- Build logs are written to Cloud Storage in one shot, at the end of the build.
When the build request completes, `gcloud` will show all build logs at once
without streaming.
- Build logs are written to the source upload bucket, and not a separate logs
bucket as is the default in GCB.
- Builds cannot be cancelled. The client doesn't know the build ID until it's
completed.
## Not yet implemented
- [ ] `timing` is not collected or reported.
- [ ] `timeout` is not configurable. If Cloud Run request times out, client
gets a 502.
@ -79,5 +88,3 @@ statusDetail: ''
Grafeas instance.
- [ ] `projects.builds.list` is not yet implemented.
- [ ] `operations.get` and `operations.list` are not yet implemented.
- [ ] `projects.builds.cancel` is not implementable (the client doesn't get the
build ID until it's complete).

View file

@ -18,13 +18,16 @@ import (
"cloud.google.com/go/compute/metadata"
"cloud.google.com/go/datastore"
"cloud.google.com/go/storage"
"github.com/google/go-containerregistry/pkg/authn"
"github.com/google/go-containerregistry/pkg/name"
"github.com/google/go-containerregistry/pkg/v1"
"github.com/google/go-containerregistry/pkg/v1/remote"
"github.com/google/uuid"
"github.com/imjasonh/kontain.me/pkg/run"
"golang.org/x/oauth2"
gcb "google.golang.org/api/cloudbuild/v1"
"google.golang.org/api/option"
)
const base = "packs/run:v3alpha2"
@ -82,6 +85,15 @@ func extractToken(r *http.Request) string {
return r.URL.Query().Get("access_token")
}
func (s *server) logWriter(req *gcb.Build, tok string) io.WriteCloser {
ctx := context.Background() // TODO
gcs, err := storage.NewClient(ctx, option.WithTokenSource(oauth2.StaticTokenSource(&oauth2.Token{AccessToken: tok})))
if err != nil {
log.Fatalf("storage.NewClient: %v", err)
}
return gcs.Bucket(req.LogsBucket).Object(fmt.Sprintf("log-%s.txt", req.Id)).NewWriter(ctx)
}
func (s *server) ServeHTTP(w http.ResponseWriter, r *http.Request) {
s.info.Println("handler:", r.Method, r.URL)
projectID := extractPath(r.URL.Path, projectRE)
@ -275,6 +287,12 @@ func (s *server) prepareWorkspace(tok string) (string, string, error) {
func (s *server) fetchAndBuild(src, layers, tok string, req *gcb.Build) error {
image := req.Images[0]
source := fmt.Sprintf("https://storage.googleapis.com/%s/%s?access_token=%s", req.Source.StorageSource.Bucket, req.Source.StorageSource.Object, tok)
w := s.logWriter(req, tok)
defer func() {
if err := w.Close(); err != nil {
s.error.Printf("Closing GCS log: %v", err)
}
}()
for _, cmd := range []string{
fmt.Sprintf("chown -R %d:%d %s", os.Geteuid(), os.Getgid(), src),
fmt.Sprintf("chown -R %d:%d %s", os.Geteuid(), os.Getgid(), layers),
@ -284,7 +302,7 @@ func (s *server) fetchAndBuild(src, layers, tok string, req *gcb.Build) error {
fmt.Sprintf("/lifecycle/builder -layers=%s -app=%s -group=%s/group.toml -plan=%s/plan.toml", layers, src, layers, layers),
fmt.Sprintf("/lifecycle/exporter -layers=%s -helpers=false -app=%s -image=%s -group=%s/group.toml %s", layers, src, base, layers, image),
} {
if err := run.Do(s.info.Writer(), cmd); err != nil {
if err := run.Do(io.MultiWriter(s.info.Writer(), w), cmd); err != nil {
return fmt.Errorf("Running %q: %v", cmd, err)
}
}