From df036f06a7994a7248acfba3b370fe5576df2561 Mon Sep 17 00:00:00 2001 From: Sarah Adams Date: Thu, 1 Aug 2019 09:53:34 -0700 Subject: [PATCH 1/6] 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 9e3e06fbc..f2a5a83e3 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 2f15ac59a..f012126db 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 000000000..e9c823b90 --- /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 5011f305e0f43cd257cb6f4e8513a8f76d99412c Mon Sep 17 00:00:00 2001 From: Venkata Krishna Annam Date: Thu, 1 Aug 2019 23:27:26 +0530 Subject: [PATCH 2/6] 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 15628ea6c..02c70ae41 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 1e80fc9c0f92e919fed470ccfe53697dfb8ea0c8 Mon Sep 17 00:00:00 2001 From: Omer Zach Date: Thu, 1 Aug 2019 11:21:37 -0700 Subject: [PATCH 3/6] 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 e473de50b..61c938f60 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 f5471c7f8dfec21c75eee6721b3f6f422921c54a 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/6] 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 000000000..1ca31b622 --- /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 33f25493a..23b336dcc 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 f834854f8a5634b18fd9f54b819682e804014133 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/6] 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 23b336dcc..d776d8706 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 From a9dc90b001857b1bb6ecea3f9a93ad735e36f149 Mon Sep 17 00:00:00 2001 From: Alvin Huang <17609145+alvin-huang@users.noreply.github.com> Date: Fri, 2 Aug 2019 19:00:39 -0400 Subject: [PATCH 6/6] fix grpc-addr-config hosts template --- command/connect/envoy/testdata/grpc-addr-config.golden | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/command/connect/envoy/testdata/grpc-addr-config.golden b/command/connect/envoy/testdata/grpc-addr-config.golden index e9c823b90..3a686b03b 100644 --- a/command/connect/envoy/testdata/grpc-addr-config.golden +++ b/command/connect/envoy/testdata/grpc-addr-config.golden @@ -19,14 +19,12 @@ "connect_timeout": "1s", "type": "STATIC", "http2_protocol_options": {}, - "hosts": [ - { + "hosts": [{ "socket_address": { "address": "127.0.0.1", "port_value": 9999 } - } - ] + }] } ] },