From 896749d5857e6d91bafcc5876d94de984e99e767 Mon Sep 17 00:00:00 2001 From: Sarah Adams Date: Thu, 1 Aug 2019 09:53:34 -0700 Subject: [PATCH 1/5] fix 'consul connect envoy' to try to use previously-configured grpc port (#6245) fix 'consul connect envoy' to try to use previously-configured grpc port on running agent before defaulting to 8502 Fixes #5011 --- command/connect/envoy/envoy.go | 41 +++++++++++-- command/connect/envoy/envoy_test.go | 61 ++++++++++++++++++- .../envoy/testdata/grpc-addr-config.golden | 60 ++++++++++++++++++ 3 files changed, 156 insertions(+), 6 deletions(-) create mode 100644 command/connect/envoy/testdata/grpc-addr-config.golden diff --git a/command/connect/envoy/envoy.go b/command/connect/envoy/envoy.go index 9e3e06fbcf..f2a5a83e3c 100644 --- a/command/connect/envoy/envoy.go +++ b/command/connect/envoy/envoy.go @@ -115,11 +115,6 @@ func (c *cmd) Run(args []string) int { if c.grpcAddr == "" { c.grpcAddr = os.Getenv(api.GRPCAddrEnvName) } - if c.grpcAddr == "" { - // This is the dev mode default and recommended production setting if - // enabled. - c.grpcAddr = "localhost:8502" - } if c.http.Token() == "" && c.http.TokenFile() == "" { // Extra check needed since CONSUL_HTTP_TOKEN has not been consulted yet but // calling SetToken with empty will force that to override the @@ -151,6 +146,21 @@ func (c *cmd) Run(args []string) int { return 1 } + // See if we need to lookup grpcAddr + if c.grpcAddr == "" { + port, err := c.lookupGRPCPort() + if err != nil { + c.UI.Error(fmt.Sprintf("Error connecting to Consul agent: %s", err)) + } + if port <= 0 { + // This is the dev mode default and recommended production setting if + // enabled. + port = 8502 + c.UI.Info(fmt.Sprintf("Defaulting to grpc port = %d", port)) + } + c.grpcAddr = fmt.Sprintf("localhost:%v", port) + } + // Generate config bootstrapJson, err := c.generateConfig() if err != nil { @@ -321,6 +331,27 @@ func (c *cmd) lookupProxyIDForSidecar() (string, error) { return proxyCmd.LookupProxyIDForSidecar(c.client, c.sidecarFor) } +func (c *cmd) lookupGRPCPort() (int, error) { + self, err := c.client.Agent().Self() + if err != nil { + return 0, err + } + cfg, ok := self["DebugConfig"] + if !ok { + return 0, fmt.Errorf("unexpected agent response: no debug config") + } + port, ok := cfg["GRPCPort"] + if !ok { + return 0, fmt.Errorf("agent does not have grpc port enabled") + } + portN, ok := port.(float64) + if !ok { + return 0, fmt.Errorf("invalid grpc port in agent response") + } + + return int(portN), nil +} + func (c *cmd) Synopsis() string { return synopsis } diff --git a/command/connect/envoy/envoy_test.go b/command/connect/envoy/envoy_test.go index 2f15ac59a8..f012126db8 100644 --- a/command/connect/envoy/envoy_test.go +++ b/command/connect/envoy/envoy_test.go @@ -11,6 +11,7 @@ import ( "strings" "testing" + "github.com/hashicorp/consul/agent" "github.com/hashicorp/consul/agent/xds" "github.com/hashicorp/consul/api" "github.com/hashicorp/consul/sdk/testutil" @@ -66,6 +67,7 @@ func TestGenerateConfig(t *testing.T) { Env []string Files map[string]string ProxyConfig map[string]interface{} + GRPCPort int // only used for testing custom-configured grpc port WantArgs BootstrapTplArgs WantErr string }{ @@ -206,6 +208,24 @@ func TestGenerateConfig(t *testing.T) { LocalAgentClusterName: xds.LocalAgentClusterName, }, }, + { + Name: "grpc-addr-config", + Flags: []string{"-proxy-id", "test-proxy"}, + GRPCPort: 9999, + WantArgs: BootstrapTplArgs{ + ProxyCluster: "test-proxy", + ProxyID: "test-proxy", + // Should resolve IP, note this might not resolve the same way + // everywhere which might make this test brittle but not sure what else + // to do. + AgentAddress: "127.0.0.1", + AgentPort: "9999", + AdminAccessLogPath: "/dev/null", + AdminBindAddress: "127.0.0.1", + AdminBindPort: "19000", + LocalAgentClusterName: xds.LocalAgentClusterName, + }, + }, { Name: "access-log-path", Flags: []string{"-proxy-id", "test-proxy", "-admin-access-log-path", "/some/path/access.log"}, @@ -437,7 +457,7 @@ func TestGenerateConfig(t *testing.T) { // Run a mock agent API that just always returns the proxy config in the // test. - srv := httptest.NewServer(testMockAgentProxyConfig(tc.ProxyConfig)) + srv := httptest.NewServer(testMockAgent(tc.ProxyConfig, tc.GRPCPort)) defer srv.Close() // Set the agent HTTP address in ENV to be our mock @@ -485,6 +505,25 @@ func TestGenerateConfig(t *testing.T) { } } +// testMockAgent combines testMockAgentProxyConfig and testMockAgentSelf, +// routing /agent/service/... requests to testMockAgentProxyConfig and +// routing /agent/self requests to testMockAgentSelf. +func testMockAgent(agentCfg map[string]interface{}, grpcPort int) http.HandlerFunc { + return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + if strings.Contains(r.URL.Path, "/agent/service") { + testMockAgentProxyConfig(agentCfg)(w, r) + return + } + + if strings.Contains(r.URL.Path, "/agent/self") { + testMockAgentSelf(grpcPort)(w, r) + return + } + + http.NotFound(w, r) + }) +} + func testMockAgentProxyConfig(cfg map[string]interface{}) http.HandlerFunc { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { // Parse the proxy-id from the end of the URL (blindly assuming it's correct @@ -512,3 +551,23 @@ func testMockAgentProxyConfig(cfg map[string]interface{}) http.HandlerFunc { w.Write(cfgJSON) }) } + +// testMockAgentSelf returns an empty /v1/agent/self response except GRPC +// port is filled in to match the given wantGRPCPort argument. +func testMockAgentSelf(wantGRPCPort int) http.HandlerFunc { + return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + resp := agent.Self{ + DebugConfig: map[string]interface{}{ + "GRPCPort": wantGRPCPort, + }, + } + + selfJSON, err := json.Marshal(resp) + if err != nil { + w.WriteHeader(500) + w.Write([]byte(err.Error())) + return + } + w.Write(selfJSON) + }) +} diff --git a/command/connect/envoy/testdata/grpc-addr-config.golden b/command/connect/envoy/testdata/grpc-addr-config.golden new file mode 100644 index 0000000000..e9c823b905 --- /dev/null +++ b/command/connect/envoy/testdata/grpc-addr-config.golden @@ -0,0 +1,60 @@ +{ + "admin": { + "access_log_path": "/dev/null", + "address": { + "socket_address": { + "address": "127.0.0.1", + "port_value": 19000 + } + } + }, + "node": { + "cluster": "test-proxy", + "id": "test-proxy" + }, + "static_resources": { + "clusters": [ + { + "name": "local_agent", + "connect_timeout": "1s", + "type": "STATIC", + "http2_protocol_options": {}, + "hosts": [ + { + "socket_address": { + "address": "127.0.0.1", + "port_value": 9999 + } + } + ] + } + ] + }, + "stats_config": { + "stats_tags": [ + { + "tag_name": "local_cluster", + "fixed_value": "test-proxy" + } + ], + "use_all_default_tags": true + }, + "dynamic_resources": { + "lds_config": { "ads": {} }, + "cds_config": { "ads": {} }, + "ads_config": { + "api_type": "GRPC", + "grpc_services": { + "initial_metadata": [ + { + "key": "x-consul-token", + "value": "" + } + ], + "envoy_grpc": { + "cluster_name": "local_agent" + } + } + } + } +} From 80f091e107bf48b0a0f139390421565a402aac63 Mon Sep 17 00:00:00 2001 From: Venkata Krishna Annam Date: Thu, 1 Aug 2019 23:27:26 +0530 Subject: [PATCH 2/5] docs: Fix minor mistakes in index.html.md (#6239) --- website/source/docs/connect/index.html.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/website/source/docs/connect/index.html.md b/website/source/docs/connect/index.html.md index 15628ea6cb..02c70ae418 100644 --- a/website/source/docs/connect/index.html.md +++ b/website/source/docs/connect/index.html.md @@ -31,7 +31,7 @@ networks, software-defined networks, cross-cloud, and more. ## Observability -One of the key benefits Consul Connect is the uniform and consistent view it can +One of the key benefits of Consul Connect is the uniform and consistent view it can provide of all the services on your network, irrespective of their different programming languages and frameworks. When you configure Consul Connect to use sidecar proxies, those proxies "see" all service-to-service traffic and can @@ -52,7 +52,7 @@ There are several ways to try Connect in different environments. locally without installing anything else. - The [Kubernetes guide](https://learn.hashicorp.com/consul/getting-started-k8s/minikube) - walks you though configuring Consul Connect in Kubernetes using the Helm + walks you through configuring Consul Connect in Kubernetes using the Helm chart, and using intentions. You can run the guide on Minikube or an extant Kubernets cluster. From 6785e33d8af7aea401a3b5ccad7f822bc0d7b05e Mon Sep 17 00:00:00 2001 From: Omer Zach Date: Thu, 1 Aug 2019 11:21:37 -0700 Subject: [PATCH 3/5] Fix typo in architecture.html.md (#6261) --- website/source/docs/internals/architecture.html.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/website/source/docs/internals/architecture.html.md b/website/source/docs/internals/architecture.html.md index e473de50ba..61c938f603 100644 --- a/website/source/docs/internals/architecture.html.md +++ b/website/source/docs/internals/architecture.html.md @@ -41,7 +41,7 @@ This means there is a gossip pool that contains all the agents for a given datac a few purposes: first, there is no need to configure clients with the addresses of servers; discovery is done automatically. Second, the work of detecting agent failures is not placed on the servers but is distributed. This makes failure detection much more -scalable than naive heartbeating schemes. It also provides failure detection for the nodes; if the agent is not reachable, than the node may have experienced a failure. Thirdly, it is used as a messaging layer to notify +scalable than naive heartbeating schemes. It also provides failure detection for the nodes; if the agent is not reachable, then the node may have experienced a failure. Thirdly, it is used as a messaging layer to notify when important events such as leader election take place. The servers in each datacenter are all part of a single Raft peer set. This means that From dd7b3ece64706fa88e19e6ab6d9a2518211705ac Mon Sep 17 00:00:00 2001 From: Alvin Huang <17609145+alvin-huang@users.noreply.github.com> Date: Fri, 2 Aug 2019 15:15:59 -0400 Subject: [PATCH 4/5] Add arm builds (#6263) * try arm builds * Update .circleci/config.yml Co-Authored-By: Matt Keeler * Update .circleci/config.yml Co-Authored-By: Matt Keeler * Update .circleci/config.yml Co-Authored-By: Matt Keeler --- .circleci/bash_env.sh | 7 +++++++ .circleci/config.yml | 39 +++++++++++++++++++++++++++++++++------ 2 files changed, 40 insertions(+), 6 deletions(-) create mode 100644 .circleci/bash_env.sh diff --git a/.circleci/bash_env.sh b/.circleci/bash_env.sh new file mode 100644 index 0000000000..1ca31b6223 --- /dev/null +++ b/.circleci/bash_env.sh @@ -0,0 +1,7 @@ +#!/bin/bash + +export GIT_COMMIT=$(git rev-parse --short HEAD) +export GIT_DIRTY=$(test -n "`git status --porcelain`" && echo "+CHANGES" || true) +export GIT_DESCRIBE=$(git describe --tags --always --match "v*") +export GIT_IMPORT=github.com/hashicorp/consul/version +export GOLDFLAGS="-X ${GIT_IMPORT}.GitCommit=${GIT_COMMIT}${GIT_DIRTY} -X ${GIT_IMPORT}.GitDescribe=${GIT_DESCRIBE}" \ No newline at end of file diff --git a/.circleci/config.yml b/.circleci/config.yml index 33f25493ab..23b336dcc8 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -21,6 +21,7 @@ references: GIT_AUTHOR_NAME: circleci-consul GIT_COMMITTER_NAME: circleci-consul S3_ARTIFACT_BUCKET: consul-dev-artifacts + BASH_ENV: .circleci/bash_env.sh jobs: # lint consul tests @@ -140,6 +141,7 @@ jobs: docker: - image: *GOLANG_IMAGE environment: &build-env + <<: *ENVIRONMENT GOXPARALLEL: 2 # CircleCI containers are 2 CPU x 4GB RAM steps: - checkout @@ -167,17 +169,42 @@ jobs: XC_ARCH: "amd64" # build all arm/arm64 architecture supported OS binaries - build-arm-arm64: - <<: *build-distros + build-arm: + docker: + - image: *GOLANG_IMAGE environment: - <<: *build-env - XC_OS: linux - XC_ARCH: "arm arm64" + <<: *ENVIRONMENT + CGO_ENABLED: 1 + GOOS: linux + steps: + - checkout + - run: sudo apt-get update && sudo apt-get install -y gcc-arm-linux-gnueabi gcc-arm-linux-gnueabihf gcc-aarch64-linux-gnu + - run: + environment: + GOARM: 5 + CC: arm-linux-gnueabi-gcc + GOARCH: arm + command: go build -o ./pkg/bin/linux_armel/consul -ldflags="${GOLDFLAGS}" + - run: + environment: + GOARM: 6 + CC: arm-linux-gnueabihf-gcc + GOARCH: arm + command: go build -o ./pkg/bin/linux_armhf/consul -ldflags="${GOLDFLAGS}" + - run: + environment: + CC: aarch64-linux-gnu-gcc + GOARCH: arm64 + command: go build -o ./pkg/bin/linux_aarch64/consul -ldflags="${GOLDFLAGS}" + - store_artifacts: + path: ./pkg/bin # create a development build dev-build: docker: - image: *GOLANG_IMAGE + environment: + <<: *ENVIRONMENT steps: - checkout - restore_cache: @@ -493,7 +520,7 @@ workflows: jobs: - build-386 - build-amd64 - - build-arm-arm64 + - build-arm test-integrations: jobs: - dev-build From de01a1e279230624fcc2d7e692b7e773d570204b Mon Sep 17 00:00:00 2001 From: Alvin Huang <17609145+alvin-huang@users.noreply.github.com> Date: Fri, 2 Aug 2019 16:11:41 -0400 Subject: [PATCH 5/5] add generic master merge into release/* branches (#6249) --- .circleci/config.yml | 134 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 134 insertions(+) diff --git a/.circleci/config.yml b/.circleci/config.yml index 23b336dcc8..d776d87067 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -500,8 +500,142 @@ jobs: ENVOY_VERSIONS: "1.10.0" steps: *ENVOY_INTEGRATION_TEST_STEPS + # This job merges master into the 'current' branch (${CIRCLE_BRANCH}) specified + # in the branch filtering of the workflow + merge-master: + docker: + - image: *GOLANG_IMAGE + steps: + - add_ssh_keys: + fingerprints: + - c6:96:98:82:dc:04:6c:39:dd:ac:83:05:e3:15:1c:98 + - checkout + - run: + name: Merge Consul OSS master branch into current branch + command: | + set -eu -o pipefail + + # Configure Git + git config --global user.email "hashicorp-ci@users.noreply.github.com" + git config --global user.name "hashicorp-ci" + + # Fetch latest master + git fetch origin + + # Create a merge branch to run tests on + git_merge_branch="ci/master-merge-${CIRCLE_BRANCH}-$(date +%Y%m%d%H%M%S)" + git checkout -b "${git_merge_branch}" + latest_oss_commit="$(git rev-parse origin/master)" + + if ! errors=$(git merge -m "Merge Consul OSS branch 'master' at commit ${latest_oss_commit}" "${latest_oss_commit}"); then + printf "oss/master merge into ${CIRCLE_BRANCH} failed because git was unable to auto-merge!\n${errors}" + curl -X POST -H 'Content-type: application/json' \ + --data \ + "{ \ + \"attachments\": [ \ + { \ + \"fallback\": \"master merge into ${CIRCLE_BRANCH} failed because git was unable to auto-merge!\", \ + \"text\": \"Nightly *master* merge into *${CIRCLE_BRANCH}* failed!\n\nBuild Log: ${CIRCLE_BUILD_URL}\n\nGit was unable to auto-merge due to possible merge conflict.\n\n*Errors:*\n${errors}\", \ + \"footer\": \"${CIRCLE_PROJECT_USERNAME}/${CIRCLE_PROJECT_REPONAME}\", \ + \"ts\": \"$(date +%s)\", \ + \"color\": \"danger\" \ + } \ + ] \ + }" ${CONSUL_SLACK_WEBHOOK_URL} + exit 1 + fi + + git push origin "${git_merge_branch}" + sleep 15 # Wait for merge branch to start CircleCI pipeline + + # Wait for OSS merge branch CircleCI pipeline to finish + # return shallow results for better performance + project_url="https://circleci.com/api/v1.1/project/github/hashicorp/consul/tree/${git_merge_branch}?shallow=true" + echo "Waiting for master merge branch CI pipeline to finish..." + builds= + unfinished_builds="will be populated in the until loop below" + min_waited=0 + until [[ -z "${unfinished_builds}" ]]; do + builds="$(curl \ + --header 'Accept: application/json' \ + --show-error \ + --silent \ + "${project_url}")" + unfinished_builds="$(echo "${builds}" \ + | jq --raw-output '.[] | select(.lifecycle!="finished") | .workflows.job_name')" + sleep 60 + let "min_waited += 1" + echo "Waited ${min_waited} min..." + done + + # Fail this job if the merge branch CI pipeline failed + # unsuccessful_builds will be a multiline string variable with a line format of " $job_name: $build_url" + unsuccessful_builds="$(echo "${builds}" \ + | jq --raw-output '.[] | select(.outcome!="success") | "\(.workflows.job_name): \(.build_url)"')" + if [[ -n "${unsuccessful_builds}" ]]; then + printf "master merge CI pipeline jobs failed:\n${unsuccessful_builds}\n" + curl -X POST -H 'Content-type: application/json' \ + --data \ + "{ \ + \"attachments\": [ \ + { \ + \"fallback\": \"Nightly Master Merge Failed!\", \ + \"text\": \"Nightly *master* merge into *${CIRCLE_BRANCH}* failed!\n\nBuild Log: ${CIRCLE_BUILD_URL}\n\nAttempted merge from: https://github.com/${CIRCLE_PROJECT_USERNAME}/${CIRCLE_PROJECT_REPONAME}/tree/${git_merge_branch}\n\nThere may be a merge conflict to resolve.\", \ + \"footer\": \"${CIRCLE_PROJECT_USERNAME}/${CIRCLE_PROJECT_REPONAME}\", \ + \"ts\": \"$(date +%s)\", \ + \"color\": \"danger\" \ + } \ + ] \ + }" ${CONSUL_SLACK_WEBHOOK_URL} + exit 1 + fi + + current_ref=$(git rev-parse HEAD) + # Set CLA check to pass + echo "Setting CLA check" + curl -u "${HASHICORP_CI_GITHUB_TOKEN}:" -X POST \ + --header "Accept: application/json" \ + --show-error \ + --silent \ + --fail \ + --output /dev/null \ + -d "{ \"state\": \"success\", \ + \"target_url\": \"https://cla.hashicorp.com/hashicorp/consul\", \ + \"description\": \"Contributor License Agreement is signed.\", \ + \"context\": \"license/cla\"}" https://api.github.com/repos/hashicorp/consul/statuses/${current_ref} + + # CircleCI jobs passed, merging to release branch + echo "master merge CI pipeline passed successfully so merging to ${CIRCLE_BRANCH}!" + git checkout "${CIRCLE_BRANCH}" + git merge "${git_merge_branch}" + git push origin "${CIRCLE_BRANCH}" + git push --delete origin "${git_merge_branch}" + curl -X POST -H 'Content-type: application/json' \ + --data \ + "{ \ + \"attachments\": [ \ + { \ + \"fallback\": \"Nightly master merge success!\", \ + \"text\": \"Nightly *master* merge into *${CIRCLE_BRANCH}* succeeded!\", \ + \"footer\": \"${CIRCLE_PROJECT_USERNAME}/${CIRCLE_PROJECT_REPONAME}\", \ + \"ts\": \"$(date +%s)\", \ + \"color\": \"good\" \ + } \ + ] \ + }" ${CONSUL_SLACK_WEBHOOK_URL} + workflows: version: 2 + merge-master-to-release: + jobs: + - merge-master + triggers: + - schedule: + cron: "0 2 * * *" # 2AM UTC <> 10PM EST <> 7PM PST should have no impact + filters: + branches: + only: + - /^release\/.*$/ go-tests: jobs: - check-vendor