Skip to content

Commit

Permalink
Merge pull request #4281 from emissary-ingress/lukeshu/no-gha-retry
Browse files Browse the repository at this point in the history
[v2.3.2] Don't retry tests at the GHA level
  • Loading branch information
LukeShu committed Jun 15, 2022
2 parents 4741794 + a1810d6 commit fd0aff9
Show file tree
Hide file tree
Showing 11 changed files with 2,310 additions and 190 deletions.
52 changes: 22 additions & 30 deletions .github/workflows/execute-tests-and-promote.yml
Original file line number Diff line number Diff line change
Expand Up @@ -159,24 +159,20 @@ jobs:
username: ${{ secrets.GH_DOCKER_BUILD_USERNAME }}
password: ${{ secrets.GH_DOCKER_BUILD_TOKEN }}
- name: make pytest-${{ matrix.test }}
uses: nick-invision/retry@v2.4.0
with:
max_attempts: 3
timeout_minutes: 20
command: |
export USE_LOCAL_K3S_CLUSTER=1
sudo sysctl -w fs.file-max=1600000
sudo sysctl -w fs.inotify.max_user_instances=4096
run: |
export USE_LOCAL_K3S_CLUSTER=1
sudo sysctl -w fs.file-max=1600000
sudo sysctl -w fs.inotify.max_user_instances=4096
make ci/setup-k3d K3D_CLUSTER_NAME=amb-ci
make ci/setup-k3d K3D_CLUSTER_NAME=amb-ci
export DEV_KUBE_NO_PVC=yes
export KAT_REQ_LIMIT=900
export TEST_XML_DIR=/tmp/test-logs/xml/
export DEV_KUBECONFIG=~/.kube/config
export DEV_REGISTRY=${{ secrets.DEV_REGISTRY }}
mkdir -p ${TEST_XML_DIR}
make pytest-${{ matrix.test }}
export DEV_KUBE_NO_PVC=yes
export KAT_REQ_LIMIT=900
export TEST_XML_DIR=/tmp/test-logs/xml/
export DEV_KUBECONFIG=~/.kube/config
export DEV_REGISTRY=${{ secrets.DEV_REGISTRY }}
mkdir -p ${TEST_XML_DIR}
make pytest-${{ matrix.test }}
- uses: ./.github/actions/after-job
if: always()
with:
Expand Down Expand Up @@ -206,21 +202,17 @@ jobs:
username: ${{ secrets.GH_DOCKER_BUILD_USERNAME }}
password: ${{ secrets.GH_DOCKER_BUILD_TOKEN }}
- name: make pytest-${{ matrix.test }}
uses: nick-invision/retry@v2.4.0
with:
max_attempts: 3
timeout_minutes: 20
command: |
sudo sysctl -w fs.file-max=1600000
sudo sysctl -w fs.inotify.max_user_instances=4096
run: |
sudo sysctl -w fs.file-max=1600000
sudo sysctl -w fs.inotify.max_user_instances=4096
export DEV_KUBE_NO_PVC=yes
export KAT_REQ_LIMIT=900
export TEST_XML_DIR=/tmp/test-logs/xml/
export DEV_KUBECONFIG=~/.kube/config
export DEV_REGISTRY=${{ secrets.DEV_REGISTRY }}
mkdir -p ${TEST_XML_DIR}
make pytest-${{ matrix.test }}
export DEV_KUBE_NO_PVC=yes
export KAT_REQ_LIMIT=900
export TEST_XML_DIR=/tmp/test-logs/xml/
export DEV_KUBECONFIG=~/.kube/config
export DEV_REGISTRY=${{ secrets.DEV_REGISTRY }}
mkdir -p ${TEST_XML_DIR}
make pytest-${{ matrix.test }}
- uses: ./.github/actions/after-job
if: always()
with:
Expand Down
1 change: 1 addition & 0 deletions pkg/k8s/watcher_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,7 @@ func TestWatchCustomCollision(t *testing.T) {
}

func TestWatchQuery(t *testing.T) {
t.Skip("FIXME(lukeshu): This test is notoriously flakey, and the code under test hasn't changed in ages. Write better tests!")
t.Parallel()
ctx := dlog.NewTestContext(t, false)
w, err := k8s.NewWatcher(info(ctx))
Expand Down
27 changes: 26 additions & 1 deletion pkg/snapshot/v1/annotations_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,30 @@ service: quote:80
},
}

svcWithEmptyAnnotation := &kates.Service{
TypeMeta: metav1.TypeMeta{
Kind: "Service",
},
ObjectMeta: metav1.ObjectMeta{
Name: "svc-empty",
Namespace: "ambassador",
Annotations: map[string]string{
"getambassador.io/config": "",
},
},
}

