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