cmd/tip: add a cert cache, clean up Kubernetes config, use update-deps

Fixes expired cert issue too, either by virtue of newer autocert, or
that we're no longer hitting some LetsEncrypt rate limit.

But we have a cache now at least, so we should be nicer to LetsEncrypt
when the process dies. I did see some process crashes (old?) in the
logs. So maybe we were crashing and re-hitting LE often.

Verified that the cert now expires:
    Sunday, October 29, 2017 at 9:57:00 PM Pacific
and that it's cached in GCS.

Fixes golang/go#21251

Change-Id: I3def551ae8eef5df0ec7c51927c4d4bb52cd7a6a
Reviewed-on: https://go-review.googlesource.com/52390
Reviewed-by: Chris Broadfoot <cbro@golang.org>
Reviewed-by: Jessie Frazelle <me@jessfraz.com>
Run-TryBot: Jessie Frazelle <me@jessfraz.com>
diff --git a/cmd/tip/Dockerfile b/cmd/tip/Dockerfile
index 9c80137..3604d52 100644
--- a/cmd/tip/Dockerfile
+++ b/cmd/tip/Dockerfile
@@ -5,7 +5,124 @@
 # golang puts its go install here (weird but true)
 ENV GOROOT_BOOTSTRAP /usr/local/go
 
-RUN go get -d golang.org/x/crypto/acme/autocert
+# BEGIN deps (run `make update-deps` to update)
+
+# Repo cloud.google.com/go at 76d607c (2017-07-20)
+ENV REV=76d607c4e7a2b9df49f1d1a58a3f3d2dd2614704
+RUN go get -d cloud.google.com/go/compute/metadata `#and 6 other pkgs` &&\
+    (cd /go/src/cloud.google.com/go && (git cat-file -t $REV 2>/dev/null || git fetch -q origin $REV) && git reset --hard $REV)
+
+# Repo github.com/golang/protobuf at 0a4f71a (2017-07-11)
+ENV REV=0a4f71a498b7c4812f64969510bcb4eca251e33a
+RUN go get -d github.com/golang/protobuf/proto `#and 6 other pkgs` &&\
+    (cd /go/src/github.com/golang/protobuf && (git cat-file -t $REV 2>/dev/null || git fetch -q origin $REV) && git reset --hard $REV)
+
+# Repo github.com/googleapis/gax-go at 84ed267 (2017-06-10)
+ENV REV=84ed26760e7f6f80887a2fbfb50db3cc415d2cea
+RUN go get -d github.com/googleapis/gax-go &&\
+    (cd /go/src/github.com/googleapis/gax-go && (git cat-file -t $REV 2>/dev/null || git fetch -q origin $REV) && git reset --hard $REV)
+
+# Repo golang.org/x/build at da1460b (2017-07-31)
+ENV REV=da1460b7c9c9b65383d1336593ed9ad346f6a1c5
+RUN go get -d golang.org/x/build/autocertcache &&\
+    (cd /go/src/golang.org/x/build && (git cat-file -t $REV 2>/dev/null || git fetch -q origin $REV) && git reset --hard $REV)
+
+# Repo golang.org/x/crypto at 6914964 (2017-07-20)
+ENV REV=6914964337150723782436d56b3f21610a74ce7b
+RUN go get -d golang.org/x/crypto/acme `#and 2 other pkgs` &&\
+    (cd /go/src/golang.org/x/crypto && (git cat-file -t $REV 2>/dev/null || git fetch -q origin $REV) && git reset --hard $REV)
+
+# Repo golang.org/x/net at ab54850 (2017-07-21)
+ENV REV=ab5485076ff3407ad2d02db054635913f017b0ed
+RUN go get -d golang.org/x/net/context `#and 8 other pkgs` &&\
+    (cd /go/src/golang.org/x/net && (git cat-file -t $REV 2>/dev/null || git fetch -q origin $REV) && git reset --hard $REV)
+
+# Repo golang.org/x/oauth2 at b53b38a (2017-07-19)
+ENV REV=b53b38ad8a6435bd399ea76d0fa74f23149cca4e
+RUN go get -d golang.org/x/oauth2 `#and 5 other pkgs` &&\
+    (cd /go/src/golang.org/x/oauth2 && (git cat-file -t $REV 2>/dev/null || git fetch -q origin $REV) && git reset --hard $REV)
+
+# Repo golang.org/x/text at 836efe4 (2017-07-14)
+ENV REV=836efe42bb4aa16aaa17b9c155d8813d336ed720
+RUN go get -d golang.org/x/text/secure/bidirule `#and 4 other pkgs` &&\
+    (cd /go/src/golang.org/x/text && (git cat-file -t $REV 2>/dev/null || git fetch -q origin $REV) && git reset --hard $REV)
+
+# Repo google.golang.org/api at 295e4bb (2017-07-18)
+ENV REV=295e4bb0ade057ae2cfb9876ab0b54635dbfcea4
+RUN go get -d google.golang.org/api/gensupport `#and 9 other pkgs` &&\
+    (cd /go/src/google.golang.org/api && (git cat-file -t $REV 2>/dev/null || git fetch -q origin $REV) && git reset --hard $REV)
+
+# Repo google.golang.org/genproto at b0a3dcf (2017-07-12)
+ENV REV=b0a3dcfcd1a9bd48e63634bd8802960804cf8315
+RUN go get -d google.golang.org/genproto/googleapis/api/annotations `#and 3 other pkgs` &&\
+    (cd /go/src/google.golang.org/genproto && (git cat-file -t $REV 2>/dev/null || git fetch -q origin $REV) && git reset --hard $REV)
+
+# Repo google.golang.org/grpc at fa1cb32 (2017-07-31)
+ENV REV=fa1cb32dc4f81e23ab862dd5e7ac4f2920a33088
+RUN go get -d google.golang.org/grpc `#and 14 other pkgs` &&\
+    (cd /go/src/google.golang.org/grpc && (git cat-file -t $REV 2>/dev/null || git fetch -q origin $REV) && git reset --hard $REV)
+
+# Optimization to speed up iterative development, not necessary for correctness:
+RUN go install cloud.google.com/go/compute/metadata \
+	cloud.google.com/go/iam \
+	cloud.google.com/go/internal \
+	cloud.google.com/go/internal/optional \
+	cloud.google.com/go/internal/version \
+	cloud.google.com/go/storage \
+	github.com/golang/protobuf/proto \
+	github.com/golang/protobuf/protoc-gen-go/descriptor \
+	github.com/golang/protobuf/ptypes \
+	github.com/golang/protobuf/ptypes/any \
+	github.com/golang/protobuf/ptypes/duration \
+	github.com/golang/protobuf/ptypes/timestamp \
+	github.com/googleapis/gax-go \
+	golang.org/x/build/autocertcache \
+	golang.org/x/crypto/acme \
+	golang.org/x/crypto/acme/autocert \
+	golang.org/x/net/context \
+	golang.org/x/net/context/ctxhttp \
+	golang.org/x/net/http2 \
+	golang.org/x/net/http2/hpack \
+	golang.org/x/net/idna \
+	golang.org/x/net/internal/timeseries \
+	golang.org/x/net/lex/httplex \
+	golang.org/x/net/trace \
+	golang.org/x/oauth2 \
+	golang.org/x/oauth2/google \
+	golang.org/x/oauth2/internal \
+	golang.org/x/oauth2/jws \
+	golang.org/x/oauth2/jwt \
+	golang.org/x/text/secure/bidirule \
+	golang.org/x/text/transform \
+	golang.org/x/text/unicode/bidi \
+	golang.org/x/text/unicode/norm \
+	google.golang.org/api/gensupport \
+	google.golang.org/api/googleapi \
+	google.golang.org/api/googleapi/internal/uritemplates \
+	google.golang.org/api/googleapi/transport \
+	google.golang.org/api/internal \
+	google.golang.org/api/iterator \
+	google.golang.org/api/option \
+	google.golang.org/api/storage/v1 \
+	google.golang.org/api/transport/http \
+	google.golang.org/genproto/googleapis/api/annotations \
+	google.golang.org/genproto/googleapis/iam/v1 \
+	google.golang.org/genproto/googleapis/rpc/status \
+	google.golang.org/grpc \
+	google.golang.org/grpc/codes \
+	google.golang.org/grpc/credentials \
+	google.golang.org/grpc/grpclb/grpc_lb_v1 \
+	google.golang.org/grpc/grpclog \
+	google.golang.org/grpc/internal \
+	google.golang.org/grpc/keepalive \
+	google.golang.org/grpc/metadata \
+	google.golang.org/grpc/naming \
+	google.golang.org/grpc/peer \
+	google.golang.org/grpc/stats \
+	google.golang.org/grpc/status \
+	google.golang.org/grpc/tap \
+	google.golang.org/grpc/transport
+# END deps.
 
 # golang sets GOPATH=/go
 ADD . /go/src/tip
