Repository: fortio/fortio
Pull request #363 (2020-06-19 21:59:42)

Switching to go1.14 and go modules and update all dependencies
No more vendor/ toml or dep
Switched version to 2.0.0 to indicate breaking compatibility with go1.8 which was maintained up to 1.3.1
updated to the latest grpc (1.29.1) and other dependencies

codeclimate[bot]: Code Climate has analyzed commit 1def1942 and detected **0 issues** on this pull request.

View more on [Code Climate](https://codeclimate.com/github/fortio/fortio/pull/363).

ldemailly: docker cloud build seems to be failing because it's using vendor/ for no reason (there is no more submodule but it seems to keep it anyway)

Patch:
diff --git a/.circleci/config.yml b/.circleci/config.yml
index b06bdf8..9c8c298 100644
--- a/.circleci/config.yml
+++ b/.circleci/config.yml
@@ -7,7 +7,7 @@ version: 2
 defaultEnv: &defaultEnv
     docker:
       # specify the version
-      - image: docker.io/fortio/fortio.build:v13
+      - image: docker.io/fortio/fortio.build:v20
     working_directory: /go/src/fortio.org/fortio
 
 jobs:
@@ -15,7 +15,6 @@ jobs:
     <<: *defaultEnv
     steps:
       - checkout
-      - run: make submodule
       - run: make test
   release-tests:
     <<: *defaultEnv
@@ -23,20 +22,17 @@ jobs:
       - setup_remote_docker:
           version: 17.11.0-ce
       - checkout
-      - run: make submodule
       - run: make release-test
   linters:
     <<: *defaultEnv
     steps:
       - checkout
-      - run: make submodule
       # If ran with default we get random errors because OOM killer kills some linters
       - run: make install local-lint  DEBUG_LINTERS="--concurrency=2"
   codecov:
     <<: *defaultEnv
     steps:
       - checkout
-      - run: make submodule
       - run: make coverage
 
 workflows:
diff --git a/.gitmodules b/.gitmodules
index 4d1a5fe..e69de29 100644
--- a/.gitmodules
+++ b/.gitmodules
@@ -1,4 +0,0 @@
-[submodule "vendor"]
-	path = vendor
-	url = https://github.com/fortio/vendor-fortio.git
-	branch = master
diff --git a/Dockerfile b/Dockerfile
index 0c7e950..4d65d96 100644
--- a/Dockerfile
+++ b/Dockerfile
@@ -1,16 +1,12 @@
 # Build the binaries in larger image
-FROM docker.io/fortio/fortio.build:v13 as build
+FROM docker.io/fortio/fortio.build:v20 as build
 WORKDIR /go/src/fortio.org
 COPY . fortio
-# Submodule handling
-RUN make -C fortio submodule
 # We moved a lot of the logic into the Makefile so it can be reused in brew
 # but that also couples the 2, this expects to find binaries in the right place etc
 RUN make -C fortio official-build-version BUILD_DIR=/build OFFICIAL_BIN=../fortio_go_latest.bin
 # Check we still build with go 1.8 (and macos does not break)
-RUN make -C fortio official-build BUILD_DIR=/build OFFICIAL_BIN=../fortio_go1.8.mac GOOS=darwin GO_BIN=/usr/local/go/bin/go
-# Optionally (comment out) Build with 1.8 for perf comparison
-# RUN make -C fortio official-build-version BUILD_DIR= OFFICIAL_BIN=../fortio_go1.8.bin GO_BIN=/usr/local/go/bin/go
+RUN make -C fortio official-build BUILD_DIR=/build OFFICIAL_BIN=../fortio_go_latest.mac GOOS=darwin GO_BIN=/usr/local/go/bin/go
 # Just check it stays compiling on Windows (would need to set the rsrcDir too)
 RUN make -C fortio official-build BUILD_DIR=/build OFFICIAL_BIN=../fortio.exe GOOS=windows
 # Minimal image with just the binary and certs
@@ -20,8 +16,6 @@ COPY --from=build /etc/ssl/certs/ca-certificates.crt /etc/ssl/certs/
 # TODO: get rid of *.bak, *~ and other spurious non source files
 COPY --from=build /go/src/fortio.org/fortio/ui/static /usr/share/fortio/static
 COPY --from=build /go/src/fortio.org/fortio/ui/templates /usr/share/fortio/templates
-#COPY --from=build /go/src/fortio.org/fortio_go_latest.bin /usr/bin/fortio_go_latest
-#COPY --from=build /go/src/fortio.org/fortio_go1.8.bin /usr/bin/fortio_go1.8
 COPY --from=build /go/src/fortio.org/fortio_go_latest.bin /usr/bin/fortio
 EXPOSE 8079
 EXPOSE 8080
diff --git a/Dockerfile.build b/Dockerfile.build
index fd5e858..67ff701 100644
--- a/Dockerfile.build
+++ b/Dockerfile.build
@@ -1,33 +1,21 @@
 # Dependencies and linters for build:
-FROM ubuntu:xenial
+FROM ubuntu:focal
 # Need gcc for -race test (and some linters though those work with CGO_ENABLED=0)
 RUN apt-get -y update && \
   apt-get --no-install-recommends -y upgrade && \
-  apt-get --no-install-recommends -y install ca-certificates curl make git gcc \
-  libc6-dev apt-transport-https ssh ruby-dev build-essential rpm
+  DEBIAN_FRONTEND=noninteractive apt-get --no-install-recommends -y install ca-certificates curl make git gcc \
+  libc6-dev apt-transport-https ssh ruby-dev build-essential rpm gnupg
 # Install FPM
-RUN gem install --no-ri --no-rdoc fpm
-# Install both go1.11 [go1.10.3] and go1.8.7 so we don't become incompatible with 1.8
-RUN curl -f https://storage.googleapis.com/golang/go1.8.7.linux-amd64.tar.gz | tar xfz - -C /usr/local
-# Newer go have no problem with being installed in random directories without requiring GOROOT so we
-# leave the old go in /usr/local and put the new ones, despite being preferred, in a different root:
-# No report of issues with 1.11 so far so skipping 1.10
-#RUN mkdir /go1.10
-#RUN curl -f https://dl.google.com/go/go1.10.4.linux-amd64.tar.gz | tar xfz - -C /go1.10
-RUN mkdir /go1.11
-RUN curl -f https://dl.google.com/go/go1.11.5.linux-amd64.tar.gz | tar xfz - -C /go1.11
+RUN gem install --no-document fpm
+# From fortio 2.0 we dropped go 1.8 compatibility
+RUN curl -f https://dl.google.com/go/go1.14.4.linux-amd64.tar.gz | tar xfz - -C /usr/local
 ENV GOPATH /go
 RUN mkdir -p $GOPATH/bin
-# We do pick the latest go first in the path
-ENV PATH /go1.11/go/bin:/usr/local/go/bin:$PATH:$GOPATH/bin
+ENV PATH /usr/local/go/bin:$PATH:$GOPATH/bin
 RUN go version # check it's indeed the version we expect
-# This is now handled through dep and vendor submodule
-# RUN go get -u google.golang.org/grpc
-# Install dep
-RUN curl https://raw.githubusercontent.com/golang/dep/master/install.sh | sh
 # Install meta linters
 RUN go get -u github.com/alecthomas/gometalinter
-RUN gometalinter -i -u
+RUN gometalinter -i
 WORKDIR /go/src/fortio.org
 # Docker:
 RUN curl -fsSL "https://download.docker.com/linux/ubuntu/gpg" | apt-key add
diff --git a/Dockerfile.echosrv b/Dockerfile.echosrv
index 902fc63..605b4cd 100644
--- a/Dockerfile.echosrv
+++ b/Dockerfile.echosrv
@@ -1,5 +1,5 @@
 # Build the binaries in larger image
-FROM docker.io/fortio/fortio.build:v13 as build
+FROM docker.io/fortio/fortio.build:v20 as build
 WORKDIR /go/src/fortio.org
 COPY . fortio
 RUN make -C fortio official-build-version BUILD_DIR=/build OFFICIAL_TARGET=fortio.org/fortio/echosrv OFFICIAL_BIN=../echosrv.bin
diff --git a/Dockerfile.fcurl b/Dockerfile.fcurl
index b4dc63d..e79c7e7 100644
--- a/Dockerfile.fcurl
+++ b/Dockerfile.fcurl
@@ -1,5 +1,5 @@
 # Build the binaries in larger image
-FROM docker.io/fortio/fortio.build:v13 as build
+FROM docker.io/fortio/fortio.build:v20 as build
 WORKDIR /go/src/fortio.org
 COPY . fortio
 # fcurl should not need vendor/no dependencies
diff --git a/Gopkg.lock b/Gopkg.lock
deleted file mode 100644
index db3ed03..0000000
--- a/Gopkg.lock
+++ /dev/null
@@ -1,125 +0,0 @@
-# This file is autogenerated, do not edit; changes may be undone by the next 'dep ensure'.
-
-
-[[projects]]
-  digest = "1:5ae5b54d7cd695bafa92bf426b7c3d046f907260ec0fcb4fe5c368d937597c00"
-  name = "github.com/golang/protobuf"
-  packages = [
-    "proto",
-    "protoc-gen-go/descriptor",
-    "ptypes",
-    "ptypes/any",
-    "ptypes/duration",
-    "ptypes/timestamp",
-  ]
-  pruneopts = "NUT"
-  revision = "aa810b61a9c79d51363740d207bb46cf8e620ed5"
-  version = "v1.2.0"
-
-[[projects]]
-  digest = "1:fef1e6ae1eb8ada90ce7bd138db294fe4c6c84169c7233944e75be2b3af54662"
-  name = "golang.org/x/net"
-  packages = [
-    "context",
-    "http/httpguts",
-    "http2",
-    "http2/hpack",
-    "idna",
-    "internal/timeseries",
-    "trace",
-  ]
-  pruneopts = "NUT"
-  revision = "c44066c5c816ec500d459a2a324a753f78531ae0"
-
-[[projects]]
-  branch = "master"
-  digest = "1:46a9ac711b02534a076654f721b3fcec4afa658dce559762177b1508b52578b9"
-  name = "golang.org/x/sys"
-  packages = ["unix"]
-  pruneopts = "NUT"
-  revision = "41f3e6584952bb034a481797859f6ab34b6803bd"
-
-[[projects]]
-  digest = "1:e7071ed636b5422cc51c0e3a6cebc229d6c9fffc528814b519a980641422d619"
-  name = "golang.org/x/text"
-  packages = [
-    "collate",
-    "collate/build",
-    "internal/colltab",
-    "internal/gen",
-    "internal/tag",
-    "internal/triegen",
-    "internal/ucd",
-    "language",
-    "secure/bidirule",
-    "transform",
-    "unicode/bidi",
-    "unicode/cldr",
-    "unicode/norm",
-    "unicode/rangetable",
-  ]
-  pruneopts = "NUT"
-  revision = "f21a4dfb5e38f5895301dc265a8def02365cc3d0"
-  version = "v0.3.0"
-
-[[projects]]
-  branch = "master"
-  digest = "1:077c1c599507b3b3e9156d17d36e1e61928ee9b53a5b420f10f28ebd4a0b275c"
-  name = "google.golang.org/genproto"
-  packages = ["googleapis/rpc/status"]
-  pruneopts = "NUT"
-  revision = "4b09977fb92221987e99d190c8f88f2c92727a29"
-
-[[projects]]
-  digest = "1:d875a2689e969ed607d0f89cc17535a8186cf988095de31c11d0436f6146291b"
-  name = "google.golang.org/grpc"
-  packages = [
-    ".",
-    "balancer",
-    "balancer/base",
-    "balancer/roundrobin",
-    "codes",
-    "connectivity",
-    "credentials",
-    "encoding",
-    "encoding/proto",
-    "grpclog",
-    "health",
-    "health/grpc_health_v1",
-    "internal",
-    "internal/backoff",
-    "internal/channelz",
-    "internal/envconfig",
-    "internal/grpcrand",
-    "internal/transport",
-    "keepalive",
-    "metadata",
-    "naming",
-    "peer",
-    "reflection",
-    "reflection/grpc_reflection_v1alpha",
-    "resolver",
-    "resolver/dns",
-    "resolver/passthrough",
-    "stats",
-    "status",
-    "tap",
-  ]
-  pruneopts = "NUT"
-  revision = "2e463a05d100327ca47ac218281906921038fd95"
-  version = "v1.16.0"
-
-[solve-meta]
-  analyzer-name = "dep"
-  analyzer-version = 1
-  input-imports = [
-    "github.com/golang/protobuf/proto",
-    "golang.org/x/net/context",
-    "google.golang.org/grpc",
-    "google.golang.org/grpc/credentials",
-    "google.golang.org/grpc/health",
-    "google.golang.org/grpc/health/grpc_health_v1",
-    "google.golang.org/grpc/reflection",
-  ]
-  solver-name = "gps-cdcl"
-  solver-version = 1
diff --git a/Gopkg.toml b/Gopkg.toml
deleted file mode 100644
index 6c54ac4..0000000
--- a/Gopkg.toml
+++ /dev/null
@@ -1,25 +0,0 @@
-# Gopkg.toml
-#
-# Initially from "dep init"
-#
-
-# DO NOT ADD MORE DEPENDENCIES TO FORTIO
-
-[[constraint]]
-  name = "github.com/golang/protobuf"
-  version = "1.2.0"
-
-[[constraint]]
-  revision = "c44066c5c816ec500d459a2a324a753f78531ae0" # before go 1.8 support drop
-  name = "golang.org/x/net"
-
-[[constraint]]
-  name = "google.golang.org/grpc"
-  version = "=1.16.0" # 1.17 removes go 1.8 support
-
-# Minimize vendor/
-
-[prune]
-  go-tests = true
-  unused-packages = true
-  non-go = true
diff --git a/Makefile b/Makefile
index d690f7d..9d176ad 100755
--- a/Makefile
+++ b/Makefile
@@ -7,7 +7,7 @@
 IMAGES=echosrv fcurl # plus the combo image / Dockerfile without ext.
 
 DOCKER_PREFIX := docker.io/fortio/fortio
-BUILD_IMAGE_TAG := v13
+BUILD_IMAGE_TAG := v20
 BUILD_IMAGE := $(DOCKER_PREFIX).build:$(BUILD_IMAGE_TAG)
 
 TAG:=$(USER)$(shell date +%y%m%d_%H%M%S)
@@ -22,15 +22,14 @@ CERT_TEMP_DIR := ./cert-tmp/
 # ps: can't use go list (and get packages as canonical fortio.org/fortio/x)
 # as somehow that makes gometaliner silently not find/report errors...
 PACKAGES ?= $(shell find . -type d -print | egrep -v "/(\.|vendor|tmp|static|templates|release|docs|json|cert-tmp|debian)")
-# Marker for whether vendor submodule is here or not already
-GRPC_DIR:=./vendor/google.golang.org/grpc
+# from fortio 1.4 we use go 1.14 (from go 1.8 up to fortio 1.3) and switched to go modules (from vendor)
 
 # Local targets:
-go-install: submodule
+go-install:
 	go install $(PACKAGES)
 
 # Run/test dependencies
-dependencies: submodule certs
+dependencies: certs
 
 # Only generate certs if needed
 certs: $(CERT_TEMP_DIR)/server.cert
@@ -52,7 +51,7 @@ test: dependencies
 # To debug strange linter errors, uncomment
 # DEBUG_LINTERS="--debug"
 
-local-lint: dependencies vendor.check
+local-lint: dependencies
 	gometalinter $(DEBUG_LINTERS) \
 	--deadline=180s --enable-all --aggregate --exclude=.pb.go \
 	--disable=gocyclo --disable=gas --disable=gosec \
@@ -81,47 +80,9 @@ coverage: dependencies
 	./.circleci/coverage.sh
 	curl -s https://codecov.io/bash | bash
 
-# Submodule handling when not already there
-submodule: $(GRPC_DIR)
-
-$(GRPC_DIR):
-	$(MAKE) submodule-sync
-
-# If you want to force update/sync, invoke 'make submodule-sync' directly
-submodule-sync:
-	git submodule sync
-	git submodule update --init
-
 # Short cut for pulling/updating to latest of the current branch
 pull:
 	git pull
-	$(MAKE) submodule-sync
-
-# https://github.com/istio/vendor-istio#how-do-i-add--change-a-dependency
-# PS: for fortio no dependencies should be added, only grpc updated.
-depend.status:
-	@echo "No error means your Gopkg.* are in sync and ok with vendor/"
-	dep status
-	cp Gopkg.* vendor/
-
-depend.update.full: depend.cleanlock depend.update
-
-depend.cleanlock:
-	-rm Gopkg.lock
-
-depend.update:
-	@echo "Running dep ensure with DEPARGS=$(DEPARGS)"
-	time dep ensure $(DEPARGS)
-	cp Gopkg.* vendor/
-	@echo "now check the diff in vendor/ and make a PR"
-
-vendor.check:
-	@echo "Checking that Gopkg.* are in sync with vendor/ submodule:"
-	@echo "if this fails, 'make pull' and/or seek on-call help"
-	diff Gopkg.toml vendor/
-	diff Gopkg.lock vendor/
-
-.PHONY: depend.status depend.cleanlock depend.update depend.update.full vendor.check
 
 
 # Docker: Pushes the combo image and the smaller image(s)
@@ -140,6 +101,7 @@ update-build-image:
 	$(MAKE) docker-push-internal IMAGE=.build TAG=$(BUILD_IMAGE_TAG)
 
 update-build-image-tag:
+	@echo 'Need to use gnu sed (brew install gnu-sed; PATH="/usr/local/opt/gnu-sed/libexec/gnubin:$$PATH")'
 	sed --in-place=.bak -e 's!$(DOCKER_PREFIX).build:v..!$(BUILD_IMAGE)!g' $(FILES_WITH_IMAGE)
 
 docker-version:
@@ -161,7 +123,7 @@ release: dist
 
 .PHONY: go-install lint install-linters coverage webtest release-test update-build-image
 
-.PHONY: local-lint update-build-image-tag release submodule submodule-sync pull certs certs-clean
+.PHONY: local-lint update-build-image-tag release pull certs certs-clean
 
 # Targets used for official builds (initially from Dockerfile)
 BUILD_DIR := /tmp/fortio_build
@@ -203,7 +165,7 @@ official-build-version: official-build
 official-build-clean:
 	-$(RM) $(BUILD_DIR)/build-info.txt $(BUILD_DIR)/link-flags.txt $(OFFICIAL_BIN) release/Makefile
 
-# Create a complete source tree (including submodule) with naming matching debian package conventions
+# Create a complete source tree with naming matching debian package conventions
 TAR ?= tar # on macos need gtar to get --owner
 DIST_VERSION ?= $(shell echo $(GIT_TAG) | sed -e "s/^v//")
 DIST_PATH:=release/fortio_$(DIST_VERSION).orig.tar
@@ -216,10 +178,10 @@ release/Makefile: release/Makefile.dist
 	echo "GIT_SHA := $(GIT_SHA)" >> $@
 	cat $< >> $@
 
-dist: submodule release/Makefile
+dist: release/Makefile
 	# put the source files where they can be used as gopath by go,
 	# except leave the debian dir where it needs to be (below the version dir)
-	git ls-files --recurse-submodules \
+	git ls-files \
 		| awk '{printf("src/fortio.org/fortio/%s\n", $$0)}' \
 		| (cd ../../.. ; $(TAR) \
 		--xform="s|^src|fortio-$(DIST_VERSION)/src|;s|^.*debian/|fortio-$(DIST_VERSION)/debian/|" \
diff --git a/debian/changelog b/debian/changelog
index 5619986..c391568 100644
--- a/debian/changelog
+++ b/debian/changelog
@@ -1,3 +1,9 @@
+fortio (1.4.0-1) unstable; urgency=medium
+
+  * Switch to go modules and go 1.14 and newest grpc
+
+ -- Laurent Demailly <ldemailly@gmail.com>  Fri Jun 19 15:31:12 PDT 2020
+
 fortio (1.3.1-1) unstable; urgency=medium
 
   * Bump for 1.3.1
diff --git a/fgrpc/grpcrunner.go b/fgrpc/grpcrunner.go
index 2e37c71..ff5ca98 100644
--- a/fgrpc/grpcrunner.go
+++ b/fgrpc/grpcrunner.go
@@ -58,8 +58,8 @@ func Dial(o *GRPCRunnerOptions) (conn *grpc.ClientConn, err error) {
 	serverAddr := grpcDestination(o.Destination)
 	if o.UnixDomainSocket != "" {
 		log.Warnf("Using domain socket %v instead of %v for grpc connection", o.UnixDomainSocket, serverAddr)
-		opts = append(opts, grpc.WithDialer(func(addr string, timeout time.Duration) (net.Conn, error) {
-			return net.DialTimeout(fnet.UnixDomainSocket, o.UnixDomainSocket, timeout)
+		opts = append(opts, grpc.WithContextDialer(func(ctx context.Context, addr string) (net.Conn, error) {
+			return net.Dial(fnet.UnixDomainSocket, o.UnixDomainSocket)
 		}))
 	}
 	conn, err = grpc.Dial(serverAddr, opts...)
diff --git a/go.mod b/go.mod
new file mode 100644
index 0000000..faa3397
--- /dev/null
+++ b/go.mod
@@ -0,0 +1,12 @@
+module fortio.org/fortio
+
+go 1.14
+
+require (
+	github.com/golang/protobuf v1.4.2
+	golang.org/x/net v0.0.0-20200602114024-627f9648deb9
+	golang.org/x/sys v0.0.0-20200615200032-f1bc736245b1 // indirect
+	golang.org/x/text v0.3.3 // indirect
+	google.golang.org/genproto v0.0.0-20200619004808-3e7fca5c55db // indirect
+	google.golang.org/grpc v1.29.1
+)
diff --git a/go.sum b/go.sum
new file mode 100644
index 0000000..6432072
--- /dev/null
+++ b/go.sum
@@ -0,0 +1,83 @@
+cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
+github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
+github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
+github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
+github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc=
+github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
+github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
+github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98=
+github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=
+github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
+github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
+github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
+github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
+github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw=
+github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8=
+github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA=
+github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs=
+github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w=
+github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0=
+github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QDs8UjoX8=
+github.com/golang/protobuf v1.4.2 h1:+Z5KGCizgyZCbGh1KZqA0fcLLkwbsjIzS4aV2v7wJX0=
+github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
+github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M=
+github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
+github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
+github.com/google/go-cmp v0.4.0 h1:xsAVV57WRhGj6kEIi8ReJzQlHHqcBYCElAvkovg3B/4=
+github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
+github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
+golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
+golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
+golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
+golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU=
+golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
+golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
+golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
+golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
+golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
+golang.org/x/net v0.0.0-20200602114024-627f9648deb9 h1:pNX+40auqi2JqRfOP1akLGtYcn15TUbkhwuCO3foqqM=
+golang.org/x/net v0.0.0-20200602114024-627f9648deb9/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
+golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
+golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
+golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
+golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
+golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
+golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
+golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20200615200032-f1bc736245b1 h1:ogLJMz+qpzav7lGMh10LMvAkM/fAoGlaiiHYiFYdm80=
+golang.org/x/sys v0.0.0-20200615200032-f1bc736245b1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
+golang.org/x/text v0.3.3 h1:cokOdA+Jmi5PJGXLlLllQSgYigAEfHXJAERHVMaCc2k=
+golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
+golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
+golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
+golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY=
+golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
+golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
+golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4=
+golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
+google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=
+google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
+google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
+google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc=
+google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo=
+google.golang.org/genproto v0.0.0-20200619004808-3e7fca5c55db h1:Q5+mRMPseAnmi+ah5YkFXuVnZqUTgxmQF6e4PnjSkcE=
+google.golang.org/genproto v0.0.0-20200619004808-3e7fca5c55db/go.mod h1:jDfRM7FcilCzHH/e9qn6dsT145K34l5v+OpcnNgKAAA=
+google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
+google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg=
+google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY=
+google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=
+google.golang.org/grpc v1.29.1 h1:EC2SB8S04d2r73uptxphDSUG+kTKVgjRPF+N3xpxRB4=
+google.golang.org/grpc v1.29.1/go.mod h1:itym6AZVZYACWQqET3MqgPpjcuV5QH3BxFS3IjizoKk=
+google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8=
+google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0=
+google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM=
+google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE=
+google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo=
+google.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
+google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
+google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
+google.golang.org/protobuf v1.24.0 h1:UhZDfRO8JRQru4/+LlLE0BRKGF8L+PICnvYZmx/fEGA=
+google.golang.org/protobuf v1.24.0/go.mod h1:r/3tXBNzIEhYS9I1OUVjXDlt8tc493IdKGjtUeSXeh4=
+honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
+honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
diff --git a/release/Dockerfile.in b/release/Dockerfile.in
index 75aaed2..0c16e93 100644
--- a/release/Dockerfile.in
+++ b/release/Dockerfile.in
@@ -1,5 +1,5 @@
 # Concatenated after ../Dockerfile to create the tgz
-FROM docker.io/fortio/fortio.build:v13 as stage
+FROM docker.io/fortio/fortio.build:v20 as stage
 WORKDIR /stage
 COPY --from=release /usr/bin/fortio usr/bin/fortio
 COPY --from=release /usr/share/fortio usr/share/fortio
diff --git a/vendor b/vendor
deleted file mode 160000
index 4f962d7..0000000
--- a/vendor
+++ /dev/null
@@ -1,1 +0,0 @@
-Subproject commit 4f962d7cf91dd71a745c8f635a65860930a79c8f
diff --git a/version/version.go b/version/version.go
index 92f8fdd..26b2fc1 100644
--- a/version/version.go
+++ b/version/version.go
@@ -23,8 +23,8 @@ import (
 
 const (
 	major = 1
-	minor = 3
-	patch = 2
+	minor = 4
+	patch = 0
 
 	debug = false // turn on to debug init()
 )


Test patch:
diff --git a/Dockerfile.test b/Dockerfile.test
index 543c772..c2d927c 100644
--- a/Dockerfile.test
+++ b/Dockerfile.test
@@ -1,5 +1,5 @@
 # Getting the source tree ready for running tests (sut)
-FROM docker.io/fortio/fortio.build:v13
+FROM docker.io/fortio/fortio.build:v20
 WORKDIR /go/src/fortio.org
 COPY . fortio
 RUN make -C fortio dependencies
diff --git a/Webtest.sh b/Webtest.sh
index 286914c..cc14c41 100755
--- a/Webtest.sh
+++ b/Webtest.sh
@@ -16,7 +16,7 @@ set -x
 # Check we can build the image
 make docker-internal TAG=webtest || exit 1
 FORTIO_UI_PREFIX=/newprefix/ # test the non default prefix (not /fortio/)
-FILE_LIMIT=20 # must be low to detect leaks
+FILE_LIMIT=25 # must be low to detect leaks, go 1.14 seems to need more than go1.8 (!)
 LOGLEVEL=info # change to debug to debug
 MAXPAYLOAD=8 # Max Payload size for echo?size= in kb
 CERT=/etc/ssl/certs/ca-certificates.crt
@@ -28,6 +28,7 @@ FORTIO_BIN_PATH=fortio # /usr/bin/fortio is the full path but isn't needed
 DOCKERID=$(docker run -d --ulimit nofile=$FILE_LIMIT --name $DOCKERNAME fortio/fortio:webtest server -ui-path $FORTIO_UI_PREFIX -loglevel $LOGLEVEL -maxpayloadsizekb $MAXPAYLOAD)
 function cleanup {
   set +e # errors are ok during cleanup
+#  docker logs $DOCKERID # uncomment to debug
   docker stop $DOCKERID
   docker rm -f $DOCKERNAME
   docker stop $DOCKERSECID # may not be set yet, it's ok
@@ -42,7 +43,7 @@ BASE_URL="http://localhost:8080"
 BASE_FORTIO="$BASE_URL$FORTIO_UI_PREFIX"
 CURL="docker exec $DOCKERNAME $FORTIO_BIN_PATH curl -loglevel $LOGLEVEL"
 # Check https works (certs are in the image) - also tests autoswitch to std client for https
-$CURL https://istio.io/robots.txt
+$CURL https://www.google.com/robots.txt > /dev/null
 
 # Check we can connect, and run a http QPS test against ourselves through fetch
 $CURL "${BASE_FORTIO}fetch/localhost:8080$FORTIO_UI_PREFIX?url=http://localhost:8080/debug&load=Start&qps=-1&json=on" | grep ActualQPS
@@ -103,7 +104,7 @@ docker exec $DOCKERNAME $FORTIO_BIN_PATH grpcping localhost
 PPROF_URL="$BASE_URL/debug/pprof/heap?debug=1"
 $CURL $PPROF_URL | grep -i TotalAlloc # should find this in memory profile
 # creating dummy container to hold a volume for test certs due to remote docker bind mount limitation.
-docker create -v $TEST_CERT_VOL --name $DOCKERSECVOLNAME docker.io/fortio/fortio.build:v13 /bin/true # cleaned up by name
+docker create -v $TEST_CERT_VOL --name $DOCKERSECVOLNAME docker.io/fortio/fortio.build:v20 /bin/true # cleaned up by name
 # copying cert files into the certs volume of the dummy container
 for f in ca.crt server.crt server.key; do docker cp $PWD/cert-tmp/$f $DOCKERSECVOLNAME:$TEST_CERT_VOL/$f; done
 # start server in secure grpc mode. uses non-default ports to avoid conflicts with fortio_server container.
diff --git a/fhttp/http_test.go b/fhttp/http_test.go
index 988d7f3..273f9f8 100644
--- a/fhttp/http_test.go
+++ b/fhttp/http_test.go
@@ -623,12 +623,13 @@ func TestBadUrl(t *testing.T) {
 }
 
 func TestDefaultPort(t *testing.T) {
-	url := "http://fortio.istio.io/" // shall imply port 80
+	// TODO: change back to fortio demo server once setup
+	url := "http://istio.io/" // shall imply port 80
 	opts := NewHTTPOptions(url)
 	cli := NewFastClient(opts)
 	code, _, _ := cli.Fetch()
-	if code != 303 {
-		t.Errorf("unexpected code for %s: %d (expecting 303 redirect to https)", url, code)
+	if code != 301 {
+		t.Errorf("unexpected code for %s: %d (expecting 301 redirect to https)", url, code)
 	}
 	conn := cli.(*FastClient).connect()
 	if conn != nil {
@@ -641,8 +642,8 @@ func TestDefaultPort(t *testing.T) {
 		t.Errorf("unable to connect to %s", url)
 	}
 	cli.Close()
-	opts.URL = "https://fortio.istio.io" // will be https port 443
-	opts.Insecure = true                 // not needed as we have valid certs but to exercise that code
+	opts.URL = "https://fortio.org" // will be https port 443
+	opts.Insecure = true            // not needed as we have valid certs but to exercise that code
 	cli = NewFastClient(opts)
 	if cli != nil {
 		// If https support was added, remove this whitebox/for coverage purpose assertion