From 55f6f3b8f0da7b4f469266d7045516c6187a0a42 Mon Sep 17 00:00:00 2001 From: Luke Shumaker Date: Thu, 15 Apr 2021 17:22:52 -0600 Subject: [PATCH 01/20] (from AES) watt: aggregator: Make invokeHook more readable --- cmd/watt/aggregator/aggregator.go | 44 +++++++++---------------------- 1 file changed, 13 insertions(+), 31 deletions(-) diff --git a/cmd/watt/aggregator/aggregator.go b/cmd/watt/aggregator/aggregator.go index 3fe8636f46..bc0fa93e22 100644 --- a/cmd/watt/aggregator/aggregator.go +++ b/cmd/watt/aggregator/aggregator.go @@ -1,9 +1,9 @@ package aggregator import ( + "bytes" + "context" "encoding/json" - "os/exec" - "strings" "sync" "time" @@ -16,6 +16,8 @@ import ( "github.com/datawire/ambassador/pkg/limiter" "github.com/datawire/ambassador/pkg/supervisor" "github.com/datawire/ambassador/pkg/watt" + "github.com/datawire/dlib/dexec" + "github.com/datawire/dlib/dlog" ) type WatchHook func(p *supervisor.Process, snapshot string) watchapi.WatchSet @@ -366,7 +368,7 @@ func ExecWatchHook(watchHooks []string) WatchHook { result := watchapi.WatchSet{} for _, hook := range watchHooks { - ws := invokeHook(p, hook, snapshot) + ws := invokeHook(p.Context(), hook, snapshot) result.KubernetesWatches = append(result.KubernetesWatches, ws.KubernetesWatches...) result.ConsulWatches = append(result.ConsulWatches, ws.ConsulWatches...) } @@ -375,39 +377,19 @@ func ExecWatchHook(watchHooks []string) WatchHook { } } -func lines(st string) []string { - return strings.Split(st, "\n") -} - -func invokeHook(p *supervisor.Process, hook, snapshot string) watchapi.WatchSet { - cmd := exec.Command("sh", "-c", hook) - cmd.Stdin = strings.NewReader(snapshot) - var watches, errors strings.Builder - cmd.Stdout = &watches - cmd.Stderr = &errors - err := cmd.Run() - stderr := errors.String() - if stderr != "" { - for _, line := range lines(stderr) { - p.Logf("watch hook stderr: %s", line) - } - } +func invokeHook(ctx context.Context, hook, snapshot string) watchapi.WatchSet { + watches, err := dexec.CommandContext(ctx, "sh", "-c", hook).Output() if err != nil { - p.Logf("watch hook failed: %v", err) + dlog.Infof(ctx, "watch hook failed: %v", err) return watchapi.WatchSet{} } - encoded := watches.String() - - decoder := json.NewDecoder(strings.NewReader(encoded)) + decoder := json.NewDecoder(bytes.NewReader(watches)) decoder.DisallowUnknownFields() - result := watchapi.WatchSet{} - err = decoder.Decode(&result) - if err != nil { - for _, line := range lines(encoded) { - p.Debugf("watch hook: %s", line) - } - p.Logf("watchset decode failed: %v", err) + + var result watchapi.WatchSet + if err := decoder.Decode(&result); err != nil { + dlog.Infof(ctx, "watchset decode failed: %v", err) return watchapi.WatchSet{} } From 13c71d3f9849bc2097eef53dc7618b5bea3be331 Mon Sep 17 00:00:00 2001 From: Luke Shumaker Date: Thu, 15 Apr 2021 17:23:03 -0600 Subject: [PATCH 02/20] (from AES) secret.py: Add some comments --- python/ambassador/fetch/secret.py | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/python/ambassador/fetch/secret.py b/python/ambassador/fetch/secret.py index 11417c8729..a02a922fdf 100644 --- a/python/ambassador/fetch/secret.py +++ b/python/ambassador/fetch/secret.py @@ -20,12 +20,12 @@ class SecretProcessor (ManagedKubernetesProcessor): ] KNOWN_DATA_KEYS = [ - 'tls.crt', - 'tls.key', - 'user.key', - 'cert-chain.pem', - 'key.pem', - 'root-cert.pem', + 'tls.crt', # type="kubernetes.io/tls" + 'tls.key', # type="kubernetes.io/tls" + 'user.key', # type="Opaque", used for AES ACME + 'cert-chain.pem', # type="istio.io/key-and-cert" + 'key.pem', # type="istio.io/key-and-cert" + 'root-cert.pem', # type="istio.io/key-and-cert" ] def __init__(self, manager: ResourceManager) -> None: From 77a4508966fb25730fc53fb7b7dfd80a19d172a1 Mon Sep 17 00:00:00 2001 From: Luke Shumaker Date: Mon, 19 Apr 2021 15:07:35 -0600 Subject: [PATCH 03/20] (from AES) envoy.mk: Fix typoed superfluous variable --- _cxx/envoy.mk | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/_cxx/envoy.mk b/_cxx/envoy.mk index aa9c42c137..64918d358e 100644 --- a/_cxx/envoy.mk +++ b/_cxx/envoy.mk @@ -158,7 +158,7 @@ $(OSS_HOME)/docker/base-envoy/envoy-static: $(ENVOY_BASH.deps) FORCE ); \ fi; \ } -%-stripped: % $(ENOVY_BASH.deps) FORCE +%-stripped: % FORCE @PS4=; set -ex; { \ if [ '$(ENVOY_COMMIT)' != '-' ] && docker run --rm --entrypoint=true $(ENVOY_FULL_DOCKER_TAG); then \ rsync -Pav --blocking-io -e 'docker run --rm -i' $$(docker image inspect $(ENVOY_FULL_DOCKER_TAG) --format='{{.Id}}' | sed 's/^sha256://'):/usr/local/bin/$(@F) $@; \ From cc1c75f79ae2e48a5f3420f8d141371d5efe0959 Mon Sep 17 00:00:00 2001 From: Alix Cook Date: Wed, 21 Apr 2021 10:36:59 -0400 Subject: [PATCH 04/20] (from AES) make agent tests less flaky probs by not letting it talk to k8s (#2558) * make agent tests less flaky probs by not letting it talk to k8s * fix golint --- pkg/agent/agent.go | 36 +++++++---- pkg/agent/agent_internal_test.go | 105 +++++++++++++++++++++---------- 2 files changed, 96 insertions(+), 45 deletions(-) diff --git a/pkg/agent/agent.go b/pkg/agent/agent.go index f51410a832..2dca2b3d68 100644 --- a/pkg/agent/agent.go +++ b/pkg/agent/agent.go @@ -257,12 +257,6 @@ func (a *Agent) Watch(ctx context.Context, snapshotURL string) error { } }() - ambHost, err := parseAmbassadorAdminHost(snapshotURL) - if err != nil { - // if we can't parse the host out of the url we won't be able to talk to ambassador - // anyway - return err - } client, err := kates.NewClient(kates.ClientConfig{}) if err != nil { return err @@ -294,18 +288,35 @@ func (a *Agent) Watch(ctx context.Context, snapshotURL string) error { dc := NewDynamicClient(client.DynamicInterface(), NewK8sInformer) rolloutGvr, _ := schema.ParseResourceArg("rollouts.v1alpha1.argoproj.io") rolloutCallback := dc.WatchGeneric(ctx, ns, rolloutGvr) - rolloutStore := NewRolloutStore() applicationGvr, _ := schema.ParseResourceArg("applications.v1alpha1.argoproj.io") applicationCallback := dc.WatchGeneric(ctx, ns, applicationGvr) - applicationStore := NewApplicationStore() + return a.watch(ctx, snapshotURL, configAcc, acc, rolloutCallback, applicationCallback) +} + +type accumulator interface { + Changed() chan struct{} + FilteredUpdate(target interface{}, deltas *[]*kates.Delta, predicate func(*kates.Unstructured) bool) bool +} + +func (a *Agent) watch(ctx context.Context, snapshotURL string, configAccumulator accumulator, podAccumulator accumulator, rolloutCallback <-chan *GenericCallback, applicationCallback <-chan *GenericCallback) error { + var err error // for the watch // we're not watching CRDs or anything special, so i'm pretty sure it's okay just to say all // the pods are valid isValid := func(un *kates.Unstructured) bool { return true } + ambHost, err := parseAmbassadorAdminHost(snapshotURL) + if err != nil { + // if we can't parse the host out of the url we won't be able to talk to ambassador + // anyway + return err + } + + applicationStore := NewApplicationStore() + rolloutStore := NewRolloutStore() dlog.Info(ctx, "Agent is running") for { // Wait for an event @@ -318,21 +329,21 @@ func (a *Agent) Watch(ctx context.Context, snapshotURL string) error { // bunch case <-time.After(1 * time.Second): // just a ticker, this will fallthru to the snapshot getting thing - case <-configAcc.Changed(): + case <-configAccumulator.Changed(): configSnapshot := struct { Secrets []kates.Secret ConfigMaps []kates.ConfigMap }{} - if !configAcc.FilteredUpdate(&configSnapshot, &[]*kates.Delta{}, isValid) { + if !configAccumulator.FilteredUpdate(&configSnapshot, &[]*kates.Delta{}, isValid) { continue } a.handleAPIKeyConfigChange(ctx, configSnapshot.Secrets, configSnapshot.ConfigMaps) - case <-acc.Changed(): + case <-podAccumulator.Changed(): var deltas []*kates.Delta podSnapshot := struct { Pods []kates.Pod }{} - if !acc.FilteredUpdate(&podSnapshot, &deltas, isValid) { + if !podAccumulator.FilteredUpdate(&podSnapshot, &deltas, isValid) { continue } a.podStore = NewPodStore(podSnapshot.Pods) @@ -371,6 +382,7 @@ func (a *Agent) Watch(ctx context.Context, snapshotURL string) error { a.MaybeReport(ctx) } + } func (a *Agent) MaybeReport(ctx context.Context) { diff --git a/pkg/agent/agent_internal_test.go b/pkg/agent/agent_internal_test.go index 0e13e97745..050d7c1b90 100644 --- a/pkg/agent/agent_internal_test.go +++ b/pkg/agent/agent_internal_test.go @@ -410,33 +410,23 @@ func TestProcessSnapshot(t *testing.T) { } } -// Call agent.Watch() with a cancellable context, then cancel the context and make sure the watch -// completes to ensure graceful exits. -func TestWatchSnapshotContextCancelled(t *testing.T) { - // cancellable context - ctx, cancel := getCtxLog() +type mockAccumulator struct { + changedChan chan struct{} + targetInterface interface{} +} - a := NewAgent(nil) - watchDone := make(chan error) +func (m *mockAccumulator) Changed() chan struct{} { + return m.changedChan +} - // setup async watch - go func() { - err := a.Watch(ctx, "http://localhost:9697/snapshot-external") - watchDone <- err - }() - // sleep for a sec so we enter the Watch loop - time.Sleep(2 * time.Second) +func (m *mockAccumulator) FilteredUpdate(target interface{}, deltas *[]*kates.Delta, predicate func(*kates.Unstructured) bool) bool { + rawtarget, err := json.Marshal(m.targetInterface) - // cancel the context - cancel() - select { - // make sure the watch exits without error - case err := <-watchDone: - assert.Nil(t, err) - case <-time.After(3 * time.Second): - t.Fatal("Timed out waiting for watch to finish after cancelling context") + if err != nil { + return false } - assert.False(t, a.reportRunning.Value()) + err = json.Unmarshal(rawtarget, target) + return true } // Set up a watch and send a MinReportPeriod directive to the directive channel @@ -457,8 +447,17 @@ func TestWatchReportPeriodDirective(t *testing.T) { expectedDuration, err := time.ParseDuration("50s10ns") assert.Nil(t, err) + podAcc := &mockAccumulator{ + changedChan: make(chan struct{}), + } + configAcc := &mockAccumulator{ + changedChan: make(chan struct{}), + } + rolloutCallback := make(chan *GenericCallback) + appCallback := make(chan *GenericCallback) + go func() { - err := a.Watch(ctx, "http://localhost:9697") + err := a.watch(ctx, "http://localhost:9697", configAcc, podAcc, rolloutCallback, appCallback) watchDone <- err }() dur := durationpb.Duration{ @@ -482,7 +481,7 @@ func TestWatchReportPeriodDirective(t *testing.T) { select { case err := <-watchDone: assert.Nil(t, err) - case <-time.After(3 * time.Second): + case <-time.After(10 * time.Second): t.Fatal("Timed out waiting for watch to finish after cancelling context") } // make sure that the agent's min report period is what we expect @@ -502,8 +501,16 @@ func TestWatchEmptyDirectives(t *testing.T) { directiveChan := make(chan *agent.Directive) a.newDirective = directiveChan + podAcc := &mockAccumulator{ + changedChan: make(chan struct{}), + } + configAcc := &mockAccumulator{ + changedChan: make(chan struct{}), + } + rolloutCallback := make(chan *GenericCallback) + appCallback := make(chan *GenericCallback) go func() { - err := a.Watch(ctx, "http://localhost:9697") + err := a.watch(ctx, "http://localhost:9697", configAcc, podAcc, rolloutCallback, appCallback) watchDone <- err }() @@ -537,7 +544,7 @@ func TestWatchEmptyDirectives(t *testing.T) { select { case err := <-watchDone: assert.Nil(t, err) - case <-time.After(3 * time.Second): + case <-time.After(10 * time.Second): t.Fatal("Timed out waiting for watch to finish after cancelling context") } } @@ -567,10 +574,18 @@ func TestWatchStopReportingDirective(t *testing.T) { } a.comm = c a.connInfo = &ConnInfo{hostname: "localhost", port: "8080", secure: false} + podAcc := &mockAccumulator{ + changedChan: make(chan struct{}), + } + configAcc := &mockAccumulator{ + changedChan: make(chan struct{}), + } + rolloutCallback := make(chan *GenericCallback) + appCallback := make(chan *GenericCallback) // start watch go func() { - err := a.Watch(ctx, "http://thisdoesntmatter") + err := a.watch(ctx, "http://localhost:9697", configAcc, podAcc, rolloutCallback, appCallback) watchDone <- err }() @@ -589,7 +604,7 @@ func TestWatchStopReportingDirective(t *testing.T) { select { case err := <-watchDone: assert.Nil(t, err) - case <-time.After(3 * time.Second): + case <-time.After(10 * time.Second): t.Fatal("Timed out waiting for watch to finish after cancelling context") } // make sure that reportingStopped is still set @@ -655,10 +670,18 @@ func TestWatchErrorSendingSnapshot(t *testing.T) { a.comm = c watchDone := make(chan error) + podAcc := &mockAccumulator{ + changedChan: make(chan struct{}), + } + configAcc := &mockAccumulator{ + changedChan: make(chan struct{}), + } + rolloutCallback := make(chan *GenericCallback) + appCallback := make(chan *GenericCallback) // start the watch go func() { - err := a.Watch(ctx, ts.URL) + err := a.watch(ctx, ts.URL, configAcc, podAcc, rolloutCallback, appCallback) watchDone <- err }() @@ -783,10 +806,18 @@ func TestWatchWithSnapshot(t *testing.T) { a.comm = c watchDone := make(chan error) + podAcc := &mockAccumulator{ + changedChan: make(chan struct{}), + } + configAcc := &mockAccumulator{ + changedChan: make(chan struct{}), + } + rolloutCallback := make(chan *GenericCallback) + appCallback := make(chan *GenericCallback) // start the watch go func() { - err := a.Watch(ctx, ts.URL) + err := a.watch(ctx, ts.URL, configAcc, podAcc, rolloutCallback, appCallback) watchDone <- err }() @@ -814,7 +845,7 @@ func TestWatchWithSnapshot(t *testing.T) { case err := <-watchDone: // make sure the watch finishes without a problem assert.Nil(t, err) - case <-time.After(3 * time.Second): + case <-time.After(10 * time.Second): t.Fatal("Timed out waiting for watch to finish after cancelling context") } sentSnaps := client.GetSnapshots() @@ -912,6 +943,14 @@ func TestWatchEmptySnapshot(t *testing.T) { } })) defer ts.Close() + podAcc := &mockAccumulator{ + changedChan: make(chan struct{}), + } + configAcc := &mockAccumulator{ + changedChan: make(chan struct{}), + } + rolloutCallback := make(chan *GenericCallback) + appCallback := make(chan *GenericCallback) go func() { defer func() { if r := recover(); r != nil { @@ -919,7 +958,7 @@ func TestWatchEmptySnapshot(t *testing.T) { t.Errorf("Panic-ed while sending an empty snapshot") } }() - err := a.Watch(ctx, ts.URL) + err := a.watch(ctx, ts.URL, configAcc, podAcc, rolloutCallback, appCallback) watchDone <- err }() select { From f14b925512f47d95c874aaa3eff9827c1d4aa9b9 Mon Sep 17 00:00:00 2001 From: Alix Cook Date: Wed, 21 Apr 2021 16:45:28 -0400 Subject: [PATCH 05/20] (from AES) edge stack env var (#2578) * edge stack env var * fix linter --- cmd/entrypoint/env.go | 3 ++ python/ambassador/ambscout.py | 7 +++-- python/ambassador/fetch/fetcher.py | 48 ++++++++++++++++++++++++++---- python/ambassador/ir/ir.py | 9 ++++-- python/ambassador_cli/mockery.py | 7 +++-- python/kat/harness.py | 38 ++++++++++++++++------- python/post_update.py | 3 +- 7 files changed, 92 insertions(+), 23 deletions(-) diff --git a/cmd/entrypoint/env.go b/cmd/entrypoint/env.go index e579e94a90..a8b447a9b8 100644 --- a/cmd/entrypoint/env.go +++ b/cmd/entrypoint/env.go @@ -249,6 +249,9 @@ func IsAmbassadorSingleNamespace() bool { } func IsEdgeStack() bool { + if envbool("EDGE_STACK") { + return true + } _, err := os.Stat("/ambassador/.edge_stack") if err == nil { return true diff --git a/python/ambassador/ambscout.py b/python/ambassador/ambscout.py index 2b461a4974..b0d3faa74f 100644 --- a/python/ambassador/ambscout.py +++ b/python/ambassador/ambscout.py @@ -10,7 +10,7 @@ import semantic_version from .scout import Scout -from .utils import parse_json, dump_json +from .utils import parse_json, dump_json, parse_bool # Import version stuff directly from ambassador.VERSION to avoid a circular import. from .VERSION import Version, Build, BuildInfo @@ -86,7 +86,10 @@ def __init__(self, install_id=None, update_frequency=datetime.timedelta(hours=12 self.runtime = "kubernetes" if os.environ.get('KUBERNETES_SERVICE_HOST', None) else "docker" self.namespace = os.environ.get('AMBASSADOR_NAMESPACE', 'default') - self.is_edge_stack = os.path.exists('/ambassador/.edge_stack') + # Allow an environment variable to state whether we're in Edge Stack. But keep the + # existing condition as sufficient, so that there is less of a chance of breaking + # things running in a container with this file present. + self.is_edge_stack = parse_bool(os.environ.get('EDGE_STACK', 'false')) or os.path.exists('/ambassador/.edge_stack') self.app = "aes" if self.is_edge_stack else "ambassador" self.version = Version self.semver = self.get_semver(self.version) diff --git a/python/ambassador/fetch/fetcher.py b/python/ambassador/fetch/fetcher.py index 3c6444a8f5..0cfcfbd6b5 100644 --- a/python/ambassador/fetch/fetcher.py +++ b/python/ambassador/fetch/fetcher.py @@ -7,7 +7,7 @@ import re from ..config import ACResource, Config -from ..utils import parse_yaml, parse_json, dump_json +from ..utils import parse_yaml, parse_json, dump_json, parse_bool from .dependency import DependencyManager, IngressClassesDependency, SecretDependency, ServiceDependency from .resource import NormalizedResource, ResourceManager @@ -99,8 +99,34 @@ def __init__(self, logger: logging.Logger, aconf: 'Config', # doesn't move around if you change the configuration base. init_dir = '/ambassador/init-config' - if os.path.isdir(init_dir): - self.load_from_filesystem(init_dir, k8s=True, recurse=True, finalize=False) + automatic_manifests = [] + edge_stack_mappings_path = os.path.join(init_dir, "edge-stack-mappings.yaml") + if parse_bool(os.environ.get('EDGE_STACK', 'false')) and not os.path.exists(edge_stack_mappings_path): + # HACK + # If we're running in Edge Stack via environment variable and the magic "edge-stack-mappings.yaml" file doesn't + # exist in its well known location, then go ahead and add it. This should _not_ be necessary under + # normal circumstances where Edge Stack is running in its container. We do this so that tests can + # run outside of a container with this environment variable set. + automatic_manifests.append(''' +--- +apiVersion: getambassador.io/v2 +kind: Mapping +metadata: + name: ambassador-edge-stack + namespace: _automatic_ + labels: + product: aes + ambassador_diag_class: private +spec: + ambassador_id: [ "_automatic_" ] + prefix: /.ambassador/ + rewrite: "" + service: "127.0.0.1:8500" + precedence: 1000000 +''') + + if os.path.isdir(init_dir) or len(automatic_manifests) > 0: + self.load_from_filesystem(init_dir, k8s=True, recurse=True, finalize=False, automatic_manifests=automatic_manifests) @property def elements(self) -> List[ACResource]: @@ -111,7 +137,8 @@ def location(self) -> str: return str(self.manager.locations.current) def load_from_filesystem(self, config_dir_path, recurse: bool=False, - k8s: bool=False, finalize: bool=True): + k8s: bool=False, finalize: bool=True, + automatic_manifests: List[str]=[]): inputs: List[Tuple[str, str]] = [] if os.path.isdir(config_dir_path): @@ -139,10 +166,14 @@ def load_from_filesystem(self, config_dir_path, recurse: bool=False, # self.logger.debug("%s: SAVE configuration file" % filepath) inputs.append((filepath, filename)) - else: + elif os.path.isfile(config_dir_path): # this allows a file to be passed into the ambassador cli # rather than just a directory inputs.append((config_dir_path, os.path.basename(config_dir_path))) + elif len(automatic_manifests) == 0: + # The config_dir_path wasn't a directory nor a file, and there are + # no automatic manifests. Nothing to do. + self.logger.debug("no init directory/file at path %s and no automatic manifests, doing nothing" % config_dir_path) for filepath, filename in inputs: self.logger.debug("reading %s (%s)" % (filename, filepath)) @@ -153,6 +184,13 @@ def load_from_filesystem(self, config_dir_path, recurse: bool=False, except IOError as e: self.aconf.post_error("could not read YAML from %s: %s" % (filepath, e)) + for manifest in automatic_manifests: + self.logger.debug("reading automatic manifest: %s" % manifest) + try: + self.parse_yaml(manifest, k8s=k8s, filename="_automatic_", finalize=False) + except IOError as e: + self.aconf.post_error("could not read automatic manifest: %s\n%s" % (manifest, e)) + if finalize: self.finalize() diff --git a/python/ambassador/ir/ir.py b/python/ambassador/ir/ir.py index f5a1b8c304..13075dbe5f 100644 --- a/python/ambassador/ir/ir.py +++ b/python/ambassador/ir/ir.py @@ -22,7 +22,7 @@ from ..constants import Constants -from ..utils import RichStatus, SavedSecret, SecretHandler, SecretInfo, dump_json +from ..utils import RichStatus, SavedSecret, SecretHandler, SecretInfo, dump_json, parse_bool from ..cache import Cache, NullCache from ..config import Config @@ -188,7 +188,10 @@ def __init__(self, aconf: Config, # within $AMBASSADOR_CONFIG_BASE_DIR: it stays in /ambassador no matter what. self.agent_active = (os.environ.get("AGENT_SERVICE", None) != None) - self.edge_stack_allowed = os.path.exists('/ambassador/.edge_stack') + # Allow an environment variable to state whether we're in Edge Stack. But keep the + # existing condition as sufficient, so that there is less of a chance of breaking + # things running in a container with this file present. + self.edge_stack_allowed = parse_bool(os.environ.get('EDGE_STACK', 'false')) or os.path.exists('/ambassador/.edge_stack') self.agent_origination_ctx = None # OK, time to get this show on the road. First things first: set up the @@ -359,7 +362,7 @@ def __init__(self, aconf: Config, # not necessarily the same. This is currently fine, since we never use # envoy config as a source of truth - we leave that to the cluster annotations # and CRDs. - # + # # Another important consideration is that when the cache is active, we need # to shred any cached cluster with this mangled_name, because the mangled_name # can change as new clusters appear! This is obviously not ideal. diff --git a/python/ambassador_cli/mockery.py b/python/ambassador_cli/mockery.py index ba87a66a50..1b156e1c04 100644 --- a/python/ambassador_cli/mockery.py +++ b/python/ambassador_cli/mockery.py @@ -45,7 +45,7 @@ from ambassador import Config, IR, Diagnostics, EnvoyConfig from ambassador.fetch import ResourceFetcher -from ambassador.utils import parse_yaml, SecretHandler, SecretInfo, dump_json +from ambassador.utils import parse_yaml, SecretHandler, SecretInfo, dump_json, parse_bool from kat.utils import ShellCommand if TYPE_CHECKING: @@ -294,7 +294,10 @@ def run_hook(self) -> Tuple[bool, bool]: class MockSecretHandler(SecretHandler): def load_secret(self, resource: 'IRResource', secret_name: str, namespace: str) -> Optional[SecretInfo]: - if os.path.exists('/ambassador/.edge_stack'): + # Allow an environment variable to state whether we're in Edge Stack. But keep the + # existing condition as sufficient, so that there is less of a chance of breaking + # things running in a container with this file present. + if parse_bool(os.environ.get('EDGE_STACK', 'false')) or os.path.exists('/ambassador/.edge_stack'): if ((secret_name == "fallback-self-signed-cert") and (namespace == Config.ambassador_namespace)): # This is Edge Stack. Force the fake TLS secret. diff --git a/python/kat/harness.py b/python/kat/harness.py index 6adcd5b68a..0ac91fe1a5 100755 --- a/python/kat/harness.py +++ b/python/kat/harness.py @@ -19,6 +19,7 @@ import traceback from .utils import ShellCommand, namespace_manifest +from ambassador.utils import parse_bool from yaml.scanner import ScannerError as YAMLScanError @@ -42,21 +43,38 @@ # or all (allow both). Default is all. RUN_MODE = os.environ.get('KAT_RUN_MODE', 'all').lower() -# Figure out if we're running in Edge Stack or what. -EDGE_STACK = False -GOLD_ROOT = "/buildroot/ambassador/python/tests/gold" -MANIFEST_ROOT = "/buildroot/ambassador/python/tests/manifests" +# We may have a SOURCE_ROOT override from the environment +SOURCE_ROOT = os.environ.get('SOURCE_ROOT', '') +# Figure out if we're running in Edge Stack or what. if os.path.exists("/buildroot/apro.version"): + # We let /buildroot/apro.version remain a source of truth to minimize the + # chances that we break anything that currently uses the builder shell. + EDGE_STACK = True +else: + # If we do not see concrete evidence of running in an apro builder shell, + # then try to decide if the user wants us to assume we're running Edge Stack + # from an environment variable. And if that isn't set, just assume OSS. + EDGE_STACK = parse_bool(os.environ.get('EDGE_STACK', 'false')) + +if EDGE_STACK: # Hey look, we're running inside Edge Stack! print("RUNNING IN EDGE STACK") - EDGE_STACK = True - GOLD_ROOT = "/buildroot/apro/tests/pytest/gold" - MANIFEST_ROOT = "/buildroot/apro/tests/pytest/manifests" - # RUN_MODE = "envoy" + # SOURCE_ROOT is optional, and we assume that if it isn't set, the user is + # running in a build shell and we should look for sources in the usual location. + if not SOURCE_ROOT: + SOURCE_ROOT = "/buildroot/apro" + GOLD_ROOT = os.path.join(SOURCE_ROOT, "tests/pytest/gold") + MANIFEST_ROOT = os.path.join(SOURCE_ROOT, "tests/pytest/manifests") else: + # We're either not running in Edge Stack or we're not sure, so just assume OSS. print("RUNNING IN OSS") - + # SOURCE_ROOT is optional, and we assume that if it isn't set, the user is + # running in a build shell and we should look for sources in the usual location. + if not SOURCE_ROOT: + SOURCE_ROOT = "/buildroot/ambassador" + GOLD_ROOT = os.path.join(SOURCE_ROOT, "python/tests/gold") + MANIFEST_ROOT = os.path.join(SOURCE_ROOT, "python/tests/manifests") def load_manifest(manifest_name: str) -> str: return open(os.path.join(MANIFEST_ROOT, f"{manifest_name.lower()}.yaml"), "r").read() @@ -1551,7 +1569,7 @@ def _setup_k8s(self, selected): time.sleep(5) else: print(f'CRDS unchanged {reason}, skipping apply.') - + # Next up: the KAT pod. KAT_CLIENT_POD = load_manifest("kat_client_pod") if os.environ.get("DEV_USE_IMAGEPULLSECRET", False): diff --git a/python/post_update.py b/python/post_update.py index d22427ad44..4481e21f38 100644 --- a/python/post_update.py +++ b/python/post_update.py @@ -4,6 +4,7 @@ import urllib import requests +from ambassador.utils import parse_bool def usage(program): sys.stderr.write(f'Usage: {program} [--watt|--k8s|--fs] UPDATE_URL\n') @@ -42,7 +43,7 @@ def usage(program): urls = [ f'{base_host}/{base_path}/{url_type}' ] -if os.path.exists('/ambassador/.edge_stack'): +if parse_bool(os.environ.get('EDGE_STACK', 'false')) or os.path.exists('/ambassador/.edge_stack'): urls.append(f'{sidecar_host}/{sidecar_path}/{url_type}') exitcode = 0 From 6f09d6b752bc9fc2954f90c6d86aab173f35dcbc Mon Sep 17 00:00:00 2001 From: Rafael Schloming Date: Fri, 23 Apr 2021 12:02:25 -0400 Subject: [PATCH 06/20] (from AES) Fixup a booboo leftover from the recent release. --- docs/yaml/versions.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/docs/yaml/versions.yml b/docs/yaml/versions.yml index dd429be576..d83b0c327a 100644 --- a/docs/yaml/versions.yml +++ b/docs/yaml/versions.yml @@ -1,3 +1,2 @@ version: 1.13.1 quoteVersion: 0.4.1 -branch: relelase/v1.13 From 57b395581153df3bd4c2ce2c74fa08d5491fb905 Mon Sep 17 00:00:00 2001 From: Rafael Schloming Date: Fri, 23 Apr 2021 12:06:28 -0400 Subject: [PATCH 07/20] (from AES) Changelog fixup. --- CHANGELOG.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index e6eb1ce1cc..9acacf02bc 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -63,7 +63,8 @@ Please see the [Envoy documentation](https://www.envoyproxy.io/docs/envoy/latest ## RELEASE NOTES -## [1.13.1] April 21, 2021 +## [1.13.1] April 22, 2021 +[1.13.1]: https://github.com/datawire/ambassador/compare/v1.13.0...v1.13.1 - Bugfix: Potentially increased CPU Usage for deployments with large numbers of Hosts ([#3358]) From 1e47f0105e1ea5fc1b1dfff68d242ce6b9b86705 Mon Sep 17 00:00:00 2001 From: Alix Cook Date: Mon, 26 Apr 2021 11:40:25 -0400 Subject: [PATCH 08/20] (from AES) perf baseline 2 k3ds (#2582) --- .ci/cluster-claim | 11 +++++++++++ .circleci/config.yml | 1 + .circleci/config.yml.d/amb_jobs.yml | 1 + 3 files changed, 13 insertions(+) diff --git a/.ci/cluster-claim b/.ci/cluster-claim index 38471c41af..dadee75463 100755 --- a/.ci/cluster-claim +++ b/.ci/cluster-claim @@ -44,6 +44,17 @@ set -o errexit set -o nounset set -o xtrace +if [ -n "${USE_LOCAL_K3S_CLUSTER:-}" ] ; then + mkdir -p ~/.kube + export DEV_KUBECONFIG=~/.kube/kubeception.yaml + touch ${DEV_KUBECONFIG} + if [ -z "${K3S_CLUSTER_NAME:-}" ] ; then + K3S_CLUSTER_NAME=amb-ci + fi + KUBECONFIG=${DEV_KUBECONFIG} k3d cluster create ${K3S_CLUSTER_NAME} --k3s-server-arg "--no-deploy=traefik" + exit 0 +fi + if [ -n "${KUBECEPTION_TOKEN}" ]; then trap push_metrics EXIT diff --git a/.circleci/config.yml b/.circleci/config.yml index 97d11b54c9..f9cc290c7e 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -150,6 +150,7 @@ commands: # time it still runs OK if there's plenty of RAM. run: | echo >>"$BASH_ENV" 'export KUBECEPTION_PROFILE=large' + - install-helm - amb-config-cluster-and-registry - # main run: diff --git a/.circleci/config.yml.d/amb_jobs.yml b/.circleci/config.yml.d/amb_jobs.yml index aaf9e7c2ed..aaea7f39ff 100644 --- a/.circleci/config.yml.d/amb_jobs.yml +++ b/.circleci/config.yml.d/amb_jobs.yml @@ -161,6 +161,7 @@ commands: # time it still runs OK if there's plenty of RAM. - run: | echo >>"$BASH_ENV" 'export KUBECEPTION_PROFILE=large' + - install-helm - amb-config-cluster-and-registry # main From 9df8893a36087a32939f3235d31740665c5378c7 Mon Sep 17 00:00:00 2001 From: Alix Cook Date: Mon, 26 Apr 2021 11:53:34 -0400 Subject: [PATCH 09/20] (from AES) run gotests without a kluster+build container in CI (#2569) * gotest runs without kluster+builder container * agentcom dockerfile * share create-venv --- .circleci/config.yml | 119 +- .circleci/config.yml.d/amb_jobs.yml | 35 +- .circleci/config.yml.d/amb_oss.yml | 71 +- .circleci/config.yml.d/generic_util.yml | 13 + .gitignore | 3 + OPENSOURCE.md | 12 +- build-aux-local/generate.mk | 7 +- builder/builder.mk | 36 +- builder/builder.sh | 14 +- cmd/agent/agent_test.go | 249 -- cmd/agent/test/argo-application-crd.yaml | 1760 ------------ cmd/agent/test/argo-application.yaml | 16 - cmd/agent/test/argo-rollouts-crd.yaml | 3273 ---------------------- cmd/agent/test/argo-rollouts.yaml | 40 - cmd/edgectl/edgectl_test.go | 191 -- go.mod | 6 +- go.sum | 15 + pkg/agent/agent_internal_test.go | 8 + pkg/envoy/prefixer.go | 2 + pkg/gateway/dispatcher_test.go | 15 + pkg/gateway/gw_transforms_test.go | 2 + pkg/k8s/client_test.go | 1 + pkg/k8s/resource_test.go | 1 + pkg/k8s/watcher_test.go | 4 + 24 files changed, 305 insertions(+), 5588 deletions(-) delete mode 100644 cmd/agent/agent_test.go delete mode 100644 cmd/agent/test/argo-application-crd.yaml delete mode 100644 cmd/agent/test/argo-application.yaml delete mode 100644 cmd/agent/test/argo-rollouts-crd.yaml delete mode 100644 cmd/agent/test/argo-rollouts.yaml delete mode 100644 cmd/edgectl/edgectl_test.go diff --git a/.circleci/config.yml b/.circleci/config.yml index f9cc290c7e..6b89a3f08b 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -100,6 +100,38 @@ commands: # teardown - dirty-check - amb-images-save-workspace + "job-gotest": + parameters: + "fast-reconfigure": + type: boolean + default: false + "legacy-mode": + type: boolean + default: false + steps: + # setup + - amb-linux-install + - install-gotestsum + - amb-checkout + - skip-if-only-changes: + to: docs/ + - amb-config-registry + - run: + name: "Test" + no_output_timeout: "30m" + command: | + export DEV_KUBE_NO_PVC=yes + export KAT_REQ_LIMIT=900 + export AMBASSADOR_LEGACY_MODE=<< parameters.legacy-mode >> # ParseBool + export AMBASSADOR_FAST_RECONFIGURE=<< parameters.fast-reconfigure >> # ParseBool + export TEST_XML_DIR=/tmp/test-logs/xml/ + mkdir -p ${TEST_XML_DIR} + make gotest + # teardown + - amb-save-logs + - store_test_results: + path: /tmp/test-logs/xml/ + - dirty-check "job-test": parameters: "test": @@ -107,7 +139,6 @@ commands: enum: - "test" # everything but pytest-envoy - "ingresstest" - - "gotest" - "pytest" - "pytest-envoy" - "pytest-envoy-v3" @@ -434,6 +465,19 @@ commands: - amb-checkout - skip-if-no-changes: to: docs/ + install-gotestsum: + steps: + - run: + name: "Install gotestsum" + command: | + go get gotest.tools/gotestsum + install-redis: + steps: + - run: + name: "Install Redis" + command: | + sudo apt update -y + sudo apt install -y redis-server install-k3d: parameters: version: @@ -642,6 +686,19 @@ jobs: steps: - job-images: release: << parameters.release >> + oss-gotest: + executor: oss-linux + parameters: + fast-reconfigure: + type: boolean + default: false + legacy-mode: + type: boolean + default: false + steps: + - job-gotest: + fast-reconfigure: << parameters.fast-reconfigure >> + legacy-mode: << parameters.legacy-mode >> oss-test: executor: oss-linux parameters: @@ -650,7 +707,6 @@ jobs: enum: - "test" # everything but pytest-envoy - "ingresstest" - - "gotest" - "pytest" - "pytest-envoy" - "pytest-envoy-v3" @@ -759,6 +815,19 @@ workflows: name: "oss-dev-lint" - oss-chart: name: "oss-dev-chart" + - oss-gotest: + name: "oss-dev-gotest<<# matrix.fast-reconfigure >>-fastreconfigure<><<# matrix.legacy-mode >>-legacy<>" + matrix: + alias: "oss-dev-gotest" + parameters: + fast-reconfigure: + - true + - false + legacy-mode: + - false + # If you enable testing with legacy-mode true as well, you'll also need + # to add some exclusions -- see the Release workflow for more. - oss-test: requires: - "oss-dev-images" @@ -769,7 +838,6 @@ workflows: alias: "oss-dev-test" parameters: test: - - "gotest" - "pytest" - "pytest-envoy" - "pytest-envoy-v3" @@ -835,6 +903,27 @@ workflows: only: /^v[0-9]+\.[0-9]+\.[0-9]+-(rc|ea)\.[0-9]+$/ branches: ignore: /.*/ + - oss-gotest: + name: "oss-release-gotest<<# matrix.fast-reconfigure >>-fastreconfigure<><<# matrix.legacy-mode >>-legacy<>" + matrix: + alias: "oss-release-gotest" + parameters: + fast-reconfigure: + - true + - false + legacy-mode: + - true + - false + exclude: + - fast-reconfigure: true + legacy-mode: true + filters: + tags: + only: /^v[0-9]+\.[0-9]+\.[0-9]+-(rc|ea)\.[0-9]+$/ + branches: + ignore: /.*/ - oss-test: requires: - "oss-release-images" @@ -845,7 +934,6 @@ workflows: alias: "oss-release-test" parameters: test: - - "gotest" - "pytest" - "pytest-envoy" - "pytest-envoy-v3" @@ -862,9 +950,6 @@ workflows: - true - false exclude: - - test: gotest - fast-reconfigure: true - legacy-mode: true - test: pytest fast-reconfigure: true legacy-mode: true @@ -908,6 +993,22 @@ workflows: jobs: - oss-images: name: "oss-nightly-images" + - oss-gotest: + name: "oss-nightly-gotest<<# matrix.fast-reconfigure >>-fastreconfigure<><<# matrix.legacy-mode >>-legacy<>" + matrix: + alias: "oss-nightly-gotest" + parameters: + fast-reconfigure: + - true + - false + legacy-mode: + - true + - false + exclude: + - fast-reconfigure: true + legacy-mode: true - oss-test: requires: - "oss-nightly-images" @@ -918,7 +1019,6 @@ workflows: alias: "oss-nightly-test" parameters: test: - - "gotest" - "pytest" - "pytest-envoy" # Running the ingresstests would require we install `kind` and @@ -934,9 +1034,6 @@ workflows: - true - false exclude: - - test: gotest - fast-reconfigure: true - legacy-mode: true - test: pytest fast-reconfigure: true legacy-mode: true diff --git a/.circleci/config.yml.d/amb_jobs.yml b/.circleci/config.yml.d/amb_jobs.yml index aaea7f39ff..5659395522 100644 --- a/.circleci/config.yml.d/amb_jobs.yml +++ b/.circleci/config.yml.d/amb_jobs.yml @@ -111,6 +111,40 @@ commands: - dirty-check - amb-images-save-workspace + "job-gotest": + parameters: + "fast-reconfigure": + type: boolean + default: false + "legacy-mode": + type: boolean + default: false + steps: + # setup + - amb-linux-install + - install-gotestsum + - amb-checkout + - skip-if-only-changes: + to: docs/ + - amb-config-registry + - run: + name: "Test" + no_output_timeout: "30m" + command: | + export DEV_KUBE_NO_PVC=yes + export KAT_REQ_LIMIT=900 + export AMBASSADOR_LEGACY_MODE=<< parameters.legacy-mode >> # ParseBool + export AMBASSADOR_FAST_RECONFIGURE=<< parameters.fast-reconfigure >> # ParseBool + export TEST_XML_DIR=/tmp/test-logs/xml/ + mkdir -p ${TEST_XML_DIR} + make gotest + + # teardown + - amb-save-logs + - store_test_results: + path: /tmp/test-logs/xml/ + - dirty-check + "job-test": parameters: "test": @@ -118,7 +152,6 @@ commands: enum: - "test" # everything but pytest-envoy - "ingresstest" - - "gotest" - "pytest" - "pytest-envoy" - "pytest-envoy-v3" diff --git a/.circleci/config.yml.d/amb_oss.yml b/.circleci/config.yml.d/amb_oss.yml index c8a6c23e1e..3a7e4fe738 100644 --- a/.circleci/config.yml.d/amb_oss.yml +++ b/.circleci/config.yml.d/amb_oss.yml @@ -22,6 +22,20 @@ jobs: - job-images: release: << parameters.release >> + "oss-gotest": + executor: oss-linux + parameters: + "fast-reconfigure": + type: boolean + default: false + "legacy-mode": + type: boolean + default: false + steps: + - job-gotest: + fast-reconfigure: << parameters.fast-reconfigure >> + legacy-mode: << parameters.legacy-mode >> + "oss-test": executor: oss-linux parameters: @@ -30,7 +44,6 @@ jobs: enum: - "test" # everything but pytest-envoy - "ingresstest" - - "gotest" - "pytest" - "pytest-envoy" - "pytest-envoy-v3" @@ -113,6 +126,18 @@ workflows: name: "oss-dev-lint" - "oss-chart": name: "oss-dev-chart" + - "oss-gotest": + name: "oss-dev-gotest<<# matrix.fast-reconfigure >>-fastreconfigure<><<# matrix.legacy-mode >>-legacy<>" + matrix: + alias: "oss-dev-gotest" + parameters: + fast-reconfigure: + - true + - false + legacy-mode: + - false + # If you enable testing with legacy-mode true as well, you'll also need + # to add some exclusions -- see the Release workflow for more. - "oss-test": requires: ["oss-dev-images"] name: "oss-dev-<< matrix.test >><<# matrix.fast-reconfigure >>-fastreconfigure<><<# matrix.legacy-mode >>-legacy<>" @@ -120,7 +145,6 @@ workflows: alias: "oss-dev-test" parameters: test: - - "gotest" - "pytest" - "pytest-envoy" - "pytest-envoy-v3" @@ -165,6 +189,24 @@ workflows: - "oss-lint": <<: *filter-prerelease-only name: "oss-release-lint" + - "oss-gotest": + <<: *filter-prerelease-only + name: "oss-release-gotest<<# matrix.fast-reconfigure >>-fastreconfigure<><<# matrix.legacy-mode >>-legacy<>" + matrix: + alias: "oss-release-gotest" + parameters: + fast-reconfigure: + - true + - false + legacy-mode: + - true + - false + exclude: + # It's not meaningful to set fast reconfigure and legacy mode at the same time. + # Annoyingly, we have to iterate all the 'test' values that we're using for + # this to work. + - fast-reconfigure: true + legacy-mode: true - "oss-test": <<: *filter-prerelease-only requires: ["oss-release-images"] @@ -173,7 +215,6 @@ workflows: alias: "oss-release-test" parameters: test: - - "gotest" - "pytest" - "pytest-envoy" - "pytest-envoy-v3" @@ -192,9 +233,6 @@ workflows: # It's not meaningful to set fast reconfigure and legacy mode at the same time. # Annoyingly, we have to iterate all the 'test' values that we're using for # this to work. - - test: gotest - fast-reconfigure: true - legacy-mode: true - test: pytest fast-reconfigure: true legacy-mode: true @@ -229,6 +267,23 @@ workflows: # build+push - "oss-images": name: "oss-nightly-images" + - "oss-gotest": + name: "oss-nightly-gotest<<# matrix.fast-reconfigure >>-fastreconfigure<><<# matrix.legacy-mode >>-legacy<>" + matrix: + alias: "oss-nightly-gotest" + parameters: + fast-reconfigure: + - true + - false + legacy-mode: + - true + - false + exclude: + # It's not meaningful to set fast reconfigure and legacy mode at the same time. + # Annoyingly, we have to iterate all the 'test' values that we're using for + # this to work. + - fast-reconfigure: true + legacy-mode: true - "oss-test": requires: ["oss-nightly-images"] name: "oss-nightly-<< matrix.test >><<# matrix.fast-reconfigure >>-fastreconfigure<><<# matrix.legacy-mode >>-legacy<>" @@ -236,7 +291,6 @@ workflows: alias: "oss-nightly-test" parameters: test: - - "gotest" - "pytest" - "pytest-envoy" # Running the ingresstests would require we install `kind` and @@ -254,9 +308,6 @@ workflows: # It's not meaningful to set fast reconfigure and legacy mode at the same time. # Annoyingly, we have to iterate all the 'test' values that we're using for # this to work. - - test: gotest - fast-reconfigure: true - legacy-mode: true - test: pytest fast-reconfigure: true legacy-mode: true diff --git a/.circleci/config.yml.d/generic_util.yml b/.circleci/config.yml.d/generic_util.yml index 89ab8f9364..4625468650 100644 --- a/.circleci/config.yml.d/generic_util.yml +++ b/.circleci/config.yml.d/generic_util.yml @@ -5,6 +5,19 @@ version: 2.1 commands: + "install-gotestsum": + steps: + - run: + name: "Install gotestsum" + command: | + go get gotest.tools/gotestsum + "install-redis": + steps: + - run: + name: "Install Redis" + command: | + sudo apt update -y + sudo apt install -y redis-server "install-k3d": parameters: diff --git a/.gitignore b/.gitignore index d7901facf1..cebaa476cf 100644 --- a/.gitignore +++ b/.gitignore @@ -30,6 +30,9 @@ vendor_bootstrap_hack.go /tools/sandbox/grpc_web/docker-compose.yaml /tools/sandbox/http_auth/docker-compose.yml +/docker/images.sh +/docker/images.tar +/docker/volume.tar /docker/container.txt /docker/container.txt.stamp *.docker diff --git a/OPENSOURCE.md b/OPENSOURCE.md index dc7befe0a0..df7bd41ff5 100644 --- a/OPENSOURCE.md +++ b/OPENSOURCE.md @@ -58,7 +58,7 @@ Free and Open Source software: github.com/evanphx/json-patch v4.9.0+incompatible 3-clause BSD license github.com/exponent-io/jsonpath v0.0.0-20151013193312-d6023ce2651d MIT license github.com/fatih/camelcase v1.0.0 MIT license - github.com/fatih/color v1.7.0 MIT license + github.com/fatih/color v1.10.0 MIT license github.com/form3tech-oss/jwt-go v3.2.2+incompatible MIT license github.com/fsnotify/fsnotify v1.4.9 3-clause BSD license github.com/ghodss/yaml v1.0.0 3-clause BSD license, MIT license @@ -76,9 +76,9 @@ Free and Open Source software: github.com/golang/protobuf v1.4.3 3-clause BSD license github.com/golang/snappy v0.0.1 3-clause BSD license github.com/google/btree v1.0.0 Apache License 2.0 - github.com/google/go-cmp v0.5.2 3-clause BSD license + github.com/google/go-cmp v0.5.5 3-clause BSD license github.com/google/gofuzz v1.1.0 Apache License 2.0 - github.com/google/shlex v0.0.0-20181106134648-c34317bd91bf Apache License 2.0 + github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 Apache License 2.0 github.com/google/uuid v1.1.2 3-clause BSD license github.com/googleapis/gnostic v0.5.1 Apache License 2.0 github.com/gookit/color v1.2.3 MIT license @@ -105,8 +105,8 @@ Free and Open Source software: github.com/lib/pq v1.9.0 MIT license github.com/liggitt/tabwriter v0.0.0-20181228230101-89fcab3d43de 3-clause BSD license github.com/mailru/easyjson v0.7.0 MIT license - github.com/mattn/go-colorable v0.1.2 MIT license - github.com/mattn/go-isatty v0.0.8 MIT license + github.com/mattn/go-colorable v0.1.8 MIT license + github.com/mattn/go-isatty v0.0.12 MIT license github.com/mattn/go-runewidth v0.0.4 MIT license github.com/matttproud/golang_protobuf_extensions v1.0.2-0.20181231171920-c182affec369 Apache License 2.0 github.com/mholt/archiver/v3 v3.3.0 MIT license @@ -159,7 +159,7 @@ Free and Open Source software: golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1 3-clause BSD license golang.org/x/text v0.3.4 3-clause BSD license golang.org/x/time v0.0.0-20200630173020-3af7569d3a1e 3-clause BSD license - golang.org/x/tools v0.0.0-20200904185747-39188db58858 3-clause BSD license + golang.org/x/tools v0.1.0 3-clause BSD license golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 3-clause BSD license google.golang.org/appengine v1.6.7 Apache License 2.0 google.golang.org/genproto v0.0.0-20201110150050-8816d57aaa9a Apache License 2.0 diff --git a/build-aux-local/generate.mk b/build-aux-local/generate.mk index 53642a3007..3da194511b 100644 --- a/build-aux-local/generate.mk +++ b/build-aux-local/generate.mk @@ -378,9 +378,8 @@ $(OSS_HOME)/OPENSOURCE.md: $(tools/go-mkopensource) $(tools/py-mkopensource) $(O { sed 's/^---$$//' $(OSS_HOME)/build-aux-local/pip-show.txt; echo; } | $(tools/py-mkopensource); \ } > $@ -python-setup: - [ -d $(OSS_HOME)/.venv ] || python3 -m virtualenv $(OSS_HOME)/.venv - $(OSS_HOME)/.venv/bin/python -m pip install ruamel.yaml +python-setup: create-venv + $(OSS_HOME)/venv/bin/python -m pip install ruamel.yaml .PHONY: python-setup define generate_yaml_from_helm @@ -388,7 +387,7 @@ define generate_yaml_from_helm helm template ambassador -n $(2) \ -f $(OSS_HOME)/k8s-config/$(1)/values.yaml \ $(OSS_HOME)/charts/ambassador > $(OSS_HOME)/build/yaml/$(1)/helm-expanded.yaml - $(OSS_HOME)/.venv/bin/python $(OSS_HOME)/k8s-config/create_yaml.py \ + $(OSS_HOME)/venv/bin/python $(OSS_HOME)/k8s-config/create_yaml.py \ $(OSS_HOME)/build/yaml/$(1)/helm-expanded.yaml $(OSS_HOME)/k8s-config/$(1)/require.yaml > $(3) endef diff --git a/builder/builder.mk b/builder/builder.mk index 6bf136bc3c..685bd0cd5a 100644 --- a/builder/builder.mk +++ b/builder/builder.mk @@ -415,30 +415,28 @@ mypy: mypy-server .PHONY: mypy GOTEST_PKGS = github.com/datawire/ambassador/... +GOTEST_MODDIRS = $(OSS_HOME) export GOTEST_PKGS +export GOTEST_MODDIRS -GOTEST_ARGS ?= -race +GOTEST_ARGS ?= -race -count=1 export GOTEST_ARGS -gotest: test-ready docker/kat-server.docker.push.remote docker/$(LCNAME).docker.push.remote +create-venv: + [[ -d $(OSS_HOME)/venv ]] || python3 -m venv $(OSS_HOME)/venv +.PHONY: create-venv + +setup-diagd: create-venv + . $(OSS_HOME)/venv/bin/activate && pip install orjson && \ + pip install -r $(OSS_HOME)/builder/requirements.txt && \ + pip install -e $(OSS_HOME)/python +.PHONY: setup-diagd + +gotest: setup-diagd @printf "$(CYN)==> $(GRN)Running $(BLU)go$(GRN) tests$(END)\n" - docker exec \ - -e AMBASSADOR_DOCKER_IMAGE=$$(sed -n 2p docker/$(LCNAME).docker.push.remote) \ - -e DTEST_REGISTRY=$(DEV_REGISTRY) \ - -e DTEST_KUBECONFIG=/buildroot/kubeconfig.yaml \ - -e KAT_SERVER_DOCKER_IMAGE=$$(sed -n 2p docker/kat-server.docker.push.remote) \ - -e GOTEST_PKGS \ - -e GOTEST_ARGS \ - -e DEV_USE_IMAGEPULLSECRET \ - -e DEV_REGISTRY \ - -e DOCKER_BUILD_USERNAME \ - -e DOCKER_BUILD_PASSWORD \ - -it $(shell $(BUILDER)) /buildroot/builder.sh gotest-internal ; test_exit=$$? ; \ - [ -n "$(TEST_XML_DIR)" ] && docker cp $(shell $(BUILDER)):/tmp/test-xml.tar.gz $(TEST_XML_DIR) && tar -xvf $(TEST_XML_DIR)/test-xml.tar.gz -C $(TEST_XML_DIR) ; [ $$test_exit == 0 ] || exit $$test_exit - docker exec \ - -w /buildroot/ambassador \ - -e GOOS=windows \ - -it $(shell $(BUILDER)) go build -o /dev/null ./cmd/edgectl + . $(OSS_HOME)/venv/bin/activate; \ + EDGE_STACK=$(GOTEST_AES_ENABLED) \ + $(OSS_HOME)/builder/builder.sh gotest-local .PHONY: gotest # Ingress v1 conformance tests, using KIND and the Ingress Conformance Tests suite. diff --git a/builder/builder.sh b/builder/builder.sh index 52f301d7b2..91f865bff9 100755 --- a/builder/builder.sh +++ b/builder/builder.sh @@ -591,22 +591,24 @@ case "${cmd}" in exit 1 fi ;; - gotest-internal) - # This runs inside the builder image + gotest-local) + [ -n "${TEST_XML_DIR}" ] && mkdir -p ${TEST_XML_DIR} fail="" - mkdir -p ${TEST_DATA_DIR} - for MODDIR in $(find-modules); do + for MODDIR in ${GOTEST_MODDIRS} ; do if [ -e "${MODDIR}/go.mod" ]; then pkgs=$(cd ${MODDIR} && go list -f='{{ if or (gt (len .TestGoFiles) 0) (gt (len .XTestGoFiles) 0) }}{{ .ImportPath }}{{ end }}' ${GOTEST_PKGS}) if [ -n "${pkgs}" ]; then modname=`basename ${MODDIR}` - if ! (cd ${MODDIR} && gotestsum --junitfile ${TEST_DATA_DIR}/${modname}-gotest.xml --packages="${pkgs}" -- ${GOTEST_ARGS}) ; then + junitarg= + if [[ -n "${TEST_XML_DIR}" ]] ; then + junitarg="--junitfile ${TEST_XML_DIR}/${modname}-gotest.xml" + fi + if ! (cd ${MODDIR} && gotestsum ${junitarg} --rerun-fails=3 --packages="${pkgs}" -- ${GOTEST_ARGS}) ; then fail="yes" fi fi fi done - tar -C ${TEST_DATA_DIR} -cvf /tmp/test-xml.tar.gz . if [ "${fail}" = yes ]; then exit 1 diff --git a/cmd/agent/agent_test.go b/cmd/agent/agent_test.go deleted file mode 100644 index b1daa37ecd..0000000000 --- a/cmd/agent/agent_test.go +++ /dev/null @@ -1,249 +0,0 @@ -package agent - -import ( - "context" - "encoding/json" - "errors" - "fmt" - "io/ioutil" - "os" - "strings" - "testing" - "time" - - "github.com/datawire/dlib/dexec" - "github.com/stretchr/testify/assert" - - "github.com/datawire/ambassador/pkg/api/agent" - "github.com/datawire/ambassador/pkg/dtest" - "github.com/datawire/ambassador/pkg/k8s" - "github.com/datawire/ambassador/pkg/kates" - "github.com/datawire/ambassador/pkg/kubeapply" - snapshotTypes "github.com/datawire/ambassador/pkg/snapshot/v1" -) - -// This test is supposed to be a very lightweight end to end test. -// We're essentially testing that the k8s yaml configuration allows the agent to report on all the -// things the cloud app needs. We do this with dtest, which spins up a k3ds cluster by default, or -// you can point it at your own cluster by running `go test` with env var `DTEST_KUBECONFIG=$HOME/.kube/config` -// More complicated business logic tests live in ambassador.git/pkg/agent -func TestAgentE2E(t *testing.T) { - kubeconfig := dtest.Kubeconfig() - cli, err := kates.NewClient(kates.ClientConfig{Kubeconfig: kubeconfig}) - assert.Nil(t, err) - // applies all k8s yaml to dtest cluter - // ambassador, ambassador-agent, rbac, crds, and a fake agentcom that implements the grpc - // server for the agent - setup(t, kubeconfig, cli) - defer deleteArgoResources(t, kubeconfig) - - // eh lets make sure the agent came up - time.Sleep(time.Second * 3) - - hasArgo := false - reportSnapshot, ambSnapshot := getAgentComSnapshots(t, kubeconfig, cli, hasArgo) - - // Do actual assertions here. kind of lazy way to retry, but it should work - assert.NotEmpty(t, reportSnapshot.Identity.ClusterId) - assert.NotEmpty(t, reportSnapshot.Identity.Hostname) - assert.NotEmpty(t, reportSnapshot.RawSnapshot) - assert.NotEmpty(t, reportSnapshot.ApiVersion) - assert.NotEmpty(t, reportSnapshot.SnapshotTs) - assert.Equal(t, reportSnapshot.ApiVersion, snapshotTypes.ApiVersion) - - assert.NotEmpty(t, ambSnapshot.Kubernetes) - - // just make sure the stuff we really need for the service catalog is in there - assert.NotEmpty(t, ambSnapshot.Kubernetes.Services, "No services in snapshot") - assert.NotEmpty(t, ambSnapshot.Kubernetes.Mappings, "No mappings in snapshot") - - // pods not being empty basically ensures that the rbac in the yaml is correct - assert.NotEmpty(t, ambSnapshot.Kubernetes.Pods, "No pods found in snapshot") - assert.Empty(t, ambSnapshot.Kubernetes.ArgoRollouts, "rollouts found in snapshot") - assert.Empty(t, ambSnapshot.Kubernetes.ArgoApplications, "applications found in snapshot") - - applyArgoResources(t, kubeconfig, cli) - hasArgo = true - reportSnapshot, ambSnapshot = getAgentComSnapshots(t, kubeconfig, cli, hasArgo) - assert.NotEmpty(t, ambSnapshot.Kubernetes.ArgoRollouts, "No argo rollouts found in snapshot") - assert.NotEmpty(t, ambSnapshot.Kubernetes.ArgoApplications, "No argo applications found in snapshot") -} - -func getAgentComSnapshots(t *testing.T, kubeconfig string, cli *kates.Client, waitArgo bool) (*agent.Snapshot, *snapshotTypes.Snapshot) { - found := false - reportSnapshot := &agent.Snapshot{} - ambSnapshot := &snapshotTypes.Snapshot{} - ctx := context.Background() - - // now we're going to go copy the snapshot.json file from our fake agentcom - // when the agentcom gets a snapshot from the agent, it'll store it at /tmp/snapshot.json - // we do this in a loop because it might take ambassador and the agent a sec to get into the - // state we're asserting. this is okay, this test is just to make sure that the agent RBAC - // is correct and that the agent can talk to the ambassador-agent service. - // any tests that do any more complicated assertions should live in ambassador.git/pkg/agent - for i := 0; i < 15; i++ { - podName, err := getFakeAgentComPodName(cli) - assert.Nil(t, err) - - podFile := fmt.Sprintf("%s:%s", podName, "/tmp/snapshot.json") - localSnapshot := fmt.Sprintf("%s/snapshot.json", t.TempDir()) - time.Sleep(time.Second * time.Duration(i)) - cmd := dexec.CommandContext(ctx, "kubectl", "--kubeconfig", kubeconfig, "cp", podFile, localSnapshot) - out, err := cmd.CombinedOutput() - t.Log(fmt.Sprintf("Kubectl cp output: %s", out)) - if err != nil { - t.Log(fmt.Sprintf("Error running kubectl cp: %+v", err)) - continue - } - if _, err := os.Stat(localSnapshot); os.IsNotExist(err) { - t.Log("Could not copy file from agentcom, retrying...") - continue - } - snapbytes, err := ioutil.ReadFile(localSnapshot) - if err != nil { - t.Log(fmt.Sprintf("Error reading snapshot file: %+v", err)) - continue - } - found = true - - err = json.Unmarshal(snapbytes, reportSnapshot) - if err != nil { - t.Fatal("Could not unmarshal report snapshot") - } - - err = json.Unmarshal(reportSnapshot.RawSnapshot, ambSnapshot) - if err != nil { - t.Fatal("Could not unmarshal ambassador snapshot") - } - if !snapshotIsSane(ambSnapshot, t, waitArgo) { - continue - } - break - } - assert.True(t, found, "Could not cp file from agentcom") - return reportSnapshot, ambSnapshot -} - -func snapshotIsSane(ambSnapshot *snapshotTypes.Snapshot, t *testing.T, hasArgo bool) bool { - if ambSnapshot.Kubernetes == nil { - t.Log("K8s snapshot empty, retrying") - return false - } - if len(ambSnapshot.Kubernetes.Services) == 0 { - t.Log("K8s snapshot services empty, retrying") - return false - } - if len(ambSnapshot.Kubernetes.Mappings) == 0 { - t.Log("K8s snapshot mappings empty, retrying") - return false - } - if len(ambSnapshot.Kubernetes.Pods) == 0 { - t.Log("K8s snapshot pods empty, retrying") - return false - } - if hasArgo && len(ambSnapshot.Kubernetes.ArgoRollouts) == 0 { - t.Log("K8s snapshot argo rollouts empty, retrying") - return false - } - if hasArgo && len(ambSnapshot.Kubernetes.ArgoApplications) == 0 { - t.Log("K8s snapshot argo applications empty, retrying") - return false - } - if !hasArgo && len(ambSnapshot.Kubernetes.ArgoRollouts) != 0 { - t.Log("K8s snapshot argo rollouts should be empty, retrying") - return false - } - if !hasArgo && len(ambSnapshot.Kubernetes.ArgoApplications) != 0 { - t.Log("K8s snapshot argo applications should be empty, retrying") - return false - } - - return true -} -func applyArgoResources(t *testing.T, kubeconfig string, cli *kates.Client) { - kubeinfo := k8s.NewKubeInfo(kubeconfig, "", "") - err := kubeapply.Kubeapply(kubeinfo, time.Minute, true, false, "./test/argo-rollouts-crd.yaml") - assert.Nil(t, err) - err = kubeapply.Kubeapply(kubeinfo, time.Minute, true, false, "./test/argo-rollouts.yaml") - assert.Nil(t, err) - err = kubeapply.Kubeapply(kubeinfo, time.Minute, true, false, "./test/argo-application-crd.yaml") - assert.Nil(t, err) - err = kubeapply.Kubeapply(kubeinfo, time.Minute, true, false, "./test/argo-application.yaml") - assert.Nil(t, err) -} - -func setup(t *testing.T, kubeconfig string, cli *kates.Client) { - // okay, yes this is gross, but we're revamping all the yaml right now, so i'm just making - // this as frictionless as possible for the time being - // TODO(acookin): this will probably need to change when we finish #1280 - yamlPath := "../../docs/yaml/" - crdFile := yamlPath + "ambassador/ambassador-crds.yaml" - aesFile := yamlPath + "aes.yaml" - aesDat, err := ioutil.ReadFile(aesFile) - assert.Nil(t, err) - image := os.Getenv("AMBASSADOR_DOCKER_IMAGE") - assert.NotEmpty(t, image) - ctx := context.Background() - - aesReplaced := strings.ReplaceAll(string(aesDat), "docker.io/datawire/aes:$version$", image) - newAesFile := t.TempDir() + "/aes.yaml" - - err = ioutil.WriteFile(newAesFile, []byte(aesReplaced), 0644) - assert.Nil(t, err) - kubeinfo := k8s.NewKubeInfo(kubeconfig, "", "") - - err = kubeapply.Kubeapply(kubeinfo, time.Minute, true, false, crdFile) - assert.Nil(t, err) - err = kubeapply.Kubeapply(kubeinfo, time.Second*120, true, false, newAesFile) - assert.Nil(t, err) - err = kubeapply.Kubeapply(kubeinfo, time.Second*120, true, false, "./fake-agentcom.yaml") - assert.Nil(t, err) - - dep := &kates.Deployment{ - TypeMeta: kates.TypeMeta{ - Kind: "Deployment", - }, - ObjectMeta: kates.ObjectMeta{ - Name: "ambassador-agent", - Namespace: "ambassador", - }, - } - - patch := fmt.Sprintf(`{"spec":{"template":{"spec":{"containers":[{"name":"agent","env":[{"name":"%s", "value":"%s"}]}]}}}}`, "RPC_CONNECTION_ADDRESS", "http://agentcom-server.default:8080/") - err = cli.Patch(ctx, dep, kates.StrategicMergePatchType, []byte(patch), dep) - assert.Nil(t, err) -} - -func deleteArgoResources(t *testing.T, kubeconfig string) { - ctx := context.Background() - // cleaning up argo crds so the e2e test can be deterministic - cmd := dexec.CommandContext(ctx, "kubectl", "--kubeconfig", kubeconfig, "delete", "crd", "--ignore-not-found=true", "rollouts.argoproj.io") - out, err := cmd.CombinedOutput() - t.Log(fmt.Sprintf("Kubectl delete crd rollouts output: %s", out)) - if err != nil { - t.Errorf("Error running kubectl delete crd rollouts: %s", err) - } - cmd = dexec.CommandContext(ctx, "kubectl", "--kubeconfig", kubeconfig, "delete", "crd", "--ignore-not-found=true", "applications.argoproj.io") - out, err = cmd.CombinedOutput() - t.Log(fmt.Sprintf("Kubectl delete crd applications output: %s", out)) - if err != nil { - t.Errorf("Error running kubectl delete crd applications: %s", err) - } -} - -func getFakeAgentComPodName(cli *kates.Client) (string, error) { - query := kates.Query{ - Kind: "Pod", - LabelSelector: "app=agentcom-server", - Namespace: "default", - } - pods := []*kates.Pod{} - err := cli.List(context.Background(), query, &pods) - if err != nil { - return "", err - } - if len(pods) < 1 { - return "", errors.New("No pods found with label app=agentcom-server") - } - return pods[0].ObjectMeta.Name, nil -} diff --git a/cmd/agent/test/argo-application-crd.yaml b/cmd/agent/test/argo-application-crd.yaml deleted file mode 100644 index 74364ae4e6..0000000000 --- a/cmd/agent/test/argo-application-crd.yaml +++ /dev/null @@ -1,1760 +0,0 @@ -apiVersion: apiextensions.k8s.io/v1 -kind: CustomResourceDefinition -metadata: - labels: - app.kubernetes.io/name: applications.argoproj.io - app.kubernetes.io/part-of: argocd - name: applications.argoproj.io -spec: - group: argoproj.io - names: - kind: Application - listKind: ApplicationList - plural: applications - shortNames: - - app - - apps - singular: application - scope: Namespaced - versions: - - additionalPrinterColumns: - - jsonPath: .status.sync.status - name: Sync Status - type: string - - jsonPath: .status.health.status - name: Health Status - type: string - - jsonPath: .status.sync.revision - name: Revision - priority: 10 - type: string - name: v1alpha1 - schema: - openAPIV3Schema: - description: Application is a definition of Application resource. - properties: - apiVersion: - description: 'APIVersion defines the versioned schema of this representation of an object. Servers should convert recognized schemas to the latest internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources' - type: string - kind: - description: 'Kind is a string value representing the REST resource this object represents. Servers may infer this from the endpoint the client submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds' - type: string - metadata: - type: object - operation: - description: Operation contains information about a requested or running operation - properties: - info: - description: Info is a list of informational items for this operation - items: - properties: - name: - type: string - value: - type: string - required: - - name - - value - type: object - type: array - initiatedBy: - description: InitiatedBy contains information about who initiated the operations - properties: - automated: - description: Automated is set to true if operation was initiated automatically by the application controller. - type: boolean - username: - description: Username contains the name of a user who started operation - type: string - type: object - retry: - description: Retry controls the strategy to apply if a sync fails - properties: - backoff: - description: Backoff controls how to backoff on subsequent retries of failed syncs - properties: - duration: - description: Duration is the amount to back off. Default unit is seconds, but could also be a duration (e.g. "2m", "1h") - type: string - factor: - description: Factor is a factor to multiply the base duration after each failed retry - format: int64 - type: integer - maxDuration: - description: MaxDuration is the maximum amount of time allowed for the backoff strategy - type: string - type: object - limit: - description: Limit is the maximum number of attempts for retrying a failed sync. If set to 0, no retries will be performed. - format: int64 - type: integer - type: object - sync: - description: Sync contains parameters for the operation - properties: - dryRun: - description: DryRun specifies to perform a `kubectl apply --dry-run` without actually performing the sync - type: boolean - manifests: - description: Manifests is an optional field that overrides sync source with a local directory for development - items: - type: string - type: array - prune: - description: Prune specifies to delete resources from the cluster that are no longer tracked in git - type: boolean - resources: - description: Resources describes which resources shall be part of the sync - items: - description: SyncOperationResource contains resources to sync. - properties: - group: - type: string - kind: - type: string - name: - type: string - namespace: - type: string - required: - - kind - - name - type: object - type: array - revision: - description: Revision is the revision (Git) or chart version (Helm) which to sync the application to If omitted, will use the revision specified in app spec. - type: string - source: - description: Source overrides the source definition set in the application. This is typically set in a Rollback operation and is nil during a Sync operation - properties: - chart: - description: Chart is a Helm chart name, and must be specified for applications sourced from a Helm repo. - type: string - directory: - description: Directory holds path/directory specific options - properties: - exclude: - description: Exclude contains a glob pattern to match paths against that should be explicitly excluded from being used during manifest generation - type: string - include: - description: Include contains a glob pattern to match paths against that should be explicitly included during manifest generation - type: string - jsonnet: - description: Jsonnet holds options specific to Jsonnet - properties: - extVars: - description: ExtVars is a list of Jsonnet External Variables - items: - description: JsonnetVar represents a variable to be passed to jsonnet during manifest generation - properties: - code: - type: boolean - name: - type: string - value: - type: string - required: - - name - - value - type: object - type: array - libs: - description: Additional library search dirs - items: - type: string - type: array - tlas: - description: TLAS is a list of Jsonnet Top-level Arguments - items: - description: JsonnetVar represents a variable to be passed to jsonnet during manifest generation - properties: - code: - type: boolean - name: - type: string - value: - type: string - required: - - name - - value - type: object - type: array - type: object - recurse: - description: Recurse specifies whether to scan a directory recursively for manifests - type: boolean - type: object - helm: - description: Helm holds helm specific options - properties: - fileParameters: - description: FileParameters are file parameters to the helm template - items: - description: HelmFileParameter is a file parameter that's passed to helm template during manifest generation - properties: - name: - description: Name is the name of the Helm parameter - type: string - path: - description: Path is the path to the file containing the values for the Helm parameter - type: string - type: object - type: array - parameters: - description: Parameters is a list of Helm parameters which are passed to the helm template command upon manifest generation - items: - description: HelmParameter is a parameter that's passed to helm template during manifest generation - properties: - forceString: - description: ForceString determines whether to tell Helm to interpret booleans and numbers as strings - type: boolean - name: - description: Name is the name of the Helm parameter - type: string - value: - description: Value is the value for the Helm parameter - type: string - type: object - type: array - releaseName: - description: ReleaseName is the Helm release name to use. If omitted it will use the application name - type: string - valueFiles: - description: ValuesFiles is a list of Helm value files to use when generating a template - items: - type: string - type: array - values: - description: Values specifies Helm values to be passed to helm template, typically defined as a block - type: string - version: - description: Version is the Helm version to use for templating (either "2" or "3") - type: string - type: object - ksonnet: - description: Ksonnet holds ksonnet specific options - properties: - environment: - description: Environment is a ksonnet application environment name - type: string - parameters: - description: Parameters are a list of ksonnet component parameter override values - items: - description: KsonnetParameter is a ksonnet component parameter - properties: - component: - type: string - name: - type: string - value: - type: string - required: - - name - - value - type: object - type: array - type: object - kustomize: - description: Kustomize holds kustomize specific options - properties: - commonAnnotations: - additionalProperties: - type: string - description: CommonAnnotations is a list of additional annotations to add to rendered manifests - type: object - commonLabels: - additionalProperties: - type: string - description: CommonLabels is a list of additional labels to add to rendered manifests - type: object - images: - description: Images is a list of Kustomize image override specifications - items: - description: KustomizeImage represents a Kustomize image definition in the format [old_image_name=]: - type: string - type: array - namePrefix: - description: NamePrefix is a prefix appended to resources for Kustomize apps - type: string - nameSuffix: - description: NameSuffix is a suffix appended to resources for Kustomize apps - type: string - version: - description: Version controls which version of Kustomize to use for rendering manifests - type: string - type: object - path: - description: Path is a directory path within the Git repository, and is only valid for applications sourced from Git. - type: string - plugin: - description: ConfigManagementPlugin holds config management plugin specific options - properties: - env: - description: Env is a list of environment variable entries - items: - description: EnvEntry represents an entry in the application's environment - properties: - name: - description: Name is the name of the variable, usually expressed in uppercase - type: string - value: - description: Value is the value of the variable - type: string - required: - - name - - value - type: object - type: array - name: - type: string - type: object - repoURL: - description: RepoURL is the URL to the repository (Git or Helm) that contains the application manifests - type: string - targetRevision: - description: TargetRevision defines the revision of the source to sync the application to. In case of Git, this can be commit, tag, or branch. If omitted, will equal to HEAD. In case of Helm, this is a semver tag for the Chart's version. - type: string - required: - - repoURL - type: object - syncOptions: - description: SyncOptions provide per-sync sync-options, e.g. Validate=false - items: - type: string - type: array - syncStrategy: - description: SyncStrategy describes how to perform the sync - properties: - apply: - description: Apply will perform a `kubectl apply` to perform the sync. - properties: - force: - description: Force indicates whether or not to supply the --force flag to `kubectl apply`. The --force flag deletes and re-create the resource, when PATCH encounters conflict and has retried for 5 times. - type: boolean - type: object - hook: - description: Hook will submit any referenced resources to perform the sync. This is the default strategy - properties: - force: - description: Force indicates whether or not to supply the --force flag to `kubectl apply`. The --force flag deletes and re-create the resource, when PATCH encounters conflict and has retried for 5 times. - type: boolean - type: object - type: object - type: object - type: object - spec: - description: ApplicationSpec represents desired application state. Contains link to repository with application definition and additional parameters link definition revision. - properties: - destination: - description: Destination is a reference to the target Kubernetes server and namespace - properties: - name: - description: Name is an alternate way of specifying the target cluster by its symbolic name - type: string - namespace: - description: Namespace specifies the target namespace for the application's resources. The namespace will only be set for namespace-scoped resources that have not set a value for .metadata.namespace - type: string - server: - description: Server specifies the URL of the target cluster and must be set to the Kubernetes control plane API - type: string - type: object - ignoreDifferences: - description: IgnoreDifferences is a list of resources and their fields which should be ignored during comparison - items: - description: ResourceIgnoreDifferences contains resource filter and list of json paths which should be ignored during comparison with live state. - properties: - group: - type: string - jsonPointers: - items: - type: string - type: array - kind: - type: string - name: - type: string - namespace: - type: string - required: - - jsonPointers - - kind - type: object - type: array - info: - description: Info contains a list of information (URLs, email addresses, and plain text) that relates to the application - items: - properties: - name: - type: string - value: - type: string - required: - - name - - value - type: object - type: array - project: - description: Project is a reference to the project this application belongs to. The empty string means that application belongs to the 'default' project. - type: string - revisionHistoryLimit: - description: RevisionHistoryLimit limits the number of items kept in the application's revision history, which is used for informational purposes as well as for rollbacks to previous versions. This should only be changed in exceptional circumstances. Setting to zero will store no history. This will reduce storage used. Increasing will increase the space used to store the history, so we do not recommend increasing it. Default is 10. - format: int64 - type: integer - source: - description: Source is a reference to the location of the application's manifests or chart - properties: - chart: - description: Chart is a Helm chart name, and must be specified for applications sourced from a Helm repo. - type: string - directory: - description: Directory holds path/directory specific options - properties: - exclude: - description: Exclude contains a glob pattern to match paths against that should be explicitly excluded from being used during manifest generation - type: string - include: - description: Include contains a glob pattern to match paths against that should be explicitly included during manifest generation - type: string - jsonnet: - description: Jsonnet holds options specific to Jsonnet - properties: - extVars: - description: ExtVars is a list of Jsonnet External Variables - items: - description: JsonnetVar represents a variable to be passed to jsonnet during manifest generation - properties: - code: - type: boolean - name: - type: string - value: - type: string - required: - - name - - value - type: object - type: array - libs: - description: Additional library search dirs - items: - type: string - type: array - tlas: - description: TLAS is a list of Jsonnet Top-level Arguments - items: - description: JsonnetVar represents a variable to be passed to jsonnet during manifest generation - properties: - code: - type: boolean - name: - type: string - value: - type: string - required: - - name - - value - type: object - type: array - type: object - recurse: - description: Recurse specifies whether to scan a directory recursively for manifests - type: boolean - type: object - helm: - description: Helm holds helm specific options - properties: - fileParameters: - description: FileParameters are file parameters to the helm template - items: - description: HelmFileParameter is a file parameter that's passed to helm template during manifest generation - properties: - name: - description: Name is the name of the Helm parameter - type: string - path: - description: Path is the path to the file containing the values for the Helm parameter - type: string - type: object - type: array - parameters: - description: Parameters is a list of Helm parameters which are passed to the helm template command upon manifest generation - items: - description: HelmParameter is a parameter that's passed to helm template during manifest generation - properties: - forceString: - description: ForceString determines whether to tell Helm to interpret booleans and numbers as strings - type: boolean - name: - description: Name is the name of the Helm parameter - type: string - value: - description: Value is the value for the Helm parameter - type: string - type: object - type: array - releaseName: - description: ReleaseName is the Helm release name to use. If omitted it will use the application name - type: string - valueFiles: - description: ValuesFiles is a list of Helm value files to use when generating a template - items: - type: string - type: array - values: - description: Values specifies Helm values to be passed to helm template, typically defined as a block - type: string - version: - description: Version is the Helm version to use for templating (either "2" or "3") - type: string - type: object - ksonnet: - description: Ksonnet holds ksonnet specific options - properties: - environment: - description: Environment is a ksonnet application environment name - type: string - parameters: - description: Parameters are a list of ksonnet component parameter override values - items: - description: KsonnetParameter is a ksonnet component parameter - properties: - component: - type: string - name: - type: string - value: - type: string - required: - - name - - value - type: object - type: array - type: object - kustomize: - description: Kustomize holds kustomize specific options - properties: - commonAnnotations: - additionalProperties: - type: string - description: CommonAnnotations is a list of additional annotations to add to rendered manifests - type: object - commonLabels: - additionalProperties: - type: string - description: CommonLabels is a list of additional labels to add to rendered manifests - type: object - images: - description: Images is a list of Kustomize image override specifications - items: - description: KustomizeImage represents a Kustomize image definition in the format [old_image_name=]: - type: string - type: array - namePrefix: - description: NamePrefix is a prefix appended to resources for Kustomize apps - type: string - nameSuffix: - description: NameSuffix is a suffix appended to resources for Kustomize apps - type: string - version: - description: Version controls which version of Kustomize to use for rendering manifests - type: string - type: object - path: - description: Path is a directory path within the Git repository, and is only valid for applications sourced from Git. - type: string - plugin: - description: ConfigManagementPlugin holds config management plugin specific options - properties: - env: - description: Env is a list of environment variable entries - items: - description: EnvEntry represents an entry in the application's environment - properties: - name: - description: Name is the name of the variable, usually expressed in uppercase - type: string - value: - description: Value is the value of the variable - type: string - required: - - name - - value - type: object - type: array - name: - type: string - type: object - repoURL: - description: RepoURL is the URL to the repository (Git or Helm) that contains the application manifests - type: string - targetRevision: - description: TargetRevision defines the revision of the source to sync the application to. In case of Git, this can be commit, tag, or branch. If omitted, will equal to HEAD. In case of Helm, this is a semver tag for the Chart's version. - type: string - required: - - repoURL - type: object - syncPolicy: - description: SyncPolicy controls when and how a sync will be performed - properties: - automated: - description: Automated will keep an application synced to the target revision - properties: - allowEmpty: - description: 'AllowEmpty allows apps have zero live resources (default: false)' - type: boolean - prune: - description: 'Prune specifies whether to delete resources from the cluster that are not found in the sources anymore as part of automated sync (default: false)' - type: boolean - selfHeal: - description: 'SelfHeal specifes whether to revert resources back to their desired state upon modification in the cluster (default: false)' - type: boolean - type: object - retry: - description: Retry controls failed sync retry behavior - properties: - backoff: - description: Backoff controls how to backoff on subsequent retries of failed syncs - properties: - duration: - description: Duration is the amount to back off. Default unit is seconds, but could also be a duration (e.g. "2m", "1h") - type: string - factor: - description: Factor is a factor to multiply the base duration after each failed retry - format: int64 - type: integer - maxDuration: - description: MaxDuration is the maximum amount of time allowed for the backoff strategy - type: string - type: object - limit: - description: Limit is the maximum number of attempts for retrying a failed sync. If set to 0, no retries will be performed. - format: int64 - type: integer - type: object - syncOptions: - description: Options allow you to specify whole app sync-options - items: - type: string - type: array - type: object - required: - - destination - - project - - source - type: object - status: - description: ApplicationStatus contains status information for the application - properties: - conditions: - description: Conditions is a list of currently observed application conditions - items: - description: ApplicationCondition contains details about an application condition, which is usally an error or warning - properties: - lastTransitionTime: - description: LastTransitionTime is the time the condition was last observed - format: date-time - type: string - message: - description: Message contains human-readable message indicating details about condition - type: string - type: - description: Type is an application condition type - type: string - required: - - message - - type - type: object - type: array - health: - description: Health contains information about the application's current health status - properties: - message: - description: Message is a human-readable informational message describing the health status - type: string - status: - description: Status holds the status code of the application or resource - type: string - type: object - history: - description: History contains information about the application's sync history - items: - description: RevisionHistory contains history information about a previous sync - properties: - deployStartedAt: - description: DeployStartedAt holds the time the sync operation started - format: date-time - type: string - deployedAt: - description: DeployedAt holds the time the sync operation completed - format: date-time - type: string - id: - description: ID is an auto incrementing identifier of the RevisionHistory - format: int64 - type: integer - revision: - description: Revision holds the revision the sync was performed against - type: string - source: - description: Source is a reference to the application source used for the sync operation - properties: - chart: - description: Chart is a Helm chart name, and must be specified for applications sourced from a Helm repo. - type: string - directory: - description: Directory holds path/directory specific options - properties: - exclude: - description: Exclude contains a glob pattern to match paths against that should be explicitly excluded from being used during manifest generation - type: string - include: - description: Include contains a glob pattern to match paths against that should be explicitly included during manifest generation - type: string - jsonnet: - description: Jsonnet holds options specific to Jsonnet - properties: - extVars: - description: ExtVars is a list of Jsonnet External Variables - items: - description: JsonnetVar represents a variable to be passed to jsonnet during manifest generation - properties: - code: - type: boolean - name: - type: string - value: - type: string - required: - - name - - value - type: object - type: array - libs: - description: Additional library search dirs - items: - type: string - type: array - tlas: - description: TLAS is a list of Jsonnet Top-level Arguments - items: - description: JsonnetVar represents a variable to be passed to jsonnet during manifest generation - properties: - code: - type: boolean - name: - type: string - value: - type: string - required: - - name - - value - type: object - type: array - type: object - recurse: - description: Recurse specifies whether to scan a directory recursively for manifests - type: boolean - type: object - helm: - description: Helm holds helm specific options - properties: - fileParameters: - description: FileParameters are file parameters to the helm template - items: - description: HelmFileParameter is a file parameter that's passed to helm template during manifest generation - properties: - name: - description: Name is the name of the Helm parameter - type: string - path: - description: Path is the path to the file containing the values for the Helm parameter - type: string - type: object - type: array - parameters: - description: Parameters is a list of Helm parameters which are passed to the helm template command upon manifest generation - items: - description: HelmParameter is a parameter that's passed to helm template during manifest generation - properties: - forceString: - description: ForceString determines whether to tell Helm to interpret booleans and numbers as strings - type: boolean - name: - description: Name is the name of the Helm parameter - type: string - value: - description: Value is the value for the Helm parameter - type: string - type: object - type: array - releaseName: - description: ReleaseName is the Helm release name to use. If omitted it will use the application name - type: string - valueFiles: - description: ValuesFiles is a list of Helm value files to use when generating a template - items: - type: string - type: array - values: - description: Values specifies Helm values to be passed to helm template, typically defined as a block - type: string - version: - description: Version is the Helm version to use for templating (either "2" or "3") - type: string - type: object - ksonnet: - description: Ksonnet holds ksonnet specific options - properties: - environment: - description: Environment is a ksonnet application environment name - type: string - parameters: - description: Parameters are a list of ksonnet component parameter override values - items: - description: KsonnetParameter is a ksonnet component parameter - properties: - component: - type: string - name: - type: string - value: - type: string - required: - - name - - value - type: object - type: array - type: object - kustomize: - description: Kustomize holds kustomize specific options - properties: - commonAnnotations: - additionalProperties: - type: string - description: CommonAnnotations is a list of additional annotations to add to rendered manifests - type: object - commonLabels: - additionalProperties: - type: string - description: CommonLabels is a list of additional labels to add to rendered manifests - type: object - images: - description: Images is a list of Kustomize image override specifications - items: - description: KustomizeImage represents a Kustomize image definition in the format [old_image_name=]: - type: string - type: array - namePrefix: - description: NamePrefix is a prefix appended to resources for Kustomize apps - type: string - nameSuffix: - description: NameSuffix is a suffix appended to resources for Kustomize apps - type: string - version: - description: Version controls which version of Kustomize to use for rendering manifests - type: string - type: object - path: - description: Path is a directory path within the Git repository, and is only valid for applications sourced from Git. - type: string - plugin: - description: ConfigManagementPlugin holds config management plugin specific options - properties: - env: - description: Env is a list of environment variable entries - items: - description: EnvEntry represents an entry in the application's environment - properties: - name: - description: Name is the name of the variable, usually expressed in uppercase - type: string - value: - description: Value is the value of the variable - type: string - required: - - name - - value - type: object - type: array - name: - type: string - type: object - repoURL: - description: RepoURL is the URL to the repository (Git or Helm) that contains the application manifests - type: string - targetRevision: - description: TargetRevision defines the revision of the source to sync the application to. In case of Git, this can be commit, tag, or branch. If omitted, will equal to HEAD. In case of Helm, this is a semver tag for the Chart's version. - type: string - required: - - repoURL - type: object - required: - - deployedAt - - id - - revision - type: object - type: array - observedAt: - description: 'ObservedAt indicates when the application state was updated without querying latest git state Deprecated: controller no longer updates ObservedAt field' - format: date-time - type: string - operationState: - description: OperationState contains information about any ongoing operations, such as a sync - properties: - finishedAt: - description: FinishedAt contains time of operation completion - format: date-time - type: string - message: - description: Message holds any pertinent messages when attempting to perform operation (typically errors). - type: string - operation: - description: Operation is the original requested operation - properties: - info: - description: Info is a list of informational items for this operation - items: - properties: - name: - type: string - value: - type: string - required: - - name - - value - type: object - type: array - initiatedBy: - description: InitiatedBy contains information about who initiated the operations - properties: - automated: - description: Automated is set to true if operation was initiated automatically by the application controller. - type: boolean - username: - description: Username contains the name of a user who started operation - type: string - type: object - retry: - description: Retry controls the strategy to apply if a sync fails - properties: - backoff: - description: Backoff controls how to backoff on subsequent retries of failed syncs - properties: - duration: - description: Duration is the amount to back off. Default unit is seconds, but could also be a duration (e.g. "2m", "1h") - type: string - factor: - description: Factor is a factor to multiply the base duration after each failed retry - format: int64 - type: integer - maxDuration: - description: MaxDuration is the maximum amount of time allowed for the backoff strategy - type: string - type: object - limit: - description: Limit is the maximum number of attempts for retrying a failed sync. If set to 0, no retries will be performed. - format: int64 - type: integer - type: object - sync: - description: Sync contains parameters for the operation - properties: - dryRun: - description: DryRun specifies to perform a `kubectl apply --dry-run` without actually performing the sync - type: boolean - manifests: - description: Manifests is an optional field that overrides sync source with a local directory for development - items: - type: string - type: array - prune: - description: Prune specifies to delete resources from the cluster that are no longer tracked in git - type: boolean - resources: - description: Resources describes which resources shall be part of the sync - items: - description: SyncOperationResource contains resources to sync. - properties: - group: - type: string - kind: - type: string - name: - type: string - namespace: - type: string - required: - - kind - - name - type: object - type: array - revision: - description: Revision is the revision (Git) or chart version (Helm) which to sync the application to If omitted, will use the revision specified in app spec. - type: string - source: - description: Source overrides the source definition set in the application. This is typically set in a Rollback operation and is nil during a Sync operation - properties: - chart: - description: Chart is a Helm chart name, and must be specified for applications sourced from a Helm repo. - type: string - directory: - description: Directory holds path/directory specific options - properties: - exclude: - description: Exclude contains a glob pattern to match paths against that should be explicitly excluded from being used during manifest generation - type: string - include: - description: Include contains a glob pattern to match paths against that should be explicitly included during manifest generation - type: string - jsonnet: - description: Jsonnet holds options specific to Jsonnet - properties: - extVars: - description: ExtVars is a list of Jsonnet External Variables - items: - description: JsonnetVar represents a variable to be passed to jsonnet during manifest generation - properties: - code: - type: boolean - name: - type: string - value: - type: string - required: - - name - - value - type: object - type: array - libs: - description: Additional library search dirs - items: - type: string - type: array - tlas: - description: TLAS is a list of Jsonnet Top-level Arguments - items: - description: JsonnetVar represents a variable to be passed to jsonnet during manifest generation - properties: - code: - type: boolean - name: - type: string - value: - type: string - required: - - name - - value - type: object - type: array - type: object - recurse: - description: Recurse specifies whether to scan a directory recursively for manifests - type: boolean - type: object - helm: - description: Helm holds helm specific options - properties: - fileParameters: - description: FileParameters are file parameters to the helm template - items: - description: HelmFileParameter is a file parameter that's passed to helm template during manifest generation - properties: - name: - description: Name is the name of the Helm parameter - type: string - path: - description: Path is the path to the file containing the values for the Helm parameter - type: string - type: object - type: array - parameters: - description: Parameters is a list of Helm parameters which are passed to the helm template command upon manifest generation - items: - description: HelmParameter is a parameter that's passed to helm template during manifest generation - properties: - forceString: - description: ForceString determines whether to tell Helm to interpret booleans and numbers as strings - type: boolean - name: - description: Name is the name of the Helm parameter - type: string - value: - description: Value is the value for the Helm parameter - type: string - type: object - type: array - releaseName: - description: ReleaseName is the Helm release name to use. If omitted it will use the application name - type: string - valueFiles: - description: ValuesFiles is a list of Helm value files to use when generating a template - items: - type: string - type: array - values: - description: Values specifies Helm values to be passed to helm template, typically defined as a block - type: string - version: - description: Version is the Helm version to use for templating (either "2" or "3") - type: string - type: object - ksonnet: - description: Ksonnet holds ksonnet specific options - properties: - environment: - description: Environment is a ksonnet application environment name - type: string - parameters: - description: Parameters are a list of ksonnet component parameter override values - items: - description: KsonnetParameter is a ksonnet component parameter - properties: - component: - type: string - name: - type: string - value: - type: string - required: - - name - - value - type: object - type: array - type: object - kustomize: - description: Kustomize holds kustomize specific options - properties: - commonAnnotations: - additionalProperties: - type: string - description: CommonAnnotations is a list of additional annotations to add to rendered manifests - type: object - commonLabels: - additionalProperties: - type: string - description: CommonLabels is a list of additional labels to add to rendered manifests - type: object - images: - description: Images is a list of Kustomize image override specifications - items: - description: KustomizeImage represents a Kustomize image definition in the format [old_image_name=]: - type: string - type: array - namePrefix: - description: NamePrefix is a prefix appended to resources for Kustomize apps - type: string - nameSuffix: - description: NameSuffix is a suffix appended to resources for Kustomize apps - type: string - version: - description: Version controls which version of Kustomize to use for rendering manifests - type: string - type: object - path: - description: Path is a directory path within the Git repository, and is only valid for applications sourced from Git. - type: string - plugin: - description: ConfigManagementPlugin holds config management plugin specific options - properties: - env: - description: Env is a list of environment variable entries - items: - description: EnvEntry represents an entry in the application's environment - properties: - name: - description: Name is the name of the variable, usually expressed in uppercase - type: string - value: - description: Value is the value of the variable - type: string - required: - - name - - value - type: object - type: array - name: - type: string - type: object - repoURL: - description: RepoURL is the URL to the repository (Git or Helm) that contains the application manifests - type: string - targetRevision: - description: TargetRevision defines the revision of the source to sync the application to. In case of Git, this can be commit, tag, or branch. If omitted, will equal to HEAD. In case of Helm, this is a semver tag for the Chart's version. - type: string - required: - - repoURL - type: object - syncOptions: - description: SyncOptions provide per-sync sync-options, e.g. Validate=false - items: - type: string - type: array - syncStrategy: - description: SyncStrategy describes how to perform the sync - properties: - apply: - description: Apply will perform a `kubectl apply` to perform the sync. - properties: - force: - description: Force indicates whether or not to supply the --force flag to `kubectl apply`. The --force flag deletes and re-create the resource, when PATCH encounters conflict and has retried for 5 times. - type: boolean - type: object - hook: - description: Hook will submit any referenced resources to perform the sync. This is the default strategy - properties: - force: - description: Force indicates whether or not to supply the --force flag to `kubectl apply`. The --force flag deletes and re-create the resource, when PATCH encounters conflict and has retried for 5 times. - type: boolean - type: object - type: object - type: object - type: object - phase: - description: Phase is the current phase of the operation - type: string - retryCount: - description: RetryCount contains time of operation retries - format: int64 - type: integer - startedAt: - description: StartedAt contains time of operation start - format: date-time - type: string - syncResult: - description: SyncResult is the result of a Sync operation - properties: - resources: - description: Resources contains a list of sync result items for each individual resource in a sync operation - items: - description: ResourceResult holds the operation result details of a specific resource - properties: - group: - description: Group specifies the API group of the resource - type: string - hookPhase: - description: HookPhase contains the state of any operation associated with this resource OR hook This can also contain values for non-hook resources. - type: string - hookType: - description: HookType specifies the type of the hook. Empty for non-hook resources - type: string - kind: - description: Kind specifies the API kind of the resource - type: string - message: - description: Message contains an informational or error message for the last sync OR operation - type: string - name: - description: Name specifies the name of the resource - type: string - namespace: - description: Namespace specifies the target namespace of the resource - type: string - status: - description: Status holds the final result of the sync. Will be empty if the resources is yet to be applied/pruned and is always zero-value for hooks - type: string - syncPhase: - description: SyncPhase indicates the particular phase of the sync that this result was acquired in - type: string - version: - description: Version specifies the API version of the resource - type: string - required: - - group - - kind - - name - - namespace - - version - type: object - type: array - revision: - description: Revision holds the revision this sync operation was performed to - type: string - source: - description: Source records the application source information of the sync, used for comparing auto-sync - properties: - chart: - description: Chart is a Helm chart name, and must be specified for applications sourced from a Helm repo. - type: string - directory: - description: Directory holds path/directory specific options - properties: - exclude: - description: Exclude contains a glob pattern to match paths against that should be explicitly excluded from being used during manifest generation - type: string - include: - description: Include contains a glob pattern to match paths against that should be explicitly included during manifest generation - type: string - jsonnet: - description: Jsonnet holds options specific to Jsonnet - properties: - extVars: - description: ExtVars is a list of Jsonnet External Variables - items: - description: JsonnetVar represents a variable to be passed to jsonnet during manifest generation - properties: - code: - type: boolean - name: - type: string - value: - type: string - required: - - name - - value - type: object - type: array - libs: - description: Additional library search dirs - items: - type: string - type: array - tlas: - description: TLAS is a list of Jsonnet Top-level Arguments - items: - description: JsonnetVar represents a variable to be passed to jsonnet during manifest generation - properties: - code: - type: boolean - name: - type: string - value: - type: string - required: - - name - - value - type: object - type: array - type: object - recurse: - description: Recurse specifies whether to scan a directory recursively for manifests - type: boolean - type: object - helm: - description: Helm holds helm specific options - properties: - fileParameters: - description: FileParameters are file parameters to the helm template - items: - description: HelmFileParameter is a file parameter that's passed to helm template during manifest generation - properties: - name: - description: Name is the name of the Helm parameter - type: string - path: - description: Path is the path to the file containing the values for the Helm parameter - type: string - type: object - type: array - parameters: - description: Parameters is a list of Helm parameters which are passed to the helm template command upon manifest generation - items: - description: HelmParameter is a parameter that's passed to helm template during manifest generation - properties: - forceString: - description: ForceString determines whether to tell Helm to interpret booleans and numbers as strings - type: boolean - name: - description: Name is the name of the Helm parameter - type: string - value: - description: Value is the value for the Helm parameter - type: string - type: object - type: array - releaseName: - description: ReleaseName is the Helm release name to use. If omitted it will use the application name - type: string - valueFiles: - description: ValuesFiles is a list of Helm value files to use when generating a template - items: - type: string - type: array - values: - description: Values specifies Helm values to be passed to helm template, typically defined as a block - type: string - version: - description: Version is the Helm version to use for templating (either "2" or "3") - type: string - type: object - ksonnet: - description: Ksonnet holds ksonnet specific options - properties: - environment: - description: Environment is a ksonnet application environment name - type: string - parameters: - description: Parameters are a list of ksonnet component parameter override values - items: - description: KsonnetParameter is a ksonnet component parameter - properties: - component: - type: string - name: - type: string - value: - type: string - required: - - name - - value - type: object - type: array - type: object - kustomize: - description: Kustomize holds kustomize specific options - properties: - commonAnnotations: - additionalProperties: - type: string - description: CommonAnnotations is a list of additional annotations to add to rendered manifests - type: object - commonLabels: - additionalProperties: - type: string - description: CommonLabels is a list of additional labels to add to rendered manifests - type: object - images: - description: Images is a list of Kustomize image override specifications - items: - description: KustomizeImage represents a Kustomize image definition in the format [old_image_name=]: - type: string - type: array - namePrefix: - description: NamePrefix is a prefix appended to resources for Kustomize apps - type: string - nameSuffix: - description: NameSuffix is a suffix appended to resources for Kustomize apps - type: string - version: - description: Version controls which version of Kustomize to use for rendering manifests - type: string - type: object - path: - description: Path is a directory path within the Git repository, and is only valid for applications sourced from Git. - type: string - plugin: - description: ConfigManagementPlugin holds config management plugin specific options - properties: - env: - description: Env is a list of environment variable entries - items: - description: EnvEntry represents an entry in the application's environment - properties: - name: - description: Name is the name of the variable, usually expressed in uppercase - type: string - value: - description: Value is the value of the variable - type: string - required: - - name - - value - type: object - type: array - name: - type: string - type: object - repoURL: - description: RepoURL is the URL to the repository (Git or Helm) that contains the application manifests - type: string - targetRevision: - description: TargetRevision defines the revision of the source to sync the application to. In case of Git, this can be commit, tag, or branch. If omitted, will equal to HEAD. In case of Helm, this is a semver tag for the Chart's version. - type: string - required: - - repoURL - type: object - required: - - revision - type: object - required: - - operation - - phase - - startedAt - type: object - reconciledAt: - description: ReconciledAt indicates when the application state was reconciled using the latest git version - format: date-time - type: string - resources: - description: Resources is a list of Kubernetes resources managed by this application - items: - description: 'ResourceStatus holds the current sync and health status of a resource TODO: describe members of this type' - properties: - group: - type: string - health: - description: HealthStatus contains information about the currently observed health state of an application or resource - properties: - message: - description: Message is a human-readable informational message describing the health status - type: string - status: - description: Status holds the status code of the application or resource - type: string - type: object - hook: - type: boolean - kind: - type: string - name: - type: string - namespace: - type: string - requiresPruning: - type: boolean - status: - description: SyncStatusCode is a type which represents possible comparison results - type: string - version: - type: string - type: object - type: array - sourceType: - description: SourceType specifies the type of this application - type: string - summary: - description: Summary contains a list of URLs and container images used by this application - properties: - externalURLs: - description: ExternalURLs holds all external URLs of application child resources. - items: - type: string - type: array - images: - description: Images holds all images of application child resources. - items: - type: string - type: array - type: object - sync: - description: Sync contains information about the application's current sync status - properties: - comparedTo: - description: ComparedTo contains information about what has been compared - properties: - destination: - description: Destination is a reference to the application's destination used for comparison - properties: - name: - description: Name is an alternate way of specifying the target cluster by its symbolic name - type: string - namespace: - description: Namespace specifies the target namespace for the application's resources. The namespace will only be set for namespace-scoped resources that have not set a value for .metadata.namespace - type: string - server: - description: Server specifies the URL of the target cluster and must be set to the Kubernetes control plane API - type: string - type: object - source: - description: Source is a reference to the application's source used for comparison - properties: - chart: - description: Chart is a Helm chart name, and must be specified for applications sourced from a Helm repo. - type: string - directory: - description: Directory holds path/directory specific options - properties: - exclude: - description: Exclude contains a glob pattern to match paths against that should be explicitly excluded from being used during manifest generation - type: string - include: - description: Include contains a glob pattern to match paths against that should be explicitly included during manifest generation - type: string - jsonnet: - description: Jsonnet holds options specific to Jsonnet - properties: - extVars: - description: ExtVars is a list of Jsonnet External Variables - items: - description: JsonnetVar represents a variable to be passed to jsonnet during manifest generation - properties: - code: - type: boolean - name: - type: string - value: - type: string - required: - - name - - value - type: object - type: array - libs: - description: Additional library search dirs - items: - type: string - type: array - tlas: - description: TLAS is a list of Jsonnet Top-level Arguments - items: - description: JsonnetVar represents a variable to be passed to jsonnet during manifest generation - properties: - code: - type: boolean - name: - type: string - value: - type: string - required: - - name - - value - type: object - type: array - type: object - recurse: - description: Recurse specifies whether to scan a directory recursively for manifests - type: boolean - type: object - helm: - description: Helm holds helm specific options - properties: - fileParameters: - description: FileParameters are file parameters to the helm template - items: - description: HelmFileParameter is a file parameter that's passed to helm template during manifest generation - properties: - name: - description: Name is the name of the Helm parameter - type: string - path: - description: Path is the path to the file containing the values for the Helm parameter - type: string - type: object - type: array - parameters: - description: Parameters is a list of Helm parameters which are passed to the helm template command upon manifest generation - items: - description: HelmParameter is a parameter that's passed to helm template during manifest generation - properties: - forceString: - description: ForceString determines whether to tell Helm to interpret booleans and numbers as strings - type: boolean - name: - description: Name is the name of the Helm parameter - type: string - value: - description: Value is the value for the Helm parameter - type: string - type: object - type: array - releaseName: - description: ReleaseName is the Helm release name to use. If omitted it will use the application name - type: string - valueFiles: - description: ValuesFiles is a list of Helm value files to use when generating a template - items: - type: string - type: array - values: - description: Values specifies Helm values to be passed to helm template, typically defined as a block - type: string - version: - description: Version is the Helm version to use for templating (either "2" or "3") - type: string - type: object - ksonnet: - description: Ksonnet holds ksonnet specific options - properties: - environment: - description: Environment is a ksonnet application environment name - type: string - parameters: - description: Parameters are a list of ksonnet component parameter override values - items: - description: KsonnetParameter is a ksonnet component parameter - properties: - component: - type: string - name: - type: string - value: - type: string - required: - - name - - value - type: object - type: array - type: object - kustomize: - description: Kustomize holds kustomize specific options - properties: - commonAnnotations: - additionalProperties: - type: string - description: CommonAnnotations is a list of additional annotations to add to rendered manifests - type: object - commonLabels: - additionalProperties: - type: string - description: CommonLabels is a list of additional labels to add to rendered manifests - type: object - images: - description: Images is a list of Kustomize image override specifications - items: - description: KustomizeImage represents a Kustomize image definition in the format [old_image_name=]: - type: string - type: array - namePrefix: - description: NamePrefix is a prefix appended to resources for Kustomize apps - type: string - nameSuffix: - description: NameSuffix is a suffix appended to resources for Kustomize apps - type: string - version: - description: Version controls which version of Kustomize to use for rendering manifests - type: string - type: object - path: - description: Path is a directory path within the Git repository, and is only valid for applications sourced from Git. - type: string - plugin: - description: ConfigManagementPlugin holds config management plugin specific options - properties: - env: - description: Env is a list of environment variable entries - items: - description: EnvEntry represents an entry in the application's environment - properties: - name: - description: Name is the name of the variable, usually expressed in uppercase - type: string - value: - description: Value is the value of the variable - type: string - required: - - name - - value - type: object - type: array - name: - type: string - type: object - repoURL: - description: RepoURL is the URL to the repository (Git or Helm) that contains the application manifests - type: string - targetRevision: - description: TargetRevision defines the revision of the source to sync the application to. In case of Git, this can be commit, tag, or branch. If omitted, will equal to HEAD. In case of Helm, this is a semver tag for the Chart's version. - type: string - required: - - repoURL - type: object - required: - - destination - - source - type: object - revision: - description: Revision contains information about the revision the comparison has been performed to - type: string - status: - description: Status is the sync state of the comparison - type: string - required: - - status - type: object - type: object - required: - - metadata - - spec - type: object - served: true - storage: true - subresources: {} diff --git a/cmd/agent/test/argo-application.yaml b/cmd/agent/test/argo-application.yaml deleted file mode 100644 index cc922892ad..0000000000 --- a/cmd/agent/test/argo-application.yaml +++ /dev/null @@ -1,16 +0,0 @@ -apiVersion: argoproj.io/v1alpha1 -kind: Application -metadata: - name: test-application - namespace: default -spec: - destination: - namespace: default - server: https://kubernetes.default.svc - project: default - source: - path: examples/ambassador-canary - repoURL: git@github.com:datawire/argo-rollouts.git - targetRevision: ambassador/test/echo - syncPolicy: - automated: {} diff --git a/cmd/agent/test/argo-rollouts-crd.yaml b/cmd/agent/test/argo-rollouts-crd.yaml deleted file mode 100644 index 25cb90c5f9..0000000000 --- a/cmd/agent/test/argo-rollouts-crd.yaml +++ /dev/null @@ -1,3273 +0,0 @@ -apiVersion: apiextensions.k8s.io/v1beta1 -kind: CustomResourceDefinition -metadata: - annotations: - controller-gen.kubebuilder.io/version: v0.4.1 - name: rollouts.argoproj.io -spec: - additionalPrinterColumns: - - JSONPath: .spec.replicas - description: Number of desired pods - name: Desired - type: integer - - JSONPath: .status.replicas - description: Total number of non-terminated pods targeted by this rollout - name: Current - type: integer - - JSONPath: .status.updatedReplicas - description: Total number of non-terminated pods targeted by this rollout that have the desired template spec - name: Up-to-date - type: integer - - JSONPath: .status.availableReplicas - description: Total number of available pods (ready for at least minReadySeconds) targeted by this rollout - name: Available - type: integer - group: argoproj.io - names: - kind: Rollout - listKind: RolloutList - plural: rollouts - shortNames: - - ro - singular: rollout - scope: Namespaced - subresources: - scale: - labelSelectorPath: .status.selector - specReplicasPath: .spec.replicas - statusReplicasPath: .status.HPAReplicas - status: {} - validation: - openAPIV3Schema: - properties: - apiVersion: - type: string - kind: - type: string - metadata: - type: object - spec: - properties: - minReadySeconds: - format: int32 - type: integer - paused: - type: boolean - progressDeadlineSeconds: - format: int32 - type: integer - replicas: - format: int32 - type: integer - restartAt: - format: date-time - type: string - revisionHistoryLimit: - format: int32 - type: integer - selector: - properties: - matchExpressions: - items: - properties: - key: - type: string - operator: - type: string - values: - items: - type: string - type: array - required: - - key - - operator - type: object - type: array - matchLabels: - additionalProperties: - type: string - type: object - type: object - strategy: - properties: - blueGreen: - properties: - activeService: - type: string - antiAffinity: - properties: - preferredDuringSchedulingIgnoredDuringExecution: - properties: - weight: - format: int32 - type: integer - required: - - weight - type: object - requiredDuringSchedulingIgnoredDuringExecution: - type: object - type: object - autoPromotionEnabled: - type: boolean - autoPromotionSeconds: - format: int32 - type: integer - postPromotionAnalysis: - properties: - args: - items: - properties: - name: - type: string - value: - type: string - valueFrom: - properties: - fieldRef: - properties: - fieldPath: - type: string - required: - - fieldPath - type: object - podTemplateHashValue: - type: string - type: object - required: - - name - type: object - type: array - clusterScope: - type: boolean - templateName: - type: string - templates: - items: - properties: - clusterScope: - type: boolean - templateName: - type: string - type: object - type: array - type: object - prePromotionAnalysis: - properties: - args: - items: - properties: - name: - type: string - value: - type: string - valueFrom: - properties: - fieldRef: - properties: - fieldPath: - type: string - required: - - fieldPath - type: object - podTemplateHashValue: - type: string - type: object - required: - - name - type: object - type: array - clusterScope: - type: boolean - templateName: - type: string - templates: - items: - properties: - clusterScope: - type: boolean - templateName: - type: string - type: object - type: array - type: object - previewReplicaCount: - format: int32 - type: integer - previewService: - type: string - scaleDownDelayRevisionLimit: - format: int32 - type: integer - scaleDownDelaySeconds: - format: int32 - type: integer - required: - - activeService - type: object - canary: - properties: - analysis: - properties: - args: - items: - properties: - name: - type: string - value: - type: string - valueFrom: - properties: - fieldRef: - properties: - fieldPath: - type: string - required: - - fieldPath - type: object - podTemplateHashValue: - type: string - type: object - required: - - name - type: object - type: array - clusterScope: - type: boolean - startingStep: - format: int32 - type: integer - templateName: - type: string - templates: - items: - properties: - clusterScope: - type: boolean - templateName: - type: string - type: object - type: array - type: object - antiAffinity: - properties: - preferredDuringSchedulingIgnoredDuringExecution: - properties: - weight: - format: int32 - type: integer - required: - - weight - type: object - requiredDuringSchedulingIgnoredDuringExecution: - type: object - type: object - canaryMetadata: - properties: - annotations: - additionalProperties: - type: string - type: object - labels: - additionalProperties: - type: string - type: object - type: object - canaryService: - type: string - maxSurge: - anyOf: - - type: integer - - type: string - x-kubernetes-int-or-string: true - maxUnavailable: - anyOf: - - type: integer - - type: string - x-kubernetes-int-or-string: true - stableMetadata: - properties: - annotations: - additionalProperties: - type: string - type: object - labels: - additionalProperties: - type: string - type: object - type: object - stableService: - type: string - steps: - items: - properties: - analysis: - properties: - args: - items: - properties: - name: - type: string - value: - type: string - valueFrom: - properties: - fieldRef: - properties: - fieldPath: - type: string - required: - - fieldPath - type: object - podTemplateHashValue: - type: string - type: object - required: - - name - type: object - type: array - clusterScope: - type: boolean - templateName: - type: string - templates: - items: - properties: - clusterScope: - type: boolean - templateName: - type: string - type: object - type: array - type: object - experiment: - properties: - analyses: - items: - properties: - args: - items: - properties: - name: - type: string - value: - type: string - valueFrom: - properties: - fieldRef: - properties: - fieldPath: - type: string - required: - - fieldPath - type: object - podTemplateHashValue: - type: string - type: object - required: - - name - type: object - type: array - clusterScope: - type: boolean - name: - type: string - requiredForCompletion: - type: boolean - templateName: - type: string - required: - - name - - templateName - type: object - type: array - duration: - type: string - templates: - items: - properties: - metadata: - properties: - annotations: - additionalProperties: - type: string - type: object - labels: - additionalProperties: - type: string - type: object - type: object - name: - type: string - replicas: - format: int32 - type: integer - selector: - properties: - matchExpressions: - items: - properties: - key: - type: string - operator: - type: string - values: - items: - type: string - type: array - required: - - key - - operator - type: object - type: array - matchLabels: - additionalProperties: - type: string - type: object - type: object - specRef: - type: string - required: - - name - - specRef - type: object - type: array - required: - - templates - type: object - pause: - properties: - duration: - anyOf: - - type: integer - - type: string - x-kubernetes-int-or-string: true - type: object - setCanaryScale: - properties: - matchTrafficWeight: - type: boolean - replicas: - format: int32 - type: integer - weight: - format: int32 - type: integer - type: object - setWeight: - format: int32 - type: integer - type: object - type: array - trafficRouting: - properties: - alb: - properties: - annotationPrefix: - type: string - ingress: - type: string - rootService: - type: string - servicePort: - format: int32 - type: integer - required: - - ingress - - servicePort - type: object - ambassador: - properties: - apiVersion: - type: string - mappings: - items: - type: string - type: array - required: - - mappings - type: object - istio: - properties: - virtualService: - properties: - name: - type: string - routes: - items: - type: string - type: array - required: - - name - - routes - type: object - required: - - virtualService - type: object - nginx: - properties: - additionalIngressAnnotations: - additionalProperties: - type: string - type: object - annotationPrefix: - type: string - stableIngress: - type: string - required: - - stableIngress - type: object - smi: - properties: - rootService: - type: string - trafficSplitName: - type: string - type: object - type: object - type: object - type: object - template: - properties: - metadata: - properties: - annotations: - additionalProperties: - type: string - type: object - labels: - additionalProperties: - type: string - type: object - type: object - spec: - properties: - activeDeadlineSeconds: - format: int64 - type: integer - affinity: - properties: - nodeAffinity: - properties: - preferredDuringSchedulingIgnoredDuringExecution: - items: - properties: - preference: - properties: - matchExpressions: - items: - properties: - key: - type: string - operator: - type: string - values: - items: - type: string - type: array - required: - - key - - operator - type: object - type: array - matchFields: - items: - properties: - key: - type: string - operator: - type: string - values: - items: - type: string - type: array - required: - - key - - operator - type: object - type: array - type: object - weight: - format: int32 - type: integer - required: - - preference - - weight - type: object - type: array - requiredDuringSchedulingIgnoredDuringExecution: - properties: - nodeSelectorTerms: - items: - properties: - matchExpressions: - items: - properties: - key: - type: string - operator: - type: string - values: - items: - type: string - type: array - required: - - key - - operator - type: object - type: array - matchFields: - items: - properties: - key: - type: string - operator: - type: string - values: - items: - type: string - type: array - required: - - key - - operator - type: object - type: array - type: object - type: array - required: - - nodeSelectorTerms - type: object - type: object - podAffinity: - properties: - preferredDuringSchedulingIgnoredDuringExecution: - items: - properties: - podAffinityTerm: - properties: - labelSelector: - properties: - matchExpressions: - items: - properties: - key: - type: string - operator: - type: string - values: - items: - type: string - type: array - required: - - key - - operator - type: object - type: array - matchLabels: - additionalProperties: - type: string - type: object - type: object - namespaces: - items: - type: string - type: array - topologyKey: - type: string - required: - - topologyKey - type: object - weight: - format: int32 - type: integer - required: - - podAffinityTerm - - weight - type: object - type: array - requiredDuringSchedulingIgnoredDuringExecution: - items: - properties: - labelSelector: - properties: - matchExpressions: - items: - properties: - key: - type: string - operator: - type: string - values: - items: - type: string - type: array - required: - - key - - operator - type: object - type: array - matchLabels: - additionalProperties: - type: string - type: object - type: object - namespaces: - items: - type: string - type: array - topologyKey: - type: string - required: - - topologyKey - type: object - type: array - type: object - podAntiAffinity: - properties: - preferredDuringSchedulingIgnoredDuringExecution: - items: - properties: - podAffinityTerm: - properties: - labelSelector: - properties: - matchExpressions: - items: - properties: - key: - type: string - operator: - type: string - values: - items: - type: string - type: array - required: - - key - - operator - type: object - type: array - matchLabels: - additionalProperties: - type: string - type: object - type: object - namespaces: - items: - type: string - type: array - topologyKey: - type: string - required: - - topologyKey - type: object - weight: - format: int32 - type: integer - required: - - podAffinityTerm - - weight - type: object - type: array - requiredDuringSchedulingIgnoredDuringExecution: - items: - properties: - labelSelector: - properties: - matchExpressions: - items: - properties: - key: - type: string - operator: - type: string - values: - items: - type: string - type: array - required: - - key - - operator - type: object - type: array - matchLabels: - additionalProperties: - type: string - type: object - type: object - namespaces: - items: - type: string - type: array - topologyKey: - type: string - required: - - topologyKey - type: object - type: array - type: object - type: object - automountServiceAccountToken: - type: boolean - containers: - items: - properties: - args: - items: - type: string - type: array - command: - items: - type: string - type: array - env: - items: - properties: - name: - type: string - value: - type: string - valueFrom: - properties: - configMapKeyRef: - properties: - key: - type: string - name: - type: string - optional: - type: boolean - required: - - key - type: object - fieldRef: - properties: - apiVersion: - type: string - fieldPath: - type: string - required: - - fieldPath - type: object - resourceFieldRef: - properties: - containerName: - type: string - divisor: - anyOf: - - type: integer - - type: string - pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ - x-kubernetes-int-or-string: true - resource: - type: string - required: - - resource - type: object - secretKeyRef: - properties: - key: - type: string - name: - type: string - optional: - type: boolean - required: - - key - type: object - type: object - required: - - name - type: object - type: array - envFrom: - items: - properties: - configMapRef: - properties: - name: - type: string - optional: - type: boolean - type: object - prefix: - type: string - secretRef: - properties: - name: - type: string - optional: - type: boolean - type: object - type: object - type: array - image: - type: string - imagePullPolicy: - type: string - lifecycle: - properties: - postStart: - properties: - exec: - properties: - command: - items: - type: string - type: array - type: object - httpGet: - properties: - host: - type: string - httpHeaders: - items: - properties: - name: - type: string - value: - type: string - required: - - name - - value - type: object - type: array - path: - type: string - port: - anyOf: - - type: integer - - type: string - x-kubernetes-int-or-string: true - scheme: - type: string - required: - - port - type: object - tcpSocket: - properties: - host: - type: string - port: - anyOf: - - type: integer - - type: string - x-kubernetes-int-or-string: true - required: - - port - type: object - type: object - preStop: - properties: - exec: - properties: - command: - items: - type: string - type: array - type: object - httpGet: - properties: - host: - type: string - httpHeaders: - items: - properties: - name: - type: string - value: - type: string - required: - - name - - value - type: object - type: array - path: - type: string - port: - anyOf: - - type: integer - - type: string - x-kubernetes-int-or-string: true - scheme: - type: string - required: - - port - type: object - tcpSocket: - properties: - host: - type: string - port: - anyOf: - - type: integer - - type: string - x-kubernetes-int-or-string: true - required: - - port - type: object - type: object - type: object - livenessProbe: - properties: - exec: - properties: - command: - items: - type: string - type: array - type: object - failureThreshold: - format: int32 - type: integer - httpGet: - properties: - host: - type: string - httpHeaders: - items: - properties: - name: - type: string - value: - type: string - required: - - name - - value - type: object - type: array - path: - type: string - port: - anyOf: - - type: integer - - type: string - x-kubernetes-int-or-string: true - scheme: - type: string - required: - - port - type: object - initialDelaySeconds: - format: int32 - type: integer - periodSeconds: - format: int32 - type: integer - successThreshold: - format: int32 - type: integer - tcpSocket: - properties: - host: - type: string - port: - anyOf: - - type: integer - - type: string - x-kubernetes-int-or-string: true - required: - - port - type: object - timeoutSeconds: - format: int32 - type: integer - type: object - name: - type: string - ports: - items: - properties: - containerPort: - format: int32 - type: integer - hostIP: - type: string - hostPort: - format: int32 - type: integer - name: - type: string - protocol: - type: string - required: - - containerPort - type: object - type: array - readinessProbe: - properties: - exec: - properties: - command: - items: - type: string - type: array - type: object - failureThreshold: - format: int32 - type: integer - httpGet: - properties: - host: - type: string - httpHeaders: - items: - properties: - name: - type: string - value: - type: string - required: - - name - - value - type: object - type: array - path: - type: string - port: - anyOf: - - type: integer - - type: string - x-kubernetes-int-or-string: true - scheme: - type: string - required: - - port - type: object - initialDelaySeconds: - format: int32 - type: integer - periodSeconds: - format: int32 - type: integer - successThreshold: - format: int32 - type: integer - tcpSocket: - properties: - host: - type: string - port: - anyOf: - - type: integer - - type: string - x-kubernetes-int-or-string: true - required: - - port - type: object - timeoutSeconds: - format: int32 - type: integer - type: object - resources: - type: object - securityContext: - properties: - allowPrivilegeEscalation: - type: boolean - capabilities: - properties: - add: - items: - type: string - type: array - drop: - items: - type: string - type: array - type: object - privileged: - type: boolean - procMount: - type: string - readOnlyRootFilesystem: - type: boolean - runAsGroup: - format: int64 - type: integer - runAsNonRoot: - type: boolean - runAsUser: - format: int64 - type: integer - seLinuxOptions: - properties: - level: - type: string - role: - type: string - type: - type: string - user: - type: string - type: object - seccompProfile: - properties: - localhostProfile: - type: string - type: - type: string - required: - - type - type: object - windowsOptions: - properties: - gmsaCredentialSpec: - type: string - gmsaCredentialSpecName: - type: string - runAsUserName: - type: string - type: object - type: object - startupProbe: - properties: - exec: - properties: - command: - items: - type: string - type: array - type: object - failureThreshold: - format: int32 - type: integer - httpGet: - properties: - host: - type: string - httpHeaders: - items: - properties: - name: - type: string - value: - type: string - required: - - name - - value - type: object - type: array - path: - type: string - port: - anyOf: - - type: integer - - type: string - x-kubernetes-int-or-string: true - scheme: - type: string - required: - - port - type: object - initialDelaySeconds: - format: int32 - type: integer - periodSeconds: - format: int32 - type: integer - successThreshold: - format: int32 - type: integer - tcpSocket: - properties: - host: - type: string - port: - anyOf: - - type: integer - - type: string - x-kubernetes-int-or-string: true - required: - - port - type: object - timeoutSeconds: - format: int32 - type: integer - type: object - stdin: - type: boolean - stdinOnce: - type: boolean - terminationMessagePath: - type: string - terminationMessagePolicy: - type: string - tty: - type: boolean - volumeDevices: - items: - properties: - devicePath: - type: string - name: - type: string - required: - - devicePath - - name - type: object - type: array - volumeMounts: - items: - properties: - mountPath: - type: string - mountPropagation: - type: string - name: - type: string - readOnly: - type: boolean - subPath: - type: string - subPathExpr: - type: string - required: - - mountPath - - name - type: object - type: array - workingDir: - type: string - required: - - name - type: object - type: array - dnsConfig: - properties: - nameservers: - items: - type: string - type: array - options: - items: - properties: - name: - type: string - value: - type: string - type: object - type: array - searches: - items: - type: string - type: array - type: object - dnsPolicy: - type: string - enableServiceLinks: - type: boolean - ephemeralContainers: - items: - properties: - args: - items: - type: string - type: array - command: - items: - type: string - type: array - env: - items: - properties: - name: - type: string - value: - type: string - valueFrom: - properties: - configMapKeyRef: - properties: - key: - type: string - name: - type: string - optional: - type: boolean - required: - - key - type: object - fieldRef: - properties: - apiVersion: - type: string - fieldPath: - type: string - required: - - fieldPath - type: object - resourceFieldRef: - properties: - containerName: - type: string - divisor: - anyOf: - - type: integer - - type: string - pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ - x-kubernetes-int-or-string: true - resource: - type: string - required: - - resource - type: object - secretKeyRef: - properties: - key: - type: string - name: - type: string - optional: - type: boolean - required: - - key - type: object - type: object - required: - - name - type: object - type: array - envFrom: - items: - properties: - configMapRef: - properties: - name: - type: string - optional: - type: boolean - type: object - prefix: - type: string - secretRef: - properties: - name: - type: string - optional: - type: boolean - type: object - type: object - type: array - image: - type: string - imagePullPolicy: - type: string - lifecycle: - properties: - postStart: - properties: - exec: - properties: - command: - items: - type: string - type: array - type: object - httpGet: - properties: - host: - type: string - httpHeaders: - items: - properties: - name: - type: string - value: - type: string - required: - - name - - value - type: object - type: array - path: - type: string - port: - anyOf: - - type: integer - - type: string - x-kubernetes-int-or-string: true - scheme: - type: string - required: - - port - type: object - tcpSocket: - properties: - host: - type: string - port: - anyOf: - - type: integer - - type: string - x-kubernetes-int-or-string: true - required: - - port - type: object - type: object - preStop: - properties: - exec: - properties: - command: - items: - type: string - type: array - type: object - httpGet: - properties: - host: - type: string - httpHeaders: - items: - properties: - name: - type: string - value: - type: string - required: - - name - - value - type: object - type: array - path: - type: string - port: - anyOf: - - type: integer - - type: string - x-kubernetes-int-or-string: true - scheme: - type: string - required: - - port - type: object - tcpSocket: - properties: - host: - type: string - port: - anyOf: - - type: integer - - type: string - x-kubernetes-int-or-string: true - required: - - port - type: object - type: object - type: object - livenessProbe: - properties: - exec: - properties: - command: - items: - type: string - type: array - type: object - failureThreshold: - format: int32 - type: integer - httpGet: - properties: - host: - type: string - httpHeaders: - items: - properties: - name: - type: string - value: - type: string - required: - - name - - value - type: object - type: array - path: - type: string - port: - anyOf: - - type: integer - - type: string - x-kubernetes-int-or-string: true - scheme: - type: string - required: - - port - type: object - initialDelaySeconds: - format: int32 - type: integer - periodSeconds: - format: int32 - type: integer - successThreshold: - format: int32 - type: integer - tcpSocket: - properties: - host: - type: string - port: - anyOf: - - type: integer - - type: string - x-kubernetes-int-or-string: true - required: - - port - type: object - timeoutSeconds: - format: int32 - type: integer - type: object - name: - type: string - ports: - items: - properties: - containerPort: - format: int32 - type: integer - hostIP: - type: string - hostPort: - format: int32 - type: integer - name: - type: string - protocol: - type: string - required: - - containerPort - type: object - type: array - readinessProbe: - properties: - exec: - properties: - command: - items: - type: string - type: array - type: object - failureThreshold: - format: int32 - type: integer - httpGet: - properties: - host: - type: string - httpHeaders: - items: - properties: - name: - type: string - value: - type: string - required: - - name - - value - type: object - type: array - path: - type: string - port: - anyOf: - - type: integer - - type: string - x-kubernetes-int-or-string: true - scheme: - type: string - required: - - port - type: object - initialDelaySeconds: - format: int32 - type: integer - periodSeconds: - format: int32 - type: integer - successThreshold: - format: int32 - type: integer - tcpSocket: - properties: - host: - type: string - port: - anyOf: - - type: integer - - type: string - x-kubernetes-int-or-string: true - required: - - port - type: object - timeoutSeconds: - format: int32 - type: integer - type: object - resources: - type: object - securityContext: - properties: - allowPrivilegeEscalation: - type: boolean - capabilities: - properties: - add: - items: - type: string - type: array - drop: - items: - type: string - type: array - type: object - privileged: - type: boolean - procMount: - type: string - readOnlyRootFilesystem: - type: boolean - runAsGroup: - format: int64 - type: integer - runAsNonRoot: - type: boolean - runAsUser: - format: int64 - type: integer - seLinuxOptions: - properties: - level: - type: string - role: - type: string - type: - type: string - user: - type: string - type: object - seccompProfile: - properties: - localhostProfile: - type: string - type: - type: string - required: - - type - type: object - windowsOptions: - properties: - gmsaCredentialSpec: - type: string - gmsaCredentialSpecName: - type: string - runAsUserName: - type: string - type: object - type: object - startupProbe: - properties: - exec: - properties: - command: - items: - type: string - type: array - type: object - failureThreshold: - format: int32 - type: integer - httpGet: - properties: - host: - type: string - httpHeaders: - items: - properties: - name: - type: string - value: - type: string - required: - - name - - value - type: object - type: array - path: - type: string - port: - anyOf: - - type: integer - - type: string - x-kubernetes-int-or-string: true - scheme: - type: string - required: - - port - type: object - initialDelaySeconds: - format: int32 - type: integer - periodSeconds: - format: int32 - type: integer - successThreshold: - format: int32 - type: integer - tcpSocket: - properties: - host: - type: string - port: - anyOf: - - type: integer - - type: string - x-kubernetes-int-or-string: true - required: - - port - type: object - timeoutSeconds: - format: int32 - type: integer - type: object - stdin: - type: boolean - stdinOnce: - type: boolean - targetContainerName: - type: string - terminationMessagePath: - type: string - terminationMessagePolicy: - type: string - tty: - type: boolean - volumeDevices: - items: - properties: - devicePath: - type: string - name: - type: string - required: - - devicePath - - name - type: object - type: array - volumeMounts: - items: - properties: - mountPath: - type: string - mountPropagation: - type: string - name: - type: string - readOnly: - type: boolean - subPath: - type: string - subPathExpr: - type: string - required: - - mountPath - - name - type: object - type: array - workingDir: - type: string - required: - - name - type: object - type: array - hostAliases: - items: - properties: - hostnames: - items: - type: string - type: array - ip: - type: string - type: object - type: array - hostIPC: - type: boolean - hostNetwork: - type: boolean - hostPID: - type: boolean - hostname: - type: string - imagePullSecrets: - items: - properties: - name: - type: string - type: object - type: array - initContainers: - items: - properties: - args: - items: - type: string - type: array - command: - items: - type: string - type: array - env: - items: - properties: - name: - type: string - value: - type: string - valueFrom: - properties: - configMapKeyRef: - properties: - key: - type: string - name: - type: string - optional: - type: boolean - required: - - key - type: object - fieldRef: - properties: - apiVersion: - type: string - fieldPath: - type: string - required: - - fieldPath - type: object - resourceFieldRef: - properties: - containerName: - type: string - divisor: - anyOf: - - type: integer - - type: string - pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ - x-kubernetes-int-or-string: true - resource: - type: string - required: - - resource - type: object - secretKeyRef: - properties: - key: - type: string - name: - type: string - optional: - type: boolean - required: - - key - type: object - type: object - required: - - name - type: object - type: array - envFrom: - items: - properties: - configMapRef: - properties: - name: - type: string - optional: - type: boolean - type: object - prefix: - type: string - secretRef: - properties: - name: - type: string - optional: - type: boolean - type: object - type: object - type: array - image: - type: string - imagePullPolicy: - type: string - lifecycle: - properties: - postStart: - properties: - exec: - properties: - command: - items: - type: string - type: array - type: object - httpGet: - properties: - host: - type: string - httpHeaders: - items: - properties: - name: - type: string - value: - type: string - required: - - name - - value - type: object - type: array - path: - type: string - port: - anyOf: - - type: integer - - type: string - x-kubernetes-int-or-string: true - scheme: - type: string - required: - - port - type: object - tcpSocket: - properties: - host: - type: string - port: - anyOf: - - type: integer - - type: string - x-kubernetes-int-or-string: true - required: - - port - type: object - type: object - preStop: - properties: - exec: - properties: - command: - items: - type: string - type: array - type: object - httpGet: - properties: - host: - type: string - httpHeaders: - items: - properties: - name: - type: string - value: - type: string - required: - - name - - value - type: object - type: array - path: - type: string - port: - anyOf: - - type: integer - - type: string - x-kubernetes-int-or-string: true - scheme: - type: string - required: - - port - type: object - tcpSocket: - properties: - host: - type: string - port: - anyOf: - - type: integer - - type: string - x-kubernetes-int-or-string: true - required: - - port - type: object - type: object - type: object - livenessProbe: - properties: - exec: - properties: - command: - items: - type: string - type: array - type: object - failureThreshold: - format: int32 - type: integer - httpGet: - properties: - host: - type: string - httpHeaders: - items: - properties: - name: - type: string - value: - type: string - required: - - name - - value - type: object - type: array - path: - type: string - port: - anyOf: - - type: integer - - type: string - x-kubernetes-int-or-string: true - scheme: - type: string - required: - - port - type: object - initialDelaySeconds: - format: int32 - type: integer - periodSeconds: - format: int32 - type: integer - successThreshold: - format: int32 - type: integer - tcpSocket: - properties: - host: - type: string - port: - anyOf: - - type: integer - - type: string - x-kubernetes-int-or-string: true - required: - - port - type: object - timeoutSeconds: - format: int32 - type: integer - type: object - name: - type: string - ports: - items: - properties: - containerPort: - format: int32 - type: integer - hostIP: - type: string - hostPort: - format: int32 - type: integer - name: - type: string - protocol: - type: string - required: - - containerPort - type: object - type: array - readinessProbe: - properties: - exec: - properties: - command: - items: - type: string - type: array - type: object - failureThreshold: - format: int32 - type: integer - httpGet: - properties: - host: - type: string - httpHeaders: - items: - properties: - name: - type: string - value: - type: string - required: - - name - - value - type: object - type: array - path: - type: string - port: - anyOf: - - type: integer - - type: string - x-kubernetes-int-or-string: true - scheme: - type: string - required: - - port - type: object - initialDelaySeconds: - format: int32 - type: integer - periodSeconds: - format: int32 - type: integer - successThreshold: - format: int32 - type: integer - tcpSocket: - properties: - host: - type: string - port: - anyOf: - - type: integer - - type: string - x-kubernetes-int-or-string: true - required: - - port - type: object - timeoutSeconds: - format: int32 - type: integer - type: object - resources: - type: object - securityContext: - properties: - allowPrivilegeEscalation: - type: boolean - capabilities: - properties: - add: - items: - type: string - type: array - drop: - items: - type: string - type: array - type: object - privileged: - type: boolean - procMount: - type: string - readOnlyRootFilesystem: - type: boolean - runAsGroup: - format: int64 - type: integer - runAsNonRoot: - type: boolean - runAsUser: - format: int64 - type: integer - seLinuxOptions: - properties: - level: - type: string - role: - type: string - type: - type: string - user: - type: string - type: object - seccompProfile: - properties: - localhostProfile: - type: string - type: - type: string - required: - - type - type: object - windowsOptions: - properties: - gmsaCredentialSpec: - type: string - gmsaCredentialSpecName: - type: string - runAsUserName: - type: string - type: object - type: object - startupProbe: - properties: - exec: - properties: - command: - items: - type: string - type: array - type: object - failureThreshold: - format: int32 - type: integer - httpGet: - properties: - host: - type: string - httpHeaders: - items: - properties: - name: - type: string - value: - type: string - required: - - name - - value - type: object - type: array - path: - type: string - port: - anyOf: - - type: integer - - type: string - x-kubernetes-int-or-string: true - scheme: - type: string - required: - - port - type: object - initialDelaySeconds: - format: int32 - type: integer - periodSeconds: - format: int32 - type: integer - successThreshold: - format: int32 - type: integer - tcpSocket: - properties: - host: - type: string - port: - anyOf: - - type: integer - - type: string - x-kubernetes-int-or-string: true - required: - - port - type: object - timeoutSeconds: - format: int32 - type: integer - type: object - stdin: - type: boolean - stdinOnce: - type: boolean - terminationMessagePath: - type: string - terminationMessagePolicy: - type: string - tty: - type: boolean - volumeDevices: - items: - properties: - devicePath: - type: string - name: - type: string - required: - - devicePath - - name - type: object - type: array - volumeMounts: - items: - properties: - mountPath: - type: string - mountPropagation: - type: string - name: - type: string - readOnly: - type: boolean - subPath: - type: string - subPathExpr: - type: string - required: - - mountPath - - name - type: object - type: array - workingDir: - type: string - required: - - name - type: object - type: array - nodeName: - type: string - nodeSelector: - additionalProperties: - type: string - type: object - overhead: - additionalProperties: - anyOf: - - type: integer - - type: string - pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ - x-kubernetes-int-or-string: true - type: object - preemptionPolicy: - type: string - priority: - format: int32 - type: integer - priorityClassName: - type: string - readinessGates: - items: - properties: - conditionType: - type: string - required: - - conditionType - type: object - type: array - restartPolicy: - type: string - runtimeClassName: - type: string - schedulerName: - type: string - securityContext: - properties: - fsGroup: - format: int64 - type: integer - fsGroupChangePolicy: - type: string - runAsGroup: - format: int64 - type: integer - runAsNonRoot: - type: boolean - runAsUser: - format: int64 - type: integer - seLinuxOptions: - properties: - level: - type: string - role: - type: string - type: - type: string - user: - type: string - type: object - seccompProfile: - properties: - localhostProfile: - type: string - type: - type: string - required: - - type - type: object - supplementalGroups: - items: - format: int64 - type: integer - type: array - sysctls: - items: - properties: - name: - type: string - value: - type: string - required: - - name - - value - type: object - type: array - windowsOptions: - properties: - gmsaCredentialSpec: - type: string - gmsaCredentialSpecName: - type: string - runAsUserName: - type: string - type: object - type: object - serviceAccount: - type: string - serviceAccountName: - type: string - setHostnameAsFQDN: - type: boolean - shareProcessNamespace: - type: boolean - subdomain: - type: string - terminationGracePeriodSeconds: - format: int64 - type: integer - tolerations: - items: - properties: - effect: - type: string - key: - type: string - operator: - type: string - tolerationSeconds: - format: int64 - type: integer - value: - type: string - type: object - type: array - topologySpreadConstraints: - items: - properties: - labelSelector: - properties: - matchExpressions: - items: - properties: - key: - type: string - operator: - type: string - values: - items: - type: string - type: array - required: - - key - - operator - type: object - type: array - matchLabels: - additionalProperties: - type: string - type: object - type: object - maxSkew: - format: int32 - type: integer - topologyKey: - type: string - whenUnsatisfiable: - type: string - required: - - maxSkew - - topologyKey - - whenUnsatisfiable - type: object - type: array - volumes: - items: - properties: - awsElasticBlockStore: - properties: - fsType: - type: string - partition: - format: int32 - type: integer - readOnly: - type: boolean - volumeID: - type: string - required: - - volumeID - type: object - azureDisk: - properties: - cachingMode: - type: string - diskName: - type: string - diskURI: - type: string - fsType: - type: string - kind: - type: string - readOnly: - type: boolean - required: - - diskName - - diskURI - type: object - azureFile: - properties: - readOnly: - type: boolean - secretName: - type: string - shareName: - type: string - required: - - secretName - - shareName - type: object - cephfs: - properties: - monitors: - items: - type: string - type: array - path: - type: string - readOnly: - type: boolean - secretFile: - type: string - secretRef: - properties: - name: - type: string - type: object - user: - type: string - required: - - monitors - type: object - cinder: - properties: - fsType: - type: string - readOnly: - type: boolean - secretRef: - properties: - name: - type: string - type: object - volumeID: - type: string - required: - - volumeID - type: object - csi: - properties: - driver: - type: string - fsType: - type: string - nodePublishSecretRef: - properties: - name: - type: string - type: object - readOnly: - type: boolean - volumeAttributes: - additionalProperties: - type: string - type: object - required: - - driver - type: object - emptyDir: - properties: - medium: - type: string - sizeLimit: - anyOf: - - type: integer - - type: string - pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ - x-kubernetes-int-or-string: true - type: object - ephemeral: - properties: - readOnly: - type: boolean - volumeClaimTemplate: - properties: - metadata: - type: object - spec: - properties: - accessModes: - items: - type: string - type: array - dataSource: - properties: - apiGroup: - type: string - kind: - type: string - name: - type: string - required: - - kind - - name - type: object - resources: - properties: - limits: - additionalProperties: - anyOf: - - type: integer - - type: string - pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ - x-kubernetes-int-or-string: true - type: object - requests: - additionalProperties: - anyOf: - - type: integer - - type: string - pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ - x-kubernetes-int-or-string: true - type: object - type: object - selector: - properties: - matchExpressions: - items: - properties: - key: - type: string - operator: - type: string - values: - items: - type: string - type: array - required: - - key - - operator - type: object - type: array - matchLabels: - additionalProperties: - type: string - type: object - type: object - storageClassName: - type: string - volumeMode: - type: string - volumeName: - type: string - type: object - required: - - spec - type: object - type: object - fc: - properties: - fsType: - type: string - lun: - format: int32 - type: integer - readOnly: - type: boolean - targetWWNs: - items: - type: string - type: array - wwids: - items: - type: string - type: array - type: object - flexVolume: - properties: - driver: - type: string - fsType: - type: string - options: - additionalProperties: - type: string - type: object - readOnly: - type: boolean - secretRef: - properties: - name: - type: string - type: object - required: - - driver - type: object - flocker: - properties: - datasetName: - type: string - datasetUUID: - type: string - type: object - gcePersistentDisk: - properties: - fsType: - type: string - partition: - format: int32 - type: integer - pdName: - type: string - readOnly: - type: boolean - required: - - pdName - type: object - gitRepo: - properties: - directory: - type: string - repository: - type: string - revision: - type: string - required: - - repository - type: object - glusterfs: - properties: - endpoints: - type: string - path: - type: string - readOnly: - type: boolean - required: - - endpoints - - path - type: object - hostPath: - properties: - path: - type: string - type: - type: string - required: - - path - type: object - iscsi: - properties: - chapAuthDiscovery: - type: boolean - chapAuthSession: - type: boolean - fsType: - type: string - initiatorName: - type: string - iqn: - type: string - iscsiInterface: - type: string - lun: - format: int32 - type: integer - portals: - items: - type: string - type: array - readOnly: - type: boolean - secretRef: - properties: - name: - type: string - type: object - targetPortal: - type: string - required: - - iqn - - lun - - targetPortal - type: object - name: - type: string - nfs: - properties: - path: - type: string - readOnly: - type: boolean - server: - type: string - required: - - path - - server - type: object - persistentVolumeClaim: - properties: - claimName: - type: string - readOnly: - type: boolean - required: - - claimName - type: object - photonPersistentDisk: - properties: - fsType: - type: string - pdID: - type: string - required: - - pdID - type: object - portworxVolume: - properties: - fsType: - type: string - readOnly: - type: boolean - volumeID: - type: string - required: - - volumeID - type: object - projected: - properties: - defaultMode: - format: int32 - type: integer - sources: - items: - properties: - serviceAccountToken: - properties: - audience: - type: string - expirationSeconds: - format: int64 - type: integer - path: - type: string - required: - - path - type: object - type: object - type: array - required: - - sources - type: object - quobyte: - properties: - group: - type: string - readOnly: - type: boolean - registry: - type: string - tenant: - type: string - user: - type: string - volume: - type: string - required: - - registry - - volume - type: object - rbd: - properties: - fsType: - type: string - image: - type: string - keyring: - type: string - monitors: - items: - type: string - type: array - pool: - type: string - readOnly: - type: boolean - secretRef: - properties: - name: - type: string - type: object - user: - type: string - required: - - image - - monitors - type: object - scaleIO: - properties: - fsType: - type: string - gateway: - type: string - protectionDomain: - type: string - readOnly: - type: boolean - secretRef: - properties: - name: - type: string - type: object - sslEnabled: - type: boolean - storageMode: - type: string - storagePool: - type: string - system: - type: string - volumeName: - type: string - required: - - gateway - - secretRef - - system - type: object - storageos: - properties: - fsType: - type: string - readOnly: - type: boolean - secretRef: - properties: - name: - type: string - type: object - volumeName: - type: string - volumeNamespace: - type: string - type: object - vsphereVolume: - properties: - fsType: - type: string - storagePolicyID: - type: string - storagePolicyName: - type: string - volumePath: - type: string - required: - - volumePath - type: object - required: - - name - type: object - type: array - required: - - containers - type: object - type: object - required: - - selector - - template - type: object - status: - properties: - HPAReplicas: - format: int32 - type: integer - abort: - type: boolean - abortedAt: - format: date-time - type: string - availableReplicas: - format: int32 - type: integer - blueGreen: - properties: - activeSelector: - type: string - postPromotionAnalysisRun: - type: string - postPromotionAnalysisRunStatus: - properties: - message: - type: string - name: - type: string - status: - type: string - required: - - name - - status - type: object - prePromotionAnalysisRun: - type: string - prePromotionAnalysisRunStatus: - properties: - message: - type: string - name: - type: string - status: - type: string - required: - - name - - status - type: object - previewSelector: - type: string - previousActiveSelector: - type: string - scaleDownDelayStartTime: - format: date-time - type: string - scaleUpPreviewCheckPoint: - type: boolean - type: object - canary: - properties: - currentBackgroundAnalysisRun: - type: string - currentBackgroundAnalysisRunStatus: - properties: - message: - type: string - name: - type: string - status: - type: string - required: - - name - - status - type: object - currentExperiment: - type: string - currentStepAnalysisRun: - type: string - currentStepAnalysisRunStatus: - properties: - message: - type: string - name: - type: string - status: - type: string - required: - - name - - status - type: object - type: object - collisionCount: - format: int32 - type: integer - conditions: - items: - properties: - lastTransitionTime: - format: date-time - type: string - lastUpdateTime: - format: date-time - type: string - message: - type: string - reason: - type: string - status: - type: string - type: - type: string - required: - - lastTransitionTime - - lastUpdateTime - - message - - reason - - status - - type - type: object - type: array - controllerPause: - type: boolean - currentPodHash: - type: string - currentStepHash: - type: string - currentStepIndex: - format: int32 - type: integer - observedGeneration: - type: string - pauseConditions: - items: - properties: - reason: - type: string - startTime: - format: date-time - type: string - required: - - reason - - startTime - type: object - type: array - promoteFull: - type: boolean - readyReplicas: - format: int32 - type: integer - replicas: - format: int32 - type: integer - restartedAt: - format: date-time - type: string - selector: - type: string - stableRS: - type: string - updatedReplicas: - format: int32 - type: integer - type: object - required: - - spec - type: object - version: v1alpha1 - versions: - - name: v1alpha1 - served: true - storage: true diff --git a/cmd/agent/test/argo-rollouts.yaml b/cmd/agent/test/argo-rollouts.yaml deleted file mode 100644 index cb843cffd6..0000000000 --- a/cmd/agent/test/argo-rollouts.yaml +++ /dev/null @@ -1,40 +0,0 @@ -apiVersion: argoproj.io/v1alpha1 -kind: Rollout -metadata: - name: agent-e2e-test-rollout - annotations: - getambassador.io/rolloutId: "87544c25-710e-41fa-9fa8-3e0b2c0ed927" -spec: - replicas: 5 - revisionHistoryLimit: 2 - selector: - matchLabels: - app: echo - template: - metadata: - labels: - app: echo - spec: - containers: - - image: hashicorp/http-echo - args: - - "-text=VERSION 1" - - -listen=:8080 - imagePullPolicy: Always - name: echo-v1 - ports: - - containerPort: 8080 - strategy: - canary: - stableService: echo-stable - canaryService: echo-canary - trafficRouting: - ambassador: - apiVersion: getambassador.io/v1 - mappings: - - echo - steps: - - setWeight: 20 - - pause: {duration: 10s} - - setWeight: 100 - - pause: {duration: 10} diff --git a/cmd/edgectl/edgectl_test.go b/cmd/edgectl/edgectl_test.go deleted file mode 100644 index cfd64b6986..0000000000 --- a/cmd/edgectl/edgectl_test.go +++ /dev/null @@ -1,191 +0,0 @@ -package main - -import ( - "fmt" - "io/ioutil" - "os" - "runtime" - "strings" - "testing" - "time" - - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" - - "github.com/datawire/ambassador/pkg/dtest" - "github.com/datawire/ambassador/pkg/dtest/testprocess" - "github.com/datawire/dlib/dexec" - "github.com/datawire/dlib/dlog" -) - -var kubeconfig string - -func TestMain(m *testing.M) { - testprocess.Dispatch() - kubeconfig = dtest.Kubeconfig() - os.Setenv("DTEST_KUBECONFIG", kubeconfig) - dtest.WithMachineLock(func() { - os.Exit(m.Run()) - }) -} - -func newCmd(t testing.TB, args ...string) *dexec.Cmd { - ctx := dlog.NewTestContext(t, false) - cmd := dexec.CommandContext(ctx, args[0], args[1:]...) - cmd.Env = append(os.Environ(), "KUBECONFIG="+kubeconfig) - return cmd -} - -func run(t testing.TB, args ...string) error { - return newCmd(t, args...).Run() -} - -func capture(t testing.TB, args ...string) (string, error) { - output, err := newCmd(t, args...).CombinedOutput() - return string(output), err -} - -// doBuildExecutable calls make in a subprocess running as the user -func doBuildExecutable(t testing.TB) error { - if !strings.Contains(os.Getenv("MAKEFLAGS"), "--jobserver-auth") { - alreadySudoed := os.Getuid() == 0 && os.Getenv("SUDO_USER") != "" - args := []string{"make", "-C", "../..", "bin_" + runtime.GOOS + "_" + runtime.GOARCH + "/edgectl"} - if alreadySudoed { - // un-sudo - args = append([]string{"sudo", "-E", "-u", os.Getenv("SUDO_USER"), "--"}, args...) - } - return run(t, args...) - } - return nil -} - -var executable = "../../bin_" + runtime.GOOS + "_" + runtime.GOARCH + "/edgectl" - -func TestSmokeOutbound(t *testing.T) { - var out string - var err error - - namespace := fmt.Sprintf("edgectl-%d", os.Getpid()) - nsArg := fmt.Sprintf("--namespace=%s", namespace) - - t.Log("setup") - require.NoError(t, run(t, "sudo", "true"), "setup: acquire privileges") - require.NoError(t, run(t, "printenv", "KUBECONFIG"), "setup: ensure cluster is set") - require.NoError(t, run(t, "sudo", "rm", "-f", "/tmp/edgectl.log"), "setup: remove old log") - require.NoError(t, - run(t, "kubectl", "delete", "pod", "teleproxy", "--ignore-not-found", "--wait=true"), - "setup: check cluster connectivity", - ) - require.NoError(t, doBuildExecutable(t), "setup: build executable") - require.NoError(t, run(t, "kubectl", "create", "namespace", namespace), "setup: create test namespace") - require.NoError(t, - run(t, "kubectl", nsArg, "create", "deploy", "hello-world", "--image=ark3/hello-world"), - "setup: create deployment", - ) - require.NoError(t, - run(t, "kubectl", nsArg, "expose", "deploy", "hello-world", "--port=80", "--target-port=8000"), - "setup: create service", - ) - require.NoError(t, - run(t, "kubectl", nsArg, "get", "svc,deploy", "hello-world"), - "setup: check svc/deploy", - ) - defer func() { - require.NoError(t, - run(t, "kubectl", "delete", "namespace", namespace, "--wait=false"), - "cleanup: delete test namespace", - ) - }() - - t.Log("pre-daemon") - require.Error(t, run(t, executable, "status"), "status with no daemon") - require.Error(t, run(t, executable, "daemon"), "daemon without sudo") - - t.Log("launch daemon") - if !assert.NoError(t, run(t, "sudo", executable, "daemon"), "launch daemon") { - logBytes, _ := ioutil.ReadFile("/tmp/edgectl.log") - for _, line := range strings.Split(string(logBytes), "\n") { - t.Logf("/tmp/edgectl.log: %q", line) - } - t.FailNow() - } - require.NoError(t, run(t, executable, "version"), "version with daemon") - require.NoError(t, run(t, executable, "status"), "status with daemon") - defer func() { require.NoError(t, run(t, executable, "quit"), "quit daemon") }() - - t.Log("await net overrides") - func() { - for i := 0; i < 120; i++ { - out, _ := capture(t, executable, "status") - if !strings.Contains(out, "Network overrides NOT established") { - return - } - time.Sleep(500 * time.Millisecond) - } - t.Fatal("timed out waiting for net overrides") - }() - - t.Log("connect") - require.Error(t, run(t, executable, "connect"), "connect without --legacy") - require.NoError(t, run(t, executable, "connect", "--legacy", "-n", namespace), "connect with --legacy") - out, err = capture(t, executable, "status") - require.NoError(t, err, "status connected") - if !strings.Contains(out, "Context") { - t.Fatal("Expected Context in connected status output") - } - defer func() { - require.NoError(t, - run(t, "kubectl", "delete", "pod", "teleproxy", "--ignore-not-found", "--wait=false"), - "make next time quicker", - ) - }() - - t.Log("await bridge") - func() { - for i := 0; i < 120; i++ { - out, _ := capture(t, executable, "status") - if strings.Contains(out, "Proxy: ON") { - return - } - time.Sleep(500 * time.Millisecond) - } - _ = run(t, "kubectl", "get", "pod", "teleproxy") - t.Fatal("timed out waiting for bridge") - }() - - t.Log("await service") - func() { - for i := 0; i < 120; i++ { - err := run(t, - // `kubectl` and global args - "kubectl", nsArg, - // `kubectl run` and args - "run", "--rm", "-it", "--image=pstauffer/curl", "--restart=Never", "curl-from-cluster", "--", - // `curl` and args - "curl", "--silent", "--output", "/dev/null", "http://hello-world."+namespace, - ) - if err == nil { - return - } - time.Sleep(500 * time.Millisecond) - } - t.Fatal("timed out waiting for hello-world service") - }() - - t.Log("check bridge") - require.NoError(t, run(t, "curl", "-sv", "hello-world."+namespace), "check bridge") - - t.Log("wind down") - out, err = capture(t, executable, "status") - require.NoError(t, err, "status connected") - if !strings.Contains(out, "Context") { - t.Fatal("Expected Context in connected status output") - } - require.NoError(t, run(t, executable, "disconnect"), "disconnect") - out, err = capture(t, executable, "status") - require.NoError(t, err, "status disconnected") - if !strings.Contains(out, "Not connected") { - t.Fatal("Expected Not connected in status output") - } - require.Error(t, run(t, "curl", "-sv", "hello-world."+namespace), "check disconnected") -} diff --git a/go.mod b/go.mod index 28be7dee1e..036258571f 100644 --- a/go.mod +++ b/go.mod @@ -64,10 +64,11 @@ require ( github.com/dgrijalva/jwt-go v3.2.0+incompatible github.com/ecodia/golang-awaitility v0.0.0-20180710094957-fb55e59708c7 github.com/envoyproxy/protoc-gen-validate v0.3.0-java.0.20200609174644-bd816e4522c1 + github.com/fatih/color v1.10.0 // indirect github.com/fsnotify/fsnotify v1.4.9 github.com/golang/protobuf v1.4.3 - github.com/google/go-cmp v0.5.2 - github.com/google/shlex v0.0.0-20181106134648-c34317bd91bf + github.com/google/go-cmp v0.5.5 + github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 github.com/google/uuid v1.1.2 github.com/gookit/color v1.2.3 github.com/gorilla/websocket v1.4.2 @@ -87,6 +88,7 @@ require ( golang.org/x/crypto v0.0.0-20201221181555-eec23a3978ad golang.org/x/net v0.0.0-20210119194325-5f4716e94777 golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c + golang.org/x/tools v0.1.0 // indirect google.golang.org/genproto v0.0.0-20201110150050-8816d57aaa9a google.golang.org/grpc v1.34.0 google.golang.org/protobuf v1.25.0 diff --git a/go.sum b/go.sum index 31864e097e..cd2689b6ff 100644 --- a/go.sum +++ b/go.sum @@ -283,6 +283,8 @@ github.com/fatih/camelcase v1.0.0 h1:hxNvNX/xYBp0ovncs8WyWZrOrpBNub/JfaMvbURyft8 github.com/fatih/camelcase v1.0.0/go.mod h1:yN2Sb0lFhZJUdVvtELVWefmrXpuZESvPmqwoZc+/fpc= github.com/fatih/color v1.7.0 h1:DkWD4oS2D8LGGgTQ6IvwJJXSL5Vp2ffcQg58nFV38Ys= github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4= +github.com/fatih/color v1.10.0 h1:s36xzo75JdqLaaWoiEHk767eHiwo0598uUxyfiPkDsg= +github.com/fatih/color v1.10.0/go.mod h1:ELkj/draVOlAH/xkhN6mQ50Qd0MPOk5AAr3maGEBuJM= github.com/form3tech-oss/jwt-go v3.2.2+incompatible h1:TcekIExNqud5crz4xD2pavyTgWiPvpYe4Xau31I0PRk= github.com/form3tech-oss/jwt-go v3.2.2+incompatible/go.mod h1:pbq4aXjuKjdthFRnoDwaVPLA+WlJuPGy+QneDUgJi2k= github.com/franela/goblin v0.0.0-20200105215937-c9ffbefa60db/go.mod h1:7dvUGVsVBjqR7JHJk0brhHOZYGmfBYOrK0ZhYMEtBr4= @@ -439,6 +441,8 @@ github.com/google/go-cmp v0.4.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/ github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.2 h1:X2ev0eStA3AbceY54o37/0PQ/UWqKEiiO2dKL5OPaFM= github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.5 h1:Khx7svrCpmxxtHBq5j2mp/xVjsi8hQMfNLvJFAlrGgU= +github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= github.com/google/gofuzz v1.1.0 h1:Hsa8mG0dQ46ij8Sl2AYJDUv1oA9/d6Vk+3LG99Oe02g= github.com/google/gofuzz v1.1.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= @@ -451,6 +455,8 @@ github.com/google/pprof v0.0.0-20200229191704-1ebb73c60ed3/go.mod h1:ZgVRPoUq/hf github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= github.com/google/shlex v0.0.0-20181106134648-c34317bd91bf h1:7+FW5aGwISbqUtkfmIpZJGRgNFg2ioYPvFaUxdqpDsg= github.com/google/shlex v0.0.0-20181106134648-c34317bd91bf/go.mod h1:RpwtwJQFrIEPstU94h88MWPXP2ektJZ8cZ0YntAmXiE= +github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 h1:El6M4kTTCOh6aBiKaUGG7oYTSPP8MxqL4YI3kZKwcP4= +github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510/go.mod h1:pupxD2MaaD3pAXIBCelhxNneeOaAeabZDe5s4K6zSpQ= github.com/google/uuid v1.0.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.1.2 h1:EVhdT+1Kseyi1/pUmXKaFxYsDNy9RQYkMWRH68J/W7Y= @@ -613,10 +619,14 @@ github.com/marstr/guid v1.1.0/go.mod h1:74gB1z2wpxxInTG6yaqA7KrtM0NZ+RbrcqDvYHef github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU= github.com/mattn/go-colorable v0.1.2 h1:/bC9yWikZXAL9uJdulbSfyVNIR3n3trXl+v8+1sx8mU= github.com/mattn/go-colorable v0.1.2/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE= +github.com/mattn/go-colorable v0.1.8 h1:c1ghPdyEDarC70ftn0y+A/Ee++9zz8ljHG1b13eJ0s8= +github.com/mattn/go-colorable v0.1.8/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc= github.com/mattn/go-isatty v0.0.3/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= github.com/mattn/go-isatty v0.0.4/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= github.com/mattn/go-isatty v0.0.8 h1:HLtExJ+uU2HOZ+wI0Tt5DtUDrx8yhUqDcp7fYERX4CE= github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= +github.com/mattn/go-isatty v0.0.12 h1:wuysRhFDzyxgEmMf5xjvJ2M9dZoWAXNNr5LSBS7uHXY= +github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU= github.com/mattn/go-oci8 v0.0.7/go.mod h1:wjDx6Xm9q7dFtHJvIlrI99JytznLw5wQ4R+9mNXJwGI= github.com/mattn/go-runewidth v0.0.2/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU= github.com/mattn/go-runewidth v0.0.4 h1:2BvfKmzob6Bmd4YsL0zygOqfdFnK7GR4QL06Do4/p7Y= @@ -1022,6 +1032,7 @@ golang.org/x/net v0.0.0-20200301022130-244492dfa37a/go.mod h1:z5CRVTTTmAJ677TzLL golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= golang.org/x/net v0.0.0-20200520004742-59133d7f0dd7/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= +golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/net v0.0.0-20201110031124-69a78807bb2b/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/net v0.0.0-20210119194325-5f4716e94777 h1:003p0dJM77cxMSyCPFphvZf/Y5/NXf5fzg6ufd1/Oew= golang.org/x/net v0.0.0-20210119194325-5f4716e94777/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= @@ -1082,6 +1093,7 @@ golang.org/x/sys v0.0.0-20191220142924-d4481acd189f/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20191228213918-04cbcbbfeed8/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200106162015-b016eb3dc98e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200113162924-86b910548bc1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200120151820-655fe14d7479/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200122134326-e047566fdf82/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200202164722-d101bd2416d5/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -1096,6 +1108,7 @@ golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20201112073958-5cba982894dd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201201145000-ef89a241ccb3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210119212857-b64e53b001e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c h1:VwygUrnw9jn88c4u8GD3rZQbqrP/tgas88tPUbBxQrk= golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw= @@ -1168,6 +1181,8 @@ golang.org/x/tools v0.0.0-20200616133436-c1934b75d054/go.mod h1:EkVYQZoAsY45+roY golang.org/x/tools v0.0.0-20200616195046-dc31b401abb5/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= golang.org/x/tools v0.0.0-20200904185747-39188db58858 h1:xLt+iB5ksWcZVxqc+g9K41ZHy+6MKWfXCDsjSThnsPA= golang.org/x/tools v0.0.0-20200904185747-39188db58858/go.mod h1:Cj7w3i3Rnn0Xh82ur9kSqwfTHTeVxaDqrfMjpcNT6bE= +golang.org/x/tools v0.1.0 h1:po9/4sTYwZU9lPhi1tOrb4hCv3qrhiQ77LZfGa2OjwY= +golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= diff --git a/pkg/agent/agent_internal_test.go b/pkg/agent/agent_internal_test.go index 050d7c1b90..5b03d34515 100644 --- a/pkg/agent/agent_internal_test.go +++ b/pkg/agent/agent_internal_test.go @@ -56,6 +56,7 @@ func getCtxLog() (context.Context, context.CancelFunc) { } func TestHandleAPIKeyConfigChange(t *testing.T) { + t.Parallel() objMeta := metav1.ObjectMeta{ Name: "coolname", Namespace: "coolnamespace", @@ -215,6 +216,7 @@ func TestHandleAPIKeyConfigChange(t *testing.T) { } func TestProcessSnapshot(t *testing.T) { + t.Parallel() snapshotTests := []struct { // name of test (passed to t.Run()) testName string @@ -432,6 +434,7 @@ func (m *mockAccumulator) FilteredUpdate(target interface{}, deltas *[]*kates.De // Set up a watch and send a MinReportPeriod directive to the directive channel // Make sure that Agent.MinReportPeriod is set to this new value func TestWatchReportPeriodDirective(t *testing.T) { + t.Parallel() ctx, cancel := getCtxLog() a := NewAgent(nil) @@ -492,6 +495,7 @@ func TestWatchReportPeriodDirective(t *testing.T) { // Start a watch and send a nil then empty directive through the channel // make sure nothing errors or panics func TestWatchEmptyDirectives(t *testing.T) { + t.Parallel() ctx, cancel := getCtxLog() a := NewAgent(nil) @@ -553,6 +557,7 @@ func TestWatchEmptyDirectives(t *testing.T) { // send a directive to tell the agent to stop sending reports to the agent comm. // Then, send a snapshot through the channel and ensure that it doesn't get sent to the agent com func TestWatchStopReportingDirective(t *testing.T) { + t.Parallel() ctx, cancel := getCtxLog() a := NewAgent(nil) @@ -618,6 +623,7 @@ func TestWatchStopReportingDirective(t *testing.T) { // Send a snapshot through the channel, and make sure the error propogates thru the agent.reportComplete // channel, and that the error doesn't make things sad. func TestWatchErrorSendingSnapshot(t *testing.T) { + t.Parallel() ctx, cancel := getCtxLog() ambId := getRandomAmbassadorID() a := NewAgent(nil) @@ -717,6 +723,7 @@ func TestWatchErrorSendingSnapshot(t *testing.T) { // Make sure the Snapshot.KubernetesSecrets and Snapshot.Invalid get scrubbed of sensitive data and // we send a SnapshotTs that makes sense (so the agent com can throw out older snapshots) func TestWatchWithSnapshot(t *testing.T) { + t.Parallel() ctx, cancel := getCtxLog() clusterID := "coolcluster" ambId := getRandomAmbassadorID() @@ -914,6 +921,7 @@ func TestWatchWithSnapshot(t *testing.T) { // Send a snapshot with no cluster id // Make sure we don't try to send anything and that nothing errors or panics func TestWatchEmptySnapshot(t *testing.T) { + t.Parallel() ctx, cancel := getCtxLog() a := NewAgent(nil) diff --git a/pkg/envoy/prefixer.go b/pkg/envoy/prefixer.go index f78241ee31..c68cc07b38 100644 --- a/pkg/envoy/prefixer.go +++ b/pkg/envoy/prefixer.go @@ -41,6 +41,8 @@ func (p *Prefixer) Write(b []byte) (int, error) { if n < len(munged) { p.leftover = munged[n:] + } else { + p.output.Write([]byte("\n")) } return len(b), err diff --git a/pkg/gateway/dispatcher_test.go b/pkg/gateway/dispatcher_test.go index 999ccd8803..755b9ec142 100644 --- a/pkg/gateway/dispatcher_test.go +++ b/pkg/gateway/dispatcher_test.go @@ -22,6 +22,7 @@ func assertErrorContains(t *testing.T, err error, msg string) { } func TestDispatcherRegister(t *testing.T) { + t.Parallel() disp := gateway.NewDispatcher() err := disp.Register("Foo", compile_Foo) require.NoError(t, err) @@ -33,6 +34,7 @@ func TestDispatcherRegister(t *testing.T) { } func TestDispatcherDuplicateRegister(t *testing.T) { + t.Parallel() disp := gateway.NewDispatcher() err := disp.Register("Foo", compile_Foo) require.NoError(t, err) @@ -41,6 +43,7 @@ func TestDispatcherDuplicateRegister(t *testing.T) { } func TestIsRegistered(t *testing.T) { + t.Parallel() disp := gateway.NewDispatcher() err := disp.Register("Foo", compile_Foo) require.NoError(t, err) @@ -49,6 +52,7 @@ func TestIsRegistered(t *testing.T) { } func TestDispatcherFaultIsolation1(t *testing.T) { + t.Parallel() disp := gateway.NewDispatcher() err := disp.Register("Foo", compile_Foo) require.NoError(t, err) @@ -59,6 +63,7 @@ func TestDispatcherFaultIsolation1(t *testing.T) { } func TestDispatcherFaultIsolation2(t *testing.T) { + t.Parallel() disp := gateway.NewDispatcher() err := disp.Register("Foo", compile_Foo) require.NoError(t, err) @@ -69,6 +74,7 @@ func TestDispatcherFaultIsolation2(t *testing.T) { } func TestDispatcherTransformError(t *testing.T) { + t.Parallel() disp := gateway.NewDispatcher() err := disp.Register("Foo", compile_FooWithErrors) require.NoError(t, err) @@ -123,6 +129,7 @@ func compile_FooWithErrors(f *Foo) *gateway.CompiledConfig { } func TestDispatcherNoTransform(t *testing.T) { + t.Parallel() disp := gateway.NewDispatcher() foo := makeFoo("default", "foo", "bar") err := disp.Upsert(foo) @@ -130,6 +137,7 @@ func TestDispatcherNoTransform(t *testing.T) { } func TestDispatcherDelete(t *testing.T) { + t.Parallel() disp := gateway.NewDispatcher() err := disp.Register("Foo", compile_Foo) require.NoError(t, err) @@ -144,6 +152,7 @@ func TestDispatcherDelete(t *testing.T) { } func TestDispatcherDeleteKey(t *testing.T) { + t.Parallel() disp := gateway.NewDispatcher() err := disp.Register("Foo", compile_Foo) require.NoError(t, err) @@ -172,6 +181,7 @@ func compile_Foo(f *Foo) *gateway.CompiledConfig { } func TestDispatcherUpsertYamlErr(t *testing.T) { + t.Parallel() disp := gateway.NewDispatcher() err := disp.UpsertYaml("{") assertErrorContains(t, err, "error converting") @@ -190,6 +200,7 @@ spec: } func TestDispatcherAssemblyWithRouteConfg(t *testing.T) { + t.Parallel() disp := gateway.NewDispatcher() err := disp.Register("Foo", compile_FooWithRouteConfigName) require.NoError(t, err) @@ -254,6 +265,7 @@ func compile_FooWithRouteConfigName(f *Foo) *gateway.CompiledConfig { } func TestDispatcherAssemblyWithEmptyRouteConfigName(t *testing.T) { + t.Parallel() disp := gateway.NewDispatcher() err := disp.Register("Foo", compile_FooWithEmptyRouteConfigName) require.NoError(t, err) @@ -314,6 +326,7 @@ func compile_FooWithEmptyRouteConfigName(f *Foo) *gateway.CompiledConfig { } func TestDispatcherAssemblyWithoutRds(t *testing.T) { + t.Parallel() disp := gateway.NewDispatcher() err := disp.Register("Foo", compile_FooWithoutRds) require.NoError(t, err) @@ -365,6 +378,7 @@ func compile_FooWithoutRds(f *Foo) *gateway.CompiledConfig { } func TestDispatcherAssemblyEndpointDefaulting(t *testing.T) { + t.Parallel() disp := gateway.NewDispatcher() err := disp.Register("Foo", compile_FooWithClusterRefs) require.NoError(t, err) @@ -394,6 +408,7 @@ func compile_FooWithClusterRefs(f *Foo) *gateway.CompiledConfig { } func TestDispatcherAssemblyEndpointWatches(t *testing.T) { + t.Parallel() disp := gateway.NewDispatcher() err := disp.Register("Foo", compile_FooEndpointWatches) require.NoError(t, err) diff --git a/pkg/gateway/gw_transforms_test.go b/pkg/gateway/gw_transforms_test.go index 3d5ef01140..cb2ea962b8 100644 --- a/pkg/gateway/gw_transforms_test.go +++ b/pkg/gateway/gw_transforms_test.go @@ -14,6 +14,7 @@ import ( ) func TestGatewayMatches(t *testing.T) { + t.Parallel() envoy.SetupRequestLogger(t, ":9000", ":9002") e := envoy.SetupEnvoyController(t, ":8003") envoy.SetupEnvoy(t, envoy.GetLoopbackAddr(8003), "8080:8080") @@ -122,6 +123,7 @@ spec: } func TestBadMatchTypes(t *testing.T) { + t.Parallel() d := makeDispatcher(t) // One rule for each type of path match (exact, prefix, regex) and each type of header match diff --git a/pkg/k8s/client_test.go b/pkg/k8s/client_test.go index 4d3c9ca959..727dbb5a68 100644 --- a/pkg/k8s/client_test.go +++ b/pkg/k8s/client_test.go @@ -19,6 +19,7 @@ func TestMain(m *testing.M) { } func TestList(t *testing.T) { + t.Parallel() c, err := k8s.NewClient(info()) if err != nil { t.Error(err) diff --git a/pkg/k8s/resource_test.go b/pkg/k8s/resource_test.go index 65406c20f6..c0e245da86 100644 --- a/pkg/k8s/resource_test.go +++ b/pkg/k8s/resource_test.go @@ -8,6 +8,7 @@ import ( ) func TestQKind(t *testing.T) { + t.Parallel() testcases := []struct { Resource k8s.Resource QKind string diff --git a/pkg/k8s/watcher_test.go b/pkg/k8s/watcher_test.go index f9af3a67a8..d274f58aaa 100644 --- a/pkg/k8s/watcher_test.go +++ b/pkg/k8s/watcher_test.go @@ -42,6 +42,7 @@ func info() *k8s.KubeInfo { } func TestUpdateStatus(t *testing.T) { + t.Parallel() w := k8s.MustNewWatcher(info()) svc := fetch(w, "services", "kubernetes.default") @@ -67,6 +68,7 @@ func TestUpdateStatus(t *testing.T) { } func TestWatchCustom(t *testing.T) { + t.Parallel() w := k8s.MustNewWatcher(info()) // XXX: we can only watch custom resources... k8s doesn't @@ -83,6 +85,7 @@ func TestWatchCustom(t *testing.T) { } func TestWatchCustomCollision(t *testing.T) { + t.Parallel() w := k8s.MustNewWatcher(info()) easter := fetch(w, "csrv", "easter.default") @@ -98,6 +101,7 @@ func TestWatchCustomCollision(t *testing.T) { } func TestWatchQuery(t *testing.T) { + t.Parallel() w := k8s.MustNewWatcher(info()) services := []string{} From ca22d5140a46b43cc1e3d42bb7f9dc7720794263 Mon Sep 17 00:00:00 2001 From: Alix Cook Date: Mon, 26 Apr 2021 14:29:35 -0400 Subject: [PATCH 10/20] (from AES) template helm image on enableAES (#2590) --- charts/ambassador/CHANGELOG.md | 4 ++++ charts/ambassador/ci/02-oss-values.yaml | 1 - charts/ambassador/templates/_helpers.tpl | 19 +++++++++++++++++++ .../templates/ambassador-agent.yaml | 6 +----- charts/ambassador/templates/deployment.yaml | 6 +----- charts/ambassador/values.yaml | 1 - 6 files changed, 25 insertions(+), 12 deletions(-) diff --git a/charts/ambassador/CHANGELOG.md b/charts/ambassador/CHANGELOG.md index 602f4dde05..3ba01cced5 100644 --- a/charts/ambassador/CHANGELOG.md +++ b/charts/ambassador/CHANGELOG.md @@ -3,6 +3,10 @@ This file documents all notable changes to Ambassador Helm Chart. The release numbering uses [semantic versioning](http://semver.org). +## Next release + +- Change: unless image.repository or image.fullImageOverride is explicitly set, the ambassador image used will be templated on .Values.enableAES. If AES is enabled, the chart will use docker.io/datawire/aes, otherwise will use docker.io/datawire/ambassador. + ## v6.7.1 - Update Ambassador chart image to version v1.13.1: [CHANGELOG](https://github.com/datawire/ambassador/blob/master/CHANGELOG.md) diff --git a/charts/ambassador/ci/02-oss-values.yaml b/charts/ambassador/ci/02-oss-values.yaml index a048307dca..f9fbd4f4a6 100644 --- a/charts/ambassador/ci/02-oss-values.yaml +++ b/charts/ambassador/ci/02-oss-values.yaml @@ -1,6 +1,5 @@ # install the Ambassador API Gateway image: - repository: docker.io/datawire/ambassador tag: 1.5.5 pullPolicy: IfNotPresent diff --git a/charts/ambassador/templates/_helpers.tpl b/charts/ambassador/templates/_helpers.tpl index a708275354..6f3bd604ff 100644 --- a/charts/ambassador/templates/_helpers.tpl +++ b/charts/ambassador/templates/_helpers.tpl @@ -24,6 +24,25 @@ If release name contains chart name it will be used as a full name. {{- end -}} {{- end -}} +{{/* +Set the image that should be used for ambassador. +Use fullImageOverride if present, +Then if the image repository is explicitly set, use "repository:image" +Otherwise, check if AES is enabled +Use AES image if AES is enabled, ambassador image if not +*/}} +{{- define "ambassador.image" -}} +{{- if .Values.image.fullImageOverride }} +{{- .Values.image.fullImageOverride }} +{{- else if hasKey .Values.image "repository" -}} +{{- printf "%s:%s" .Values.image.repository .Values.image.tag -}} +{{- else if .Values.enableAES -}} +{{- printf "%s:%s" "docker.io/datawire/aes" .Values.image.tag -}} +{{- else -}} +{{- printf "%s:%s" "docker.io/datawire/ambassador" .Values.image.tag -}} +{{- end -}} +{{- end -}} + {{/* Create chart namespace based on override value. */}} diff --git a/charts/ambassador/templates/ambassador-agent.yaml b/charts/ambassador/templates/ambassador-agent.yaml index f4c1e1499c..815005aa8b 100644 --- a/charts/ambassador/templates/ambassador-agent.yaml +++ b/charts/ambassador/templates/ambassador-agent.yaml @@ -282,11 +282,7 @@ spec: serviceAccountName: {{ include "ambassador.fullname" . }}-agent containers: - name: agent - {{- if .Values.image.fullImageOverride }} - image: '{{ .Values.image.fullImageOverride }}' - {{- else }} - image: "{{ .Values.agent.image.repository | default .Values.image.repository }}:{{ .Values.agent.image.tag | default .Values.image.tag }}" - {{- end }} + image: {{ include "ambassador.image" . }} imagePullPolicy: {{ .Values.image.pullPolicy }} command: [ "agent" ] env: diff --git a/charts/ambassador/templates/deployment.yaml b/charts/ambassador/templates/deployment.yaml index ff0ca4db52..762cf2d9c2 100644 --- a/charts/ambassador/templates/deployment.yaml +++ b/charts/ambassador/templates/deployment.yaml @@ -160,11 +160,7 @@ spec: {{- toYaml .Values.prometheusExporter.resources | nindent 12 }} {{- end }} - name: {{ if .Values.containerNameOverride }}{{ .Values.containerNameOverride }}{{ else }}{{ .Chart.Name }}{{ end }} - {{- if .Values.image.fullImageOverride }} - image: '{{ .Values.image.fullImageOverride }}' - {{- else }} - image: "{{ .Values.image.repository }}:{{ .Values.image.tag }}" - {{- end }} + image: {{ include "ambassador.image" . }} imagePullPolicy: {{ .Values.image.pullPolicy }} ports: {{- range .Values.service.ports }} diff --git a/charts/ambassador/values.yaml b/charts/ambassador/values.yaml index 437d769421..c97150512a 100644 --- a/charts/ambassador/values.yaml +++ b/charts/ambassador/values.yaml @@ -118,7 +118,6 @@ security: # rule: MustRunAsNonRoot image: - repository: docker.io/datawire/aes tag: 1.13.1 pullPolicy: IfNotPresent From 2bc3268845c9ca0171a58ecf098f2eb2178b6411 Mon Sep 17 00:00:00 2001 From: Alix Cook Date: Mon, 26 Apr 2021 14:55:52 -0400 Subject: [PATCH 11/20] (from AES) e2etest to k3ds (#2584) --- .circleci/config.yml | 3 +++ .circleci/config.yml.d/amb_jobs.yml | 4 +++- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 6b89a3f08b..58848c7bec 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -162,6 +162,8 @@ commands: steps: - skip-if-only-changes: to: "(ambassador/|tests/pytest/gold/)" + - run: | + echo >>"$BASH_ENV" 'export USE_LOCAL_K3S_CLUSTER=1' - when: condition: or: @@ -182,6 +184,7 @@ commands: run: | echo >>"$BASH_ENV" 'export KUBECEPTION_PROFILE=large' - install-helm + - install-k3d - amb-config-cluster-and-registry - # main run: diff --git a/.circleci/config.yml.d/amb_jobs.yml b/.circleci/config.yml.d/amb_jobs.yml index 5659395522..0140684ac3 100644 --- a/.circleci/config.yml.d/amb_jobs.yml +++ b/.circleci/config.yml.d/amb_jobs.yml @@ -175,6 +175,8 @@ commands: steps: - skip-if-only-changes: to: "(ambassador/|tests/pytest/gold/)" + - run: | + echo >>"$BASH_ENV" 'export USE_LOCAL_K3S_CLUSTER=1' - when: condition: or: @@ -195,8 +197,8 @@ commands: - run: | echo >>"$BASH_ENV" 'export KUBECEPTION_PROFILE=large' - install-helm + - install-k3d - amb-config-cluster-and-registry - # main - run: name: "Ensure CI configuration is up-to-date" From 9ef8176a3f149c8c3d717b58152e28bc1960547a Mon Sep 17 00:00:00 2001 From: Flynn Date: Mon, 26 Apr 2021 15:37:07 -0400 Subject: [PATCH 12/20] (from AES) Default prune_unreachable_routes to True --- python/ambassador/ir/irambassador.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/python/ambassador/ir/irambassador.py b/python/ambassador/ir/irambassador.py index 70d1ad9931..936a2c869b 100644 --- a/python/ambassador/ir/irambassador.py +++ b/python/ambassador/ir/irambassador.py @@ -131,7 +131,7 @@ def __init__(self, ir: 'IR', aconf: Config, use_proxy_proto=False, enable_http10=False, proper_case=False, - prune_unreachable_routes=False, + prune_unreachable_routes=True, # default True; can be updated in finalize() use_remote_address=use_remote_address, x_forwarded_proto_redirect=False, load_balancer=None, From 4e1462613957942f85ba6706354000da90cd10e6 Mon Sep 17 00:00:00 2001 From: Flynn Date: Tue, 27 Apr 2021 10:32:11 -0400 Subject: [PATCH 13/20] (from AES) CHANGELOG --- CHANGELOG.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 9acacf02bc..cb4b08857d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -63,6 +63,12 @@ Please see the [Envoy documentation](https://www.envoyproxy.io/docs/envoy/latest ## RELEASE NOTES +## Next Release + +### Emissary Ingress and Ambassador Edge Stack + +- Change: `prune_unreachable_routes` now defaults to true, which should reduce Envoy memory requirements for installations with many `Host`s + ## [1.13.1] April 22, 2021 [1.13.1]: https://github.com/datawire/ambassador/compare/v1.13.0...v1.13.1 From b2d6e636aa4bf876fe7f14439545f38040feecfb Mon Sep 17 00:00:00 2001 From: Flynn Date: Tue, 27 Apr 2021 11:06:55 -0400 Subject: [PATCH 14/20] (from AES) Update and synchronize pull-request templates --- .github/pull_request_template.md | 58 +++++++++++++++++++------------- 1 file changed, 34 insertions(+), 24 deletions(-) diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md index 1c34d3037f..505123cc5d 100644 --- a/.github/pull_request_template.md +++ b/.github/pull_request_template.md @@ -7,28 +7,38 @@ List related issues. ## Testing A few sentences describing what testing you've done, e.g., manual tests, automated tests, deployed in production, etc. -## Tasks That Must Be Done -- [ ] Did you update CHANGELOG.md? - + [ ] Is this a new feature? - + [ ] Are there any non-backward-compatible changes? - + [ ] Did the envoy version change? - + [ ] Are there any deprecations? - + [ ] Will the changes impact how ambassador performs at scale? - - [ ] Might an existing production deployment need to change: - + memory limits? - + cpu limits? - + replica counts? - - [ ] Does the change impact data-plane latency/scalability? -- [ ] Is your change adequately tested? - + [ ] Was their sufficient test coverage for the area changed? - + [ ] Do the existing tests capture the requirements for the area changed? - + [ ] Is the bulk of your code covered by unit tests? - + [ ] Does at least one end-to-end test cover the integration points your change depends on? -- [ ] Did you update documentation? -- [ ] Were there any special dev tricks you had to use to work on this code efficiently? - + [ ] Did you add them to DEVELOPING.md? -- [ ] Is this a build change? - + [ ] If so, did you test on both Mac and Linux? +## Checklist -## Other -* If this is a documentation change for a particular release, please open the pull request against the release branch. + + + - [ ] I made sure to update `CHANGELOG.md`. + + Remember, the CHANGELOG needs to mention: + + Any new features + + Any changes to our included version of Envoy + + Any non-backward-compatible changes + + Any deprecations + + - [ ] This is unlikely to impact how Ambassador performs at scale. + + Remember, things that might have an impact at scale include: + + Any significant changes in memory use that might require adjusting the memory limits + + Any significant changes in CPU use that might require adjusting the CPU limits + + Anything that might change how many replicas users should use + + Changes that impact data-plane latency/scalability + + - [ ] My change is adequately tested. + + Remember when considering testing: + + Your change needs to be specifically covered by tests. + + Tests need to cover all the states where your change is relevant: for example, if you add a behavior that can be enabled or disabled, you'll need tests that cover the enabled case and tests that cover the disabled case. It's not sufficient just to test with the behavior enabled. + + You also need to make sure that the _entire area being changed_ has adequate test coverage. + + If existing tests don't actually cover the entire area being changed, add tests. + + This applies even for aspects of the area that you're not changing – check the test coverage, and improve it if needed! + + We should lean on the bulk of code being covered by unit tests, but... + + ... an end-to-end test should cover the integration points + + - [ ] I updated `DEVELOPING.md` with any any special dev tricks I had to use to work on this code efficiently. From 5b65c0e02b7e3b73ee55aefdb32b4db5dd0c41fa Mon Sep 17 00:00:00 2001 From: Alix Cook Date: Tue, 27 Apr 2021 12:43:53 -0400 Subject: [PATCH 15/20] (from AES) img pull secret for agent --- charts/ambassador/templates/ambassador-agent.yaml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/charts/ambassador/templates/ambassador-agent.yaml b/charts/ambassador/templates/ambassador-agent.yaml index 815005aa8b..a092bf38f5 100644 --- a/charts/ambassador/templates/ambassador-agent.yaml +++ b/charts/ambassador/templates/ambassador-agent.yaml @@ -42,6 +42,10 @@ metadata: {{- end }} {{- end }} product: aes +{{- if .Values.docker.useImagePullSecret }} +imagePullSecrets: +- name: {{ .Values.docker.imagePullSecretName }} +{{- end }} --- apiVersion: rbac.authorization.k8s.io/v1beta1 kind: RoleBinding From fb1a16cd0513f7808018dce16ba0378e07116447 Mon Sep 17 00:00:00 2001 From: Flynn Date: Tue, 27 Apr 2021 23:19:28 -0400 Subject: [PATCH 16/20] (from AES) Default to using K8s 1.19 with Kubeception clusters in CI --- .ci/cluster-claim | 2 +- build-aux/helpers.sh | 5 +++-- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/.ci/cluster-claim b/.ci/cluster-claim index dadee75463..b0456c8a08 100755 --- a/.ci/cluster-claim +++ b/.ci/cluster-claim @@ -63,7 +63,7 @@ if [ -n "${KUBECEPTION_TOKEN}" ]; then tries=0 while true ; do # get a kluster with a 1-hour timeout (by default) that is size "large" (by default) - get_cluster ${DEV_KUBECONFIG} ${KUBECEPTION_TIMEOUT:-3600} ${KUBECEPTION_PROFILE:-large} + get_cluster ${DEV_KUBECONFIG} ${KUBECEPTION_TIMEOUT:-3600} ${KUBECEPTION_PROFILE:-large} ${KUBECEPTION_VERSION:-1.19} ret=$? if [ "$ret" == "0" ] ; then wait_for_kubeconfig ${DEV_KUBECONFIG} diff --git a/build-aux/helpers.sh b/build-aux/helpers.sh index 655b6b9bf4..9ad9642026 100644 --- a/build-aux/helpers.sh +++ b/build-aux/helpers.sh @@ -145,13 +145,14 @@ start_cluster() { kubeconfig=${1} timeout=${2:-3600} profile=${3:-default} + version=${4:-1.19} retries=2 if [ -e "${kubeconfig}" ]; then echo "cannot get cluster, kubeconfig ${kubeconfig} exists" 1>&2 return 1 fi - klusterurl="https://sw.bakerstreet.io/kubeception/api/klusters/ci-?generate=true&timeoutSecs=${timeout}&profile=${profile}" - printf "${BLU}Acquiring cluster:\n==${END}\n" 1>&2 + klusterurl="https://sw.bakerstreet.io/kubeception/api/klusters/ci-?generate=true&timeoutSecs=${timeout}&profile=${profile}&version=${version}" + printf "${BLU}Acquiring cluster with K8s version ${version}:\n==${END}\n" 1>&2 curl_retry $retries "200,425" "" -o "${kubeconfig}" -H "Authorization: bearer ${KUBECEPTION_TOKEN}" "${klusterurl}" -X PUT ret="$?" if [ "${ret}" -ne "0" ] ; then From cc3ad7d98fccfc26ffe1a4296b9b3e1f5121ca0e Mon Sep 17 00:00:00 2001 From: John Esmet Date: Tue, 20 Apr 2021 16:47:43 +0000 Subject: [PATCH 17/20] (from AES) Check envoy version string for the correct commit, both on build and as a sanity check when pulling any existing image. --- .gitignore | 1 + _cxx/envoy.mk | 36 ++++++++++++++++++++++++++++++++++++ 2 files changed, 37 insertions(+) diff --git a/.gitignore b/.gitignore index cebaa476cf..a4a5131fbb 100644 --- a/.gitignore +++ b/.gitignore @@ -8,6 +8,7 @@ .DS_Store .skip_test_warning venv +.venv __pycache__ .pytest_cache .mypy_cache diff --git a/_cxx/envoy.mk b/_cxx/envoy.mk index 64918d358e..5994fda776 100644 --- a/_cxx/envoy.mk +++ b/_cxx/envoy.mk @@ -221,6 +221,15 @@ update-base: $(OSS_HOME)/docker/base-envoy/envoy-static $(OSS_HOME)/docker/base- @PS4=; set -ex; { \ if [ '$(ENVOY_COMMIT)' != '-' ] && docker pull $(ENVOY_FULL_DOCKER_TAG); then \ echo 'Already up-to-date: $(ENVOY_FULL_DOCKER_TAG)'; \ + ENVOY_VERSION_OUTPUT=$$(docker run -it --entrypoint envoy-static $(ENVOY_FULL_DOCKER_TAG) --version | grep "version:"); \ + ENVOY_VERSION_EXPECTED="envoy-static .*version:.* $(ENVOY_COMMIT)/.*"; \ + if ! echo "$$ENVOY_VERSION_OUTPUT" | grep "$$ENVOY_VERSION_EXPECTED"; then \ + echo "error: Envoy base image $(ENVOY_FULL_DOCKER_TAG) contains envoy-static binary that reported an unexpected version string!" \ + "See ENVOY_VERSION_OUTPUT and ENVOY_VERSION_EXPECTED in the output above. This error is usually not recoverable." \ + "You may need to rebuild the Envoy base image after either updating ENVOY_COMMIT or bumping BASE_ENVOY_RELVER" \ + "(or both, depending on what you are doing)."; \ + exit 1; \ + fi; \ else \ if [ -z '$(YES_I_AM_OK_WITH_COMPILING_ENVOY)' ]; then \ { set +x; } &>/dev/null; \ @@ -229,6 +238,15 @@ update-base: $(OSS_HOME)/docker/base-envoy/envoy-static $(OSS_HOME)/docker/base- fi; \ docker build --build-arg=base=$$(cat $(OSS_HOME)/_cxx/envoy-build-image.txt) -f $(OSS_HOME)/docker/base-envoy/Dockerfile -t $(ENVOY_FULL_DOCKER_TAG) $(OSS_HOME)/docker/base-envoy; \ if [ '$(ENVOY_COMMIT)' != '-' ]; then \ + ENVOY_VERSION_OUTPUT=$$(docker run -it --entrypoint envoy-static $(ENVOY_FULL_DOCKER_TAG) --version | grep "version:"); \ + ENVOY_VERSION_EXPECTED="envoy-static .*version:.* $(ENVOY_COMMIT)/.*"; \ + if ! echo "$$ENVOY_VERSION_OUTPUT" | grep "$$ENVOY_VERSION_EXPECTED"; then \ + echo "error: Envoy base image $(ENVOY_FULL_DOCKER_TAG) contains envoy-static binary that reported an unexpected version string!" \ + "See ENVOY_VERSION_OUTPUT and ENVOY_VERSION_EXPECTED in the output above. This error is usually not recoverable." \ + "You may need to rebuild the Envoy base image after either updating ENVOY_COMMIT or bumping BASE_ENVOY_RELVER" \ + "(or both, depending on what you are doing)."; \ + exit 1; \ + fi; \ docker push $(ENVOY_FULL_DOCKER_TAG); \ fi; \ fi; \ @@ -236,6 +254,15 @@ update-base: $(OSS_HOME)/docker/base-envoy/envoy-static $(OSS_HOME)/docker/base- @PS4=; set -ex; { \ if [ '$(ENVOY_COMMIT)' != '-' ] && docker pull $(ENVOY_DOCKER_TAG); then \ echo 'Already up-to-date: $(ENVOY_DOCKER_TAG)'; \ + ENVOY_VERSION_OUTPUT=$$(docker run -it --entrypoint envoy-static-stripped $(ENVOY_DOCKER_TAG) --version | grep "version:"); \ + ENVOY_VERSION_EXPECTED="envoy-static-stripped .*version:.* $(ENVOY_COMMIT)/.*"; \ + if ! echo "$$ENVOY_VERSION_OUTPUT" | grep "$$ENVOY_VERSION_EXPECTED"; then \ + echo "error: Envoy base image $(ENVOY_DOCKER_TAG) contains envoy-static-stripped binary that reported an unexpected version string!" \ + "See ENVOY_VERSION_OUTPUT and ENVOY_VERSION_EXPECTED in the output above. This error is usually not recoverable." \ + "You may need to rebuild the Envoy base image after either updating ENVOY_COMMIT or bumping BASE_ENVOY_RELVER" \ + "(or both, depending on what you are doing)."; \ + exit 1; \ + fi; \ else \ if [ -z '$(YES_I_AM_OK_WITH_COMPILING_ENVOY)' ]; then \ { set +x; } &>/dev/null; \ @@ -244,6 +271,15 @@ update-base: $(OSS_HOME)/docker/base-envoy/envoy-static $(OSS_HOME)/docker/base- fi; \ docker build -f $(OSS_HOME)/docker/base-envoy/Dockerfile.stripped -t $(ENVOY_DOCKER_TAG) $(OSS_HOME)/docker/base-envoy; \ if [ '$(ENVOY_COMMIT)' != '-' ]; then \ + ENVOY_VERSION_OUTPUT=$$(docker run -it --entrypoint envoy-static-stripped $(ENVOY_DOCKER_TAG) --version | grep "version:"); \ + ENVOY_VERSION_EXPECTED="envoy-static-stripped .*version:.* $(ENVOY_COMMIT)/.*"; \ + if ! echo "$$ENVOY_VERSION_OUTPUT" | grep "$$ENVOY_VERSION_EXPECTED"; then \ + echo "error: Envoy base image $(ENVOY_DOCKER_TAG) contains envoy-static-stripped binary that reported an unexpected version string!" \ + "See ENVOY_VERSION_OUTPUT and ENVOY_VERSION_EXPECTED in the output above. This error is usually not recoverable." \ + "You may need to rebuild the Envoy base image after either updating ENVOY_COMMIT or bumping BASE_ENVOY_RELVER" \ + "(or both, depending on what you are doing)."; \ + exit 1; \ + fi; \ docker push $(ENVOY_DOCKER_TAG); \ fi; \ fi; \ From c5afcb0232e2f3afaab9f5fadaf1212734c403e3 Mon Sep 17 00:00:00 2001 From: John Esmet Date: Wed, 28 Apr 2021 13:23:35 +0000 Subject: [PATCH 18/20] (from AES) Fix echo --- _cxx/envoy.mk | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/_cxx/envoy.mk b/_cxx/envoy.mk index 5994fda776..41ddcb1118 100644 --- a/_cxx/envoy.mk +++ b/_cxx/envoy.mk @@ -224,6 +224,7 @@ update-base: $(OSS_HOME)/docker/base-envoy/envoy-static $(OSS_HOME)/docker/base- ENVOY_VERSION_OUTPUT=$$(docker run -it --entrypoint envoy-static $(ENVOY_FULL_DOCKER_TAG) --version | grep "version:"); \ ENVOY_VERSION_EXPECTED="envoy-static .*version:.* $(ENVOY_COMMIT)/.*"; \ if ! echo "$$ENVOY_VERSION_OUTPUT" | grep "$$ENVOY_VERSION_EXPECTED"; then \ + { set +x; } &>/dev/null; \ echo "error: Envoy base image $(ENVOY_FULL_DOCKER_TAG) contains envoy-static binary that reported an unexpected version string!" \ "See ENVOY_VERSION_OUTPUT and ENVOY_VERSION_EXPECTED in the output above. This error is usually not recoverable." \ "You may need to rebuild the Envoy base image after either updating ENVOY_COMMIT or bumping BASE_ENVOY_RELVER" \ @@ -241,6 +242,7 @@ update-base: $(OSS_HOME)/docker/base-envoy/envoy-static $(OSS_HOME)/docker/base- ENVOY_VERSION_OUTPUT=$$(docker run -it --entrypoint envoy-static $(ENVOY_FULL_DOCKER_TAG) --version | grep "version:"); \ ENVOY_VERSION_EXPECTED="envoy-static .*version:.* $(ENVOY_COMMIT)/.*"; \ if ! echo "$$ENVOY_VERSION_OUTPUT" | grep "$$ENVOY_VERSION_EXPECTED"; then \ + { set +x; } &>/dev/null; \ echo "error: Envoy base image $(ENVOY_FULL_DOCKER_TAG) contains envoy-static binary that reported an unexpected version string!" \ "See ENVOY_VERSION_OUTPUT and ENVOY_VERSION_EXPECTED in the output above. This error is usually not recoverable." \ "You may need to rebuild the Envoy base image after either updating ENVOY_COMMIT or bumping BASE_ENVOY_RELVER" \ @@ -257,6 +259,7 @@ update-base: $(OSS_HOME)/docker/base-envoy/envoy-static $(OSS_HOME)/docker/base- ENVOY_VERSION_OUTPUT=$$(docker run -it --entrypoint envoy-static-stripped $(ENVOY_DOCKER_TAG) --version | grep "version:"); \ ENVOY_VERSION_EXPECTED="envoy-static-stripped .*version:.* $(ENVOY_COMMIT)/.*"; \ if ! echo "$$ENVOY_VERSION_OUTPUT" | grep "$$ENVOY_VERSION_EXPECTED"; then \ + { set +x; } &>/dev/null; \ echo "error: Envoy base image $(ENVOY_DOCKER_TAG) contains envoy-static-stripped binary that reported an unexpected version string!" \ "See ENVOY_VERSION_OUTPUT and ENVOY_VERSION_EXPECTED in the output above. This error is usually not recoverable." \ "You may need to rebuild the Envoy base image after either updating ENVOY_COMMIT or bumping BASE_ENVOY_RELVER" \ @@ -274,6 +277,7 @@ update-base: $(OSS_HOME)/docker/base-envoy/envoy-static $(OSS_HOME)/docker/base- ENVOY_VERSION_OUTPUT=$$(docker run -it --entrypoint envoy-static-stripped $(ENVOY_DOCKER_TAG) --version | grep "version:"); \ ENVOY_VERSION_EXPECTED="envoy-static-stripped .*version:.* $(ENVOY_COMMIT)/.*"; \ if ! echo "$$ENVOY_VERSION_OUTPUT" | grep "$$ENVOY_VERSION_EXPECTED"; then \ + { set +x; } &>/dev/null; \ echo "error: Envoy base image $(ENVOY_DOCKER_TAG) contains envoy-static-stripped binary that reported an unexpected version string!" \ "See ENVOY_VERSION_OUTPUT and ENVOY_VERSION_EXPECTED in the output above. This error is usually not recoverable." \ "You may need to rebuild the Envoy base image after either updating ENVOY_COMMIT or bumping BASE_ENVOY_RELVER" \ From f408f44f7cdc99d74369baf90f18beee30af6f4f Mon Sep 17 00:00:00 2001 From: Flynn Date: Wed, 3 Feb 2021 22:54:49 -0500 Subject: [PATCH 19/20] (from AES) Drop unused "enable_endpoints" in KAT --- python/tests/t_consul.py | 1 - python/tests/t_grpc.py | 8 -------- python/tests/t_loadbalancer.py | 3 --- 3 files changed, 12 deletions(-) diff --git a/python/tests/t_consul.py b/python/tests/t_consul.py index a0d9f72d17..babe187a01 100644 --- a/python/tests/t_consul.py +++ b/python/tests/t_consul.py @@ -15,7 +15,6 @@ """ class ConsulTest(AmbassadorTest): - enable_endpoints = True k8s_target: ServiceType k8s_ns_target: ServiceType diff --git a/python/tests/t_grpc.py b/python/tests/t_grpc.py index 42849a17db..77b4400cc6 100644 --- a/python/tests/t_grpc.py +++ b/python/tests/t_grpc.py @@ -3,11 +3,6 @@ from abstract_tests import AmbassadorTest, ServiceType, EGRPC class AcceptanceGrpcTest(AmbassadorTest): - - # Yes, enable endpoints here. It needs to work with them enabled but - # not used, after all. - enable_endpoints = True - target: ServiceType def init(self): @@ -62,9 +57,6 @@ def check(self): class EndpointGrpcTest(AmbassadorTest): - - enable_endpoints = True - target: ServiceType def init(self): diff --git a/python/tests/t_loadbalancer.py b/python/tests/t_loadbalancer.py index 075eea5e72..c5675b0a33 100644 --- a/python/tests/t_loadbalancer.py +++ b/python/tests/t_loadbalancer.py @@ -30,7 +30,6 @@ class LoadBalancerTest(AmbassadorTest): target: ServiceType - enable_endpoints = True def init(self): self.target = HTTP() @@ -153,7 +152,6 @@ def queries(self): class GlobalLoadBalancing(AmbassadorTest): target: ServiceType - enable_endpoints = True def init(self): self.target = HTTP() @@ -300,7 +298,6 @@ def check(self): class PerMappingLoadBalancing(AmbassadorTest): target: ServiceType - enable_endpoints = True policy: str def init(self): From b35b2474d93230f699e9bd91870798319fb9dc94 Mon Sep 17 00:00:00 2001 From: Flynn Date: Wed, 3 Feb 2021 23:05:10 -0500 Subject: [PATCH 20/20] (from AES) Drop unused resolvers --- python/tests/t_consul.py | 8 -------- 1 file changed, 8 deletions(-) diff --git a/python/tests/t_consul.py b/python/tests/t_consul.py index babe187a01..83f6adf1a7 100644 --- a/python/tests/t_consul.py +++ b/python/tests/t_consul.py @@ -118,14 +118,6 @@ def config(self): prefix: /{self.path.k8s}_k8s/ service: {self.k8s_target.path.k8s} --- -apiVersion: getambassador.io/v1 -kind: KubernetesServiceResolver -name: kubernetes-service ---- -apiVersion: getambassador.io/v1 -kind: KubernetesEndpointResolver -name: endpoint ---- apiVersion: ambassador/v1 kind: Mapping name: {self.path.k8s}_consul_mapping