svcWithMissingAnnotation := &kates.Service{
TypeMeta: metav1.TypeMeta{
Kind: "Service",
},
ObjectMeta: metav1.ObjectMeta{
Name: "svc-missing",
Namespace: "ambassador",
Annotations: map[string]string{},
},
}

ingHost := `
---
apiVersion: getambassador.io/v3alpha1
Expand Down Expand Up @@ -114,7 +138,7 @@ prefix: /blah/`
}

ks := &snapshotTypes.KubernetesSnapshot{
Services: []*kates.Service{svc, ambSvc},
Services: []*kates.Service{svc, ambSvc, svcWithEmptyAnnotation, svcWithMissingAnnotation},
Ingresses: []*snapshotTypes.Ingress{{Ingress: *ingress}},
Hosts: []*amb.Host{ignoredHost},
}
Expand All @@ -123,6 +147,7 @@ prefix: /blah/`

err := ks.PopulateAnnotations(ctx)
assert.NoError(t, err)
assert.Equal(t, len(ks.Services), 4)
assert.Equal(t, map[string]snapshotTypes.AnnotationList{
"Service/svc.ambassador": {
&amb.Mapping{
Expand Down
4 changes: 2 additions & 2 deletions python/ambassador/config/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -120,8 +120,8 @@ class Config:
fatal_errors: int
object_errors: int

def __init__(self, logger:logging.Logger=None, schema_dir_path: Optional[str]=None) -> None:
self.logger = logger or logging.getLogger("ambassador.config")
def __init__(self, schema_dir_path: Optional[str]=None) -> None:
self.logger = logging.getLogger("ambassador.config")

if not schema_dir_path:
# Note that this "resource_filename" has to do with setuptool packages, not
Expand Down
2 changes: 1 addition & 1 deletion python/ambassador/fetch/fetcher.py
Original file line number Diff line number Diff line change
Expand Up @@ -300,7 +300,7 @@ def parse_watt(self, serialization: str, finalize: bool=True) -> None:
watt_list.append(obj)

# Remove annotations from the snapshot; we'll process them separately.
annotations = watt_k8s.pop('annotations') or {}
annotations = watt_k8s.pop('annotations', {})

# These objects have to be processed first, in order, as they depend
# on each other.
Expand Down
76 changes: 43 additions & 33 deletions python/tests/unit/test_acme_privatekey_secrets.py
Original file line number Diff line number Diff line change
@@ -1,28 +1,16 @@
from typing import Any, Dict, List, Optional, Union, TextIO, TYPE_CHECKING

import logging
import os
from typing import Optional, Tuple

import hashlib
import io
import json
import logging
import os

import pytest

logging.basicConfig(
level=logging.DEBUG,
format="%(asctime)s test %(levelname)s: %(message)s",
datefmt='%Y-%m-%d %H:%M:%S'
)

logger = logging.getLogger("ambassador")
logger.setLevel(logging.DEBUG)

from ambassador import Config, IR
from ambassador.fetch import ResourceFetcher
from ambassador.utils import SecretHandler, SecretInfo, SavedSecret

if TYPE_CHECKING:
from ambassador.ir import IRResource # pragma: no cover
from ambassador.utils import SecretHandler, SavedSecret

# MemorySecretHandler is a degenerate SecretHandler that doesn't actually
# cache anything to disk. It will never load a secret that isn't already
Expand Down Expand Up @@ -73,8 +61,8 @@ def cache_internal(self, name: str, namespace: str,
return SavedSecret(name, namespace, tls_crt_path, tls_key_path, user_key_path, root_crt_path, cert_data)


def _get_ir_config(watt):
aconf = Config(logger=logger)
def _get_config_and_ir(logger: logging.Logger, watt: str) -> Tuple[Config, IR]:
aconf = Config()
fetcher = ResourceFetcher(logger, aconf)
fetcher.parse_watt(watt)
aconf.load_all(fetcher.sorted())
Expand All @@ -85,23 +73,45 @@ def _get_ir_config(watt):
assert ir
return aconf, ir

def _get_errors(caplog: pytest.LogCaptureFixture, logger_name: str, watt_data_filename: str):
watt_data = open(watt_data_filename).read()

aconf, ir = _get_config_and_ir(
logging.getLogger(logger_name),
watt_data)

log_errors = [rec for rec in caplog.record_tuples if rec[0] == logger_name and rec[1] > logging.INFO]

aconf_errors = aconf.errors
if "-global-" in aconf_errors:
# We expect some global errors related to us not being a real Emissary instance, such as
# "Pod labels are not mounted in the container". Ignore those.
del aconf_errors["-global-"]

return log_errors, aconf_errors

@pytest.mark.compilertest
def test_acme_privatekey_secrets():
test_data_dir = os.path.join(
os.path.dirname(os.path.abspath(__file__)),
"test_general_data"
)
def test_acme_privatekey_secrets(caplog: pytest.LogCaptureFixture):
caplog.set_level(logging.DEBUG)

test_data_file = os.path.join(test_data_dir, "test-acme-private-key-snapshot.json")
watt_data = open(test_data_file).read()
nl = "\n"
tab = "\t"

aconf, ir = _get_ir_config(watt_data)
# What this test is really about is ensuring that test-acme-private-key-snapshot.json doesn't
# emit any errors. But, in order to validate the test itself and ensure that the test is
# checking for errors in the correct place, we'll also run against a bad version of that file
# and check that we *do* see errors.

# Remember, you'll see no log output unless the test fails!
logger.debug("---- ACONF")
logger.debug(json.dumps(aconf.as_dict(), indent=2, sort_keys=True))
logger.debug("---- IR")
logger.debug(json.dumps(ir.as_dict(), indent=2, sort_keys=True))
badsnap_log_errors, badsnap_aconf_errors = _get_errors(caplog, "test_acme_privatekey_secrets-bad", os.path.join(
os.path.dirname(os.path.abspath(__file__)),
"test_general_data",
"test-acme-private-key-snapshot-bad.json"))
assert badsnap_log_errors
assert not badsnap_aconf_errors, "Wanted no aconf errors but got:%s" % "".join([f"{nl} {err}" for err in badsnap_aconf_errors])

assert not aconf.errors, "Wanted no errors but got:\n %s" % "\n ".join(aconf.errors)
goodsnap_log_errors, goodsnap_aconf_errors = _get_errors(caplog, "test_acme_privatekey_secrets", os.path.join(
os.path.dirname(os.path.abspath(__file__)),
"test_general_data",
"test-acme-private-key-snapshot.json"))
assert not goodsnap_log_errors, "Wanted no logged errors bug got:%s" % "".join([f"{nl} {logging.getLevelName(rec[1])}{tab}{rec[0]}:{rec[2]}" for rec in goodsnap_log_errors])
assert not goodsnap_aconf_errors, "Wanted no aconf errors but got:%s" % "".join([f"{nl} {err}" for err in goodsnap_aconf_errors])
6 changes: 4 additions & 2 deletions python/tests/unit/test_cache.py
Original file line number Diff line number Diff line change
Expand Up @@ -485,7 +485,8 @@ def test_mappings_same_name_delta():

# loop through all the clusters in the resulting envoy config and pick out two Mappings from our test set (first and lase)
# to ensure their clusters were generated properly.
cluster1_ok, cluster2_ok = False
cluster1_ok = False
cluster2_ok = False
for cluster in econf['static_resources']['clusters']:
cname = cluster.get('name', None)
assert cname is not None, \
Expand All @@ -506,7 +507,8 @@ def test_mappings_same_name_delta():
econf = b[1]
econf = econf.as_dict()

cluster1_ok, cluster2_ok = False
cluster1_ok = False
cluster2_ok = False
for cluster in econf['static_resources']['clusters']:
cname = cluster.get('name', None)
assert cname is not None, \
Expand Down
51 changes: 0 additions & 51 deletions python/tests/unit/test_cache_data/cache_test_4.yaml
Original file line number Diff line number Diff line change
@@ -1,54 +1,4 @@
---
apiVersion: v1
kind: Namespace
metadata:
name: bar0
---
apiVersion: v1
kind: Namespace
metadata:
name: bar1
---
apiVersion: v1
kind: Namespace
metadata:
name: bar2
---
apiVersion: v1
kind: Namespace
metadata:
name: bar3
---
apiVersion: v1
kind: Namespace
metadata:
name: bar4
---
apiVersion: v1
kind: Namespace
metadata:
name: bar5
---
apiVersion: v1
kind: Namespace
metadata:
name: bar6
---
apiVersion: v1
kind: Namespace
metadata:
name: bar7
---
apiVersion: v1
kind: Namespace
metadata:
name: bar8
---
apiVersion: v1
kind: Namespace
metadata:
name: bar9
---
apiVersion: getambassador.io/v3alpha1
kind: Mapping
metadata:
Expand Down Expand Up @@ -147,4 +97,3 @@ metadata:
spec:
prefix: /bar-9/
service: bar-9.example.com:6666

0 comments on commit fd0aff9

Please sign in to comment.