diff --git a/cmd/tip/Makefile b/cmd/tip/Makefile
index 5844307..7d2f6ed 100644
--- a/cmd/tip/Makefile
+++ b/cmd/tip/Makefile
@@ -2,7 +2,11 @@
 # Use of this source code is governed by a BSD-style
 # license that can be found in the LICENSE file.
 
-VERSION=v1
+VERSION=v2
+
+update-deps:
+	go install golang.org/x/build/cmd/gitlock
+	gitlock --update=Dockerfile --ignore=NONE golang.org/x/tools/cmd/tip
 
 docker-prod: Dockerfile
 	docker build -f Dockerfile --tag=gcr.io/symbolic-datum-552/tip:$(VERSION) .
@@ -10,6 +14,6 @@
 	docker build -f Dockerfile --tag=gcr.io/go-dashboard-dev/tip:$(VERSION) .
 
 push-prod: docker-prod
-	gcloud docker push -- gcr.io/symbolic-datum-552/tip:$(VERSION)
+	gcloud docker -- push gcr.io/symbolic-datum-552/tip:$(VERSION)
 push-dev: docker-dev
-	gcloud docker push -- gcr.io/go-dashboard-dev/tip:$(VERSION)
+	gcloud docker -- push gcr.io/go-dashboard-dev/tip:$(VERSION)
diff --git a/cmd/tip/tip-rc.yaml b/cmd/tip/tip-rc.yaml
index 139e614..82af3b7 100644
--- a/cmd/tip/tip-rc.yaml
+++ b/cmd/tip/tip-rc.yaml
@@ -1,7 +1,7 @@
 apiVersion: v1
 kind: ReplicationController
 metadata:
-  name: tipgodoc-v1
+  name: tipgodoc
 spec:
   replicas: 1
   selector:
@@ -17,9 +17,9 @@
         emptyDir: {}
       containers:
       - name: gitmirror
-        image: gcr.io/symbolic-datum-552/tip:v1
+        image: gcr.io/symbolic-datum-552/tip:v2
         imagePullPolicy: Always
-        command: ["/go/bin/tip", "--autocert=tip.golang.org"]
+        command: ["/go/bin/tip", "--autocert=tip.golang.org", "--autocert-bucket=golang-tip-autocert"]
         env:
         - name: TMPDIR
           value: /build
diff --git a/cmd/tip/tip.go b/cmd/tip/tip.go
index 428bcf0..30f1864 100644
--- a/cmd/tip/tip.go
+++ b/cmd/tip/tip.go
@@ -8,6 +8,7 @@
 
 import (
 	"bufio"
+	"context"
 	"crypto/tls"
 	"encoding/json"
 	"errors"
@@ -25,6 +26,8 @@
 	"sync"
 	"time"
 
+	"cloud.google.com/go/storage"
+	"golang.org/x/build/autocertcache"
 	"golang.org/x/crypto/acme/autocert"
 )
 
@@ -37,7 +40,8 @@
 var startTime = time.Now()
 
 var (
-	autoCertDomain = flag.String("autocert", "", "if non-empty, listen on port 443 and serve a LetsEncrypt cert for this hostname")
+	autoCertDomain      = flag.String("autocert", "", "if non-empty, listen on port 443 and serve a LetsEncrypt cert for this hostname")
+	autoCertCacheBucket = flag.String("autocert-bucket", "", "if non-empty, the Google Cloud Storage bucket in which to store the LetsEncrypt cache")
 )
 
 func main() {
@@ -67,9 +71,18 @@
 	}()
 	if *autoCertDomain != "" {
 		log.Printf("Listening on port 443 with LetsEncrypt support on domain %q", *autoCertDomain)
+		var cache autocert.Cache
+		if b := *autoCertCacheBucket; b != "" {
+			sc, err := storage.NewClient(context.Background())
+			if err != nil {
+				log.Fatalf("storage.NewClient: %v", err)
+			}
+			cache = autocertcache.NewGoogleCloudStorageCache(sc, b)
+		}
 		m := autocert.Manager{
 			Prompt:     autocert.AcceptTOS,
 			HostPolicy: autocert.HostWhitelist(*autoCertDomain),
+			Cache:      cache,
 		}
 		s := &http.Server{
 			Addr:      ":https",