minici is a docker continuous integration that fits in a gist.
- snapshot and reuse disk
- archive logs on gs
- plug with gh hooks
- deploy to appengine
- add custom tag metadata and push to the hub
- add custom test metadata and run tests
| // Copyright 2014 Google Inc. All Rights Reserved. | |
| // | |
| // Licensed under the Apache License, Version 2.0 (the "License"); | |
| // you may not use this file except in compliance with the License. | |
| // You may obtain a copy of the License at | |
| // | |
| // http://www.apache.org/licenses/LICENSE-2.0 | |
| // | |
| // Unless required by applicable law or agreed to in writing, software | |
| // distributed under the License is distributed on an "AS IS" BASIS, | |
| // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
| // See the License for the specific language governing permissions and | |
| // limitations under the License. | |
| // minici is a docker continuous integration that fits in a gist. | |
| // TODO(proppy): snapshot disk and reuse disk | |
| // TODO(proppy): archive logs on gs | |
| // TODO(proppy): plug with gh hooks | |
| // TODO(proppy): deploy to appengine | |
| // TODO(proppy): add custom tag metadata and push to the hub | |
| // TODO(proppy): aadd custom test metadata and run tests | |
| package main | |
| import ( | |
| "flag" | |
| "fmt" | |
| "io" | |
| "log" | |
| "net/http" | |
| "github.com/golang/oauth2" | |
| "github.com/golang/oauth2/google" | |
| "github.com/gorilla/mux" | |
| "google.golang.org/cloud" | |
| computeutil "google.golang.org/cloud/compute/util" | |
| ) | |
| var ( | |
| jsonFile = flag.String("j", "", "A path to your JSON key file for your service account downloaded from Google Developer Console, not needed if you run it on Compute Engine instances.") | |
| projID = flag.String("p", "", "The ID of your Google Cloud project.") | |
| namePrefix = flag.String("n", "minici", "The name prefix for instances.") | |
| image = flag.String("i", "projects/google-containers/global/images/container-vm-v20140929", "The image to use for the instance.") | |
| machineType = flag.String("m", "f1-micro", "The compute zone for the instance.") | |
| zone = flag.String("z", "us-central1-f", "The compute zone for the instance.") | |
| ) | |
| const ( | |
| startupScript = `#!/bin/bash | |
| set -ex | |
| curl_metadata() { | |
| curl -H 'Metadata-Flavor: Google' http://metadata/computeMetadata/v1/instance/attributes/$1 | |
| } | |
| GH_USER=$(curl_metadata gh_user) | |
| GH_REPO=$(curl_metadata gh_repo) | |
| GH_URL=$(curl_metadata gh_url) | |
| GH_REV=$(curl_metadata gh_rev) | |
| git clone ${GH_URL} /usr/src/${GH_REPO} | |
| cd /usr/src/${GH_REPO} && git checkout ${GH_REV} | |
| sudo docker build -t ${GH_USER}/${GH_REPO}:${GH_REV::6} /usr/src/${GH_REPO} | |
| ` | |
| ) | |
| var client *http.Client | |
| func init() { | |
| r := mux.NewRouter() | |
| http.Handle("/", r) | |
| r.HandleFunc("/{user}/{repo}/{rev}", func(w http.ResponseWriter, r *http.Request) { | |
| vars := mux.Vars(r) | |
| user, repo, rev := vars["user"], vars["repo"], vars["rev"] | |
| ctx := cloud.WithZone(cloud.NewContext(*projID, client), *zone) | |
| instanceName := fmt.Sprintf("%s-%s-%s-%s", *namePrefix, user, repo, rev[:6]) | |
| instance, err := computeutil.GetInstance(ctx, instanceName) | |
| if err != nil { | |
| log.Printf("create instance %q", instanceName) | |
| instance, err = computeutil.NewInstance(ctx, &computeutil.Instance{ | |
| Name: instanceName, | |
| Image: *image, | |
| MachineType: *machineType, | |
| Metadata: map[string]string{ | |
| "startup-script": startupScript, | |
| "gh_user": user, | |
| "gh_repo": repo, | |
| "gh_rev": rev, | |
| "gh_url": fmt.Sprintf("https://github.com/%s/%s", user, repo), | |
| }, | |
| }) | |
| if err != nil { | |
| http.Error(w, fmt.Sprintf("error creating instance %q: %v", instanceName, err), http.StatusInternalServerError) | |
| return | |
| } | |
| } | |
| log.Printf("instance %q: %#v", instanceName, instance) | |
| io.Copy(w, instance.SerialPortOutput(ctx)) | |
| }) | |
| } | |
| func main() { | |
| flag.Parse() | |
| if *jsonFile == "" || *projID == "" { | |
| flag.PrintDefaults() | |
| log.Fatalf("missing json credentials or project id.") | |
| } | |
| flow, err := oauth2.New( | |
| google.ServiceAccountJSONKey(*jsonFile), | |
| oauth2.Scope(computeutil.ScopeCompute), | |
| ) | |
| if err != nil { | |
| log.Fatalf("error creating oauth2 flow from %q: %v", jsonFile, err) | |
| } | |
| client = &http.Client{Transport: flow.NewTransport()} | |
| http.ListenAndServe(":8080", nil) | |
| } |
Hey @proppy what's
computeutil? Can't find it in https://github.com/GoogleCloudPlatform/gcloud-golang