Merge pull request #6274 from hashicorp/merge-master-de01a1e

Merge master at de01a1e279
This commit is contained in:
Alvin Huang 2019-08-02 19:13:54 -04:00 committed by GitHub
commit 9f58504f1c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 201 additions and 19 deletions

7
.circleci/bash_env.sh Normal file
View File

@ -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}"

View File

@ -21,6 +21,7 @@ references:
GIT_AUTHOR_NAME: circleci-consul GIT_AUTHOR_NAME: circleci-consul
GIT_COMMITTER_NAME: circleci-consul GIT_COMMITTER_NAME: circleci-consul
S3_ARTIFACT_BUCKET: consul-dev-artifacts S3_ARTIFACT_BUCKET: consul-dev-artifacts
BASH_ENV: .circleci/bash_env.sh
jobs: jobs:
# lint consul tests # lint consul tests
@ -140,6 +141,7 @@ jobs:
docker: docker:
- image: *GOLANG_IMAGE - image: *GOLANG_IMAGE
environment: &build-env environment: &build-env
<<: *ENVIRONMENT
GOXPARALLEL: 2 # CircleCI containers are 2 CPU x 4GB RAM GOXPARALLEL: 2 # CircleCI containers are 2 CPU x 4GB RAM
resource_class: large resource_class: large
steps: steps:
@ -168,17 +170,42 @@ jobs:
XC_ARCH: "amd64" XC_ARCH: "amd64"
# build all arm/arm64 architecture supported OS binaries # build all arm/arm64 architecture supported OS binaries
build-arm-arm64: build-arm:
<<: *build-distros docker:
- image: *GOLANG_IMAGE
environment: environment:
<<: *build-env <<: *ENVIRONMENT
XC_OS: linux CGO_ENABLED: 1
XC_ARCH: "arm arm64" 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 # create a development build
dev-build: dev-build:
docker: docker:
- image: *GOLANG_IMAGE - image: *GOLANG_IMAGE
environment:
<<: *ENVIRONMENT
steps: steps:
- checkout - checkout
- restore_cache: - restore_cache:
@ -497,7 +524,7 @@ jobs:
git fetch origin git fetch origin
# Create a merge branch to run tests on # Create a merge branch to run tests on
git_merge_branch="ci/master-merge-$(date +%Y%m%d%H%M%S)" git_merge_branch="ci/master-merge-${CIRCLE_BRANCH}-$(date +%Y%m%d%H%M%S)"
git checkout -b "${git_merge_branch}" git checkout -b "${git_merge_branch}"
latest_oss_commit="$(git rev-parse origin/master)" latest_oss_commit="$(git rev-parse origin/master)"
@ -554,7 +581,7 @@ jobs:
\"attachments\": [ \ \"attachments\": [ \
{ \ { \
\"fallback\": \"Nightly Master Merge Failed!\", \ \"fallback\": \"Nightly Master Merge Failed!\", \
\"text\": \"Nightly *master* merge into *release/1-6* 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.\", \ \"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}\", \ \"footer\": \"${CIRCLE_PROJECT_USERNAME}/${CIRCLE_PROJECT_REPONAME}\", \
\"ts\": \"$(date +%s)\", \ \"ts\": \"$(date +%s)\", \
\"color\": \"danger\" \ \"color\": \"danger\" \
@ -590,7 +617,7 @@ jobs:
\"attachments\": [ \ \"attachments\": [ \
{ \ { \
\"fallback\": \"Nightly master merge success!\", \ \"fallback\": \"Nightly master merge success!\", \
\"text\": \"Nightly *master* merge into *release/1-6* succeeded!\", \ \"text\": \"Nightly *master* merge into *${CIRCLE_BRANCH}* succeeded!\", \
\"footer\": \"${CIRCLE_PROJECT_USERNAME}/${CIRCLE_PROJECT_REPONAME}\", \ \"footer\": \"${CIRCLE_PROJECT_USERNAME}/${CIRCLE_PROJECT_REPONAME}\", \
\"ts\": \"$(date +%s)\", \ \"ts\": \"$(date +%s)\", \
\"color\": \"good\" \ \"color\": \"good\" \
@ -609,7 +636,7 @@ workflows:
filters: filters:
branches: branches:
only: only:
- release/1-6 - /^release\/.*$/
go-tests: go-tests:
jobs: jobs:
- check-vendor - check-vendor
@ -628,7 +655,7 @@ workflows:
jobs: jobs:
- build-386 - build-386
- build-amd64 - build-amd64
- build-arm-arm64 - build-arm
test-integrations: test-integrations:
jobs: jobs:
- dev-build - dev-build

View File

@ -220,11 +220,6 @@ func (c *cmd) Run(args []string) int {
if c.grpcAddr == "" { if c.grpcAddr == "" {
c.grpcAddr = os.Getenv(api.GRPCAddrEnvName) 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() == "" { if c.http.Token() == "" && c.http.TokenFile() == "" {
// Extra check needed since CONSUL_HTTP_TOKEN has not been consulted yet but // Extra check needed since CONSUL_HTTP_TOKEN has not been consulted yet but
// calling SetToken with empty will force that to override the // calling SetToken with empty will force that to override the
@ -360,6 +355,21 @@ func (c *cmd) Run(args []string) int {
return 1 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 // Generate config
bootstrapJson, err := c.generateConfig() bootstrapJson, err := c.generateConfig()
if err != nil { if err != nil {
@ -548,6 +558,27 @@ func (c *cmd) lookupGatewayProxy() (*api.AgentService, error) {
return proxyCmd.LookupGatewayProxy(c.client) return proxyCmd.LookupGatewayProxy(c.client)
} }
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 { func (c *cmd) Synopsis() string {
return synopsis return synopsis
} }

View File

@ -12,6 +12,7 @@ import (
"strings" "strings"
"testing" "testing"
"github.com/hashicorp/consul/agent"
"github.com/hashicorp/consul/agent/xds" "github.com/hashicorp/consul/agent/xds"
"github.com/hashicorp/consul/api" "github.com/hashicorp/consul/api"
"github.com/hashicorp/consul/sdk/testutil" "github.com/hashicorp/consul/sdk/testutil"
@ -67,6 +68,7 @@ func TestGenerateConfig(t *testing.T) {
Env []string Env []string
Files map[string]string Files map[string]string
ProxyConfig map[string]interface{} ProxyConfig map[string]interface{}
GRPCPort int // only used for testing custom-configured grpc port
WantArgs BootstrapTplArgs WantArgs BootstrapTplArgs
WantErr string WantErr string
}{ }{
@ -222,6 +224,24 @@ func TestGenerateConfig(t *testing.T) {
LocalAgentClusterName: xds.LocalAgentClusterName, 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", Name: "access-log-path",
Flags: []string{"-proxy-id", "test-proxy", "-admin-access-log-path", "/some/path/access.log"}, Flags: []string{"-proxy-id", "test-proxy", "-admin-access-log-path", "/some/path/access.log"},
@ -453,7 +473,7 @@ func TestGenerateConfig(t *testing.T) {
// Run a mock agent API that just always returns the proxy config in the // Run a mock agent API that just always returns the proxy config in the
// test. // test.
srv := httptest.NewServer(testMockAgentProxyConfig(tc.ProxyConfig)) srv := httptest.NewServer(testMockAgent(tc.ProxyConfig, tc.GRPCPort))
defer srv.Close() defer srv.Close()
// Set the agent HTTP address in ENV to be our mock // Set the agent HTTP address in ENV to be our mock
@ -501,6 +521,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 { func testMockAgentProxyConfig(cfg map[string]interface{}) http.HandlerFunc {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { 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 // Parse the proxy-id from the end of the URL (blindly assuming it's correct
@ -624,3 +663,23 @@ func TestEnvoyCommand_canBindInternal(t *testing.T) {
}) })
} }
} }
// 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)
})
}

View File

@ -0,0 +1,58 @@
{
"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"
}
}
}
}
}

View File

@ -31,7 +31,7 @@ networks, software-defined networks, cross-cloud, and more.
## Observability ## 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 provide of all the services on your network, irrespective of their different
programming languages and frameworks. When you configure Consul Connect to use programming languages and frameworks. When you configure Consul Connect to use
sidecar proxies, those proxies "see" all service-to-service traffic and can 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. locally without installing anything else.
- The [Kubernetes guide](https://learn.hashicorp.com/consul/getting-started-k8s/minikube) - 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 chart, and using intentions. You can run the guide on Minikube or an extant
Kubernets cluster. Kubernets cluster.

View File

@ -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; 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 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 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. 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 The servers in each datacenter are all part of a single Raft peer set. This means that