Skip to content

Instantly share code, notes, and snippets.

@proppy
Last active August 29, 2015 14:09
Show Gist options
  • Save proppy/5b41071fb9bfeec22994 to your computer and use it in GitHub Desktop.
Save proppy/5b41071fb9bfeec22994 to your computer and use it in GitHub Desktop.
minici: a docker CI that fits in a gist

minici

minici is a docker continuous integration that fits in a gist.

TODOs

  • 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)
}
@x1ddos
Copy link

x1ddos commented Jan 5, 2015

Hey @proppy what's computeutil? Can't find it in https://github.com/GoogleCloudPlatform/gcloud-golang

@x1ddos
Copy link

x1ddos commented Jan 5, 2015

Oh, never mind. Found it :) googleapis/google-cloud-go#80

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment