Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 27 additions & 0 deletions .github/workflows/pr-cloud.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
# Dispatch to the consul-k8s-workflows with a nightly cron
name: pr-cloud-acceptance
on:
pull_request:
types: [opened, synchronize]
# Runs on PRs to main and all release branches
branches:
- main
- "release/**"
# these should be the only settings that you will ever need to change
env:
BRANCH: ${{ github.event.pull_request.head.ref }}
CONTEXT: "pr"

jobs:
cloud-acceptance:
name: cloud-acceptance
runs-on: ubuntu-24.04
steps:
- uses: benc-uk/workflow-dispatch@25b02cc069be46d637e8fe2f1e8484008e9e9609 # v1.2.3
name: cloud
with:
workflow: cloud.yml
repo: hashicorp/consul-k8s-workflows
ref: shani/update-max-parallel
token: ${{ secrets.ELEVATED_GITHUB_TOKEN }}
inputs: '{ "context":"${{ env.CONTEXT }}-${{ github.event.pull_request.number }}", "repository":"${{ github.repository }}", "branch":"${{ env.BRANCH }}", "sha":"${{ github.sha }}", "token":"${{ secrets.ELEVATED_GITHUB_TOKEN }}" }'
4 changes: 2 additions & 2 deletions acceptance/ci-inputs/gke_acceptance_test_packages.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -3,5 +3,5 @@

# Cloud package is not included in test suite as it is triggered from a non consul-k8s repo and requires HCP credentials
- {runner: 0, test-packages: "connect peering snapshot-agent wan-federation"}
- {runner: 1, test-packages: "consul-dns example partitions metrics sync"}
- {runner: 2, test-packages: "basic cli config-entries api-gateway ingress-gateway terminating-gateway vault server"}
# - {runner: 1, test-packages: "consul-dns example partitions metrics sync"}
# - {runner: 2, test-packages: "basic cli config-entries api-gateway ingress-gateway terminating-gateway vault server"}
42 changes: 34 additions & 8 deletions acceptance/framework/k8s/kubectl.go
Original file line number Diff line number Diff line change
Expand Up @@ -44,42 +44,65 @@ func RunKubectlAndGetOutputE(t testutil.TestingTB, options *k8s.KubectlOptions,
// contains sensitive information, for example, when you can pass logger.Discard.
func RunKubectlAndGetOutputWithLoggerE(t testutil.TestingTB, options *k8s.KubectlOptions, logger *terratestLogger.Logger, args ...string) (string, error) {
var cmdArgs []string

// 1. Handle Context
if options.ContextName != "" {
cmdArgs = append(cmdArgs, "--context", options.ContextName)
}

// 2. Handle Kubeconfig
if options.ConfigPath != "" {
cmdArgs = append(cmdArgs, "--kubeconfig", options.ConfigPath)
}
if options.Namespace != "" && !sliceContains(args, "-n") && !sliceContains(args, "--namespace") {

// 3. Robust Namespace Check
// We check for both short (-n) and long (--namespace) versions
hasNamespace := sliceContains(args, "-n") || sliceContains(args, "--namespace") || sliceContains(args, "ns")
if options.Namespace != "" && !hasNamespace {
cmdArgs = append(cmdArgs, "--namespace", options.Namespace)
}

cmdArgs = append(cmdArgs, args...)

command := helpers.Command{
Command: "kubectl",
Args: cmdArgs,
Env: options.Env,
Logger: logger,
}

// Debugging: Log the full command being run
logger.Logf(t, "Running: kubectl %s", strings.Join(cmdArgs, " "))

counter := &retry.Counter{
Count: 10,
Count: 2,
Wait: 1 * time.Second,
}

var output string
var err error

retry.RunWith(counter, t, func(r *retry.R) {
output, err = helpers.RunCommand(r, options, command)
if err != nil {
// Want to retry on errors connecting to actual Kube API because
// these are intermittent.
// If it's a condition timeout, fail immediately to save time
if strings.Contains(output, "timed out waiting for the condition") {
r.Errorf("Resource failed to become ready in time: %s", output)
counter.Count = 0 // Stop the retry loop
return
}

// Only retry for known network/connectivity issues
for _, connectionErr := range kubeAPIConnectErrs {
if strings.Contains(err.Error(), connectionErr) {
r.Errorf(err.Error())
r.Errorf("Retrying due to connection error: %v", err)
return
}
}
r.Errorf("Kubectl execution failed: %v", err)
}
})

return output, err
}

Expand Down Expand Up @@ -135,13 +158,16 @@ func KubectlLabel(t *testing.T, options *k8s.KubectlOptions, objectType string,
// If there's an error running the command, fail the test.
func RunKubectl(t *testing.T, options *k8s.KubectlOptions, args ...string) {
_, err := RunKubectlAndGetOutputE(t, options, args...)
t.Log("error in kubectl", err)
require.NoError(t, err)
}

// sliceContains returns true if s contains target.
func sliceContains(s []string, target string) bool {
for _, elem := range s {
if elem == target {
func sliceContains(args []string, flag string) bool {
for _, arg := range args {
// Checks for exact match (e.g., "-n")
// OR if the argument starts with the flag and an equals (e.g., "-n=")
if arg == flag || strings.HasPrefix(arg, flag+"=") || strings.HasPrefix(arg, flag) {
return true
}
}
Expand Down
26 changes: 14 additions & 12 deletions acceptance/tests/connect/connect_external_servers_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -47,25 +47,27 @@ func TestConnectInject_ExternalServers(t *testing.T) {

consulServerCluster.Create(t)

helmValues := map[string]string{
"server.enabled": "false",
"global.acls.manageSystemACLs": strconv.FormatBool(secure),

"global.tls.enabled": strconv.FormatBool(secure),

"connectInject.enabled": "true",

"externalServers.enabled": "true",
"externalServers.hosts[0]": fmt.Sprintf("%s-consul-server", serverReleaseName),
"externalServers.httpsPort": "8500",
}
helmValues := map[string]string{
"server.enabled": "false",
"connectInject.enabled": "true",

// CORRECT HELM KEYS:
// This ensures the sidecar-injector allows Envoy enough time to reach the server.
"connectInject.sidecarProxy.startupFailureSeconds": "300",
"connectInject.sidecarProxy.livenessFailureSeconds": "300",

"externalServers.enabled": "true",
"externalServers.hosts[0]": fmt.Sprintf("%s-consul-server.default.svc.cluster.local", serverReleaseName),
"externalServers.httpsPort": "8500",
}

if secure {
helmValues["global.tls.caCert.secretName"] = fmt.Sprintf("%s-consul-ca-cert", serverReleaseName)
helmValues["global.tls.caCert.secretKey"] = "tls.crt"
helmValues["global.acls.bootstrapToken.secretName"] = fmt.Sprintf("%s-consul-bootstrap-acl-token", serverReleaseName)
helmValues["global.acls.bootstrapToken.secretKey"] = "token"
helmValues["externalServers.httpsPort"] = "8501"
helmValues["server.exposeGossipAndRPC"] = "true"
}

releaseName := helpers.RandomName()
Expand Down
74 changes: 53 additions & 21 deletions charts/consul/test/terraform/gke/main.tf
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,19 @@
terraform {
required_providers {
google = {
source = "hashicorp/google"
version = "~> 5.3.0"
}
random = {
source = "hashicorp/random"
}
null = {
source = "hashicorp/null"
}
}
}


provider "google" {
project = var.project
zone = var.zone
Expand All @@ -19,52 +27,76 @@ resource "random_id" "suffix" {
byte_length = 4
}

resource "random_string" "cluster_prefix" {
length = 8
upper = false
special = false
}

data "google_container_engine_versions" "main" {
location = var.zone
version_prefix = "1.27."
version_prefix = var.kubernetes_version_prefix

}

# We assume that the subnets are already created to save time.
data "google_compute_subnetwork" "subnet" {
name = var.subnet
resource "google_compute_network" "custom_network" {
name = "network-${random_string.cluster_prefix.result}"
auto_create_subnetworks = false
lifecycle {
prevent_destroy = false
ignore_changes = [name]
}
}

resource "google_compute_subnetwork" "subnet" {
count = var.cluster_count
name = "subnet-${random_string.cluster_prefix.result}-${count.index}" // Ensure valid name
ip_cidr_range = cidrsubnet("10.0.0.0/8", 8, count.index)
network = google_compute_network.custom_network.name
}

resource "google_container_cluster" "cluster" {
provider = "google"
provider = google
count = var.cluster_count

name = "consul-k8s-${random_id.suffix[count.index].dec}"
project = var.project
initial_node_count = 3
location = var.zone
# 2023-10-30 - There is a bug with the terraform provider where lastest_master_version is not being returned by the
# api. Hardcode GKE version for now.
min_master_version = data.google_container_engine_versions.main.latest_master_version
node_version = data.google_container_engine_versions.main.latest_master_version
name = "consul-k8s-${random_string.cluster_prefix.result}-${random_id.suffix[count.index].dec}"
remove_default_node_pool = false
initial_node_count = 3
location = var.zone
min_master_version = data.google_container_engine_versions.main.latest_master_version
node_version = data.google_container_engine_versions.main.latest_master_version
network = google_compute_network.custom_network.name
networking_mode = "VPC_NATIVE"
node_config {
tags = ["consul-k8s-${random_id.suffix[count.index].dec}"]
tags = ["consul-k8s-${random_string.cluster_prefix.result}-${random_id.suffix[count.index].dec}"]
machine_type = "e2-standard-8"
}
subnetwork = data.google_compute_subnetwork.subnet.name
subnetwork = google_compute_subnetwork.subnet[count.index].self_link
ip_allocation_policy {
cluster_ipv4_cidr_block = cidrsubnet("10.100.0.0/12", 4, count.index)
}
resource_labels = var.labels
deletion_protection = false
}


resource "google_compute_firewall" "firewall-rules" {
project = var.project
name = "consul-k8s-acceptance-firewall-${random_id.suffix[count.index].dec}"
network = "default"
description = "Creates firewall rule allowing traffic from nodes and pods of the ${random_id.suffix[count.index == 0 ? 1 : 0].dec} Kubernetes cluster."
name = format("firewall-%s-%d", substr(random_string.cluster_prefix.result, 0, 8), count.index)
network = google_compute_network.custom_network.name
description = "Firewall rule for cluster ${random_string.cluster_prefix.result}-${random_id.suffix[count.index].dec}."

count = var.cluster_count > 1 ? var.cluster_count : 0

allow {
protocol = "all"
}

source_ranges = [google_container_cluster.cluster[count.index == 0 ? 1 : 0].cluster_ipv4_cidr]
source_tags = ["consul-k8s-${random_id.suffix[count.index == 0 ? 1 : 0].dec}"]
target_tags = ["consul-k8s-${random_id.suffix[count.index].dec}"]
source_ranges = concat(
google_container_cluster.cluster[*].cluster_ipv4_cidr,
google_compute_subnetwork.subnet[*].ip_cidr_range
)
target_tags = ["consul-k8s-${random_string.cluster_prefix.result}-${random_id.suffix[count.index].dec}"]
}

resource "null_resource" "kubectl" {
Expand Down
6 changes: 6 additions & 0 deletions charts/consul/test/terraform/gke/variables.tf
Original file line number Diff line number Diff line change
Expand Up @@ -43,3 +43,9 @@ variable "subnet" {
default = "default"
description = "Subnet to create the cluster in. Currently all clusters use the default subnet and we are running out of IPs"
}

variable "kubernetes_version_prefix" {
type = string
default = "1.34."
description = "The Kubernetes version prefix to use for the GKE cluster."
}
Loading