From 7b27b678b6c2cb72f47ed26b4da12f79c3c69b00 Mon Sep 17 00:00:00 2001 From: Jake Klein Date: Mon, 4 Oct 2021 17:45:18 +0100 Subject: [PATCH 001/124] pend failing test (#4293) --- integration/tests/crud/creategetdelete_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/integration/tests/crud/creategetdelete_test.go b/integration/tests/crud/creategetdelete_test.go index dbbde64016..747c332e83 100644 --- a/integration/tests/crud/creategetdelete_test.go +++ b/integration/tests/crud/creategetdelete_test.go @@ -395,7 +395,7 @@ var _ = Describe("(Integration) Create, Get, Scale & Delete", func() { }) }) - Context("and creating a nodegroup with containerd runtime", func() { + PContext("and creating a nodegroup with containerd runtime", func() { var ( nodegroupName string ) From 9a1d4d262f053d83de55f45f3fd180071a886ba4 Mon Sep 17 00:00:00 2001 From: Gergely Brautigam <182850+Skarlso@users.noreply.github.com> Date: Wed, 6 Oct 2021 07:03:46 +0200 Subject: [PATCH 002/124] Parse task log to be more human readable (#4290) * Parse task log to be more human readable * Added new line breaks --- pkg/cfn/manager/tasks_test.go | 49 ++++++++++++++++++++--- pkg/utils/tasks/tasks.go | 75 +++++++++++++++++++++++++---------- pkg/utils/tasks/tasks_test.go | 46 ++++++++++++++++++--- 3 files changed, 139 insertions(+), 31 deletions(-) diff --git a/pkg/cfn/manager/tasks_test.go b/pkg/cfn/manager/tasks_test.go index 6907a1e44d..5a5e07d3a7 100644 --- a/pkg/cfn/manager/tasks_test.go +++ b/pkg/cfn/manager/tasks_test.go @@ -5,6 +5,7 @@ import ( . "github.com/onsi/ginkgo" . "github.com/onsi/gomega" + api "github.com/weaveworks/eksctl/pkg/apis/eksctl.io/v1alpha5" "github.com/weaveworks/eksctl/pkg/testutils/mockprovider" vpcfakes "github.com/weaveworks/eksctl/pkg/vpc/fakes" @@ -94,7 +95,10 @@ var _ = Describe("StackCollection Tasks", func() { // in these tests { tasks := stackManager.NewUnmanagedNodeGroupTask(makeNodeGroups("bar", "foo"), false, fakeVPCImporter) - Expect(tasks.Describe()).To(Equal(`2 parallel tasks: { create nodegroup "bar", create nodegroup "foo" }`)) + Expect(tasks.Describe()).To(Equal(` +2 parallel tasks: { create nodegroup "bar", create nodegroup "foo" +} +`)) } { tasks := stackManager.NewUnmanagedNodeGroupTask(makeNodeGroups("bar"), false, fakeVPCImporter) @@ -110,11 +114,21 @@ var _ = Describe("StackCollection Tasks", func() { } { tasks := stackManager.NewTasksToCreateClusterWithNodeGroups(makeNodeGroups("bar", "foo"), nil, true) - Expect(tasks.Describe()).To(Equal(`2 sequential tasks: { create cluster control plane "test-cluster", 2 parallel sub-tasks: { create nodegroup "bar", create nodegroup "foo" } }`)) + Expect(tasks.Describe()).To(Equal(` +2 sequential tasks: { create cluster control plane "test-cluster", + 2 parallel sub-tasks: { + create nodegroup "bar", + create nodegroup "foo", + } +} +`)) } { tasks := stackManager.NewTasksToCreateClusterWithNodeGroups(makeNodeGroups("bar"), nil, false) - Expect(tasks.Describe()).To(Equal(`2 sequential tasks: { create cluster control plane "test-cluster", create nodegroup "bar" }`)) + Expect(tasks.Describe()).To(Equal(` +2 sequential tasks: { create cluster control plane "test-cluster", create nodegroup "bar" +} +`)) } { tasks := stackManager.NewTasksToCreateClusterWithNodeGroups(nil, nil, true) @@ -122,15 +136,38 @@ var _ = Describe("StackCollection Tasks", func() { } { tasks := stackManager.NewTasksToCreateClusterWithNodeGroups(makeNodeGroups("bar", "foo"), makeManagedNodeGroups("m1", "m2"), false) - Expect(tasks.Describe()).To(Equal(`2 sequential tasks: { create cluster control plane "test-cluster", 4 parallel sub-tasks: { create nodegroup "bar", create nodegroup "foo", create managed nodegroup "m1", create managed nodegroup "m2" } }`)) + Expect(tasks.Describe()).To(Equal(` +2 sequential tasks: { create cluster control plane "test-cluster", + 4 parallel sub-tasks: { + create nodegroup "bar", + create nodegroup "foo", + create managed nodegroup "m1", + create managed nodegroup "m2", + } +} +`)) } { tasks := stackManager.NewTasksToCreateClusterWithNodeGroups(makeNodeGroups("foo"), makeManagedNodeGroups("m1"), true) - Expect(tasks.Describe()).To(Equal(`2 sequential tasks: { create cluster control plane "test-cluster", 2 parallel sub-tasks: { create nodegroup "foo", create managed nodegroup "m1" } }`)) + Expect(tasks.Describe()).To(Equal(` +2 sequential tasks: { create cluster control plane "test-cluster", + 2 parallel sub-tasks: { + create nodegroup "foo", + create managed nodegroup "m1", + } +} +`)) } { tasks := stackManager.NewTasksToCreateClusterWithNodeGroups(makeNodeGroups("bar"), nil, false, &task{id: 1}) - Expect(tasks.Describe()).To(Equal(`2 sequential tasks: { create cluster control plane "test-cluster", 2 sequential sub-tasks: { task 1, create nodegroup "bar" } }`)) + Expect(tasks.Describe()).To(Equal(` +2 sequential tasks: { create cluster control plane "test-cluster", + 2 sequential sub-tasks: { + task 1, + create nodegroup "bar", + } +} +`)) } }) }) diff --git a/pkg/utils/tasks/tasks.go b/pkg/utils/tasks/tasks.go index c60c294257..f625cdc74e 100644 --- a/pkg/utils/tasks/tasks.go +++ b/pkg/utils/tasks/tasks.go @@ -62,38 +62,73 @@ func (t *TaskTree) Len() int { return len(t.Tasks) } -// Describe the set +// Describe collects all tasks which have been added to the task tree. +// This is a lazy tree which does not track its nodes in any form. This function +// is recursively called from the rest of the task Describes and eventually +// returns a collection of all the tasks' `Info` value. func (t *TaskTree) Describe() string { - descriptions := []string{} - for _, task := range t.Tasks { - descriptions = append(descriptions, task.Describe()) + if t.Len() == 0 { + return "no tasks" } - mode := "sequential" - if t.Parallel { - mode = "parallel" + var descriptions []string + for _, task := range t.Tasks { + descriptions = append(descriptions, strings.TrimSuffix(task.Describe(), "\n")) } - count := len(descriptions) - var msg string noun := "task" if t.IsSubTask { noun = "sub-task" } - switch count { - case 0: - msg = "no tasks" - case 1: - msg = fmt.Sprintf("1 %s: { %s }", noun, descriptions[0]) + if len(descriptions) == 1 { + msg := fmt.Sprintf("1 %s: { %s }", noun, descriptions[0]) if t.IsSubTask { - msg = descriptions[0] // simple description for single sub-task + msg = descriptions[0] + } + return msg + } + count := len(descriptions) + mode := "sequential" + if t.Parallel { + mode = "parallel" + } + noun += "s" + head := fmt.Sprintf("\n%d %s %s: { ", count, mode, noun) + var tail string + if t.IsSubTask { + // Only add a linebreak at the end if we have multiple subtasks as well. Otherwise, leave it + // as single line. + head = fmt.Sprintf("\n%s%d %s %s: { ", strings.Repeat(" ", 4), count, mode, noun) + tail = "\n" + for _, d := range descriptions { + // all tasks are sub-tasks if they are inside a task. + // which means we don't have to care about sequential tasks. + if strings.Contains(d, "sub-task") { + // trim the previous leading tail new line... + d = strings.TrimPrefix(d, "\n") + split := strings.Split(d, "\n") + // indent all lines of the subtask one deepness more + var result []string + for _, s := range split { + result = append(result, strings.Repeat(" ", 4)+s) + } + // join it back up with line breaks + d = strings.Join(result, "\n") + } else { + d = strings.Repeat(" ", 8) + d + } + tail += fmt.Sprintf("%s,\n", d) } - default: - noun += "s" - msg = fmt.Sprintf("%d %s %s: { %s }", count, mode, noun, strings.Join(descriptions, ", ")) + // closing the final bracket + tail += fmt.Sprintf("%s}", strings.Repeat(" ", 4)) + } else { + // if it isn't a subtask, we just add the descriptions as is joined by new line. + // this results in line like `1 task: { t1.1 }` which are more readable this way. + tail = fmt.Sprintf("%s \n}", strings.Join(descriptions, ", ")) } + msg := head + tail if t.PlanMode { - return "(plan) " + msg + msg = "(plan) " + msg } - return msg + return msg + "\n" } // Do will run through the set in the background, it may return an error immediately, diff --git a/pkg/utils/tasks/tasks_test.go b/pkg/utils/tasks/tasks_test.go index cf6aed2dcc..8946e9a533 100644 --- a/pkg/utils/tasks/tasks_test.go +++ b/pkg/utils/tasks/tasks_test.go @@ -21,9 +21,15 @@ var _ = Describe("TaskTree", func() { tasks.IsSubTask = true tasks.PlanMode = true tasks.Append(&TaskTree{Parallel: false, IsSubTask: true}) - Expect(tasks.Describe()).To(Equal("(plan) 2 sequential sub-tasks: { no tasks, no tasks }")) + fmt.Println(tasks.Describe()) + expected := []byte(`(plan) + 2 sequential sub-tasks: { + no tasks, + no tasks, + } +`) + Expect([]byte(tasks.Describe())).To(Equal(expected)) } - { tasks := &TaskTree{Parallel: false} subTask1 := &TaskTree{Parallel: false, IsSubTask: true} @@ -48,7 +54,17 @@ var _ = Describe("TaskTree", func() { tasks.Append(subTask2) subTask1.Append(subTask3) - Expect(tasks.Describe()).To(Equal("2 sequential tasks: { 2 sequential sub-tasks: { t1.1, 2 parallel sub-tasks: { t3.1, t3.2 } }, t2.1 }")) + Expect(tasks.Describe()).To(Equal(` +2 sequential tasks: { + 2 sequential sub-tasks: { + t1.1, + 2 parallel sub-tasks: { + t3.1, + t3.2, + }, + }, t2.1 +} +`)) } }) @@ -130,7 +146,17 @@ var _ = Describe("TaskTree", func() { }) subTask1.Append(subTask3) - Expect(tasks.Describe()).To(Equal("2 sequential tasks: { 2 sequential sub-tasks: { t1.1, 2 parallel sub-tasks: { t3.1, t3.2 } }, t2.1 }")) + Expect(tasks.Describe()).To(Equal(` +2 sequential tasks: { + 2 sequential sub-tasks: { + t1.1, + 2 parallel sub-tasks: { + t3.1, + t3.2, + }, + }, t2.1 +} +`)) status.startTime = time.Now() errs := tasks.DoAllSync() @@ -240,7 +266,17 @@ var _ = Describe("TaskTree", func() { }) subTask1.Append(subTask3) - Expect(tasks.Describe()).To(Equal("2 sequential tasks: { 2 sequential sub-tasks: { t1.1, 2 parallel sub-tasks: { t3.1, t3.2 } }, t2.1 }")) + Expect(tasks.Describe()).To(Equal(` +2 sequential tasks: { + 2 sequential sub-tasks: { + t1.1, + 2 parallel sub-tasks: { + t3.1, + t3.2, + }, + }, t2.1 +} +`)) status.startTime = time.Now() errs := tasks.DoAllSync() From fef5af68569b5fcbae98ec9fc2ace947311f566a Mon Sep 17 00:00:00 2001 From: Jake Klein Date: Thu, 7 Oct 2021 14:09:53 +0100 Subject: [PATCH 003/124] pend failing test (#4320) --- integration/tests/managed/managed_nodegroup_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/integration/tests/managed/managed_nodegroup_test.go b/integration/tests/managed/managed_nodegroup_test.go index 77a2d22115..b147ad5861 100644 --- a/integration/tests/managed/managed_nodegroup_test.go +++ b/integration/tests/managed/managed_nodegroup_test.go @@ -118,7 +118,7 @@ var _ = Describe("(Integration) Create Managed Nodegroups", func() { }, }), - Entry("Ubuntu", &api.ManagedNodeGroup{ + PEntry("Ubuntu", &api.ManagedNodeGroup{ NodeGroupBase: &api.NodeGroupBase{ Name: "ubuntu", VolumeSize: aws.Int(25), From 3635e2715552d317f35f2de320d33055e1a6e6de Mon Sep 17 00:00:00 2001 From: Gergely Brautigam <182850+Skarlso@users.noreply.github.com> Date: Fri, 8 Oct 2021 10:52:07 +0200 Subject: [PATCH 004/124] Add release notes for 0.70 (#4324) --- docs/release_notes/0.70.0.md | 9 +++++++++ 1 file changed, 9 insertions(+) create mode 100644 docs/release_notes/0.70.0.md diff --git a/docs/release_notes/0.70.0.md b/docs/release_notes/0.70.0.md new file mode 100644 index 0000000000..7fda7caea0 --- /dev/null +++ b/docs/release_notes/0.70.0.md @@ -0,0 +1,9 @@ +# Release 0.70.0 + +## Features + +- Parse task log to be more human readable (#4290) + +## Improvements + +- Add support for specifying latest version in cluster config (#4258) From ea4278cc20a1f818beaea1bad2bba14806717cd0 Mon Sep 17 00:00:00 2001 From: Jake Klein Date: Tue, 12 Oct 2021 14:05:36 +0100 Subject: [PATCH 005/124] wait for addons to be healthy only if there are nodegroups (#4332) --- pkg/actions/addon/tasks.go | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/pkg/actions/addon/tasks.go b/pkg/actions/addon/tasks.go index e8ce296128..49bb5f3a12 100644 --- a/pkg/actions/addon/tasks.go +++ b/pkg/actions/addon/tasks.go @@ -31,6 +31,7 @@ func CreateAddonTasks(cfg *api.ClusterConfig, clusterProvider *eks.ClusterProvid clusterProvider: clusterProvider, forceAll: forceAll, timeout: timeout, + wait: false, }, ) @@ -42,6 +43,7 @@ func CreateAddonTasks(cfg *api.ClusterConfig, clusterProvider *eks.ClusterProvid clusterProvider: clusterProvider, forceAll: forceAll, timeout: timeout, + wait: len(cfg.NodeGroups) > 0 || len(cfg.ManagedNodeGroups) > 0, }, ) return preTasks, postTasks @@ -52,7 +54,7 @@ type createAddonTask struct { cfg *api.ClusterConfig clusterProvider *eks.ClusterProvider addons []*api.Addon - forceAll bool + forceAll, wait bool timeout time.Duration } @@ -89,7 +91,7 @@ func (t *createAddonTask) Do(errorCh chan error) error { if t.forceAll { a.Force = true } - err := addonManager.Create(a, true) + err := addonManager.Create(a, t.wait) if err != nil { go func() { errorCh <- err From 5e09580b1247525f18c0f13f49657eaf42481403 Mon Sep 17 00:00:00 2001 From: Weaveworks Bot Date: Tue, 12 Oct 2021 10:12:40 -0400 Subject: [PATCH 006/124] Prepare for next development iteration (#4326) --- pkg/version/release.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkg/version/release.go b/pkg/version/release.go index a4dbc7dc20..1fd11dd635 100644 --- a/pkg/version/release.go +++ b/pkg/version/release.go @@ -3,7 +3,7 @@ package version // This file was generated by release_generate.go; DO NOT EDIT. // Version is the version number in semver format X.Y.Z -var Version = "0.70.0" +var Version = "0.71.0" // PreReleaseID can be empty for releases, "rc.X" for release candidates and "dev" for snapshots var PreReleaseID = "dev" From 88e9f4dd2580fa5b9994f77a11aa93469b720131 Mon Sep 17 00:00:00 2001 From: Eng Zer Jun Date: Thu, 14 Oct 2021 00:01:47 +0800 Subject: [PATCH 007/124] refactor: move from io/ioutil to io and os package (#4333) The io/ioutil package has been deprecated as of Go 1.16, see https://golang.org/doc/go1.16#ioutil. This commit replaces the existing io/ioutil functions with their new definitions in io and os packages. Signed-off-by: Eng Zer Jun --- cmd/schema/generate.go | 3 +- integration/main.go | 3 +- integration/matchers/flux.go | 23 +++++++------- .../tests/anywhere/anywhere_run_test.go | 5 ++- .../backwards_compatibility_test.go | 3 +- .../tests/caching/credential_caching_test.go | 7 ++--- .../cluster_api/cluster_api_endpoints_test.go | 3 +- .../tests/crud/creategetdelete_test.go | 3 +- .../tests/eks_connector/eks_connector_test.go | 3 +- integration/tests/gitops/flux_test.go | 5 ++- .../tests/inferentia/inferentia_test.go | 3 +- .../unowned_cluster/unowned_cluster_test.go | 9 +++--- .../tests/update/update_cluster_test.go | 3 +- pkg/actions/anywhere/anywhere_test.go | 12 +++---- pkg/actions/irsa/update.go | 3 +- pkg/actions/repo/enable.go | 3 +- pkg/actions/repo/enable_test.go | 3 +- .../builder/managed_launch_template_test.go | 4 +-- pkg/cfn/builder/vpc_endpoint_test.go | 4 +-- pkg/cfn/template/matchers/matchers.go | 4 +-- pkg/cloudconfig/cloudconfig.go | 5 ++- pkg/connector/connector_test.go | 6 ++-- pkg/connector/kubernetes.go | 4 +-- pkg/credentials/filecache_test.go | 11 +++---- .../filter/iamserviceaccount_filter_test.go | 2 +- pkg/ctl/ctltest/utils.go | 4 +-- pkg/ctl/enable/flux.go | 3 +- pkg/eks/api.go | 6 ++-- pkg/flux/flux_test.go | 3 +- pkg/git/git.go | 3 +- pkg/git/git_test.go | 3 +- pkg/gitops/profile.go | 3 +- pkg/iam/oidc/api_test.go | 4 +-- pkg/info/info_test.go | 2 +- pkg/kubernetes/manifests_test.go | 14 ++++----- pkg/nodebootstrap/legacy/maxpods_generate.go | 7 ++--- pkg/nodebootstrap/legacy/reserved_generate.go | 1 + pkg/printers/json_test.go | 6 ++-- pkg/printers/table_test.go | 8 ++--- pkg/printers/yaml_test.go | 9 ++---- pkg/ssh/client/ssh.go | 4 +-- pkg/testutils/client.go | 9 +++--- pkg/utils/dir/dir_test.go | 7 ++--- pkg/utils/kubeconfig/kubeconfig.go | 3 +- pkg/utils/kubeconfig/kubeconfig_test.go | 31 +++++++++---------- 45 files changed, 118 insertions(+), 146 deletions(-) diff --git a/cmd/schema/generate.go b/cmd/schema/generate.go index 1a6af2066a..828ac6a707 100644 --- a/cmd/schema/generate.go +++ b/cmd/schema/generate.go @@ -2,7 +2,6 @@ package main import ( "fmt" - "io/ioutil" "os" "path/filepath" @@ -48,7 +47,7 @@ func main() { panic(err) } fmt.Println("Writing docs schema to " + outputFile) - if err := ioutil.WriteFile(outputFile, bytes, 0755); err != nil { + if err := os.WriteFile(outputFile, bytes, 0755); err != nil { panic(err) } } diff --git a/integration/main.go b/integration/main.go index 730f99d764..98b0ce2477 100644 --- a/integration/main.go +++ b/integration/main.go @@ -8,7 +8,6 @@ import ( "context" "fmt" "io" - "io/ioutil" "log" "os" "os/exec" @@ -92,7 +91,7 @@ func listModules() []string { return moduleDirs } - files, err := ioutil.ReadDir(testsDir) + files, err := os.ReadDir(testsDir) if err != nil { log.Fatalf("failed to gather test suites: %v", err) } diff --git a/integration/matchers/flux.go b/integration/matchers/flux.go index 434c4ccab7..ca9a9a7f06 100644 --- a/integration/matchers/flux.go +++ b/integration/matchers/flux.go @@ -5,7 +5,6 @@ package matchers import ( "fmt" - "io/ioutil" "os" "os/exec" "path/filepath" @@ -61,7 +60,7 @@ func assertDoesNotContainFluxDir(dir string) { } func dirExists(dir string) (bool, error) { - files, err := ioutil.ReadDir(dir) + files, err := os.ReadDir(dir) if err != nil { return false, err } @@ -80,7 +79,7 @@ func assertContainsFluxManifests(dir string) { // API server. Hence, for now, we simply ensure that all files & objects // are present, and that the main fields of these objects match expected // values. - files, err := ioutil.ReadDir(dir) + files, err := os.ReadDir(dir) Expect(err).ShouldNot(HaveOccurred()) for _, f := range files { if f.IsDir() { @@ -115,7 +114,7 @@ func assertContainsFluxManifests(dir string) { } func assertValidFluxAccountManifest(fileName string) { - bytes, err := ioutil.ReadFile(fileName) + bytes, err := os.ReadFile(fileName) Expect(err).ShouldNot(HaveOccurred()) list, err := kubernetes.NewRawExtensions(bytes) Expect(err).ShouldNot(HaveOccurred()) @@ -148,7 +147,7 @@ func assertValidFluxAccountManifest(fileName string) { } func assertValidFluxDeploymentManifest(fileName string) { - bytes, err := ioutil.ReadFile(fileName) + bytes, err := os.ReadFile(fileName) Expect(err).ShouldNot(HaveOccurred()) list, err := kubernetes.NewRawExtensions(bytes) Expect(err).ShouldNot(HaveOccurred()) @@ -175,7 +174,7 @@ func assertValidFluxDeploymentManifest(fileName string) { } func assertValidFluxSecretManifest(fileName string) { - bytes, err := ioutil.ReadFile(fileName) + bytes, err := os.ReadFile(fileName) Expect(err).ShouldNot(HaveOccurred()) list, err := kubernetes.NewRawExtensions(bytes) Expect(err).ShouldNot(HaveOccurred()) @@ -196,7 +195,7 @@ func assertValidFluxSecretManifest(fileName string) { } func assertValidFluxMemcacheDeploymentManifest(fileName string) { - bytes, err := ioutil.ReadFile(fileName) + bytes, err := os.ReadFile(fileName) Expect(err).ShouldNot(HaveOccurred()) list, err := kubernetes.NewRawExtensions(bytes) Expect(err).ShouldNot(HaveOccurred()) @@ -224,7 +223,7 @@ func assertValidFluxMemcacheDeploymentManifest(fileName string) { } func assertValidFluxMemcacheServiceManifest(fileName string) { - bytes, err := ioutil.ReadFile(fileName) + bytes, err := os.ReadFile(fileName) Expect(err).ShouldNot(HaveOccurred()) list, err := kubernetes.NewRawExtensions(bytes) Expect(err).ShouldNot(HaveOccurred()) @@ -250,7 +249,7 @@ func assertValidFluxMemcacheServiceManifest(fileName string) { } func assertValidFluxNamespaceManifest(fileName string) { - bytes, err := ioutil.ReadFile(fileName) + bytes, err := os.ReadFile(fileName) Expect(err).ShouldNot(HaveOccurred()) list, err := kubernetes.NewRawExtensions(bytes) Expect(err).ShouldNot(HaveOccurred()) @@ -269,7 +268,7 @@ func assertValidFluxNamespaceManifest(fileName string) { } func assertValidFluxHelmOperatorAccount(fileName string) { - bytes, err := ioutil.ReadFile(fileName) + bytes, err := os.ReadFile(fileName) Expect(err).ShouldNot(HaveOccurred()) list, err := kubernetes.NewRawExtensions(bytes) Expect(err).ShouldNot(HaveOccurred()) @@ -302,7 +301,7 @@ func assertValidFluxHelmOperatorAccount(fileName string) { } func assertValidFluxHelmReleaseCRD(fileName string) { - bytes, err := ioutil.ReadFile(fileName) + bytes, err := os.ReadFile(fileName) Expect(err).ShouldNot(HaveOccurred()) list, err := kubernetes.NewRawExtensions(bytes) Expect(err).ShouldNot(HaveOccurred()) @@ -323,7 +322,7 @@ func assertValidFluxHelmReleaseCRD(fileName string) { } func assertValidHelmOperatorDeployment(fileName string) { - bytes, err := ioutil.ReadFile(fileName) + bytes, err := os.ReadFile(fileName) Expect(err).ShouldNot(HaveOccurred()) list, err := kubernetes.NewRawExtensions(bytes) Expect(err).ShouldNot(HaveOccurred()) diff --git a/integration/tests/anywhere/anywhere_run_test.go b/integration/tests/anywhere/anywhere_run_test.go index 70b9f3878b..fb908a1f37 100644 --- a/integration/tests/anywhere/anywhere_run_test.go +++ b/integration/tests/anywhere/anywhere_run_test.go @@ -5,7 +5,6 @@ package anywhere import ( "fmt" - "io/ioutil" "os" "path/filepath" "testing" @@ -51,7 +50,7 @@ var _ = Describe("(Integration) [EKS Anywhere]", func() { BeforeEach(func() { var err error - tmpDir, err = ioutil.TempDir("", "anywhere-command") + tmpDir, err = os.MkdirTemp("", "anywhere-command") Expect(err).NotTo(HaveOccurred()) }) @@ -63,7 +62,7 @@ var _ = Describe("(Integration) [EKS Anywhere]", func() { var originalPath string BeforeEach(func() { - err := ioutil.WriteFile(filepath.Join(tmpDir, anywhere.BinaryFileName), []byte(`#!/usr/bin/env sh + err := os.WriteFile(filepath.Join(tmpDir, anywhere.BinaryFileName), []byte(`#!/usr/bin/env sh echo "you called?" exit 0`), 0777) Expect(err).NotTo(HaveOccurred()) diff --git a/integration/tests/backwards_compat/backwards_compatibility_test.go b/integration/tests/backwards_compat/backwards_compatibility_test.go index d9ce67da52..2d29117358 100644 --- a/integration/tests/backwards_compat/backwards_compatibility_test.go +++ b/integration/tests/backwards_compat/backwards_compatibility_test.go @@ -6,7 +6,6 @@ package backwards_compat import ( "errors" "fmt" - "io/ioutil" "os" "path" "runtime" @@ -54,7 +53,7 @@ var _ = Describe("(Integration) [Backwards compatibility test]", func() { } By("downloading a previous release") - eksctlDir, err := ioutil.TempDir(os.TempDir(), "eksctl") + eksctlDir, err := os.MkdirTemp(os.TempDir(), "eksctl") Expect(err).ToNot(HaveOccurred()) defer func() { diff --git a/integration/tests/caching/credential_caching_test.go b/integration/tests/caching/credential_caching_test.go index d73491e3a2..e04f348658 100644 --- a/integration/tests/caching/credential_caching_test.go +++ b/integration/tests/caching/credential_caching_test.go @@ -4,7 +4,6 @@ package caching import ( - "io/ioutil" "os" "path/filepath" "testing" @@ -35,7 +34,7 @@ var _ = Describe("", func() { When("credential caching is disabled", func() { var tmp string BeforeEach(func() { - tmp, err := ioutil.TempDir("", "caching_creds") + tmp, err := os.MkdirTemp("", "caching_creds") Expect(err).NotTo(HaveOccurred()) _ = os.Setenv(credentials.EksctlCacheFilenameEnvName, filepath.Join(tmp, "credentials.yaml")) // Make sure the environment property is not set on the running environment. @@ -60,7 +59,7 @@ var _ = Describe("", func() { XWhen("credential caching is enabled", func() { var tmp string BeforeEach(func() { - tmp, err := ioutil.TempDir("", "caching_creds") + tmp, err := os.MkdirTemp("", "caching_creds") Expect(err).NotTo(HaveOccurred()) _ = os.Setenv(credentials.EksctlCacheFilenameEnvName, filepath.Join(tmp, "credentials.yaml")) _ = os.Setenv(credentials.EksctlGlobalEnableCachingEnvName, "1") @@ -74,7 +73,7 @@ var _ = Describe("", func() { ).WithoutArg("--region", params.Region) Expect(cmd).Should(RunSuccessfully()) - content, err := ioutil.ReadFile(filepath.Join(tmp, "credentials.yaml")) + content, err := os.ReadFile(filepath.Join(tmp, "credentials.yaml")) Expect(err).NotTo(HaveOccurred()) Expect(content).NotTo(BeEmpty()) }) diff --git a/integration/tests/cluster_api/cluster_api_endpoints_test.go b/integration/tests/cluster_api/cluster_api_endpoints_test.go index 1d419fa848..83bb04fd1d 100644 --- a/integration/tests/cluster_api/cluster_api_endpoints_test.go +++ b/integration/tests/cluster_api/cluster_api_endpoints_test.go @@ -6,7 +6,6 @@ package cluster_api import ( "encoding/json" "fmt" - "io/ioutil" "os" "testing" "time" @@ -84,7 +83,7 @@ var _ = Describe("(Integration) Create and Update Cluster with Endpoint Configs" bytes, err := json.Marshal(cfg) Expect(err).ToNot(HaveOccurred()) Expect(len(bytes)).ToNot(BeZero()) - tmpfile, err := ioutil.TempFile("", "clusterendpointtests") + tmpfile, err := os.CreateTemp("", "clusterendpointtests") Expect(err).ToNot(HaveOccurred()) defer os.Remove(tmpfile.Name()) diff --git a/integration/tests/crud/creategetdelete_test.go b/integration/tests/crud/creategetdelete_test.go index 747c332e83..b1ffaaffdd 100644 --- a/integration/tests/crud/creategetdelete_test.go +++ b/integration/tests/crud/creategetdelete_test.go @@ -8,7 +8,6 @@ import ( "context" "encoding/json" "fmt" - "io/ioutil" "os" "strings" "testing" @@ -77,7 +76,7 @@ var _ = Describe("(Integration) Create, Get, Scale & Delete", func() { params.KubeconfigTemp = false if params.KubeconfigPath == "" { wd, _ := os.Getwd() - f, _ := ioutil.TempFile(wd, "kubeconfig-") + f, _ := os.CreateTemp(wd, "kubeconfig-") params.KubeconfigPath = f.Name() params.KubeconfigTemp = true } diff --git a/integration/tests/eks_connector/eks_connector_test.go b/integration/tests/eks_connector/eks_connector_test.go index b8bf14bb7b..e19e5f9c3a 100644 --- a/integration/tests/eks_connector/eks_connector_test.go +++ b/integration/tests/eks_connector/eks_connector_test.go @@ -5,7 +5,6 @@ package eks_connector_test import ( "fmt" - "io/ioutil" "os" "path" "testing" @@ -87,7 +86,7 @@ var _ = Describe("(Integration) [EKS Connector test]", func() { rawClient := getRawClient(params.ClusterName, params.Region) for _, f := range resourcePaths { - bytes, err := ioutil.ReadFile(f) + bytes, err := os.ReadFile(f) Expect(err).ToNot(HaveOccurred()) Expect(rawClient.CreateOrReplace(bytes, false)).To(Succeed()) } diff --git a/integration/tests/gitops/flux_test.go b/integration/tests/gitops/flux_test.go index b45ef37987..dfb72ee677 100644 --- a/integration/tests/gitops/flux_test.go +++ b/integration/tests/gitops/flux_test.go @@ -5,7 +5,6 @@ package integration_test import ( "encoding/json" - "io/ioutil" "os" "testing" @@ -90,9 +89,9 @@ var _ = Describe("Enable GitOps", func() { } configData, err := json.Marshal(&cfg) Expect(err).NotTo(HaveOccurred()) - configFile, err = ioutil.TempFile("", "") + configFile, err = os.CreateTemp("", "") Expect(err).NotTo(HaveOccurred()) - Expect(ioutil.WriteFile(configFile.Name(), configData, 0755)).To(Succeed()) + Expect(os.WriteFile(configFile.Name(), configData, 0755)).To(Succeed()) }) AfterEach(func() { diff --git a/integration/tests/inferentia/inferentia_test.go b/integration/tests/inferentia/inferentia_test.go index d12355c70c..46311c73a1 100644 --- a/integration/tests/inferentia/inferentia_test.go +++ b/integration/tests/inferentia/inferentia_test.go @@ -5,7 +5,6 @@ package inferentia import ( "context" - "io/ioutil" "os" "testing" @@ -52,7 +51,7 @@ var _ = Describe("(Integration) Inferentia nodes", func() { params.KubeconfigTemp = false if params.KubeconfigPath == "" { wd, _ := os.Getwd() - f, _ := ioutil.TempFile(wd, "kubeconfig-") + f, _ := os.CreateTemp(wd, "kubeconfig-") params.KubeconfigPath = f.Name() params.KubeconfigTemp = true } diff --git a/integration/tests/unowned_cluster/unowned_cluster_test.go b/integration/tests/unowned_cluster/unowned_cluster_test.go index 9830d6cc50..61531563d2 100644 --- a/integration/tests/unowned_cluster/unowned_cluster_test.go +++ b/integration/tests/unowned_cluster/unowned_cluster_test.go @@ -6,7 +6,6 @@ package unowned_clusters import ( "encoding/json" "fmt" - "io/ioutil" "os" "strings" "testing" @@ -70,7 +69,7 @@ var _ = Describe("(Integration) [non-eksctl cluster & nodegroup support]", func( } var err error - configFile, err = ioutil.TempFile("", "") + configFile, err = os.CreateTemp("", "") Expect(err).NotTo(HaveOccurred()) if !params.SkipCreate { @@ -112,7 +111,7 @@ var _ = Describe("(Integration) [non-eksctl cluster & nodegroup support]", func( // write config file so that the nodegroup creates have access to the vpc spec configData, err := json.Marshal(&cfg) Expect(err).NotTo(HaveOccurred()) - Expect(ioutil.WriteFile(configFile.Name(), configData, 0755)).To(Succeed()) + Expect(os.WriteFile(configFile.Name(), configData, 0755)).To(Succeed()) cmd := params.EksctlCreateNodegroupCmd. WithArgs( "--config-file", configFile.Name(), @@ -130,7 +129,7 @@ var _ = Describe("(Integration) [non-eksctl cluster & nodegroup support]", func( // write config file so that the nodegroup creates have access to the vpc spec configData, err := json.Marshal(&cfg) Expect(err).NotTo(HaveOccurred()) - Expect(ioutil.WriteFile(configFile.Name(), configData, 0755)).To(Succeed()) + Expect(os.WriteFile(configFile.Name(), configData, 0755)).To(Succeed()) cmd := params.EksctlCreateNodegroupCmd. WithArgs( "--config-file", configFile.Name(), @@ -484,7 +483,7 @@ func createClusterWithNodeGroup(clusterName, stackName, ng1, version string, ctl } func createVPCAndRole(stackName string, ctl api.ClusterProvider) ([]string, []string, string, string, string, string) { - templateBody, err := ioutil.ReadFile("cf-template.yaml") + templateBody, err := os.ReadFile("cf-template.yaml") Expect(err).NotTo(HaveOccurred()) createStackInput := &cfn.CreateStackInput{ StackName: &stackName, diff --git a/integration/tests/update/update_cluster_test.go b/integration/tests/update/update_cluster_test.go index eaac85f074..88aa43fef4 100644 --- a/integration/tests/update/update_cluster_test.go +++ b/integration/tests/update/update_cluster_test.go @@ -6,7 +6,6 @@ package update import ( "context" "fmt" - "io/ioutil" "os" "strings" "testing" @@ -64,7 +63,7 @@ var _ = Describe("(Integration) Update addons", func() { params.KubeconfigTemp = false if params.KubeconfigPath == "" { wd, _ := os.Getwd() - f, _ := ioutil.TempFile(wd, "kubeconfig-") + f, _ := os.CreateTemp(wd, "kubeconfig-") params.KubeconfigPath = f.Name() params.KubeconfigTemp = true } diff --git a/pkg/actions/anywhere/anywhere_test.go b/pkg/actions/anywhere/anywhere_test.go index 6c3f7f98fa..2d4e66abda 100644 --- a/pkg/actions/anywhere/anywhere_test.go +++ b/pkg/actions/anywhere/anywhere_test.go @@ -2,7 +2,7 @@ package anywhere_test import ( "fmt" - "io/ioutil" + "io" "os" "path/filepath" "strings" @@ -53,9 +53,9 @@ var _ = Describe("Anywhere", func() { ) BeforeEach(func() { var err error - tmpDir, err = ioutil.TempDir("", "anywhere-command") + tmpDir, err = os.MkdirTemp("", "anywhere-command") Expect(err).NotTo(HaveOccurred()) - err = ioutil.WriteFile(filepath.Join(tmpDir, anywhere.BinaryFileName), []byte(`#!/usr/bin/env sh + err = os.WriteFile(filepath.Join(tmpDir, anywhere.BinaryFileName), []byte(`#!/usr/bin/env sh echo $@ echo "EKSCTL_VERSION=$EKSCTL_VERSION" >&2 echo "stderr outputted" @@ -91,11 +91,11 @@ exit 0`), 0777) newStderrWriter.Close() By("printing the binary stderr to os.Stderr") - stderr, _ := ioutil.ReadAll(newStderrReader) + stderr, _ := io.ReadAll(newStderrReader) Expect(string(stderr)).To(Equal("stderr outputted\n")) By("printing the binary stdout to os.Stdout and passing the args to the binary") - stdout, _ := ioutil.ReadAll(newStdoutReader) + stdout, _ := io.ReadAll(newStdoutReader) stdoutLines := strings.Split(strings.TrimSuffix(string(stdout), "\n"), "\n") Expect(stdoutLines).To(HaveLen(2)) Expect(stdoutLines[0]).To(Equal("--do something")) @@ -106,7 +106,7 @@ exit 0`), 0777) When("the binary exits non-zero", func() { BeforeEach(func() { - err := ioutil.WriteFile(filepath.Join(tmpDir, anywhere.BinaryFileName), []byte(`#!/usr/bin/env sh + err := os.WriteFile(filepath.Join(tmpDir, anywhere.BinaryFileName), []byte(`#!/usr/bin/env sh exit 33`), 0777) Expect(err).NotTo(HaveOccurred()) }) diff --git a/pkg/actions/irsa/update.go b/pkg/actions/irsa/update.go index d9b49ad7f0..f5b4637fb3 100644 --- a/pkg/actions/irsa/update.go +++ b/pkg/actions/irsa/update.go @@ -2,6 +2,7 @@ package irsa import ( "fmt" + "strings" "github.com/weaveworks/eksctl/pkg/cfn/manager" @@ -9,8 +10,6 @@ import ( "github.com/weaveworks/eksctl/pkg/utils/tasks" - "strings" - api "github.com/weaveworks/eksctl/pkg/apis/eksctl.io/v1alpha5" ) diff --git a/pkg/actions/repo/enable.go b/pkg/actions/repo/enable.go index 4584a2f27c..ac3ae5cd90 100644 --- a/pkg/actions/repo/enable.go +++ b/pkg/actions/repo/enable.go @@ -5,7 +5,6 @@ import ( "context" "encoding/json" "fmt" - "io/ioutil" "net/http" "os" "path/filepath" @@ -289,7 +288,7 @@ func writeFluxManifests(baseDir string, manifests map[string][]byte) error { } for fileName, contents := range manifests { fullPath := filepath.Join(baseDir, fileName) - if err := ioutil.WriteFile(fullPath, contents, 0600); err != nil { + if err := os.WriteFile(fullPath, contents, 0600); err != nil { return errors.Wrapf(err, "failed to write Flux manifest file %s", fullPath) } } diff --git a/pkg/actions/repo/enable_test.go b/pkg/actions/repo/enable_test.go index cde88a6798..c086d56ddd 100644 --- a/pkg/actions/repo/enable_test.go +++ b/pkg/actions/repo/enable_test.go @@ -2,7 +2,6 @@ package repo_test import ( - "io/ioutil" "os" "github.com/instrumenta/kubeval/kubeval" @@ -46,7 +45,7 @@ var _ = Describe("Installer", func() { } var err error - tmpDir, err = ioutil.TempDir(os.TempDir(), "getmanifestsandsecrets") + tmpDir, err = os.MkdirTemp(os.TempDir(), "getmanifestsandsecrets") Expect(err).NotTo(HaveOccurred()) }) diff --git a/pkg/cfn/builder/managed_launch_template_test.go b/pkg/cfn/builder/managed_launch_template_test.go index 8be5098e4f..6fa087d40f 100644 --- a/pkg/cfn/builder/managed_launch_template_test.go +++ b/pkg/cfn/builder/managed_launch_template_test.go @@ -4,7 +4,7 @@ import ( "encoding/base64" "encoding/json" "fmt" - "io/ioutil" + "os" "path" "github.com/aws/aws-sdk-go/aws" @@ -77,7 +77,7 @@ var _ = Describe("ManagedNodeGroup builder", func() { actual, err := json.Marshal(template.Resources) Expect(err).ToNot(HaveOccurred()) - expected, err := ioutil.ReadFile(path.Join("testdata", "launch_template", m.resourcesFilename)) + expected, err := os.ReadFile(path.Join("testdata", "launch_template", m.resourcesFilename)) Expect(err).ToNot(HaveOccurred()) Expect(actual).To(MatchOrderedJSON(expected, WithUnorderedListKeys("Tags"))) diff --git a/pkg/cfn/builder/vpc_endpoint_test.go b/pkg/cfn/builder/vpc_endpoint_test.go index 6a2a4152c2..ce43a49fe1 100644 --- a/pkg/cfn/builder/vpc_endpoint_test.go +++ b/pkg/cfn/builder/vpc_endpoint_test.go @@ -3,7 +3,7 @@ package builder import ( "encoding/json" "fmt" - "io/ioutil" + "os" "sort" "github.com/aws/aws-sdk-go/aws" @@ -80,7 +80,7 @@ var _ = Describe("VPC Endpoint Builder", func() { resourceJSON, err := rs.template.JSON() Expect(err).ToNot(HaveOccurred()) - expectedJSON, err := ioutil.ReadFile("testdata/" + vc.expectedFile) + expectedJSON, err := os.ReadFile("testdata/" + vc.expectedFile) Expect(err).ToNot(HaveOccurred()) Expect(resourceJSON).To(MatchJSON(expectedJSON)) }, diff --git a/pkg/cfn/template/matchers/matchers.go b/pkg/cfn/template/matchers/matchers.go index 740155a87e..89c1354b48 100644 --- a/pkg/cfn/template/matchers/matchers.go +++ b/pkg/cfn/template/matchers/matchers.go @@ -3,7 +3,7 @@ package template import ( "encoding/json" "fmt" - "io/ioutil" + "os" "github.com/onsi/gomega" "github.com/onsi/gomega/types" @@ -60,7 +60,7 @@ func (m *Loader) Match(actualTemplate interface{}) (bool, error) { } if m.templatePath != "" { - js, err := ioutil.ReadFile(m.templatePath) + js, err := os.ReadFile(m.templatePath) if err != nil { return false, err } diff --git a/pkg/cloudconfig/cloudconfig.go b/pkg/cloudconfig/cloudconfig.go index a671faede7..86263e7ed4 100644 --- a/pkg/cloudconfig/cloudconfig.go +++ b/pkg/cloudconfig/cloudconfig.go @@ -6,7 +6,6 @@ import ( "encoding/base64" "fmt" "io" - "io/ioutil" "path" "github.com/kris-nova/logger" @@ -136,12 +135,12 @@ func DecodeCloudConfig(s string) (*CloudConfig, error) { return nil, err } - gr, err := gzip.NewReader(ioutil.NopCloser(bytes.NewBuffer(data))) + gr, err := gzip.NewReader(io.NopCloser(bytes.NewBuffer(data))) if err != nil { return nil, err } defer safeClose(gr) - data, err = ioutil.ReadAll(gr) + data, err = io.ReadAll(gr) if err != nil { return nil, err } diff --git a/pkg/connector/connector_test.go b/pkg/connector/connector_test.go index 6ad503a99e..c71fb48043 100644 --- a/pkg/connector/connector_test.go +++ b/pkg/connector/connector_test.go @@ -1,7 +1,7 @@ package connector_test import ( - "io/ioutil" + "os" "path" "strings" "time" @@ -27,7 +27,7 @@ type connectorCase struct { var _ = Describe("EKS Connector", func() { readManifest := func(filename string) (connector.ManifestFile, error) { - data, err := ioutil.ReadFile(path.Join("testdata", filename)) + data, err := os.ReadFile(path.Join("testdata", filename)) if err != nil { return connector.ManifestFile{}, nil } @@ -100,7 +100,7 @@ var _ = Describe("EKS Connector", func() { Expect(err).ToNot(HaveOccurred()) assertManifestEquals := func(m connector.ManifestFile, expectedFile string) { - expected, err := ioutil.ReadFile(path.Join("testdata", expectedFile)) + expected, err := os.ReadFile(path.Join("testdata", expectedFile)) Expect(err).ToNot(HaveOccurred()) Expect(m.Data).To(Equal(expected), m.Filename) } diff --git a/pkg/connector/kubernetes.go b/pkg/connector/kubernetes.go index 9809b38831..9d5af758db 100644 --- a/pkg/connector/kubernetes.go +++ b/pkg/connector/kubernetes.go @@ -1,7 +1,7 @@ package connector import ( - "io/ioutil" + "io" "net/http" "net/url" "os" @@ -72,7 +72,7 @@ func getResource(client *http.Client, url string) (ManifestFile, error) { return ManifestFile{}, errors.Errorf("expected status code %d; got %d", http.StatusOK, resp.StatusCode) } - data, err := ioutil.ReadAll(resp.Body) + data, err := io.ReadAll(resp.Body) if err != nil { return ManifestFile{}, err } diff --git a/pkg/credentials/filecache_test.go b/pkg/credentials/filecache_test.go index c878e86cd5..99a5a053ca 100644 --- a/pkg/credentials/filecache_test.go +++ b/pkg/credentials/filecache_test.go @@ -2,7 +2,6 @@ package credentials_test import ( "fmt" - "io/ioutil" "os" "path/filepath" "time" @@ -47,7 +46,7 @@ var _ = Describe("filecache", func() { err error ) BeforeEach(func() { - tmp, err = ioutil.TempDir("", "filecache") + tmp, err = os.MkdirTemp("", "filecache") Expect(err).ToNot(HaveOccurred()) _ = os.Setenv(EksctlCacheFilenameEnvName, filepath.Join(tmp, "credentials.yaml")) }) @@ -75,7 +74,7 @@ var _ = Describe("filecache", func() { Expect(value.SecretAccessKey).To(Equal("secret")) Expect(value.SessionToken).To(Equal("token")) Expect(p.IsExpired()).NotTo(BeTrue()) - content, err := ioutil.ReadFile(filepath.Join(tmp, "credentials.yaml")) + content, err := os.ReadFile(filepath.Join(tmp, "credentials.yaml")) Expect(err).ToNot(HaveOccurred()) Expect(string(content)).To(Equal(`profiles: profile: @@ -117,7 +116,7 @@ var _ = Describe("filecache", func() { providername: stubProvider expiration: 0001-01-01T00:00:00Z `) - err := ioutil.WriteFile(filepath.Join(tmp, "credentials.yaml"), content, 0700) + err := os.WriteFile(filepath.Join(tmp, "credentials.yaml"), content, 0700) Expect(err).ToNot(HaveOccurred()) c := credentials.NewCredentials(&stubProviderExpirer{}) fakeClock := &fakes.FakeClock{} @@ -153,7 +152,7 @@ var _ = Describe("filecache", func() { When("the cache file's permission is too broad", func() { It("will refuse to use that file", func() { content := []byte(`test:`) - err := ioutil.WriteFile(filepath.Join(tmp, "credentials.yaml"), content, 0777) + err := os.WriteFile(filepath.Join(tmp, "credentials.yaml"), content, 0777) Expect(err).ToNot(HaveOccurred()) c := credentials.NewCredentials(&stubProviderExpirer{}) fakeClock := &fakes.FakeClock{} @@ -164,7 +163,7 @@ var _ = Describe("filecache", func() { When("the cache data has been corrupted", func() { It("will return an appropriate error", func() { content := []byte(`not valid yaml`) - err := ioutil.WriteFile(filepath.Join(tmp, "credentials.yaml"), content, 0600) + err := os.WriteFile(filepath.Join(tmp, "credentials.yaml"), content, 0600) Expect(err).ToNot(HaveOccurred()) c := credentials.NewCredentials(&stubProviderExpirer{}) fakeClock := &fakes.FakeClock{} diff --git a/pkg/ctl/cmdutils/filter/iamserviceaccount_filter_test.go b/pkg/ctl/cmdutils/filter/iamserviceaccount_filter_test.go index ffc09fcaa2..c98e01e3fd 100644 --- a/pkg/ctl/cmdutils/filter/iamserviceaccount_filter_test.go +++ b/pkg/ctl/cmdutils/filter/iamserviceaccount_filter_test.go @@ -4,7 +4,7 @@ import ( . "github.com/onsi/ginkgo" . "github.com/onsi/gomega" - kubernetes "github.com/weaveworks/eksctl/pkg/kubernetes" + "github.com/weaveworks/eksctl/pkg/kubernetes" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/client-go/kubernetes/fake" diff --git a/pkg/ctl/ctltest/utils.go b/pkg/ctl/ctltest/utils.go index 8c62c1805b..a8bbf5a7f7 100644 --- a/pkg/ctl/ctltest/utils.go +++ b/pkg/ctl/ctltest/utils.go @@ -2,8 +2,8 @@ package ctltest import ( "bytes" - "io/ioutil" "log" + "os" "github.com/spf13/cobra" "sigs.k8s.io/yaml" @@ -51,7 +51,7 @@ func CreateConfigFile(cfg *api.ClusterConfig) string { if err != nil { log.Fatalf("unable to marshal object: %s", err.Error()) } - file, err := ioutil.TempFile("", "enable-test-config-file") + file, err := os.CreateTemp("", "enable-test-config-file") if err != nil { log.Fatalf("unable to create temp config file: %s", err.Error()) } diff --git a/pkg/ctl/enable/flux.go b/pkg/ctl/enable/flux.go index ed692b66f0..4965e06680 100644 --- a/pkg/ctl/enable/flux.go +++ b/pkg/ctl/enable/flux.go @@ -1,7 +1,6 @@ package enable import ( - "io/ioutil" "os" "github.com/kris-nova/logger" @@ -58,7 +57,7 @@ func flux2Install(cmd *cmdutils.Cmd) error { return err } - kubeCfgPath, err := ioutil.TempFile("", cmd.ClusterConfig.Metadata.Name) + kubeCfgPath, err := os.CreateTemp("", cmd.ClusterConfig.Metadata.Name) if err != nil { return err } diff --git a/pkg/eks/api.go b/pkg/eks/api.go index dc1621df2b..274d262ecc 100644 --- a/pkg/eks/api.go +++ b/pkg/eks/api.go @@ -2,7 +2,7 @@ package eks import ( "fmt" - "io/ioutil" + "io" "os" "time" @@ -278,9 +278,9 @@ func LoadConfigFromFile(configFile string) (*api.ClusterConfig, error) { func readConfig(configFile string) ([]byte, error) { if configFile == "-" { - return ioutil.ReadAll(os.Stdin) + return io.ReadAll(os.Stdin) } - return ioutil.ReadFile(configFile) + return os.ReadFile(configFile) } // IsSupportedRegion check if given region is supported diff --git a/pkg/flux/flux_test.go b/pkg/flux/flux_test.go index 1d9f3e8a5d..24752c150b 100644 --- a/pkg/flux/flux_test.go +++ b/pkg/flux/flux_test.go @@ -2,7 +2,6 @@ package flux_test import ( "errors" - "io/ioutil" "os" "path/filepath" @@ -34,7 +33,7 @@ var _ = Describe("Flux", func() { fluxClient.SetExecutor(fakeExecutor) fakeExecutor.ExecWithOutReturns([]byte("flux version 0.13.3\n"), nil) - binDir, err := ioutil.TempDir("", "bin") + binDir, err := os.MkdirTemp("", "bin") Expect(err).NotTo(HaveOccurred()) f, err := os.Create(filepath.Join(binDir, "flux")) Expect(err).NotTo(HaveOccurred()) diff --git a/pkg/git/git.go b/pkg/git/git.go index eb632400d7..33c1871a12 100644 --- a/pkg/git/git.go +++ b/pkg/git/git.go @@ -3,7 +3,6 @@ package git import ( "fmt" - "io/ioutil" "os" "os/exec" "strings" @@ -83,7 +82,7 @@ func (git *Client) WithDir(dir string) { // CloneRepoInTmpDir clones a repo specified in the gitURL in a temporary directory and checks out the specified branch func (git *Client) CloneRepoInTmpDir(tmpDirPrefix string, options CloneOptions) (string, error) { - cloneDir, err := ioutil.TempDir(os.TempDir(), tmpDirPrefix) + cloneDir, err := os.MkdirTemp(os.TempDir(), tmpDirPrefix) if err != nil { return "", fmt.Errorf("cannot create temporary directory: %s", err) } diff --git a/pkg/git/git_test.go b/pkg/git/git_test.go index 1b7cbc13f0..87c22710f8 100644 --- a/pkg/git/git_test.go +++ b/pkg/git/git_test.go @@ -2,7 +2,6 @@ package git_test import ( - "io/ioutil" "os" "os/exec" "strings" @@ -183,7 +182,7 @@ var _ = Describe("git", func() { }) It("succeeds when a valid path is provided", func() { - privateSSHKey, err := ioutil.TempFile("", "fake_id_rsa") + privateSSHKey, err := os.CreateTemp("", "fake_id_rsa") Expect(err).To(Not(HaveOccurred())) defer os.Remove(privateSSHKey.Name()) // clean up diff --git a/pkg/gitops/profile.go b/pkg/gitops/profile.go index 62e25d42fd..de8aad840d 100644 --- a/pkg/gitops/profile.go +++ b/pkg/gitops/profile.go @@ -4,7 +4,6 @@ import ( "bufio" "fmt" "io" - "io/ioutil" "os" "path" "path/filepath" @@ -52,7 +51,7 @@ func (p *Profile) Install(clusterConfig *api.ClusterConfig) error { if err != nil { return err } - usersRepoDir, err := ioutil.TempDir("", usersRepoName+"-") + usersRepoDir, err := os.MkdirTemp("", usersRepoName+"-") if err != nil { return errors.Wrapf(err, "unable to create temporary directory for %q", usersRepoName) } diff --git a/pkg/iam/oidc/api_test.go b/pkg/iam/oidc/api_test.go index 1b8e5883b3..6a2585a3cf 100644 --- a/pkg/iam/oidc/api_test.go +++ b/pkg/iam/oidc/api_test.go @@ -5,9 +5,9 @@ import ( "encoding/json" "encoding/pem" "fmt" - "io/ioutil" "net" "net/http" + "os" "os/exec" "github.com/aws/aws-sdk-go/aws" @@ -29,7 +29,7 @@ var _ = BeforeSuite(func() { session, err := gexec.Start(exec.Command("make", "-C", "testdata", "all"), GinkgoWriter, GinkgoWriter) Expect(err).NotTo(HaveOccurred()) Eventually(session, 3).Should(gexec.Exit()) - rawCert, err := ioutil.ReadFile("testdata/test-server.pem") + rawCert, err := os.ReadFile("testdata/test-server.pem") Expect(err).NotTo(HaveOccurred()) block, rest := pem.Decode(rawCert) Expect(rest).To(BeEmpty()) diff --git a/pkg/info/info_test.go b/pkg/info/info_test.go index 813c86104a..df1539086a 100644 --- a/pkg/info/info_test.go +++ b/pkg/info/info_test.go @@ -4,7 +4,7 @@ import ( "encoding/json" "strings" - semver "github.com/Masterminds/semver/v3" + "github.com/Masterminds/semver/v3" . "github.com/onsi/ginkgo" . "github.com/onsi/gomega" ) diff --git a/pkg/kubernetes/manifests_test.go b/pkg/kubernetes/manifests_test.go index a7afc5446a..5ce36de663 100644 --- a/pkg/kubernetes/manifests_test.go +++ b/pkg/kubernetes/manifests_test.go @@ -1,7 +1,7 @@ package kubernetes_test import ( - "io/ioutil" + "os" "testing" . "github.com/onsi/ginkgo" @@ -15,7 +15,7 @@ var _ = Describe("Kubernetes client toolkit", func() { Context("can load and flatten deeply nested lists", func() { It("loads all items into flattened list without errors", func() { - jb, err := ioutil.ReadFile("testdata/misc-sample-nested-list-1.json") + jb, err := os.ReadFile("testdata/misc-sample-nested-list-1.json") Expect(err).To(Not(HaveOccurred())) list, err := NewList(jb) @@ -27,7 +27,7 @@ var _ = Describe("Kubernetes client toolkit", func() { Context("can load and flatten deeply nested lists", func() { It("flatten all items into an empty list without errors", func() { - jb, err := ioutil.ReadFile("testdata/misc-sample-empty-list-1.json") + jb, err := os.ReadFile("testdata/misc-sample-empty-list-1.json") Expect(err).To(Not(HaveOccurred())) list, err := NewList(jb) @@ -39,7 +39,7 @@ var _ = Describe("Kubernetes client toolkit", func() { Context("can combine empty nested lists from a multidoc", func() { It("can load without errors", func() { - yb, err := ioutil.ReadFile("testdata/misc-sample-multidoc-empty-lists-1.yaml") + yb, err := os.ReadFile("testdata/misc-sample-multidoc-empty-lists-1.yaml") Expect(err).To(Not(HaveOccurred())) list, err := NewList(yb) @@ -52,7 +52,7 @@ var _ = Describe("Kubernetes client toolkit", func() { Context("can combine two empty lists from a multidoc", func() { It("can load without errors", func() { - yb, err := ioutil.ReadFile("testdata/misc-sample-multidoc-empty-lists-2.yaml") + yb, err := os.ReadFile("testdata/misc-sample-multidoc-empty-lists-2.yaml") Expect(err).To(Not(HaveOccurred())) list, err := NewList(yb) @@ -64,7 +64,7 @@ var _ = Describe("Kubernetes client toolkit", func() { Context("can combine empty and non-empty lists from a multidoc", func() { It("can load without errors", func() { - yb, err := ioutil.ReadFile("testdata/misc-sample-multidoc-nested-lists-1.yaml") + yb, err := os.ReadFile("testdata/misc-sample-multidoc-nested-lists-1.yaml") Expect(err).To(Not(HaveOccurred())) list, err := NewList(yb) @@ -76,7 +76,7 @@ var _ = Describe("Kubernetes client toolkit", func() { Context("can handle comment nodes", func() { It("should be able to parse lists with comment nodes", func() { - bytes, err := ioutil.ReadFile("testdata/list-with-comment-nodes.yaml") + bytes, err := os.ReadFile("testdata/list-with-comment-nodes.yaml") Expect(err).ToNot(HaveOccurred()) list, err := NewList(bytes) Expect(err).ToNot(HaveOccurred()) diff --git a/pkg/nodebootstrap/legacy/maxpods_generate.go b/pkg/nodebootstrap/legacy/maxpods_generate.go index c49491cf8f..16a549a86f 100644 --- a/pkg/nodebootstrap/legacy/maxpods_generate.go +++ b/pkg/nodebootstrap/legacy/maxpods_generate.go @@ -1,16 +1,15 @@ +//go:build ignore //+build ignore package main import ( "fmt" - "io/ioutil" "log" + "net/http" "strconv" "strings" - "net/http" - . "github.com/dave/jennifer/jen" ) @@ -30,7 +29,7 @@ func generateMap() map[string]int { log.Fatal(err.Error()) } defer resp.Body.Close() - body, err := ioutil.ReadAll(resp.Body) + body, err := io.ReadAll(resp.Body) if err != nil { log.Fatal(err.Error()) } diff --git a/pkg/nodebootstrap/legacy/reserved_generate.go b/pkg/nodebootstrap/legacy/reserved_generate.go index 22bf488d38..5316204670 100644 --- a/pkg/nodebootstrap/legacy/reserved_generate.go +++ b/pkg/nodebootstrap/legacy/reserved_generate.go @@ -1,3 +1,4 @@ +//go:build ignore //+build ignore // Fetches AWS instance type data such as memory, cpus, and diff --git a/pkg/printers/json_test.go b/pkg/printers/json_test.go index 23b49fca95..2f56afa9c0 100644 --- a/pkg/printers/json_test.go +++ b/pkg/printers/json_test.go @@ -3,7 +3,7 @@ package printers_test import ( "bufio" "bytes" - "io/ioutil" + "os" "time" . "github.com/weaveworks/eksctl/pkg/printers" @@ -69,7 +69,7 @@ var _ = Describe("JSON Printer", func() { }) It("the output should equal the golden file jsontest_single.golden", func() { - g, err := ioutil.ReadFile("testdata/jsontest_single.golden") + g, err := os.ReadFile("testdata/jsontest_single.golden") if err != nil { GinkgoT().Fatalf("failed reading .golden: %s", err) } @@ -126,7 +126,7 @@ var _ = Describe("JSON Printer", func() { }) It("the output should equal the golden file jsontest_2clusters.golden", func() { - g, err := ioutil.ReadFile("testdata/jsontest_2clusters.golden") + g, err := os.ReadFile("testdata/jsontest_2clusters.golden") if err != nil { GinkgoT().Fatalf("failed reading .golden: %s", err) } diff --git a/pkg/printers/table_test.go b/pkg/printers/table_test.go index 5dd9afed22..0309516936 100644 --- a/pkg/printers/table_test.go +++ b/pkg/printers/table_test.go @@ -3,7 +3,7 @@ package printers_test import ( "bufio" "bytes" - "io/ioutil" + "os" "time" . "github.com/weaveworks/eksctl/pkg/printers" @@ -97,7 +97,7 @@ var _ = Describe("Table Printer", func() { }) It("the output should equal the golden file tabletest_emptyslicegolden", func() { - g, err := ioutil.ReadFile("testdata/tabletest_emptyslice.golden") + g, err := os.ReadFile("testdata/tabletest_emptyslice.golden") if err != nil { GinkgoT().Fatalf("failed reading .golden: %s", err) } @@ -142,7 +142,7 @@ var _ = Describe("Table Printer", func() { }) It("the output should equal the golden file tabletest_single.golden", func() { - g, err := ioutil.ReadFile("testdata/tabletest_single.golden") + g, err := os.ReadFile("testdata/tabletest_single.golden") if err != nil { GinkgoT().Fatalf("failed reading .golden: %s", err) } @@ -199,7 +199,7 @@ var _ = Describe("Table Printer", func() { }) It("the output should equal the golden file tabletest_2clusters.golden", func() { - g, err := ioutil.ReadFile("testdata/tabletest_2clusters.golden") + g, err := os.ReadFile("testdata/tabletest_2clusters.golden") if err != nil { GinkgoT().Fatalf("failed reading .golden: %s", err) } diff --git a/pkg/printers/yaml_test.go b/pkg/printers/yaml_test.go index 9e7bd3cca6..82290b33ef 100644 --- a/pkg/printers/yaml_test.go +++ b/pkg/printers/yaml_test.go @@ -1,12 +1,9 @@ package printers_test import ( - - //"reflect" - //"fmt" "bufio" "bytes" - "io/ioutil" + "os" "time" . "github.com/weaveworks/eksctl/pkg/printers" @@ -72,7 +69,7 @@ var _ = Describe("YAML Printer", func() { }) It("the output should equal the golden file yamltest_single.golden", func() { - g, err := ioutil.ReadFile("testdata/yamltest_single.golden") + g, err := os.ReadFile("testdata/yamltest_single.golden") if err != nil { GinkgoT().Fatalf("failed reading .golden: %s", err) } @@ -129,7 +126,7 @@ var _ = Describe("YAML Printer", func() { }) It("the output should equal the golden file yamltest_2clusters.golden", func() { - g, err := ioutil.ReadFile("testdata/yamltest_2clusters.golden") + g, err := os.ReadFile("testdata/yamltest_2clusters.golden") if err != nil { GinkgoT().Fatalf("failed reading .golden: %s", err) } diff --git a/pkg/ssh/client/ssh.go b/pkg/ssh/client/ssh.go index 79444c0ba2..b079f5d8a1 100644 --- a/pkg/ssh/client/ssh.go +++ b/pkg/ssh/client/ssh.go @@ -2,7 +2,7 @@ package client import ( "fmt" - "io/ioutil" + "os" "strings" "github.com/aws/aws-sdk-go/aws/awserr" @@ -172,7 +172,7 @@ func findKeyInEc2(name string, ec2API ec2iface.EC2API) (*ec2.KeyPairInfo, error) } func readFileContents(filePath string) ([]byte, error) { - fileContents, err := ioutil.ReadFile(filePath) + fileContents, err := os.ReadFile(filePath) if err != nil { return nil, errors.Wrap(err, fmt.Sprintf("reading SSH public key file %q", filePath)) } diff --git a/pkg/testutils/client.go b/pkg/testutils/client.go index 88589fe465..6a38dc04d3 100644 --- a/pkg/testutils/client.go +++ b/pkg/testutils/client.go @@ -3,8 +3,9 @@ package testutils import ( "bytes" "fmt" - "io/ioutil" + "io" "net/http" + "os" . "github.com/onsi/gomega" @@ -27,7 +28,7 @@ func LoadSamples(manifest string) []runtime.Object { samples []runtime.Object ) - samplesData, err := ioutil.ReadFile(manifest) + samplesData, err := os.ReadFile(manifest) Expect(err).ToNot(HaveOccurred()) samplesList, err := kubernetes.NewList(samplesData) Expect(err).ToNot(HaveOccurred()) @@ -207,7 +208,7 @@ func NewFakeRawResource(item runtime.Object, missing, unionised bool, ct *Collec collection: ct, } - emptyBody := ioutil.NopCloser(bytes.NewReader([]byte{})) + emptyBody := io.NopCloser(bytes.NewReader([]byte{})) notFound := http.Response{StatusCode: http.StatusNotFound, Body: emptyBody} conflict := http.Response{StatusCode: http.StatusConflict, Body: emptyBody} @@ -218,7 +219,7 @@ func NewFakeRawResource(item runtime.Object, missing, unionised bool, ct *Collec asResult := func(req *http.Request) (*http.Response, error) { data, err := runtime.Encode(unstructured.UnstructuredJSONScheme, item) Expect(err).To(Not(HaveOccurred())) - res := &http.Response{StatusCode: http.StatusOK, Body: ioutil.NopCloser(bytes.NewReader(data))} + res := &http.Response{StatusCode: http.StatusOK, Body: io.NopCloser(bytes.NewReader(data))} return res, nil } diff --git a/pkg/utils/dir/dir_test.go b/pkg/utils/dir/dir_test.go index ee8f5d532c..eee3efeb15 100644 --- a/pkg/utils/dir/dir_test.go +++ b/pkg/utils/dir/dir_test.go @@ -1,7 +1,6 @@ package dir_test import ( - "io/ioutil" "os" "path/filepath" "testing" @@ -18,7 +17,7 @@ func TestUtilsDir(t *testing.T) { var _ = Describe("dir.IsEmpty", func() { It("should return true when passed an empty directory", func() { - d, err := ioutil.TempDir("", "test_dir_isempty") + d, err := os.MkdirTemp("", "test_dir_isempty") Expect(err).NotTo(HaveOccurred()) defer os.RemoveAll(d) // clean up. @@ -28,7 +27,7 @@ var _ = Describe("dir.IsEmpty", func() { }) It("should return false when passed a directory containing another directory", func() { - d, err := ioutil.TempDir("", "test_dir_isempty") + d, err := os.MkdirTemp("", "test_dir_isempty") Expect(err).NotTo(HaveOccurred()) defer os.RemoveAll(d) // clean up. err = os.Mkdir(filepath.Join(d, "subdir"), 0755) @@ -40,7 +39,7 @@ var _ = Describe("dir.IsEmpty", func() { }) It("should return false when passed a directory containing a file", func() { - d, err := ioutil.TempDir("", "test_dir_isempty") + d, err := os.MkdirTemp("", "test_dir_isempty") Expect(err).NotTo(HaveOccurred()) defer os.RemoveAll(d) // clean up. f, err := os.OpenFile(filepath.Join(d, "file.tmp"), os.O_CREATE, 0755) diff --git a/pkg/utils/kubeconfig/kubeconfig.go b/pkg/utils/kubeconfig/kubeconfig.go index 739a216257..66468324f9 100644 --- a/pkg/utils/kubeconfig/kubeconfig.go +++ b/pkg/utils/kubeconfig/kubeconfig.go @@ -3,12 +3,11 @@ package kubeconfig import ( "fmt" "os" + "os/exec" "path" "path/filepath" "strings" - "os/exec" - "github.com/gofrs/flock" "github.com/kris-nova/logger" "github.com/pkg/errors" diff --git a/pkg/utils/kubeconfig/kubeconfig_test.go b/pkg/utils/kubeconfig/kubeconfig_test.go index ddcb9a0f54..7000eb9ac4 100644 --- a/pkg/utils/kubeconfig/kubeconfig_test.go +++ b/pkg/utils/kubeconfig/kubeconfig_test.go @@ -1,7 +1,6 @@ package kubeconfig_test import ( - "io/ioutil" "os" "path" "sync" @@ -32,7 +31,7 @@ var _ = Describe("Kubeconfig", func() { var exampleSSHKeyPath = "~/.ssh/id_rsa.pub" BeforeEach(func() { - configFile, _ = ioutil.TempFile("", "") + configFile, _ = os.CreateTemp("", "") }) AfterEach(func() { @@ -40,12 +39,12 @@ var _ = Describe("Kubeconfig", func() { }) var writeConfig = func(filename string) error { - minikubeSample, err := ioutil.ReadFile("testdata/minikube_sample.golden") + minikubeSample, err := os.ReadFile("testdata/minikube_sample.golden") if err != nil { GinkgoT().Fatalf("failed reading .golden: %s", err) } - return ioutil.WriteFile(filename, minikubeSample, os.FileMode(0755)) + return os.WriteFile(filename, minikubeSample, os.FileMode(0755)) } It("creating new Kubeconfig", func() { @@ -72,7 +71,7 @@ var _ = Describe("Kubeconfig", func() { }) It("creating new Kubeconfig in non-existent directory", func() { - tempDir, _ := ioutil.TempDir("", "") + tempDir, _ := os.MkdirTemp("", "") filename, err := kubeconfig.Write(path.Join(tempDir, "nonexistentdir", "kubeconfig"), testConfig, false) Expect(err).To(BeNil()) Expect(filename).ToNot(BeEmpty()) @@ -229,23 +228,23 @@ var _ = Describe("Kubeconfig", func() { var err error - if emptyClusterAsBytes, err = ioutil.ReadFile("testdata/empty_cluster.golden"); err != nil { + if emptyClusterAsBytes, err = os.ReadFile("testdata/empty_cluster.golden"); err != nil { GinkgoT().Fatalf("failed reading .golden: %v", err) } - if oneClusterAsBytes, err = ioutil.ReadFile("testdata/one_cluster.golden"); err != nil { + if oneClusterAsBytes, err = os.ReadFile("testdata/one_cluster.golden"); err != nil { GinkgoT().Fatalf("failed reading .golden: %v", err) } - if twoClustersAsBytes, err = ioutil.ReadFile("testdata/two_clusters.golden"); err != nil { + if twoClustersAsBytes, err = os.ReadFile("testdata/two_clusters.golden"); err != nil { GinkgoT().Fatalf("failed reading .golden: %v", err) } - if oneClusterWithoutContextAsBytes, err = ioutil.ReadFile("testdata/one_cluster_without_context.golden"); err != nil { + if oneClusterWithoutContextAsBytes, err = os.ReadFile("testdata/one_cluster_without_context.golden"); err != nil { GinkgoT().Fatalf("failed reading .golden: %v", err) } - if oneClusterWithStaleContextAsBytes, err = ioutil.ReadFile("testdata/one_cluster_with_stale_context.golden"); err != nil { + if oneClusterWithStaleContextAsBytes, err = os.ReadFile("testdata/one_cluster_with_stale_context.golden"); err != nil { GinkgoT().Fatalf("failed reading .golden: %v", err) } @@ -264,7 +263,7 @@ var _ = Describe("Kubeconfig", func() { existingClusterConfig := GetClusterConfig("cluster-one") kubeconfig.MaybeDeleteConfig(existingClusterConfig.Metadata) - configFileAsBytes, err := ioutil.ReadFile(configFile.Name()) + configFileAsBytes, err := os.ReadFile(configFile.Name()) Expect(err).To(BeNil()) Expect(configFileAsBytes).To(MatchYAML(emptyClusterAsBytes), "Failed to delete cluster from config") }) @@ -273,7 +272,7 @@ var _ = Describe("Kubeconfig", func() { existingClusterConfig := GetClusterConfig("cluster-one") kubeconfig.MaybeDeleteConfig(existingClusterConfig.Metadata) - configFileAsBytes, err := ioutil.ReadFile(configFile.Name()) + configFileAsBytes, err := os.ReadFile(configFile.Name()) Expect(err).To(BeNil()) Expect(configFileAsBytes).To(MatchYAML(oneClusterWithoutContextAsBytes), "Failed to delete cluster from config") }) @@ -285,7 +284,7 @@ var _ = Describe("Kubeconfig", func() { existingClusterConfig := GetClusterConfig("cluster-one") kubeconfig.MaybeDeleteConfig(existingClusterConfig.Metadata) - configFileAsBytes, err := ioutil.ReadFile(configFile.Name()) + configFileAsBytes, err := os.ReadFile(configFile.Name()) Expect(err).To(BeNil()) Expect(configFileAsBytes).To(MatchYAML(oneClusterWithoutContextAsBytes), "Updated config") @@ -295,7 +294,7 @@ var _ = Describe("Kubeconfig", func() { existingClusterConfig := GetClusterConfig("cluster-two") kubeconfig.MaybeDeleteConfig(existingClusterConfig.Metadata) - configFileAsBytes, err := ioutil.ReadFile(configFile.Name()) + configFileAsBytes, err := os.ReadFile(configFile.Name()) Expect(err).To(BeNil()) Expect(configFileAsBytes).To(MatchYAML(oneClusterAsBytes), "Failed to delete cluster from config") }) @@ -304,7 +303,7 @@ var _ = Describe("Kubeconfig", func() { nonExistentClusterConfig := GetClusterConfig("not-a-cluster") kubeconfig.MaybeDeleteConfig(nonExistentClusterConfig.Metadata) - configFileAsBytes, err := ioutil.ReadFile(configFile.Name()) + configFileAsBytes, err := os.ReadFile(configFile.Name()) Expect(err).To(BeNil()) Expect(configFileAsBytes).To(MatchYAML(twoClustersAsBytes), "Should not change") }) @@ -318,7 +317,7 @@ var _ = Describe("Kubeconfig", func() { ChangeKubeconfig() var err error - tmp, err := ioutil.TempFile("", "") + tmp, err := os.CreateTemp("", "") Expect(err).To(BeNil()) { From 2caba023c61884d1b2a92cbb1c00b10453fd4e42 Mon Sep 17 00:00:00 2001 From: cpu1 Date: Thu, 14 Oct 2021 15:36:06 +0530 Subject: [PATCH 008/124] Add flag to delete VPC resource controller --- pkg/addons/assets.go | 143 +------ .../assets/vpc-admission-webhook-config.yaml | 20 - .../assets/vpc-admission-webhook-csr.yaml | 11 - .../assets/vpc-admission-webhook-dep.yaml | 61 --- pkg/addons/assets/vpc-admission-webhook.yaml | 14 - .../assets/vpc-controller-metadata.yaml | 52 +++ .../assets/vpc-resource-controller-dep.yaml | 64 --- .../assets/vpc-resource-controller.yaml | 33 -- pkg/addons/device_plugin.go | 9 + pkg/addons/vpc_controller.go | 388 +----------------- pkg/ctl/utils/install_vpc_controllers.go | 36 +- pkg/eks/tasks.go | 60 +-- 12 files changed, 130 insertions(+), 761 deletions(-) delete mode 100644 pkg/addons/assets/vpc-admission-webhook-config.yaml delete mode 100644 pkg/addons/assets/vpc-admission-webhook-csr.yaml delete mode 100644 pkg/addons/assets/vpc-admission-webhook-dep.yaml delete mode 100644 pkg/addons/assets/vpc-admission-webhook.yaml create mode 100644 pkg/addons/assets/vpc-controller-metadata.yaml delete mode 100644 pkg/addons/assets/vpc-resource-controller-dep.yaml delete mode 100644 pkg/addons/assets/vpc-resource-controller.yaml diff --git a/pkg/addons/assets.go b/pkg/addons/assets.go index 5baaf0a456..8acdc6f886 100644 --- a/pkg/addons/assets.go +++ b/pkg/addons/assets.go @@ -3,12 +3,7 @@ // assets/efa-device-plugin.yaml (3.084kB) // assets/neuron-device-plugin.yaml (3.623kB) // assets/nvidia-device-plugin.yaml (2.369kB) -// assets/vpc-admission-webhook-config.yaml (524B) -// assets/vpc-admission-webhook-csr.yaml (234B) -// assets/vpc-admission-webhook-dep.yaml (1.675kB) -// assets/vpc-admission-webhook.yaml (231B) -// assets/vpc-resource-controller-dep.yaml (1.679kB) -// assets/vpc-resource-controller.yaml (565B) +// assets/vpc-controller-metadata.yaml (924B) package addons @@ -137,123 +132,23 @@ func nvidiaDevicePluginYaml() (*asset, error) { return a, nil } -var _vpcAdmissionWebhookConfigYaml = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\x7c\x91\x4f\x6b\xf3\x30\x0c\xc6\xef\xf9\x14\x22\xf7\xa4\xf4\xf6\xe2\xdb\x4b\x29\x63\x87\xc1\x18\x63\x3b\x8c\x1d\x14\x47\x4d\x45\x62\xcb\x58\x76\x4a\xf7\xe9\x47\xfe\xb4\xac\xb0\xd5\x17\xdb\x7a\xa4\xdf\x63\xc9\x18\xf8\x8d\xa2\xb2\x78\x03\xd8\x3a\xd6\xe9\x18\xa9\x63\x4d\x11\x13\x8b\xaf\xfb\x7f\x5a\xb3\x6c\xc6\x6d\x43\x09\xb7\x45\xcf\xbe\x35\xf0\x94\x13\x26\xf6\xdd\x3b\x35\x47\x91\x7e\x27\xfe\xc0\x5d\x5e\x2a\x0a\x47\x09\x5b\x4c\x68\x0a\x00\x8f\x8e\x0c\x8c\xc1\x56\x57\x7a\x75\x5a\x8a\x2a\x7b\xe8\xd6\x0c\x0d\x68\xc9\x40\x9f\x1b\xaa\xf4\xac\x89\x5c\x01\x30\x60\x43\x83\x4e\x10\x00\x0c\xe1\x0f\x4a\xb1\xee\x73\x62\x75\xcf\xaf\x46\x87\x5f\xe2\xf1\xa4\xb5\x15\x37\x63\xed\xc0\xe4\xd3\xf2\xfa\xc5\x08\x40\x29\x8e\x6c\xe9\x72\xbd\xdb\xc2\x4d\xce\xaf\x4d\x2c\x2b\x60\x3a\x1a\x28\x37\x6e\x1a\x1b\x95\x73\x3c\xe6\x81\xf4\xe2\x52\x81\x04\x5a\xc6\xa7\x06\x3e\xa0\xdc\xbd\xec\xff\xbf\xee\x4b\xf8\xbc\x32\x30\xf0\x43\x94\x1c\x26\xbd\x2c\x6f\xe2\xeb\x0f\xce\xca\xb8\xfd\xa1\x45\x52\xc9\xd1\xd2\xac\x04\x69\x75\xd5\x0e\xc8\x43\x8e\xf4\x2c\x03\xdb\xb3\x81\xc7\xce\x4b\xa4\xe2\x3b\x00\x00\xff\xff\x49\xee\x9e\x02\x0c\x02\x00\x00") +var _vpcControllerMetadataYaml = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\xa4\x93\xc1\x6e\xc2\x40\x0c\x44\xef\xf9\x8a\xfc\xc0\x06\x71\xab\x72\x2c\xbd\xf6\x02\x52\x7b\x76\x36\x66\xb1\x92\xd8\xa9\xed\x4d\x45\xbf\xbe\x42\x14\x5a\x21\xa8\x82\x38\x27\xe3\x79\x9e\xf1\x86\x10\x0a\x18\xe9\x0d\xd5\x48\xb8\x2e\xa7\x65\xd1\x11\xb7\x75\xb9\x41\x9d\x28\x62\x31\xa0\x43\x0b\x0e\x75\x51\x96\x0c\x03\xd6\xe5\x34\xc6\x00\xed\x40\x76\x50\x84\x4f\x6c\x76\x22\xdd\xcf\x57\x1b\x21\x62\x5d\x76\xb9\xc1\x60\x7b\x73\x1c\x8a\xe2\xd2\xe2\xac\x55\x4c\x64\xae\xe0\x24\x5c\x75\x4f\x56\x91\x2c\xa6\x65\x83\x0e\x27\x88\xd7\xec\xe0\xc4\xe9\xfd\x68\xb2\x12\xde\x52\xca\x47\xc5\x5c\xb2\x10\xb7\xe9\x0e\xba\x88\xea\xb4\xa5\x08\x8e\x76\x1d\x6a\xf5\xfb\xc7\x86\x12\x13\xa7\x35\x7e\x64\x34\x9f\x4b\x54\xfd\x1f\xcf\x38\xda\xe2\x5c\xc3\x0b\x8e\xbd\xec\x07\xe4\xd9\xd3\xef\xd8\x55\x1b\x88\x15\x64\xdf\x89\xd2\xd7\x45\x0d\xa7\x65\xfb\x6c\x8e\xba\x96\xfe\xd6\x29\x28\x9a\x64\x8d\x18\xa2\xb0\xab\xf4\x3d\xea\xa3\x4e\xcf\xc4\x2d\x71\x7a\xc4\xf0\xce\x14\xaf\xcd\x9c\x9f\xe3\x9f\x47\x13\x15\x67\x37\x15\x0e\xb7\x66\xb7\x7d\xbe\x03\x00\x00\xff\xff\xad\xa6\xf6\xbd\x9c\x03\x00\x00") -func vpcAdmissionWebhookConfigYamlBytes() ([]byte, error) { +func vpcControllerMetadataYamlBytes() ([]byte, error) { return bindataRead( - _vpcAdmissionWebhookConfigYaml, - "vpc-admission-webhook-config.yaml", + _vpcControllerMetadataYaml, + "vpc-controller-metadata.yaml", ) } -func vpcAdmissionWebhookConfigYaml() (*asset, error) { - bytes, err := vpcAdmissionWebhookConfigYamlBytes() +func vpcControllerMetadataYaml() (*asset, error) { + bytes, err := vpcControllerMetadataYamlBytes() if err != nil { return nil, err } - info := bindataFileInfo{name: "vpc-admission-webhook-config.yaml", size: 0, mode: os.FileMode(0), modTime: time.Unix(0, 0)} - a := &asset{bytes: bytes, info: info, digest: [32]uint8{0x7d, 0x11, 0x23, 0x17, 0x2f, 0xdc, 0x4e, 0x18, 0xaa, 0xc8, 0x66, 0xee, 0xf3, 0xc1, 0x85, 0x63, 0xb1, 0xe3, 0x53, 0x57, 0x80, 0x96, 0xe6, 0x54, 0x26, 0x46, 0x6b, 0x3f, 0x17, 0x20, 0x31, 0x8}} - return a, nil -} - -var _vpcAdmissionWebhookCsrYaml = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\x44\x8d\x4b\x4e\xc4\x30\x10\x44\xf7\x3e\x45\x5f\x20\x41\xb3\x43\xde\x72\x03\x90\xd8\x77\xec\xc2\x69\x19\x7f\x70\xb7\x83\xe6\xf6\x28\x13\xa4\xd9\x95\xaa\x9e\x5e\x71\x97\x4f\x0c\x95\x56\x3d\x05\x0c\x93\x2f\x09\x6c\xd0\x35\xbf\xea\x2a\xed\xe5\xb8\x6d\x30\xbe\xb9\x2c\x35\x7a\x7a\x7b\x12\x1f\x92\xaa\xd4\xf4\x8e\x9f\x09\x35\x57\x60\x1c\xd9\xd8\x3b\xa2\xca\x05\x9e\x8e\x1e\x16\x8e\x45\xf4\x94\x2f\xbf\xd8\xf6\xd6\xf2\x9a\xe7\x86\x45\xef\x6a\x28\x4e\x3b\xc2\xc9\xa7\xd1\x66\xd7\x33\x2d\x74\x4d\x9e\xa7\xed\xa8\xf6\x78\x8a\x8e\x68\x2a\x27\xfc\x23\x51\x92\x18\x7f\x93\x4a\xaa\x6c\x73\xe0\xd1\x66\xdc\x09\x35\x48\xdf\x31\x0a\xaa\x5d\x36\x8c\x03\x83\x4e\x9b\xfb\x0b\x00\x00\xff\xff\xf1\x7d\x42\x97\xea\x00\x00\x00") - -func vpcAdmissionWebhookCsrYamlBytes() ([]byte, error) { - return bindataRead( - _vpcAdmissionWebhookCsrYaml, - "vpc-admission-webhook-csr.yaml", - ) -} - -func vpcAdmissionWebhookCsrYaml() (*asset, error) { - bytes, err := vpcAdmissionWebhookCsrYamlBytes() - if err != nil { - return nil, err - } - - info := bindataFileInfo{name: "vpc-admission-webhook-csr.yaml", size: 0, mode: os.FileMode(0), modTime: time.Unix(0, 0)} - a := &asset{bytes: bytes, info: info, digest: [32]uint8{0x56, 0xf4, 0x54, 0x57, 0xf8, 0xbd, 0x8a, 0x1a, 0x67, 0xb2, 0x29, 0x18, 0xe2, 0x44, 0x8a, 0xc2, 0x7f, 0x44, 0x26, 0x4c, 0x52, 0xe0, 0x70, 0xe0, 0xc8, 0x5a, 0x74, 0x76, 0x2, 0xcd, 0x3e, 0xa}} - return a, nil -} - -var _vpcAdmissionWebhookDepYaml = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\xc4\x54\xc1\x6e\xdb\x3a\x10\xbc\xfb\x2b\xf6\x92\x97\x93\xa5\x97\xa0\xc8\x81\x40\x0a\x04\x4d\x0a\x04\x6d\x93\xa0\x29\x7a\x5f\x53\x13\x99\x10\x45\xb2\xe4\x4a\x8e\xfe\xbe\xa0\xad\xa4\xb6\x1c\x37\x39\x14\xad\x0e\x3e\xec\xec\xcc\x2c\x87\x5e\x72\x30\xdf\x11\x93\xf1\x4e\x11\x87\x90\xca\xfe\x64\xd6\x18\x57\x29\xba\x44\xb0\x7e\x68\xe1\x64\xd6\x42\xb8\x62\x61\x35\x23\x72\xdc\x42\x51\x1f\xf4\x9c\xab\xd6\xa4\xcc\x9c\xaf\xb0\x58\x7a\xdf\x8c\x68\x0a\xac\xa1\xa8\xe9\x16\x98\xa7\x21\x09\xda\x19\x91\xe5\x05\x6c\xca\x02\x94\x7d\x0e\x29\xa4\x00\x9d\x9b\x22\x82\x35\x9a\x93\xa2\x93\x19\x51\x92\xc8\x82\x7a\xd8\xd0\x65\x08\x50\xf4\x15\x3a\x82\x05\x19\x86\x85\x16\x1f\x37\x70\xcb\xa2\x97\x9f\xb7\xec\x7e\x6b\x48\x24\x68\x83\x65\xc1\xc8\xde\x3a\x6a\xfe\xec\x8e\xd0\x2b\x52\x44\x4f\xf3\xe7\x4f\x7b\x27\x6c\x1c\xe2\x16\x7d\xfe\x4a\x7e\xcf\x36\xb1\xde\x62\x6d\x98\x73\xb1\xe9\x03\xa2\x7c\x34\x16\xe7\x25\x44\x97\x23\xaf\xd4\x88\x92\xd6\xbf\x45\x58\xa7\x3d\xa5\x7d\xc2\x70\x88\xd5\x60\x78\x89\x74\x7b\xbf\x8e\xf0\x7e\x8c\xf6\xb6\x47\x8c\xa6\xc2\xf9\xca\xb8\xca\xaf\xd2\xb4\x9d\x6d\xf2\xd6\xd7\xe2\x93\x54\x88\x71\x0a\xf7\xe7\xef\x26\xa5\xd3\xf7\xff\x9d\x6c\x95\x4c\xcb\x35\x14\x1d\x1f\xa5\xa2\x6a\x62\x01\x1d\x8b\xa3\x54\x1c\xa5\x12\x4d\x2a\x5f\x0c\x4b\xf5\xff\x17\xa7\xc5\xd9\xf1\x54\xe4\xae\xb3\xf6\xce\x5b\xa3\x07\x45\x17\x76\xc5\xc3\xf6\xac\xbd\xb7\x5d\x8b\x2f\xbe\x73\xb2\x17\xef\xe6\x62\x46\xf5\xf9\x3a\x9c\x9d\x0e\xa2\x36\xf3\xee\x58\x96\x8a\xf6\x83\x9c\xf4\x46\x70\x75\xeb\xec\xa0\x48\x62\x87\x11\x5c\xfa\x24\x37\x90\x95\x8f\xcd\x4e\x9d\x1f\x1e\x8c\x33\x32\xfc\x1a\xc9\xf9\x0a\x17\x7b\xd5\x2c\xfb\xa3\x33\x11\xd5\x65\x17\x8d\xab\xef\xf5\x12\x55\x67\x8d\xab\xaf\x6b\xe7\x9f\xcb\x57\x8f\xd0\x9d\xe4\x95\xde\x19\x2a\x6b\x3e\xdd\xe7\x37\xc4\x76\x2f\x81\xf5\xe6\x5c\x3d\x86\x88\x75\xd2\x13\x3c\x77\x34\x18\x14\x2d\x20\x5c\xe4\xed\x8e\x0e\x82\x54\x18\x5f\xfa\xe9\xf1\x89\x7c\x40\xe4\xbc\x94\x74\xed\xf6\xc0\x9e\x6d\x87\x3d\xfd\xec\x60\x8d\xeb\x1e\xdf\xec\xcb\x51\x2f\xff\x94\x33\xb7\xd5\xd9\xf4\x5f\xfa\xc6\x44\xfe\x41\x18\x7f\x27\x87\xcd\xbe\xbc\xf0\x7e\x1d\x5a\x93\x94\x5f\x65\xd9\x95\xdd\xd4\x6e\x0e\xbf\x7b\xa3\xca\xcf\x00\x00\x00\xff\xff\x52\xd4\x1b\x58\x8b\x06\x00\x00") - -func vpcAdmissionWebhookDepYamlBytes() ([]byte, error) { - return bindataRead( - _vpcAdmissionWebhookDepYaml, - "vpc-admission-webhook-dep.yaml", - ) -} - -func vpcAdmissionWebhookDepYaml() (*asset, error) { - bytes, err := vpcAdmissionWebhookDepYamlBytes() - if err != nil { - return nil, err - } - - info := bindataFileInfo{name: "vpc-admission-webhook-dep.yaml", size: 0, mode: os.FileMode(0), modTime: time.Unix(0, 0)} - a := &asset{bytes: bytes, info: info, digest: [32]uint8{0x3b, 0x48, 0x71, 0x63, 0xbb, 0x59, 0xcc, 0xd5, 0x1b, 0x30, 0xc7, 0x1c, 0x5e, 0xf2, 0x65, 0x72, 0xff, 0xa9, 0x4d, 0x14, 0x6c, 0xce, 0x49, 0xa8, 0x6f, 0x4d, 0x8e, 0x19, 0xf7, 0xee, 0xfa, 0x8c}} - return a, nil -} - -var _vpcAdmissionWebhookYaml = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\x84\x8c\x31\xae\xc2\x40\x0c\x05\xfb\x3d\x85\x2f\xe0\xe2\xeb\xa7\xf2\x29\x90\x90\xe8\x9d\xcd\x13\xac\x92\xcd\x5a\x6b\x13\xc4\xed\x51\x22\x0a\x1a\x44\x67\xf9\xcd\x0c\x33\x27\xb5\x72\x41\xf7\xd2\x56\xa1\xed\x2f\xcd\x65\x9d\x84\xce\xe8\x5b\xc9\x48\x15\xa1\x93\x86\x4a\x22\x5a\xb5\x42\x68\xb3\xcc\x3a\xd5\xe2\xbb\xc1\x0f\x8c\xb7\xd6\xe6\xf7\xea\xa6\x19\x42\xf3\x7d\x04\xfb\xd3\x03\x35\x11\x2d\x3a\x62\xf1\x3d\x40\xa4\x66\xdf\x0a\x6e\xc8\x3b\x64\xad\xc7\x41\xf3\x71\x0a\x0d\xc3\xff\xe1\x86\xf6\x2b\xe2\xf4\xf1\x73\x2c\xc8\xd1\xfa\xcf\xf6\x2b\x00\x00\xff\xff\xbc\xa7\x78\x3e\xe7\x00\x00\x00") - -func vpcAdmissionWebhookYamlBytes() ([]byte, error) { - return bindataRead( - _vpcAdmissionWebhookYaml, - "vpc-admission-webhook.yaml", - ) -} - -func vpcAdmissionWebhookYaml() (*asset, error) { - bytes, err := vpcAdmissionWebhookYamlBytes() - if err != nil { - return nil, err - } - - info := bindataFileInfo{name: "vpc-admission-webhook.yaml", size: 0, mode: os.FileMode(0), modTime: time.Unix(0, 0)} - a := &asset{bytes: bytes, info: info, digest: [32]uint8{0xc0, 0x14, 0x3e, 0x68, 0x1c, 0x57, 0x26, 0x7e, 0x3b, 0xab, 0xf1, 0x55, 0x21, 0x61, 0xc3, 0xe1, 0xaf, 0x46, 0xb6, 0xf7, 0xdd, 0x11, 0x29, 0x41, 0x64, 0x57, 0xc8, 0xd4, 0xea, 0x97, 0xba, 0xff}} - return a, nil -} - -var _vpcResourceControllerDepYaml = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\xc4\x94\x4f\x6f\xdb\x3c\x0c\xc6\xef\xfe\x14\xbc\x14\x3d\xd9\x49\xfa\xbe\x6b\x31\x01\x3b\x14\x6b\xb1\x15\x18\x86\x00\x0d\x76\x67\x24\x26\x16\x2c\x4b\x1a\x45\x3b\xf1\x3e\xfd\xa0\xb5\xf9\xe3\xa6\x5b\x8b\x61\xc3\x7c\x32\x9e\x9f\xc4\x87\x24\x44\x96\x65\x59\x60\xb4\x5f\x88\x93\x0d\x5e\x01\xc6\x98\x26\xfd\xac\x68\xac\x37\x0a\x6e\x28\xba\x30\xb4\xe4\xa5\x68\x49\xd0\xa0\xa0\x2a\x00\x3c\xb6\xa4\xa0\x8f\xba\x64\x4a\xa1\x63\x4d\xa5\x0e\x5e\x38\x38\x47\xfc\xc8\x53\x44\x4d\x0a\x9a\x6e\x49\x65\x1a\x92\x50\x5b\xa4\x48\x3a\x5f\x67\x8a\xce\x6a\x4c\x0a\x66\x05\x40\x22\x47\x5a\x02\x67\x02\xd0\xa2\xe8\xfa\x13\x2e\xc9\xa5\x07\x01\x72\x4a\xbf\x32\xcb\x9f\x58\x62\x05\x4b\xd4\x0d\x79\xb3\xd3\x18\x75\xa3\x20\x09\x2e\x1d\x15\x00\x42\x6d\x74\x28\xf4\xe8\x73\x54\x4e\xfe\xdc\xc8\xf2\x55\xa6\xcf\xdb\x9e\x1a\x03\xec\x0a\xff\xf1\x4f\xdc\x5b\x4d\xd7\x5a\x87\xce\xcb\x4b\x1e\x59\x40\xeb\x89\xf7\xa9\x95\xa0\x43\xdb\xa2\x37\x87\x5c\x4b\x98\xbc\x94\x29\xf2\x3a\x1d\x5f\x28\x93\x18\x62\x96\x9a\x29\xd5\xc1\x99\x77\xd6\xaf\xc2\x9e\xdb\x16\xd7\xa4\xe0\xfc\x2c\x55\xa6\xe1\x8a\x34\x57\x67\xa9\x3a\x4b\x13\x6a\xd2\x64\x63\xbd\x09\x9b\x54\xfe\xc4\x52\xf5\xd3\xea\xa2\xba\x3c\x1f\x07\x9b\x77\xce\xcd\x83\xb3\x7a\x50\x70\xed\x36\x38\xa4\x3d\x77\xb6\x27\x4f\x29\xcd\x39\x2c\xe9\x90\x23\xc0\x0a\xad\xeb\x98\x16\xbb\x1c\x15\xbc\x39\xa2\xb5\x48\xfc\x40\x72\x7c\x01\xa0\x0e\x49\x14\xcc\x2e\xae\xaa\x69\x35\xad\x66\x23\x16\x51\x6a\x05\x93\x9a\xd0\x49\xfd\x6d\x8c\x02\x8b\x82\xcb\xd9\xd5\xd5\xdb\x91\x9e\x74\x4d\xf9\xa5\x7f\x5c\x2c\xe6\x47\xc0\x7a\x2b\x16\xdd\x0d\x39\x1c\xee\x49\x07\x6f\x92\x82\xff\xa6\x47\x27\x22\xb1\x0d\xe6\x79\x26\xb6\xa5\xd0\xc9\x1e\x1e\x8a\x7a\x69\xac\x76\x0f\x48\x77\x6c\x65\x78\x1f\xbc\xd0\x76\xd4\x80\xc8\xb6\xb7\x8e\xd6\x64\x14\x08\x77\x54\x1c\xba\xf2\x99\x64\x13\xb8\x19\xe9\xb8\x5a\xe5\x52\x86\x43\x08\x1f\x0c\x5d\x9f\xa8\x79\x62\xbf\x76\x96\xc9\xdc\x74\x6c\xfd\xfa\x5e\xd7\x64\x3a\x67\xfd\xfa\x6e\xed\xc3\x5e\xbe\xdd\x92\xee\x24\x6f\x91\x51\x13\x73\xcc\xfb\xc7\x19\x5f\x10\xb7\x69\x8c\xcb\x87\x91\xbf\xdd\x46\xa6\x94\x77\xd0\x13\x9e\x4f\x34\x34\x28\x58\x92\x60\x95\xd7\x09\x7b\x12\x4a\x95\x0d\x93\x90\x9e\x1c\x05\x08\x91\x18\xf3\x36\x81\x3b\x7f\x02\x7b\x74\x1d\x9d\xc4\xcf\x0e\xce\xfa\x6e\xfb\x6a\x5f\x64\x5d\xff\x29\x67\x6c\xcd\xe5\xff\xbf\xd7\x91\x7f\xd0\x8c\xbf\xdd\x87\xef\x01\x00\x00\xff\xff\xec\x16\x91\xef\x8f\x06\x00\x00") - -func vpcResourceControllerDepYamlBytes() ([]byte, error) { - return bindataRead( - _vpcResourceControllerDepYaml, - "vpc-resource-controller-dep.yaml", - ) -} - -func vpcResourceControllerDepYaml() (*asset, error) { - bytes, err := vpcResourceControllerDepYamlBytes() - if err != nil { - return nil, err - } - - info := bindataFileInfo{name: "vpc-resource-controller-dep.yaml", size: 0, mode: os.FileMode(0), modTime: time.Unix(0, 0)} - a := &asset{bytes: bytes, info: info, digest: [32]uint8{0x0, 0xbf, 0x11, 0xf3, 0x5f, 0x76, 0xa3, 0xb2, 0x2e, 0x2f, 0x80, 0xa7, 0x86, 0xae, 0x3f, 0xb7, 0x7e, 0x76, 0xed, 0x68, 0xfe, 0x23, 0x5c, 0x76, 0xb9, 0xd0, 0xd8, 0xed, 0xf9, 0x9d, 0x96, 0x93}} - return a, nil -} - -var _vpcResourceControllerYaml = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\xa4\x90\x31\x4f\x33\x31\x0c\x86\xf7\xfc\x8a\xa8\x7b\x5a\x7d\xdb\xa7\xdb\x80\x81\xbd\x48\xec\x3e\x9f\xdb\x9a\xe6\xe2\xc8\x76\x0e\xc1\xaf\x47\x77\xd7\xc2\x80\x44\x85\x98\xf2\xc4\xf6\x6b\x4b\x4f\x4a\x29\x40\xe5\x67\x52\x63\x29\x5d\xd4\x1e\x70\x0b\xcd\x4f\xa2\xfc\x0e\xce\x52\xb6\xe7\xff\xb6\x65\xd9\x4d\xff\xc2\x99\xcb\xd0\xc5\x87\xdc\xcc\x49\xf7\x92\x29\x8c\xe4\x30\x80\x43\x17\x62\x2c\x30\x52\x17\xa7\x8a\x49\xc9\xa4\x29\x52\x42\x29\xae\x92\x33\x69\xd0\x96\xc9\xba\x90\x22\x54\x7e\x54\x69\xd5\xe6\x4c\x8a\x9b\x4d\x88\xf1\x1a\xb8\xd4\x8a\x0c\x64\x5f\xb4\x33\x07\x6f\x6b\xa1\xca\xb0\x02\x4a\x39\xf0\x71\x84\x3a\x7f\x27\xd2\xfe\x92\x6d\x75\x00\xa7\x05\x8f\xe4\xcb\x9b\xd9\x56\x78\x05\xc7\xd3\xba\xe6\x93\x50\x69\x9e\xff\x9b\x87\x7b\x2e\x03\x97\xe3\x6f\x74\x48\xa6\x3d\x1d\xe6\xc1\xab\x90\x1f\x8e\x86\x18\xbf\xbb\xbf\x75\xc2\x5a\xff\x42\xe8\x8b\xf4\x35\xfd\x44\x3a\x31\xd2\x1d\xa2\xb4\xe2\x37\x17\xac\x7d\xab\x80\xd4\xc5\x73\xeb\x29\xd9\x9b\x39\x8d\xe1\x23\x00\x00\xff\xff\x83\x2e\x8d\x64\x35\x02\x00\x00") - -func vpcResourceControllerYamlBytes() ([]byte, error) { - return bindataRead( - _vpcResourceControllerYaml, - "vpc-resource-controller.yaml", - ) -} - -func vpcResourceControllerYaml() (*asset, error) { - bytes, err := vpcResourceControllerYamlBytes() - if err != nil { - return nil, err - } - - info := bindataFileInfo{name: "vpc-resource-controller.yaml", size: 0, mode: os.FileMode(0), modTime: time.Unix(0, 0)} - a := &asset{bytes: bytes, info: info, digest: [32]uint8{0xa8, 0xff, 0xd2, 0xc, 0x46, 0xfb, 0xe4, 0x4e, 0xb, 0x26, 0x4a, 0xa0, 0x7d, 0x73, 0x5e, 0xaf, 0x6d, 0xab, 0xfd, 0xe5, 0xc2, 0x4f, 0xed, 0xae, 0xb6, 0xd7, 0x17, 0x38, 0x68, 0xb0, 0xe8, 0x2d}} + info := bindataFileInfo{name: "vpc-controller-metadata.yaml", size: 0, mode: os.FileMode(0), modTime: time.Unix(0, 0)} + a := &asset{bytes: bytes, info: info, digest: [32]uint8{0xa6, 0x89, 0x6b, 0xa9, 0x33, 0x90, 0x94, 0x63, 0xb2, 0xaf, 0x3a, 0x5c, 0x22, 0x5b, 0x19, 0xc7, 0xb9, 0x22, 0xd6, 0x5a, 0xbb, 0x68, 0xac, 0xf8, 0x24, 0x68, 0x4d, 0x2c, 0x54, 0x12, 0x18, 0x57}} return a, nil } @@ -348,15 +243,10 @@ func AssetNames() []string { // _bindata is a table, holding each asset generator, mapped to its name. var _bindata = map[string]func() (*asset, error){ - "efa-device-plugin.yaml": efaDevicePluginYaml, - "neuron-device-plugin.yaml": neuronDevicePluginYaml, - "nvidia-device-plugin.yaml": nvidiaDevicePluginYaml, - "vpc-admission-webhook-config.yaml": vpcAdmissionWebhookConfigYaml, - "vpc-admission-webhook-csr.yaml": vpcAdmissionWebhookCsrYaml, - "vpc-admission-webhook-dep.yaml": vpcAdmissionWebhookDepYaml, - "vpc-admission-webhook.yaml": vpcAdmissionWebhookYaml, - "vpc-resource-controller-dep.yaml": vpcResourceControllerDepYaml, - "vpc-resource-controller.yaml": vpcResourceControllerYaml, + "efa-device-plugin.yaml": efaDevicePluginYaml, + "neuron-device-plugin.yaml": neuronDevicePluginYaml, + "nvidia-device-plugin.yaml": nvidiaDevicePluginYaml, + "vpc-controller-metadata.yaml": vpcControllerMetadataYaml, } // AssetDebug is true if the assets were built with the debug flag enabled. @@ -406,12 +296,7 @@ var _bintree = &bintree{nil, map[string]*bintree{ "efa-device-plugin.yaml": {efaDevicePluginYaml, map[string]*bintree{}}, "neuron-device-plugin.yaml": {neuronDevicePluginYaml, map[string]*bintree{}}, "nvidia-device-plugin.yaml": {nvidiaDevicePluginYaml, map[string]*bintree{}}, - "vpc-admission-webhook-config.yaml": {vpcAdmissionWebhookConfigYaml, map[string]*bintree{}}, - "vpc-admission-webhook-csr.yaml": {vpcAdmissionWebhookCsrYaml, map[string]*bintree{}}, - "vpc-admission-webhook-dep.yaml": {vpcAdmissionWebhookDepYaml, map[string]*bintree{}}, - "vpc-admission-webhook.yaml": {vpcAdmissionWebhookYaml, map[string]*bintree{}}, - "vpc-resource-controller-dep.yaml": {vpcResourceControllerDepYaml, map[string]*bintree{}}, - "vpc-resource-controller.yaml": {vpcResourceControllerYaml, map[string]*bintree{}}, + "vpc-controller-metadata.yaml": {vpcControllerMetadataYaml, map[string]*bintree{}}, }} // RestoreAsset restores an asset under the given directory. diff --git a/pkg/addons/assets/vpc-admission-webhook-config.yaml b/pkg/addons/assets/vpc-admission-webhook-config.yaml deleted file mode 100644 index 652a257203..0000000000 --- a/pkg/addons/assets/vpc-admission-webhook-config.yaml +++ /dev/null @@ -1,20 +0,0 @@ -apiVersion: admissionregistration.k8s.io/v1beta1 -kind: MutatingWebhookConfiguration -metadata: - name: vpc-admission-webhook-cfg - namespace: kube-system - labels: - app: vpc-admission-webhook -webhooks: - - name: vpc-admission-webhook.amazonaws.com - clientConfig: - service: - name: vpc-admission-webhook - namespace: kube-system - path: "/mutate" - rules: - - operations: [ "CREATE" ] - apiGroups: [""] - apiVersions: ["v1"] - resources: ["pods"] - failurePolicy: Ignore diff --git a/pkg/addons/assets/vpc-admission-webhook-csr.yaml b/pkg/addons/assets/vpc-admission-webhook-csr.yaml deleted file mode 100644 index 09e4f77a6d..0000000000 --- a/pkg/addons/assets/vpc-admission-webhook-csr.yaml +++ /dev/null @@ -1,11 +0,0 @@ -apiVersion: certificates.k8s.io/v1beta1 -kind: CertificateSigningRequest -metadata: - name: vpc-admission-webhook.kube-system -spec: - groups: - - system:authenticated - usages: - - digital signature - - key encipherment - - server auth diff --git a/pkg/addons/assets/vpc-admission-webhook-dep.yaml b/pkg/addons/assets/vpc-admission-webhook-dep.yaml deleted file mode 100644 index 2c08acab80..0000000000 --- a/pkg/addons/assets/vpc-admission-webhook-dep.yaml +++ /dev/null @@ -1,61 +0,0 @@ -apiVersion: apps/v1 -kind: Deployment -metadata: - name: vpc-admission-webhook - namespace: kube-system - labels: - app: vpc-admission-webhook -spec: - replicas: 1 - strategy: - type: Recreate - selector: - matchLabels: - app: vpc-admission-webhook - template: - metadata: - labels: - app: vpc-admission-webhook - spec: - containers: - - name: vpc-admission-webhook - args: - - -tlsCertFile=/etc/webhook/certs/cert.pem - - -tlsKeyFile=/etc/webhook/certs/key.pem - - -OSLabelSelectorOverride=windows - - -alsologtostderr - - -v=4 - - 2>&1 - image: '%s.dkr.ecr.%s.%s/eks/vpc-admission-webhook:v0.2.6' - imagePullPolicy: Always - volumeMounts: - - name: webhook-certs - mountPath: /etc/webhook/certs - readOnly: true - hostNetwork: true - affinity: - nodeAffinity: - requiredDuringSchedulingIgnoredDuringExecution: - nodeSelectorTerms: - - matchExpressions: - - key: beta.kubernetes.io/os - operator: In - values: - - linux - - key: beta.kubernetes.io/arch - operator: In - values: - - amd64 - - matchExpressions: - - key: kubernetes.io/os - operator: In - values: - - linux - - key: kubernetes.io/arch - operator: In - values: - - amd64 - volumes: - - name: webhook-certs - secret: - secretName: vpc-admission-webhook-certs diff --git a/pkg/addons/assets/vpc-admission-webhook.yaml b/pkg/addons/assets/vpc-admission-webhook.yaml deleted file mode 100644 index b8f351fb12..0000000000 --- a/pkg/addons/assets/vpc-admission-webhook.yaml +++ /dev/null @@ -1,14 +0,0 @@ ---- -apiVersion: v1 -kind: Service -metadata: - name: vpc-admission-webhook - namespace: kube-system - labels: - app: vpc-admission-webhook -spec: - ports: - - port: 443 - targetPort: 443 - selector: - app: vpc-admission-webhook diff --git a/pkg/addons/assets/vpc-controller-metadata.yaml b/pkg/addons/assets/vpc-controller-metadata.yaml new file mode 100644 index 0000000000..93bfd78257 --- /dev/null +++ b/pkg/addons/assets/vpc-controller-metadata.yaml @@ -0,0 +1,52 @@ +--- +apiVersion: v1 +kind: Service +metadata: + name: vpc-admission-webhook + namespace: kube-system + +--- +apiVersion: admissionregistration.k8s.io/v1beta1 +kind: MutatingWebhookConfiguration +metadata: + name: vpc-admission-webhook-cfg + namespace: kube-system + +--- +apiVersion: certificates.k8s.io/v1beta1 +kind: CertificateSigningRequest +metadata: + name: vpc-admission-webhook.kube-system + +--- +apiVersion: apps/v1 +kind: Deployment +metadata: + name: vpc-admission-webhook + namespace: kube-system + +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + name: vpc-resource-controller + +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRoleBinding +metadata: + name: vpc-resource-controller + +--- +apiVersion: apps/v1 +kind: Deployment +metadata: + name: vpc-resource-controller + namespace: kube-system + +--- +apiVersion: v1 +kind: Secret +metadata: + name: vpc-admission-webhook-certs + namespace: kube-system diff --git a/pkg/addons/assets/vpc-resource-controller-dep.yaml b/pkg/addons/assets/vpc-resource-controller-dep.yaml deleted file mode 100644 index 3966657e1b..0000000000 --- a/pkg/addons/assets/vpc-resource-controller-dep.yaml +++ /dev/null @@ -1,64 +0,0 @@ ---- -apiVersion: apps/v1 -kind: Deployment -metadata: - name: vpc-resource-controller - namespace: kube-system -spec: - replicas: 1 - selector: - matchLabels: - app: vpc-resource-controller - tier: backend - track: stable - template: - metadata: - labels: - app: vpc-resource-controller - tier: backend - track: stable - spec: - serviceAccount: vpc-resource-controller - containers: - - command: - - /vpc-resource-controller - args: - - -stderrthreshold=info - image: '%s.dkr.ecr.%s.%s/eks/windows-vpc-resource-controller:v0.2.6' - imagePullPolicy: Always - livenessProbe: - failureThreshold: 5 - httpGet: - host: 127.0.0.1 - path: /healthz - port: 61779 - scheme: HTTP - initialDelaySeconds: 30 - periodSeconds: 30 - timeoutSeconds: 5 - name: vpc-resource-controller - securityContext: - privileged: true - hostNetwork: true - affinity: - nodeAffinity: - requiredDuringSchedulingIgnoredDuringExecution: - nodeSelectorTerms: - - matchExpressions: - - key: beta.kubernetes.io/os - operator: In - values: - - linux - - key: beta.kubernetes.io/arch - operator: In - values: - - amd64 - - matchExpressions: - - key: kubernetes.io/os - operator: In - values: - - linux - - key: kubernetes.io/arch - operator: In - values: - - amd64 diff --git a/pkg/addons/assets/vpc-resource-controller.yaml b/pkg/addons/assets/vpc-resource-controller.yaml deleted file mode 100644 index 91b1c9f085..0000000000 --- a/pkg/addons/assets/vpc-resource-controller.yaml +++ /dev/null @@ -1,33 +0,0 @@ ---- -apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRole -metadata: - name: vpc-resource-controller -rules: -- apiGroups: - - "" - resources: - - nodes - - nodes/status - - pods - - configmaps - verbs: - - update - - get - - list - - watch - - patch - - create ---- -apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRoleBinding -metadata: - name: vpc-resource-controller -roleRef: - apiGroup: rbac.authorization.k8s.io - kind: ClusterRole - name: vpc-resource-controller -subjects: -- kind: ServiceAccount - name: vpc-resource-controller - namespace: kube-system diff --git a/pkg/addons/device_plugin.go b/pkg/addons/device_plugin.go index 694668ad8b..70683fe99d 100644 --- a/pkg/addons/device_plugin.go +++ b/pkg/addons/device_plugin.go @@ -71,6 +71,15 @@ type DevicePlugin interface { Deploy() error } +type typeAssertionError struct { + expected interface{} + got interface{} +} + +func (t *typeAssertionError) Error() string { + return fmt.Sprintf("expected type to be %T; got %T", t.expected, t.got) +} + func applyDevicePlugin(dp DevicePlugin) error { list, err := kubernetes.NewList(dp.Manifest()) if err != nil { diff --git a/pkg/addons/vpc_controller.go b/pkg/addons/vpc_controller.go index 4af6c3ab57..f1cbf5f2d6 100644 --- a/pkg/addons/vpc_controller.go +++ b/pkg/addons/vpc_controller.go @@ -1,410 +1,50 @@ package addons import ( - "context" - "fmt" - "time" - - "github.com/cloudflare/cfssl/csr" "github.com/kris-nova/logger" "github.com/pkg/errors" - api "github.com/weaveworks/eksctl/pkg/apis/eksctl.io/v1alpha5" - "github.com/weaveworks/eksctl/pkg/assetutil" "github.com/weaveworks/eksctl/pkg/kubernetes" - "k8s.io/apimachinery/pkg/watch" - "k8s.io/client-go/kubernetes/typed/certificates/v1beta1" - admv1beta1 "k8s.io/api/admissionregistration/v1beta1" - appsv1 "k8s.io/api/apps/v1" - certsv1beta1 "k8s.io/api/certificates/v1beta1" - corev1 "k8s.io/api/core/v1" - apierrors "k8s.io/apimachinery/pkg/api/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" ) const ( vpcControllerNamespace = metav1.NamespaceSystem - vpcControllerName = "vpc-resource-controller" - webhookServiceName = "vpc-admission-webhook" - - certWaitTimeout = 45 * time.Second ) -// NewVPCController creates a new VPCController -func NewVPCController(rawClient kubernetes.RawClientInterface, irsa IRSAHelper, clusterStatus *api.ClusterStatus, region string, planMode bool) *VPCController { - return &VPCController{ - rawClient: rawClient, - irsa: irsa, - clusterStatus: clusterStatus, - region: region, - planMode: planMode, - } -} - -// A VPCController deploys Windows VPC controller to a cluster +// VPCController deletes an existing installation of VPC controller from worker nodes. type VPCController struct { - rawClient kubernetes.RawClientInterface - irsa IRSAHelper - clusterStatus *api.ClusterStatus - region string - planMode bool -} - -// Deploy deploys VPC controller to the specified cluster -func (v *VPCController) Deploy() (err error) { - defer func() { - if r := recover(); r != nil { - if ae, ok := r.(*assetutil.Error); ok { - err = ae - } else { - panic(r) - } - } - }() - - if err := v.deployVPCResourceController(); err != nil { - return err - } - - if err := v.generateCert(); err != nil { - return err - } - - return v.deployVPCWebhook() -} - -type typeAssertionError struct { - expected interface{} - got interface{} -} - -func (t *typeAssertionError) Error() string { - return fmt.Sprintf("expected type to be %T; got %T", t.expected, t.got) -} - -func (v *VPCController) generateCert() error { - var ( - csrName = fmt.Sprintf("%s.%s", webhookServiceName, vpcControllerNamespace) - csrClientSet = v.rawClient.ClientSet().CertificatesV1beta1().CertificateSigningRequests() - ) - - hasApprovedCert, err := v.hasApprovedCert() - if err != nil { - return err - } - if hasApprovedCert { - // Delete existing CSR if the secret is missing - _, err := v.rawClient.ClientSet().CoreV1().Secrets(vpcControllerNamespace).Get(context.TODO(), "vpc-admission-webhook-certs", metav1.GetOptions{}) - if err != nil { - if !apierrors.IsNotFound(err) { - return err - } - if err := csrClientSet.Delete(context.TODO(), csrName, metav1.DeleteOptions{}); err != nil { - return err - } - } - return nil - } - - csrPEM, privateKey, err := generateCertReq(webhookServiceName, vpcControllerNamespace) - if err != nil { - return errors.Wrap(err, "generating CSR") - } - - manifest := assetutil.MustLoad(vpcAdmissionWebhookCsrYamlBytes) - rawExtension, err := kubernetes.NewRawExtension(manifest) - if err != nil { - return err - } - - certificateSigningRequest, ok := rawExtension.Object.(*certsv1beta1.CertificateSigningRequest) - if !ok { - return &typeAssertionError{&certsv1beta1.CertificateSigningRequest{}, rawExtension.Object} - } - - certificateSigningRequest.Spec.Request = csrPEM - certificateSigningRequest.Name = csrName - - if err := v.applyRawResource(certificateSigningRequest); err != nil { - return errors.Wrap(err, "creating CertificateSigningRequest") - } - - certificateSigningRequest.Status.Conditions = []certsv1beta1.CertificateSigningRequestCondition{ - { - Type: certsv1beta1.CertificateApproved, - LastUpdateTime: metav1.NewTime(time.Now()), - Message: "This CSR was approved by eksctl", - Reason: "eksctl-approve", - }, - } - - if _, err := csrClientSet.UpdateApproval(context.TODO(), certificateSigningRequest, metav1.UpdateOptions{}); err != nil { - return errors.Wrap(err, "updating approval") - } - - logger.Info("waiting for certificate to be available") - - cert, err := watchCSRApproval(csrClientSet, csrName, certWaitTimeout) - if err != nil { - return err - } - - return v.createCertSecrets(privateKey, cert) -} - -func watchCSRApproval(csrClientSet v1beta1.CertificateSigningRequestInterface, csrName string, timeout time.Duration) ([]byte, error) { - watcher, err := csrClientSet.Watch(context.TODO(), metav1.ListOptions{ - FieldSelector: fmt.Sprintf("metadata.name=%s", csrName), - }) - - if err != nil { - return nil, err - } - - defer watcher.Stop() - - timer := time.NewTimer(timeout) - defer timer.Stop() - - for { - select { - case event, ok := <-watcher.ResultChan(): - if !ok { - return nil, errors.New("failed waiting for certificate: unexpected close of ResultChan") - } - switch event.Type { - case watch.Added, watch.Modified: - req := event.Object.(*certsv1beta1.CertificateSigningRequest) - if cert := req.Status.Certificate; cert != nil { - return cert, nil - } - logger.Warning("certificate not yet available (event: %s)", event.Type) - } - case <-timer.C: - return nil, fmt.Errorf("timed out (after %v) waiting for certificate", timeout) - } - - } -} - -func (v *VPCController) createCertSecrets(key, cert []byte) error { - secret := &corev1.Secret{ - TypeMeta: metav1.TypeMeta{ - Kind: "secret", - APIVersion: "v1", - }, - ObjectMeta: metav1.ObjectMeta{ - Name: "vpc-admission-webhook-certs", - Namespace: vpcControllerNamespace, - }, - Data: map[string][]byte{ - "key.pem": key, - "cert.pem": cert, - }, - } - - err := v.applyRawResource(secret) - if err != nil { - return errors.Wrap(err, "error creating secret") - } - return err + RawClient kubernetes.RawClientInterface } -func makePolicyDocument() map[string]interface{} { - return map[string]interface{}{ - "Version": "2012-10-17", - "Statement": []map[string]interface{}{ - { - "Effect": "Allow", - "Action": []string{ - "ec2:AssignPrivateIpAddresses", - "ec2:DescribeInstances", - "ec2:DescribeNetworkInterfaces", - "ec2:UnassignPrivateIpAddresses", - "ec2:DescribeRouteTables", - "ec2:DescribeSubnets", - }, - "Resource": "*", - }, - }, - } -} - -func (v *VPCController) deployVPCResourceController() error { - irsaEnabled, err := v.irsa.IsSupported() +// Delete deletes the resources for VPC controller. +func (v *VPCController) Delete() error { + vpcControllerMetadata, err := vpcControllerMetadataYamlBytes() if err != nil { - return err + return errors.Wrap(err, "unexpected error loading manifests") } - if irsaEnabled { - sa := &api.ClusterIAMServiceAccount{ - ClusterIAMMeta: api.ClusterIAMMeta{ - Name: vpcControllerName, - Namespace: vpcControllerNamespace, - }, - AttachPolicy: makePolicyDocument(), - } - if err := v.irsa.CreateOrUpdate(sa); err != nil { - return errors.Wrap(err, "error enabling IRSA") - } - } else { - // If an OIDC provider isn't associated with the cluster, the VPC controller relies on the managed policy - // attached to the node role for the AWS VPC CNI plugin. - sa := kubernetes.NewServiceAccount(metav1.ObjectMeta{ - Name: vpcControllerName, - Namespace: vpcControllerNamespace, - }) - if err := v.applyRawResource(sa); err != nil { - return err - } - } - if err := v.applyResources(assetutil.MustLoad(vpcResourceControllerYamlBytes)); err != nil { - return err - } - - return v.applyDeployment(assetutil.MustLoad(vpcResourceControllerDepYamlBytes)) -} - -func (v *VPCController) deployVPCWebhook() error { - if err := v.applyResources(assetutil.MustLoad(vpcAdmissionWebhookYamlBytes)); err != nil { - return err - } - if err := v.applyDeployment(assetutil.MustLoad(vpcAdmissionWebhookDepYamlBytes)); err != nil { - return err - } - - manifest := assetutil.MustLoad(vpcAdmissionWebhookConfigYamlBytes) - rawExtension, err := kubernetes.NewRawExtension(manifest) - if err != nil { - return err - } - - mutatingWebhook, ok := rawExtension.Object.(*admv1beta1.MutatingWebhookConfiguration) - if !ok { - return &typeAssertionError{&admv1beta1.MutatingWebhookConfiguration{}, rawExtension.Object} - } - - mutatingWebhook.Webhooks[0].ClientConfig.CABundle = v.clusterStatus.CertificateAuthorityData - return v.applyRawResource(rawExtension.Object) -} - -func (v *VPCController) hasApprovedCert() (bool, error) { - csrClientSet := v.rawClient.ClientSet().CertificatesV1beta1().CertificateSigningRequests() - request, err := csrClientSet.Get(context.TODO(), fmt.Sprintf("%s.%s", webhookServiceName, vpcControllerNamespace), metav1.GetOptions{}) + list, err := kubernetes.NewList(vpcControllerMetadata) if err != nil { - if !apierrors.IsNotFound(err) { - return false, err - } - return false, nil + return errors.Wrap(err, "unexpected error parsing manifests") } - - conditions := request.Status.Conditions - switch len(conditions) { - case 1: - if conditions[0].Type == certsv1beta1.CertificateApproved { - return true, nil - } - return false, fmt.Errorf("expected certificate to be approved; got %q", conditions[0].Type) - - case 0: - return false, nil - default: - return false, fmt.Errorf("unexpected number of request conditions: %d", len(conditions)) - } -} - -func (v *VPCController) applyResources(manifests []byte) error { - list, err := kubernetes.NewList(manifests) - if err != nil { - return err - } - for _, item := range list.Items { - if err := v.applyRawResource(item.Object); err != nil { + if err := v.deleteResource(item.Object); err != nil { return err } } return nil } -func (v *VPCController) applyDeployment(manifests []byte) error { - rawExtension, err := kubernetes.NewRawExtension(manifests) - if err != nil { - return err - } - - deployment, ok := rawExtension.Object.(*appsv1.Deployment) - if !ok { - return &typeAssertionError{&appsv1.Deployment{}, rawExtension.Object} - } - if err := UseRegionalImage(&deployment.Spec.Template, v.region); err != nil { - return err - } - return v.applyRawResource(rawExtension.Object) -} - -func (v *VPCController) applyRawResource(object runtime.Object) error { - rawResource, err := v.rawClient.NewRawResource(object) +func (v *VPCController) deleteResource(o runtime.Object) error { + r, err := v.RawClient.NewRawResource(o) if err != nil { - return err + return errors.Wrap(err, "unexpected error creating raw resource") } - - switch newObject := object.(type) { - case *corev1.Service: - r, found, err := rawResource.Get() - if err != nil { - return err - } - if found { - service, ok := r.(*corev1.Service) - if !ok { - return &typeAssertionError{&corev1.Service{}, r} - } - newObject.Spec.ClusterIP = service.Spec.ClusterIP - newObject.SetResourceVersion(service.GetResourceVersion()) - } - case *admv1beta1.MutatingWebhookConfiguration: - r, found, err := rawResource.Get() - if err != nil { - return err - } - if found { - mwc, ok := r.(*admv1beta1.MutatingWebhookConfiguration) - if !ok { - return &typeAssertionError{&admv1beta1.MutatingWebhookConfiguration{}, r} - } - newObject.SetResourceVersion(mwc.GetResourceVersion()) - } - } - - msg, err := rawResource.CreateOrReplace(v.planMode) + msg, err := r.DeleteSync() if err != nil { - return err + return errors.Wrapf(err, "error deleting resource %q", r.Info.String()) } logger.Info(msg) return nil } - -func generateCertReq(service, namespace string) ([]byte, []byte, error) { - generator := csr.Generator{ - Validator: func(request *csr.CertificateRequest) error { - // ignore validation as all required fields are being set - return nil - }, - } - - serviceCN := fmt.Sprintf("%s.%s.svc", service, namespace) - - return generator.ProcessRequest(&csr.CertificateRequest{ - KeyRequest: &csr.KeyRequest{ - A: "rsa", - S: 2048, - }, - CN: serviceCN, - Hosts: []string{ - service, - fmt.Sprintf("%s.%s", service, namespace), - serviceCN, - }, - }) -} diff --git a/pkg/ctl/utils/install_vpc_controllers.go b/pkg/ctl/utils/install_vpc_controllers.go index 79e3893844..36c7d44fb7 100644 --- a/pkg/ctl/utils/install_vpc_controllers.go +++ b/pkg/ctl/utils/install_vpc_controllers.go @@ -17,12 +17,15 @@ func installWindowsVPCController(cmd *cmdutils.Cmd) { cmd.SetDescription("install-vpc-controllers", "Install Windows VPC controller to support running Windows workloads", "") + var deleteController bool + cmd.CobraCommand.RunE = func(_ *cobra.Command, args []string) error { cmd.NameArg = cmdutils.GetNameArg(args) - return doInstallWindowsVPCController(cmd) + return doInstallWindowsVPCController(cmd, deleteController) } cmd.FlagSetGroup.InFlagSet("General", func(fs *pflag.FlagSet) { + fs.BoolVar(&deleteController, "delete", false, "Deletes VPC resource controller from worker nodes") cmdutils.AddClusterFlagWithDeprecated(fs, cfg.Metadata) cmdutils.AddRegionFlag(fs, &cmd.ProviderConfig) cmdutils.AddConfigFileFlag(fs, &cmd.ClusterConfigFile) @@ -33,33 +36,36 @@ func installWindowsVPCController(cmd *cmdutils.Cmd) { cmdutils.AddCommonFlagsForAWS(cmd.FlagSetGroup, &cmd.ProviderConfig, false) } -func doInstallWindowsVPCController(cmd *cmdutils.Cmd) error { +func doInstallWindowsVPCController(cmd *cmdutils.Cmd, deleteController bool) error { + if !deleteController { + logger.Warning("you no longer need to install the VPC resource controller on Linux worker nodes to run " + + "Windows workloads in EKS clusters. You can enable Windows IP address management on the EKS control plane via " + + "a ConfigMap setting (see https://todo.com for details). eksctl will automatically patch the ConfigMap to enable " + + "Windows IP address management when a Windows nodegroup is created. For existing clusters, you can enable it manually " + + "and re-run this command with the --delete flag to remove the worker node installation of the VPC resource controller") + return nil + } + if err := cmdutils.NewMetadataLoader(cmd).Load(); err != nil { return err } - cfg := cmd.ClusterConfig - meta := cmd.ClusterConfig.Metadata - ctl, err := cmd.NewProviderForExistingCluster() if err != nil { return err } - logger.Info("using region %s", meta.Region) - - if ok, err := ctl.CanUpdate(cfg); !ok { + logger.Info("using region %s", cmd.ClusterConfig.Metadata.Region) + rawClient, err := ctl.NewRawClient(cmd.ClusterConfig) + if err != nil { return err } - - vpcControllerTask := &eks.VPCControllerTask{ - Info: "install Windows VPC controller", - ClusterConfig: cfg, - ClusterProvider: ctl, - PlanMode: cmd.Plan, + deleteControllerTask := &eks.DeleteVPCControllerTask{ + Info: "delete Windows VPC controller", + RawClient: rawClient, } taskTree := &tasks.TaskTree{ - Tasks: []tasks.Task{vpcControllerTask}, + Tasks: []tasks.Task{deleteControllerTask}, } if errs := taskTree.DoAllSync(); len(errs) > 0 { diff --git a/pkg/eks/tasks.go b/pkg/eks/tasks.go index b457a8b22a..2db32a1328 100644 --- a/pkg/eks/tasks.go +++ b/pkg/eks/tasks.go @@ -6,11 +6,9 @@ import ( "time" "github.com/weaveworks/eksctl/pkg/actions/identityproviders" - "github.com/weaveworks/eksctl/pkg/actions/irsa" "github.com/kris-nova/logger" "github.com/pkg/errors" - "github.com/weaveworks/eksctl/pkg/cfn/manager" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" "k8s.io/apimachinery/pkg/runtime" @@ -40,44 +38,25 @@ func (t *clusterConfigTask) Do(errs chan error) error { return err } -// VPCControllerTask represents a task to install the VPC controller -type VPCControllerTask struct { - Info string - ClusterProvider *ClusterProvider - ClusterConfig *api.ClusterConfig - PlanMode bool +// DeleteVPCControllerTask is a task for deleting VPC controller resources. +type DeleteVPCControllerTask struct { + RawClient kubernetes.RawClientInterface + Info string } -// Describe implements Task -func (v *VPCControllerTask) Describe() string { return v.Info } - -// Do implements Task -func (v *VPCControllerTask) Do(errCh chan error) error { +// Do implements Task. +func (v *DeleteVPCControllerTask) Do(errCh chan error) error { defer close(errCh) - rawClient, err := v.ClusterProvider.NewRawClient(v.ClusterConfig) - if err != nil { - return err - } - oidc, err := v.ClusterProvider.NewOpenIDConnectManager(v.ClusterConfig) - if err != nil { - return err - } - stackCollection := manager.NewStackCollection(v.ClusterProvider.Provider, v.ClusterConfig) - - clientSet, err := v.ClusterProvider.NewStdClientSet(v.ClusterConfig) - if err != nil { - return err + vpcController := &addons.VPCController{ + RawClient: v.RawClient, } - irsaManager := irsa.New(v.ClusterConfig.Metadata.Name, stackCollection, oidc, clientSet) - irsa := addons.NewIRSAHelper(oidc, stackCollection, irsaManager, v.ClusterConfig.Metadata.Name) + return vpcController.Delete() +} - // TODO PlanMode doesn't work as intended - vpcController := addons.NewVPCController(rawClient, irsa, v.ClusterConfig.Status, v.ClusterProvider.Provider.Region(), v.PlanMode) - if err := vpcController.Deploy(); err != nil { - return errors.Wrap(err, "error installing VPC controller") - } - return nil +// Describe implements Task. +func (v *DeleteVPCControllerTask) Describe() string { + return v.Info } type devicePluginTask struct { @@ -188,7 +167,7 @@ func (t *restartDaemonsetTask) Do(errCh chan error) error { } // CreateExtraClusterConfigTasks returns all tasks for updating cluster configuration not depending on the control plane availability -func (c *ClusterProvider) CreateExtraClusterConfigTasks(cfg *api.ClusterConfig, installVPCController bool) *tasks.TaskTree { +func (c *ClusterProvider) CreateExtraClusterConfigTasks(cfg *api.ClusterConfig, enableWindowsSupport bool) *tasks.TaskTree { newTasks := &tasks.TaskTree{ Parallel: false, IsSubTask: true, @@ -254,11 +233,12 @@ func (c *ClusterProvider) CreateExtraClusterConfigTasks(cfg *api.ClusterConfig, newTasks.Append(identityproviders.NewAssociateProvidersTask(*cfg.Metadata, cfg.IdentityProviders, c.Provider.EKS())) } - if installVPCController { - newTasks.Append(&VPCControllerTask{ - Info: "install Windows VPC controller", - ClusterConfig: cfg, - ClusterProvider: c, + if enableWindowsSupport { + newTasks.Append(&WindowsIPAMTask{ + Info: "enable Windows IP address management", + ClientsetFunc: func() (kubernetes.Interface, error) { + return c.NewStdClientSet(cfg) + }, }) } From 9258b734c8b48e9769620cef9772713e8a22e940 Mon Sep 17 00:00:00 2001 From: cpu1 Date: Thu, 14 Oct 2021 15:36:55 +0530 Subject: [PATCH 009/124] Enable Windows IPAM when creating a Windows nodegroup --- pkg/actions/nodegroup/create.go | 9 +++ pkg/apis/eksctl.io/v1alpha5/nodegroups.go | 10 +++ pkg/ctl/create/cluster.go | 7 +- pkg/eks/tasks.go | 26 +++++++ pkg/windows/ipam.go | 93 +++++++++++++++++++++++ 5 files changed, 144 insertions(+), 1 deletion(-) create mode 100644 pkg/windows/ipam.go diff --git a/pkg/actions/nodegroup/create.go b/pkg/actions/nodegroup/create.go index 57205cc409..77cc8bbb75 100644 --- a/pkg/actions/nodegroup/create.go +++ b/pkg/actions/nodegroup/create.go @@ -160,6 +160,15 @@ func (m *Manager) nodeCreationTasks(options CreateOpts, nodegroupFilter filter.N taskTree.Append(m.stackManager.NewClusterCompatTask()) } + if m.cfg.HasWindowsNodeGroup() { + taskTree.Append(&eks.WindowsIPAMTask{ + Info: "enable Windows IPAM", + ClientsetFunc: func() (kubernetes.Interface, error) { + return m.ctl.NewStdClientSet(m.cfg) + }, + }) + } + awsNodeUsesIRSA, err := init.DoesAWSNodeUseIRSA(m.ctl.Provider, m.clientSet) if err != nil { return errors.Wrap(err, "couldn't check aws-node for annotation") diff --git a/pkg/apis/eksctl.io/v1alpha5/nodegroups.go b/pkg/apis/eksctl.io/v1alpha5/nodegroups.go index 00382c7ca2..548c6d5928 100644 --- a/pkg/apis/eksctl.io/v1alpha5/nodegroups.go +++ b/pkg/apis/eksctl.io/v1alpha5/nodegroups.go @@ -78,3 +78,13 @@ func (c *ClusterConfig) AllNodeGroups() []*NodeGroupBase { } return baseNodeGroups } + +// HasWindowsNodeGroup returns true if an unmanaged Windows nodegroup exists. +func (c *ClusterConfig) HasWindowsNodeGroup() bool { + for _, ng := range c.NodeGroups { + if IsWindowsImage(ng.AMIFamily) { + return true + } + } + return false +} diff --git a/pkg/ctl/create/cluster.go b/pkg/ctl/create/cluster.go index f3d96d66f1..4b6b163e39 100644 --- a/pkg/ctl/create/cluster.go +++ b/pkg/ctl/create/cluster.go @@ -190,6 +190,11 @@ func doCreateCluster(cmd *cmdutils.Cmd, ngFilter *filter.NodeGroupFilter, params if !eks.SupportsWindowsWorkloads(kubeNodeGroups) { return errors.New("running Windows workloads requires having both Windows and Linux (AmazonLinux2) node groups") } + logger.Warning("you no longer need to install the VPC resource controller on Linux worker nodes to run " + + "Windows workloads in EKS clusters. You can enable Windows IP address management on the EKS control plane via " + + "a ConfigMap setting (see https://todo.com for details). eksctl will automatically patch the ConfigMap to enable " + + "Windows IP address management when a Windows nodegroup is created. For existing clusters, you can enable it manually " + + "and re-run this command with the --delete flag to remove the worker node installation of the VPC resource controller") } else { eks.LogWindowsCompatibility(kubeNodeGroups, cfg.Metadata) } @@ -248,7 +253,7 @@ func doCreateCluster(cmd *cmdutils.Cmd, ngFilter *filter.NodeGroupFilter, params if err != nil { return err } - postClusterCreationTasks := ctl.CreateExtraClusterConfigTasks(cfg, params.InstallWindowsVPCController) + postClusterCreationTasks := ctl.CreateExtraClusterConfigTasks(cfg, eks.SupportsWindowsWorkloads(kubeNodeGroups)) supported, err := utils.IsMinVersion(api.Version1_18, cfg.Metadata.Version) if err != nil { diff --git a/pkg/eks/tasks.go b/pkg/eks/tasks.go index 2db32a1328..47ba733b46 100644 --- a/pkg/eks/tasks.go +++ b/pkg/eks/tasks.go @@ -6,6 +6,7 @@ import ( "time" "github.com/weaveworks/eksctl/pkg/actions/identityproviders" + "github.com/weaveworks/eksctl/pkg/windows" "github.com/kris-nova/logger" "github.com/pkg/errors" @@ -38,6 +39,31 @@ func (t *clusterConfigTask) Do(errs chan error) error { return err } +// WindowsIPAMTask is a task for enabling Windows IPAM. +type WindowsIPAMTask struct { + Info string + ClientsetFunc func() (kubernetes.Interface, error) +} + +// Do implements Task. +func (w *WindowsIPAMTask) Do(errCh chan error) error { + defer close(errCh) + + clientset, err := w.ClientsetFunc() + if err != nil { + return err + } + windowsIPAM := windows.IPAM{ + Clientset: clientset, + } + return windowsIPAM.Enable(context.TODO()) +} + +// Describe implements Task. +func (w *WindowsIPAMTask) Describe() string { + return w.Info +} + // DeleteVPCControllerTask is a task for deleting VPC controller resources. type DeleteVPCControllerTask struct { RawClient kubernetes.RawClientInterface diff --git a/pkg/windows/ipam.go b/pkg/windows/ipam.go new file mode 100644 index 0000000000..a09b5a9b5f --- /dev/null +++ b/pkg/windows/ipam.go @@ -0,0 +1,93 @@ +package windows + +import ( + "context" + "encoding/json" + + "github.com/kris-nova/logger" + + "k8s.io/apimachinery/pkg/types" + + jsonpatch "github.com/evanphx/json-patch/v5" + + corev1client "k8s.io/client-go/kubernetes/typed/core/v1" + + corev1 "k8s.io/api/core/v1" + + apierrors "k8s.io/apimachinery/pkg/api/errors" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + + "github.com/pkg/errors" + + "k8s.io/client-go/kubernetes" +) + +const ( + vpcCNIName = "amazon-vpc-cni" + vpcCNINamespace = metav1.NamespaceSystem + windowsIPAMField = "enable-windows-ipam" +) + +// IPAM enables Windows IPAM +type IPAM struct { + Clientset kubernetes.Interface +} + +// Enable enables Windows IPAM +func (w *IPAM) Enable(ctx context.Context) error { + configMaps := w.Clientset.CoreV1().ConfigMaps(metav1.NamespaceSystem) + vpcCNIConfig, err := configMaps.Get(ctx, vpcCNIName, metav1.GetOptions{}) + if err != nil { + if !apierrors.IsNotFound(err) { + return errors.Wrap(err, "error getting resource") + } + return createConfigMap(ctx, configMaps) + } + + if val, ok := vpcCNIConfig.Data[windowsIPAMField]; ok && val == "true" { + logger.Info("Windows IPAM is already enabled") + return nil + } + + patch, err := createPatch(vpcCNIConfig) + if err != nil { + return errors.Wrap(err, "error creating merge patch") + } + + _, err = configMaps.Patch(ctx, vpcCNIName, types.StrategicMergePatchType, patch, metav1.PatchOptions{}) + if err != nil { + return errors.Wrap(err, "failed to patch resource") + } + return nil +} + +func createPatch(cm *corev1.ConfigMap) ([]byte, error) { + oldData, err := json.Marshal(cm) + if err != nil { + return nil, err + } + cm.Data[windowsIPAMField] = "true" + modifiedData, err := json.Marshal(cm) + if err != nil { + return nil, err + } + return jsonpatch.CreateMergePatch(oldData, modifiedData) +} + +func createConfigMap(ctx context.Context, configMaps corev1client.ConfigMapInterface) error { + cm := &corev1.ConfigMap{ + TypeMeta: metav1.TypeMeta{ + Kind: "ConfigMap", + APIVersion: "v1", + }, + ObjectMeta: metav1.ObjectMeta{ + Name: vpcCNIName, + Namespace: vpcCNINamespace, + }, + Data: map[string]string{ + windowsIPAMField: "true", + }, + } + _, err := configMaps.Create(ctx, cm, metav1.CreateOptions{}) + return err +} From 92aefb3312863d43160d97288bd656f57f2853f1 Mon Sep 17 00:00:00 2001 From: cpu1 Date: Thu, 14 Oct 2021 16:39:49 +0530 Subject: [PATCH 010/124] Handle plan mode, deprecate command --- pkg/addons/vpc_controller.go | 16 +++++++++++----- pkg/ctl/create/cluster.go | 12 ++++++------ pkg/ctl/utils/install_vpc_controllers.go | 9 ++++----- pkg/eks/tasks.go | 8 +++++--- pkg/kubernetes/client.go | 7 +++++-- pkg/kubernetes/client_test.go | 2 +- 6 files changed, 32 insertions(+), 22 deletions(-) diff --git a/pkg/addons/vpc_controller.go b/pkg/addons/vpc_controller.go index f1cbf5f2d6..e6f9e059a3 100644 --- a/pkg/addons/vpc_controller.go +++ b/pkg/addons/vpc_controller.go @@ -5,17 +5,21 @@ import ( "github.com/pkg/errors" "github.com/weaveworks/eksctl/pkg/kubernetes" - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" ) const ( - vpcControllerNamespace = metav1.NamespaceSystem + VPCControllerInfoMessage = "you no longer need to install the VPC resource controller on Linux worker nodes to run " + + "Windows workloads in EKS clusters. You can enable Windows IP address management on the EKS control plane via " + + "a ConfigMap setting (see https://todo.com for details). eksctl will automatically patch the ConfigMap to enable " + + "Windows IP address management when a Windows nodegroup is created. For existing clusters, you can enable it manually " + + "and run `eksctl utils install-vpc-controllers` with the --delete flag to remove the worker node installation of the VPC resource controller" ) // VPCController deletes an existing installation of VPC controller from worker nodes. type VPCController struct { - RawClient kubernetes.RawClientInterface + RawClient *kubernetes.RawClient + PlanMode bool } // Delete deletes the resources for VPC controller. @@ -41,10 +45,12 @@ func (v *VPCController) deleteResource(o runtime.Object) error { if err != nil { return errors.Wrap(err, "unexpected error creating raw resource") } - msg, err := r.DeleteSync() + msg, err := r.DeleteSync(v.PlanMode) if err != nil { return errors.Wrapf(err, "error deleting resource %q", r.Info.String()) } - logger.Info(msg) + if msg != "" { + logger.Info(msg) + } return nil } diff --git a/pkg/ctl/create/cluster.go b/pkg/ctl/create/cluster.go index 4b6b163e39..45fbb32e77 100644 --- a/pkg/ctl/create/cluster.go +++ b/pkg/ctl/create/cluster.go @@ -6,6 +6,8 @@ import ( "os" "strings" + "github.com/weaveworks/eksctl/pkg/addons" + "github.com/aws/amazon-ec2-instance-selector/v2/pkg/selector" "github.com/weaveworks/eksctl/pkg/kops" "github.com/weaveworks/eksctl/pkg/utils" @@ -71,6 +73,8 @@ func createClusterCmdWithRunFunc(cmd *cmdutils.Cmd, runFunc func(cmd *cmdutils.C fs.BoolVarP(¶ms.InstallWindowsVPCController, "install-vpc-controllers", "", false, "Install VPC controller that's required for Windows workloads") fs.BoolVarP(¶ms.Fargate, "fargate", "", false, "Create a Fargate profile scheduling pods in the default and kube-system namespaces onto Fargate") fs.BoolVarP(¶ms.DryRun, "dry-run", "", false, "Dry-run mode that skips cluster creation and outputs a ClusterConfig") + + _ = fs.MarkDeprecated("install-vpc-controllers", addons.VPCControllerInfoMessage) }) cmd.FlagSetGroup.InFlagSet("Initial nodegroup", func(fs *pflag.FlagSet) { @@ -190,11 +194,7 @@ func doCreateCluster(cmd *cmdutils.Cmd, ngFilter *filter.NodeGroupFilter, params if !eks.SupportsWindowsWorkloads(kubeNodeGroups) { return errors.New("running Windows workloads requires having both Windows and Linux (AmazonLinux2) node groups") } - logger.Warning("you no longer need to install the VPC resource controller on Linux worker nodes to run " + - "Windows workloads in EKS clusters. You can enable Windows IP address management on the EKS control plane via " + - "a ConfigMap setting (see https://todo.com for details). eksctl will automatically patch the ConfigMap to enable " + - "Windows IP address management when a Windows nodegroup is created. For existing clusters, you can enable it manually " + - "and re-run this command with the --delete flag to remove the worker node installation of the VPC resource controller") + logger.Warning(addons.VPCControllerInfoMessage) } else { eks.LogWindowsCompatibility(kubeNodeGroups, cfg.Metadata) } @@ -253,7 +253,7 @@ func doCreateCluster(cmd *cmdutils.Cmd, ngFilter *filter.NodeGroupFilter, params if err != nil { return err } - postClusterCreationTasks := ctl.CreateExtraClusterConfigTasks(cfg, eks.SupportsWindowsWorkloads(kubeNodeGroups)) + postClusterCreationTasks := ctl.CreateExtraClusterConfigTasks(cfg) supported, err := utils.IsMinVersion(api.Version1_18, cfg.Metadata.Version) if err != nil { diff --git a/pkg/ctl/utils/install_vpc_controllers.go b/pkg/ctl/utils/install_vpc_controllers.go index 36c7d44fb7..1306f64e5e 100644 --- a/pkg/ctl/utils/install_vpc_controllers.go +++ b/pkg/ctl/utils/install_vpc_controllers.go @@ -4,6 +4,7 @@ import ( "github.com/kris-nova/logger" "github.com/spf13/cobra" "github.com/spf13/pflag" + "github.com/weaveworks/eksctl/pkg/addons" "github.com/weaveworks/eksctl/pkg/eks" "github.com/weaveworks/eksctl/pkg/utils/tasks" @@ -16,6 +17,7 @@ func installWindowsVPCController(cmd *cmdutils.Cmd) { cmd.ClusterConfig = cfg cmd.SetDescription("install-vpc-controllers", "Install Windows VPC controller to support running Windows workloads", "") + cmd.CobraCommand.Deprecated = addons.VPCControllerInfoMessage var deleteController bool @@ -38,11 +40,7 @@ func installWindowsVPCController(cmd *cmdutils.Cmd) { func doInstallWindowsVPCController(cmd *cmdutils.Cmd, deleteController bool) error { if !deleteController { - logger.Warning("you no longer need to install the VPC resource controller on Linux worker nodes to run " + - "Windows workloads in EKS clusters. You can enable Windows IP address management on the EKS control plane via " + - "a ConfigMap setting (see https://todo.com for details). eksctl will automatically patch the ConfigMap to enable " + - "Windows IP address management when a Windows nodegroup is created. For existing clusters, you can enable it manually " + - "and re-run this command with the --delete flag to remove the worker node installation of the VPC resource controller") + logger.Warning(addons.VPCControllerInfoMessage) return nil } @@ -61,6 +59,7 @@ func doInstallWindowsVPCController(cmd *cmdutils.Cmd, deleteController bool) err } deleteControllerTask := &eks.DeleteVPCControllerTask{ Info: "delete Windows VPC controller", + PlanMode: cmd.Plan, RawClient: rawClient, } diff --git a/pkg/eks/tasks.go b/pkg/eks/tasks.go index 47ba733b46..b749d07170 100644 --- a/pkg/eks/tasks.go +++ b/pkg/eks/tasks.go @@ -66,7 +66,8 @@ func (w *WindowsIPAMTask) Describe() string { // DeleteVPCControllerTask is a task for deleting VPC controller resources. type DeleteVPCControllerTask struct { - RawClient kubernetes.RawClientInterface + RawClient *kubernetes.RawClient + PlanMode bool Info string } @@ -76,6 +77,7 @@ func (v *DeleteVPCControllerTask) Do(errCh chan error) error { vpcController := &addons.VPCController{ RawClient: v.RawClient, + PlanMode: v.PlanMode, } return vpcController.Delete() } @@ -193,7 +195,7 @@ func (t *restartDaemonsetTask) Do(errCh chan error) error { } // CreateExtraClusterConfigTasks returns all tasks for updating cluster configuration not depending on the control plane availability -func (c *ClusterProvider) CreateExtraClusterConfigTasks(cfg *api.ClusterConfig, enableWindowsSupport bool) *tasks.TaskTree { +func (c *ClusterProvider) CreateExtraClusterConfigTasks(cfg *api.ClusterConfig) *tasks.TaskTree { newTasks := &tasks.TaskTree{ Parallel: false, IsSubTask: true, @@ -259,7 +261,7 @@ func (c *ClusterProvider) CreateExtraClusterConfigTasks(cfg *api.ClusterConfig, newTasks.Append(identityproviders.NewAssociateProvidersTask(*cfg.Metadata, cfg.IdentityProviders, c.Provider.EKS())) } - if enableWindowsSupport { + if cfg.HasWindowsNodeGroup() { newTasks.Append(&WindowsIPAMTask{ Info: "enable Windows IP address management", ClientsetFunc: func() (kubernetes.Interface, error) { diff --git a/pkg/kubernetes/client.go b/pkg/kubernetes/client.go index 10b7bf2a3e..cd6494264a 100644 --- a/pkg/kubernetes/client.go +++ b/pkg/kubernetes/client.go @@ -245,7 +245,7 @@ func (c *RawClient) deleteObject(object runtime.RawExtension) error { if err != nil { return err } - status, err := resource.DeleteSync() + status, err := resource.DeleteSync(false) if err != nil { return err } @@ -415,7 +415,7 @@ func (r *RawResource) CreatePatchOrReplace() error { // DeleteSync attempts to delete this Kubernetes resource, or returns doing // nothing if it does not exist. It blocks until the resource has been deleted. -func (r *RawResource) DeleteSync() (string, error) { +func (r *RawResource) DeleteSync(plan bool) (string, error) { _, exists, err := r.Get() if err != nil { return "", err @@ -423,6 +423,9 @@ func (r *RawResource) DeleteSync() (string, error) { if !exists { return "", nil } + if plan { + return r.LogAction(true, "deleted"), nil + } propagationPolicy := metav1.DeletePropagationForeground if _, err := r.Helper.DeleteWithOptions(r.Info.Namespace, r.Info.Name, &metav1.DeleteOptions{ PropagationPolicy: &propagationPolicy, diff --git a/pkg/kubernetes/client_test.go b/pkg/kubernetes/client_test.go index aa037e04ef..5a553a9a77 100644 --- a/pkg/kubernetes/client_test.go +++ b/pkg/kubernetes/client_test.go @@ -243,7 +243,7 @@ var _ = Describe("Kubernetes client wrappers", func() { Expect(err).ToNot(HaveOccurred()) Expect(exists).To(BeTrue()) // The Kubernetes resource already exists. - status, err := rc.DeleteSync() + status, err := rc.DeleteSync(false) Expect(err).ToNot(HaveOccurred()) Expect(status).To(Equal(fmt.Sprintf("deleted %q", rc))) Expect(track).ToNot(BeNil()) From 5439eadd289caf688d0ed5a385b119e9cdaf299d Mon Sep 17 00:00:00 2001 From: cpu1 Date: Thu, 14 Oct 2021 16:42:27 +0530 Subject: [PATCH 011/124] Remove deprecated flag from integration test --- integration/tests/windows/windows_test.go | 1 - 1 file changed, 1 deletion(-) diff --git a/integration/tests/windows/windows_test.go b/integration/tests/windows/windows_test.go index 67b08e1994..298726b343 100644 --- a/integration/tests/windows/windows_test.go +++ b/integration/tests/windows/windows_test.go @@ -70,7 +70,6 @@ var _ = Describe("(Integration) [Windows Nodegroups]", func() { "--config-file", "-", "--verbose", "4", "--kubeconfig", params.KubeconfigPath, - "--install-vpc-controllers", ). WithoutArg("--region", params.Region). WithStdin(bytes.NewReader(data)) From 384a7aeb03bb09ae087c018777b6621eb82905d5 Mon Sep 17 00:00:00 2001 From: cpu1 Date: Thu, 14 Oct 2021 16:56:24 +0530 Subject: [PATCH 012/124] Update docs and example --- examples/14-windows-nodes.yaml | 4 +++- userdocs/src/usage/windows-worker-nodes.md | 17 +++++++++++------ 2 files changed, 14 insertions(+), 7 deletions(-) diff --git a/examples/14-windows-nodes.yaml b/examples/14-windows-nodes.yaml index 59dcb25f5f..698247685c 100644 --- a/examples/14-windows-nodes.yaml +++ b/examples/14-windows-nodes.yaml @@ -1,5 +1,5 @@ # An example of ClusterConfig containing Windows and Linux node groups to support Windows workloads -# This example should be run with `eksctl create cluster -f 14-windows-nodes.yaml --install-vpc-controllers` +# This example should be run with `eksctl create cluster -f 14-windows-nodes.yaml` --- apiVersion: eksctl.io/v1alpha5 kind: ClusterConfig @@ -13,6 +13,8 @@ nodeGroups: amiFamily: WindowsServer2019FullContainer minSize: 2 maxSize: 3 + +managedNodeGroups: - name: linux-ng instanceType: t2.large minSize: 2 diff --git a/userdocs/src/usage/windows-worker-nodes.md b/userdocs/src/usage/windows-worker-nodes.md index 96bd63ba20..3a3dce626f 100644 --- a/userdocs/src/usage/windows-worker-nodes.md +++ b/userdocs/src/usage/windows-worker-nodes.md @@ -1,10 +1,15 @@ # Windows Worker Nodes From version 1.14, Amazon EKS supports [Windows Nodes][eks-user-guide] that allow running Windows containers. -In addition to having Windows nodes, a Linux node in the cluster is required to run the VPC resource controller and CoreDNS, as Microsoft doesn't support host-networking mode yet. Thus, a Windows EKS cluster will be a mixed-mode cluster containing Windows nodes and at least one Linux node. +In addition to having Windows nodes, a Linux node in the cluster is required to run CoreDNS, as Microsoft doesn't support host-networking mode yet. Thus, a Windows EKS cluster will be a mixed-mode cluster containing Windows nodes and at least one Linux node. The Linux nodes are critical to the functioning of the cluster, and thus, for a production-grade cluster, it's recommended to have at least two `t2.large` Linux nodes for HA. -`eksctl` provides a flag to install the VPC resource controller as part of cluster creation, and a command to install it after a cluster has been created. +!!!note + You no longer need to install the VPC resource controller on Linux worker nodes to run Windows workloads in EKS clusters. + You can enable Windows IP address management on the EKS control plane via a ConfigMap setting (see https://todo.com for details). + eksctl will automatically patch the ConfigMap to enable Windows IP address management when a Windows nodegroup is created. + For existing clusters, you can enable it manually and run `eksctl utils install-vpc-controllers` with the `--delete` flag + to remove the worker node installation of the VPC resource controller. ## Creating a new Windows cluster @@ -26,6 +31,8 @@ nodeGroups: amiFamily: WindowsServer2019FullContainer minSize: 2 maxSize: 3 + +managedNodeGroups: - name: linux-ng instanceType: t2.large minSize: 2 @@ -33,7 +40,7 @@ nodeGroups: ``` ```console -eksctl create cluster -f cluster.yaml --install-vpc-controllers +eksctl create cluster -f cluster.yaml ``` @@ -42,7 +49,6 @@ To create a new cluster without using a config file, issue the following command ```console eksctl create cluster --managed=false --name=windows-cluster --node-ami-family=WindowsServer2019CoreContainer eksctl create nodegroup --cluster=windows-cluster --node-ami-family=AmazonLinux2 --nodes-min=2 --node-type=t2.large -eksctl utils install-vpc-controllers --cluster=windows-cluster --approve ``` !!!note @@ -50,11 +56,10 @@ eksctl utils install-vpc-controllers --cluster=windows-cluster --approve ## Adding Windows support to an existing Linux cluster -To enable running Windows workloads on an existing cluster with Linux nodes (`AmazonLinux2` AMI family), you need to add a Windows node group and install the Windows VPC controller: +To enable running Windows workloads on an existing cluster with Linux nodes (`AmazonLinux2` AMI family), you need to add a Windows nodegroup. ```console eksctl create nodegroup --managed=false --cluster=existing-cluster --node-ami-family=WindowsServer2019CoreContainer -eksctl utils install-vpc-controllers --cluster=existing-cluster --approve ``` To ensure workloads are scheduled on the right OS, they must have a `nodeSelector` targeting the OS it must run on: From a6da10ab72027b4997b92ddc0a9b5148bfac7e84 Mon Sep 17 00:00:00 2001 From: cpu1 Date: Thu, 14 Oct 2021 18:47:11 +0530 Subject: [PATCH 013/124] Add tests for IPAM, improve error messages --- pkg/windows/ipam.go | 23 ++--- pkg/windows/ipam_test.go | 97 ++++++++++++++++++++++ pkg/windows/windows_suite_test.go | 11 +++ userdocs/src/usage/windows-worker-nodes.md | 4 +- 4 files changed, 118 insertions(+), 17 deletions(-) create mode 100644 pkg/windows/ipam_test.go create mode 100644 pkg/windows/windows_suite_test.go diff --git a/pkg/windows/ipam.go b/pkg/windows/ipam.go index a09b5a9b5f..a2390e0028 100644 --- a/pkg/windows/ipam.go +++ b/pkg/windows/ipam.go @@ -4,22 +4,15 @@ import ( "context" "encoding/json" - "github.com/kris-nova/logger" - - "k8s.io/apimachinery/pkg/types" - jsonpatch "github.com/evanphx/json-patch/v5" - - corev1client "k8s.io/client-go/kubernetes/typed/core/v1" - + "github.com/kris-nova/logger" + "github.com/pkg/errors" corev1 "k8s.io/api/core/v1" - apierrors "k8s.io/apimachinery/pkg/api/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - - "github.com/pkg/errors" - + "k8s.io/apimachinery/pkg/types" "k8s.io/client-go/kubernetes" + corev1client "k8s.io/client-go/kubernetes/typed/core/v1" ) const ( @@ -28,18 +21,18 @@ const ( windowsIPAMField = "enable-windows-ipam" ) -// IPAM enables Windows IPAM +// IPAM enables Windows IPAM in the VPC CNI ConfigMap. type IPAM struct { Clientset kubernetes.Interface } -// Enable enables Windows IPAM +// Enable enables Windows IPAM in the VPC CNI ConfigMap. func (w *IPAM) Enable(ctx context.Context) error { configMaps := w.Clientset.CoreV1().ConfigMaps(metav1.NamespaceSystem) vpcCNIConfig, err := configMaps.Get(ctx, vpcCNIName, metav1.GetOptions{}) if err != nil { if !apierrors.IsNotFound(err) { - return errors.Wrap(err, "error getting resource") + return errors.Wrapf(err, "error getting ConfigMap %q", vpcCNIName) } return createConfigMap(ctx, configMaps) } @@ -56,7 +49,7 @@ func (w *IPAM) Enable(ctx context.Context) error { _, err = configMaps.Patch(ctx, vpcCNIName, types.StrategicMergePatchType, patch, metav1.PatchOptions{}) if err != nil { - return errors.Wrap(err, "failed to patch resource") + return errors.Wrapf(err, "failed to patch resource %q", vpcCNIName) } return nil } diff --git a/pkg/windows/ipam_test.go b/pkg/windows/ipam_test.go new file mode 100644 index 0000000000..97ced2e57c --- /dev/null +++ b/pkg/windows/ipam_test.go @@ -0,0 +1,97 @@ +package windows_test + +import ( + "context" + + v1 "k8s.io/api/core/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + + . "github.com/onsi/gomega" + + . "github.com/onsi/ginkgo/extensions/table" + "github.com/weaveworks/eksctl/pkg/windows" + "k8s.io/client-go/kubernetes/fake" +) + +type ipamEntry struct { + existingConfigMapData map[string]string + + expectedConfigMapData map[string]string +} + +var _ = DescribeTable("Windows IPAM", func(e ipamEntry) { + var clientset *fake.Clientset + if e.existingConfigMapData != nil { + clientset = fake.NewSimpleClientset(&v1.ConfigMap{ + TypeMeta: metav1.TypeMeta{ + Kind: "ConfigMap", + APIVersion: "v1", + }, + ObjectMeta: metav1.ObjectMeta{ + Name: "amazon-vpc-cni", + Namespace: "kube-system", + }, + Data: e.existingConfigMapData, + }) + } else { + clientset = fake.NewSimpleClientset() + } + + ipam := &windows.IPAM{ + Clientset: clientset, + } + ctx := context.Background() + err := ipam.Enable(ctx) + Expect(err).ToNot(HaveOccurred()) + + cm, err := clientset.CoreV1().ConfigMaps("kube-system").Get(ctx, "amazon-vpc-cni", metav1.GetOptions{}) + Expect(err).ToNot(HaveOccurred()) + Expect(cm.Data).To(Equal(e.expectedConfigMapData)) + +}, + Entry("VPC CNI ConfigMap is missing", ipamEntry{ + expectedConfigMapData: map[string]string{ + "enable-windows-ipam": "true", + }, + }), + + Entry("VPC CNI ConfigMap has data", ipamEntry{ + existingConfigMapData: map[string]string{ + "VPC_CNI_1": "yes", + "VPC_CNI_2": "no", + "other": "true", + }, + expectedConfigMapData: map[string]string{ + "VPC_CNI_1": "yes", + "VPC_CNI_2": "no", + "other": "true", + "enable-windows-ipam": "true", + }, + }), + + Entry("VPC CNI ConfigMap has Windows IPAM already enabled", ipamEntry{ + existingConfigMapData: map[string]string{ + "VPC_CNI_1": "yes", + "VPC_CNI_2": "no", + "enable-windows-ipam": "true", + }, + expectedConfigMapData: map[string]string{ + "VPC_CNI_1": "yes", + "VPC_CNI_2": "no", + "enable-windows-ipam": "true", + }, + }), + + Entry("VPC CNI ConfigMap has Windows IPAM explicitly disabled", ipamEntry{ + existingConfigMapData: map[string]string{ + "VPC_CNI_1": "yes", + "VPC_CNI_2": "no", + "enable-windows-ipam": "false", + }, + expectedConfigMapData: map[string]string{ + "VPC_CNI_1": "yes", + "VPC_CNI_2": "no", + "enable-windows-ipam": "true", + }, + }), +) diff --git a/pkg/windows/windows_suite_test.go b/pkg/windows/windows_suite_test.go new file mode 100644 index 0000000000..aa7fa2b4bf --- /dev/null +++ b/pkg/windows/windows_suite_test.go @@ -0,0 +1,11 @@ +package windows_test + +import ( + "testing" + + "github.com/weaveworks/eksctl/pkg/testutils" +) + +func TestWindows(t *testing.T) { + testutils.RegisterAndRun(t) +} diff --git a/userdocs/src/usage/windows-worker-nodes.md b/userdocs/src/usage/windows-worker-nodes.md index 3a3dce626f..3c5998e872 100644 --- a/userdocs/src/usage/windows-worker-nodes.md +++ b/userdocs/src/usage/windows-worker-nodes.md @@ -1,14 +1,14 @@ # Windows Worker Nodes From version 1.14, Amazon EKS supports [Windows Nodes][eks-user-guide] that allow running Windows containers. -In addition to having Windows nodes, a Linux node in the cluster is required to run CoreDNS, as Microsoft doesn't support host-networking mode yet. Thus, a Windows EKS cluster will be a mixed-mode cluster containing Windows nodes and at least one Linux node. +In addition to having Windows nodes, a Linux node in the cluster is required to run CoreDNS, as Microsoft doesn't support host-networking mode yet. Thus, a Windows EKS cluster will be a mixture of Windows nodes and at least one Linux node. The Linux nodes are critical to the functioning of the cluster, and thus, for a production-grade cluster, it's recommended to have at least two `t2.large` Linux nodes for HA. !!!note You no longer need to install the VPC resource controller on Linux worker nodes to run Windows workloads in EKS clusters. You can enable Windows IP address management on the EKS control plane via a ConfigMap setting (see https://todo.com for details). eksctl will automatically patch the ConfigMap to enable Windows IP address management when a Windows nodegroup is created. - For existing clusters, you can enable it manually and run `eksctl utils install-vpc-controllers` with the `--delete` flag + For existing clusters, you can enable it manually, and run `eksctl utils install-vpc-controllers` with the `--delete` flag to remove the worker node installation of the VPC resource controller. ## Creating a new Windows cluster From 79b7d6189b28501a47590f2715d6b89e7f81a88d Mon Sep 17 00:00:00 2001 From: Jake Klein Date: Thu, 14 Oct 2021 17:00:31 +0100 Subject: [PATCH 014/124] Revert "Enable Windows IPAM when creating a Windows nodegroup, deprecate `install-vpc-controllers`" (#4340) --- examples/14-windows-nodes.yaml | 4 +- integration/tests/windows/windows_test.go | 1 + pkg/actions/nodegroup/create.go | 9 - pkg/addons/assets.go | 143 ++++++- .../assets/vpc-admission-webhook-config.yaml | 20 + .../assets/vpc-admission-webhook-csr.yaml | 11 + .../assets/vpc-admission-webhook-dep.yaml | 61 +++ pkg/addons/assets/vpc-admission-webhook.yaml | 14 + .../assets/vpc-controller-metadata.yaml | 52 --- .../assets/vpc-resource-controller-dep.yaml | 64 +++ .../assets/vpc-resource-controller.yaml | 33 ++ pkg/addons/device_plugin.go | 9 - pkg/addons/vpc_controller.go | 398 +++++++++++++++++- pkg/apis/eksctl.io/v1alpha5/nodegroups.go | 10 - pkg/ctl/create/cluster.go | 7 +- pkg/ctl/utils/install_vpc_controllers.go | 35 +- pkg/eks/tasks.go | 78 ++-- pkg/kubernetes/client.go | 7 +- pkg/kubernetes/client_test.go | 2 +- pkg/windows/ipam.go | 86 ---- pkg/windows/ipam_test.go | 97 ----- pkg/windows/windows_suite_test.go | 11 - userdocs/src/usage/windows-worker-nodes.md | 17 +- 23 files changed, 770 insertions(+), 399 deletions(-) create mode 100644 pkg/addons/assets/vpc-admission-webhook-config.yaml create mode 100644 pkg/addons/assets/vpc-admission-webhook-csr.yaml create mode 100644 pkg/addons/assets/vpc-admission-webhook-dep.yaml create mode 100644 pkg/addons/assets/vpc-admission-webhook.yaml delete mode 100644 pkg/addons/assets/vpc-controller-metadata.yaml create mode 100644 pkg/addons/assets/vpc-resource-controller-dep.yaml create mode 100644 pkg/addons/assets/vpc-resource-controller.yaml delete mode 100644 pkg/windows/ipam.go delete mode 100644 pkg/windows/ipam_test.go delete mode 100644 pkg/windows/windows_suite_test.go diff --git a/examples/14-windows-nodes.yaml b/examples/14-windows-nodes.yaml index 698247685c..59dcb25f5f 100644 --- a/examples/14-windows-nodes.yaml +++ b/examples/14-windows-nodes.yaml @@ -1,5 +1,5 @@ # An example of ClusterConfig containing Windows and Linux node groups to support Windows workloads -# This example should be run with `eksctl create cluster -f 14-windows-nodes.yaml` +# This example should be run with `eksctl create cluster -f 14-windows-nodes.yaml --install-vpc-controllers` --- apiVersion: eksctl.io/v1alpha5 kind: ClusterConfig @@ -13,8 +13,6 @@ nodeGroups: amiFamily: WindowsServer2019FullContainer minSize: 2 maxSize: 3 - -managedNodeGroups: - name: linux-ng instanceType: t2.large minSize: 2 diff --git a/integration/tests/windows/windows_test.go b/integration/tests/windows/windows_test.go index 298726b343..67b08e1994 100644 --- a/integration/tests/windows/windows_test.go +++ b/integration/tests/windows/windows_test.go @@ -70,6 +70,7 @@ var _ = Describe("(Integration) [Windows Nodegroups]", func() { "--config-file", "-", "--verbose", "4", "--kubeconfig", params.KubeconfigPath, + "--install-vpc-controllers", ). WithoutArg("--region", params.Region). WithStdin(bytes.NewReader(data)) diff --git a/pkg/actions/nodegroup/create.go b/pkg/actions/nodegroup/create.go index 77cc8bbb75..57205cc409 100644 --- a/pkg/actions/nodegroup/create.go +++ b/pkg/actions/nodegroup/create.go @@ -160,15 +160,6 @@ func (m *Manager) nodeCreationTasks(options CreateOpts, nodegroupFilter filter.N taskTree.Append(m.stackManager.NewClusterCompatTask()) } - if m.cfg.HasWindowsNodeGroup() { - taskTree.Append(&eks.WindowsIPAMTask{ - Info: "enable Windows IPAM", - ClientsetFunc: func() (kubernetes.Interface, error) { - return m.ctl.NewStdClientSet(m.cfg) - }, - }) - } - awsNodeUsesIRSA, err := init.DoesAWSNodeUseIRSA(m.ctl.Provider, m.clientSet) if err != nil { return errors.Wrap(err, "couldn't check aws-node for annotation") diff --git a/pkg/addons/assets.go b/pkg/addons/assets.go index 8acdc6f886..5baaf0a456 100644 --- a/pkg/addons/assets.go +++ b/pkg/addons/assets.go @@ -3,7 +3,12 @@ // assets/efa-device-plugin.yaml (3.084kB) // assets/neuron-device-plugin.yaml (3.623kB) // assets/nvidia-device-plugin.yaml (2.369kB) -// assets/vpc-controller-metadata.yaml (924B) +// assets/vpc-admission-webhook-config.yaml (524B) +// assets/vpc-admission-webhook-csr.yaml (234B) +// assets/vpc-admission-webhook-dep.yaml (1.675kB) +// assets/vpc-admission-webhook.yaml (231B) +// assets/vpc-resource-controller-dep.yaml (1.679kB) +// assets/vpc-resource-controller.yaml (565B) package addons @@ -132,23 +137,123 @@ func nvidiaDevicePluginYaml() (*asset, error) { return a, nil } -var _vpcControllerMetadataYaml = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\xa4\x93\xc1\x6e\xc2\x40\x0c\x44\xef\xf9\x8a\xfc\xc0\x06\x71\xab\x72\x2c\xbd\xf6\x02\x52\x7b\x76\x36\x66\xb1\x92\xd8\xa9\xed\x4d\x45\xbf\xbe\x42\x14\x5a\x21\xa8\x82\x38\x27\xe3\x79\x9e\xf1\x86\x10\x0a\x18\xe9\x0d\xd5\x48\xb8\x2e\xa7\x65\xd1\x11\xb7\x75\xb9\x41\x9d\x28\x62\x31\xa0\x43\x0b\x0e\x75\x51\x96\x0c\x03\xd6\xe5\x34\xc6\x00\xed\x40\x76\x50\x84\x4f\x6c\x76\x22\xdd\xcf\x57\x1b\x21\x62\x5d\x76\xb9\xc1\x60\x7b\x73\x1c\x8a\xe2\xd2\xe2\xac\x55\x4c\x64\xae\xe0\x24\x5c\x75\x4f\x56\x91\x2c\xa6\x65\x83\x0e\x27\x88\xd7\xec\xe0\xc4\xe9\xfd\x68\xb2\x12\xde\x52\xca\x47\xc5\x5c\xb2\x10\xb7\xe9\x0e\xba\x88\xea\xb4\xa5\x08\x8e\x76\x1d\x6a\xf5\xfb\xc7\x86\x12\x13\xa7\x35\x7e\x64\x34\x9f\x4b\x54\xfd\x1f\xcf\x38\xda\xe2\x5c\xc3\x0b\x8e\xbd\xec\x07\xe4\xd9\xd3\xef\xd8\x55\x1b\x88\x15\x64\xdf\x89\xd2\xd7\x45\x0d\xa7\x65\xfb\x6c\x8e\xba\x96\xfe\xd6\x29\x28\x9a\x64\x8d\x18\xa2\xb0\xab\xf4\x3d\xea\xa3\x4e\xcf\xc4\x2d\x71\x7a\xc4\xf0\xce\x14\xaf\xcd\x9c\x9f\xe3\x9f\x47\x13\x15\x67\x37\x15\x0e\xb7\x66\xb7\x7d\xbe\x03\x00\x00\xff\xff\xad\xa6\xf6\xbd\x9c\x03\x00\x00") +var _vpcAdmissionWebhookConfigYaml = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\x7c\x91\x4f\x6b\xf3\x30\x0c\xc6\xef\xf9\x14\x22\xf7\xa4\xf4\xf6\xe2\xdb\x4b\x29\x63\x87\xc1\x18\x63\x3b\x8c\x1d\x14\x47\x4d\x45\x62\xcb\x58\x76\x4a\xf7\xe9\x47\xfe\xb4\xac\xb0\xd5\x17\xdb\x7a\xa4\xdf\x63\xc9\x18\xf8\x8d\xa2\xb2\x78\x03\xd8\x3a\xd6\xe9\x18\xa9\x63\x4d\x11\x13\x8b\xaf\xfb\x7f\x5a\xb3\x6c\xc6\x6d\x43\x09\xb7\x45\xcf\xbe\x35\xf0\x94\x13\x26\xf6\xdd\x3b\x35\x47\x91\x7e\x27\xfe\xc0\x5d\x5e\x2a\x0a\x47\x09\x5b\x4c\x68\x0a\x00\x8f\x8e\x0c\x8c\xc1\x56\x57\x7a\x75\x5a\x8a\x2a\x7b\xe8\xd6\x0c\x0d\x68\xc9\x40\x9f\x1b\xaa\xf4\xac\x89\x5c\x01\x30\x60\x43\x83\x4e\x10\x00\x0c\xe1\x0f\x4a\xb1\xee\x73\x62\x75\xcf\xaf\x46\x87\x5f\xe2\xf1\xa4\xb5\x15\x37\x63\xed\xc0\xe4\xd3\xf2\xfa\xc5\x08\x40\x29\x8e\x6c\xe9\x72\xbd\xdb\xc2\x4d\xce\xaf\x4d\x2c\x2b\x60\x3a\x1a\x28\x37\x6e\x1a\x1b\x95\x73\x3c\xe6\x81\xf4\xe2\x52\x81\x04\x5a\xc6\xa7\x06\x3e\xa0\xdc\xbd\xec\xff\xbf\xee\x4b\xf8\xbc\x32\x30\xf0\x43\x94\x1c\x26\xbd\x2c\x6f\xe2\xeb\x0f\xce\xca\xb8\xfd\xa1\x45\x52\xc9\xd1\xd2\xac\x04\x69\x75\xd5\x0e\xc8\x43\x8e\xf4\x2c\x03\xdb\xb3\x81\xc7\xce\x4b\xa4\xe2\x3b\x00\x00\xff\xff\x49\xee\x9e\x02\x0c\x02\x00\x00") -func vpcControllerMetadataYamlBytes() ([]byte, error) { +func vpcAdmissionWebhookConfigYamlBytes() ([]byte, error) { return bindataRead( - _vpcControllerMetadataYaml, - "vpc-controller-metadata.yaml", + _vpcAdmissionWebhookConfigYaml, + "vpc-admission-webhook-config.yaml", ) } -func vpcControllerMetadataYaml() (*asset, error) { - bytes, err := vpcControllerMetadataYamlBytes() +func vpcAdmissionWebhookConfigYaml() (*asset, error) { + bytes, err := vpcAdmissionWebhookConfigYamlBytes() if err != nil { return nil, err } - info := bindataFileInfo{name: "vpc-controller-metadata.yaml", size: 0, mode: os.FileMode(0), modTime: time.Unix(0, 0)} - a := &asset{bytes: bytes, info: info, digest: [32]uint8{0xa6, 0x89, 0x6b, 0xa9, 0x33, 0x90, 0x94, 0x63, 0xb2, 0xaf, 0x3a, 0x5c, 0x22, 0x5b, 0x19, 0xc7, 0xb9, 0x22, 0xd6, 0x5a, 0xbb, 0x68, 0xac, 0xf8, 0x24, 0x68, 0x4d, 0x2c, 0x54, 0x12, 0x18, 0x57}} + info := bindataFileInfo{name: "vpc-admission-webhook-config.yaml", size: 0, mode: os.FileMode(0), modTime: time.Unix(0, 0)} + a := &asset{bytes: bytes, info: info, digest: [32]uint8{0x7d, 0x11, 0x23, 0x17, 0x2f, 0xdc, 0x4e, 0x18, 0xaa, 0xc8, 0x66, 0xee, 0xf3, 0xc1, 0x85, 0x63, 0xb1, 0xe3, 0x53, 0x57, 0x80, 0x96, 0xe6, 0x54, 0x26, 0x46, 0x6b, 0x3f, 0x17, 0x20, 0x31, 0x8}} + return a, nil +} + +var _vpcAdmissionWebhookCsrYaml = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\x44\x8d\x4b\x4e\xc4\x30\x10\x44\xf7\x3e\x45\x5f\x20\x41\xb3\x43\xde\x72\x03\x90\xd8\x77\xec\xc2\x69\x19\x7f\x70\xb7\x83\xe6\xf6\x28\x13\xa4\xd9\x95\xaa\x9e\x5e\x71\x97\x4f\x0c\x95\x56\x3d\x05\x0c\x93\x2f\x09\x6c\xd0\x35\xbf\xea\x2a\xed\xe5\xb8\x6d\x30\xbe\xb9\x2c\x35\x7a\x7a\x7b\x12\x1f\x92\xaa\xd4\xf4\x8e\x9f\x09\x35\x57\x60\x1c\xd9\xd8\x3b\xa2\xca\x05\x9e\x8e\x1e\x16\x8e\x45\xf4\x94\x2f\xbf\xd8\xf6\xd6\xf2\x9a\xe7\x86\x45\xef\x6a\x28\x4e\x3b\xc2\xc9\xa7\xd1\x66\xd7\x33\x2d\x74\x4d\x9e\xa7\xed\xa8\xf6\x78\x8a\x8e\x68\x2a\x27\xfc\x23\x51\x92\x18\x7f\x93\x4a\xaa\x6c\x73\xe0\xd1\x66\xdc\x09\x35\x48\xdf\x31\x0a\xaa\x5d\x36\x8c\x03\x83\x4e\x9b\xfb\x0b\x00\x00\xff\xff\xf1\x7d\x42\x97\xea\x00\x00\x00") + +func vpcAdmissionWebhookCsrYamlBytes() ([]byte, error) { + return bindataRead( + _vpcAdmissionWebhookCsrYaml, + "vpc-admission-webhook-csr.yaml", + ) +} + +func vpcAdmissionWebhookCsrYaml() (*asset, error) { + bytes, err := vpcAdmissionWebhookCsrYamlBytes() + if err != nil { + return nil, err + } + + info := bindataFileInfo{name: "vpc-admission-webhook-csr.yaml", size: 0, mode: os.FileMode(0), modTime: time.Unix(0, 0)} + a := &asset{bytes: bytes, info: info, digest: [32]uint8{0x56, 0xf4, 0x54, 0x57, 0xf8, 0xbd, 0x8a, 0x1a, 0x67, 0xb2, 0x29, 0x18, 0xe2, 0x44, 0x8a, 0xc2, 0x7f, 0x44, 0x26, 0x4c, 0x52, 0xe0, 0x70, 0xe0, 0xc8, 0x5a, 0x74, 0x76, 0x2, 0xcd, 0x3e, 0xa}} + return a, nil +} + +var _vpcAdmissionWebhookDepYaml = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\xc4\x54\xc1\x6e\xdb\x3a\x10\xbc\xfb\x2b\xf6\x92\x97\x93\xa5\x97\xa0\xc8\x81\x40\x0a\x04\x4d\x0a\x04\x6d\x93\xa0\x29\x7a\x5f\x53\x13\x99\x10\x45\xb2\xe4\x4a\x8e\xfe\xbe\xa0\xad\xa4\xb6\x1c\x37\x39\x14\xad\x0e\x3e\xec\xec\xcc\x2c\x87\x5e\x72\x30\xdf\x11\x93\xf1\x4e\x11\x87\x90\xca\xfe\x64\xd6\x18\x57\x29\xba\x44\xb0\x7e\x68\xe1\x64\xd6\x42\xb8\x62\x61\x35\x23\x72\xdc\x42\x51\x1f\xf4\x9c\xab\xd6\xa4\xcc\x9c\xaf\xb0\x58\x7a\xdf\x8c\x68\x0a\xac\xa1\xa8\xe9\x16\x98\xa7\x21\x09\xda\x19\x91\xe5\x05\x6c\xca\x02\x94\x7d\x0e\x29\xa4\x00\x9d\x9b\x22\x82\x35\x9a\x93\xa2\x93\x19\x51\x92\xc8\x82\x7a\xd8\xd0\x65\x08\x50\xf4\x15\x3a\x82\x05\x19\x86\x85\x16\x1f\x37\x70\xcb\xa2\x97\x9f\xb7\xec\x7e\x6b\x48\x24\x68\x83\x65\xc1\xc8\xde\x3a\x6a\xfe\xec\x8e\xd0\x2b\x52\x44\x4f\xf3\xe7\x4f\x7b\x27\x6c\x1c\xe2\x16\x7d\xfe\x4a\x7e\xcf\x36\xb1\xde\x62\x6d\x98\x73\xb1\xe9\x03\xa2\x7c\x34\x16\xe7\x25\x44\x97\x23\xaf\xd4\x88\x92\xd6\xbf\x45\x58\xa7\x3d\xa5\x7d\xc2\x70\x88\xd5\x60\x78\x89\x74\x7b\xbf\x8e\xf0\x7e\x8c\xf6\xb6\x47\x8c\xa6\xc2\xf9\xca\xb8\xca\xaf\xd2\xb4\x9d\x6d\xf2\xd6\xd7\xe2\x93\x54\x88\x71\x0a\xf7\xe7\xef\x26\xa5\xd3\xf7\xff\x9d\x6c\x95\x4c\xcb\x35\x14\x1d\x1f\xa5\xa2\x6a\x62\x01\x1d\x8b\xa3\x54\x1c\xa5\x12\x4d\x2a\x5f\x0c\x4b\xf5\xff\x17\xa7\xc5\xd9\xf1\x54\xe4\xae\xb3\xf6\xce\x5b\xa3\x07\x45\x17\x76\xc5\xc3\xf6\xac\xbd\xb7\x5d\x8b\x2f\xbe\x73\xb2\x17\xef\xe6\x62\x46\xf5\xf9\x3a\x9c\x9d\x0e\xa2\x36\xf3\xee\x58\x96\x8a\xf6\x83\x9c\xf4\x46\x70\x75\xeb\xec\xa0\x48\x62\x87\x11\x5c\xfa\x24\x37\x90\x95\x8f\xcd\x4e\x9d\x1f\x1e\x8c\x33\x32\xfc\x1a\xc9\xf9\x0a\x17\x7b\xd5\x2c\xfb\xa3\x33\x11\xd5\x65\x17\x8d\xab\xef\xf5\x12\x55\x67\x8d\xab\xaf\x6b\xe7\x9f\xcb\x57\x8f\xd0\x9d\xe4\x95\xde\x19\x2a\x6b\x3e\xdd\xe7\x37\xc4\x76\x2f\x81\xf5\xe6\x5c\x3d\x86\x88\x75\xd2\x13\x3c\x77\x34\x18\x14\x2d\x20\x5c\xe4\xed\x8e\x0e\x82\x54\x18\x5f\xfa\xe9\xf1\x89\x7c\x40\xe4\xbc\x94\x74\xed\xf6\xc0\x9e\x6d\x87\x3d\xfd\xec\x60\x8d\xeb\x1e\xdf\xec\xcb\x51\x2f\xff\x94\x33\xb7\xd5\xd9\xf4\x5f\xfa\xc6\x44\xfe\x41\x18\x7f\x27\x87\xcd\xbe\xbc\xf0\x7e\x1d\x5a\x93\x94\x5f\x65\xd9\x95\xdd\xd4\x6e\x0e\xbf\x7b\xa3\xca\xcf\x00\x00\x00\xff\xff\x52\xd4\x1b\x58\x8b\x06\x00\x00") + +func vpcAdmissionWebhookDepYamlBytes() ([]byte, error) { + return bindataRead( + _vpcAdmissionWebhookDepYaml, + "vpc-admission-webhook-dep.yaml", + ) +} + +func vpcAdmissionWebhookDepYaml() (*asset, error) { + bytes, err := vpcAdmissionWebhookDepYamlBytes() + if err != nil { + return nil, err + } + + info := bindataFileInfo{name: "vpc-admission-webhook-dep.yaml", size: 0, mode: os.FileMode(0), modTime: time.Unix(0, 0)} + a := &asset{bytes: bytes, info: info, digest: [32]uint8{0x3b, 0x48, 0x71, 0x63, 0xbb, 0x59, 0xcc, 0xd5, 0x1b, 0x30, 0xc7, 0x1c, 0x5e, 0xf2, 0x65, 0x72, 0xff, 0xa9, 0x4d, 0x14, 0x6c, 0xce, 0x49, 0xa8, 0x6f, 0x4d, 0x8e, 0x19, 0xf7, 0xee, 0xfa, 0x8c}} + return a, nil +} + +var _vpcAdmissionWebhookYaml = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\x84\x8c\x31\xae\xc2\x40\x0c\x05\xfb\x3d\x85\x2f\xe0\xe2\xeb\xa7\xf2\x29\x90\x90\xe8\x9d\xcd\x13\xac\x92\xcd\x5a\x6b\x13\xc4\xed\x51\x22\x0a\x1a\x44\x67\xf9\xcd\x0c\x33\x27\xb5\x72\x41\xf7\xd2\x56\xa1\xed\x2f\xcd\x65\x9d\x84\xce\xe8\x5b\xc9\x48\x15\xa1\x93\x86\x4a\x22\x5a\xb5\x42\x68\xb3\xcc\x3a\xd5\xe2\xbb\xc1\x0f\x8c\xb7\xd6\xe6\xf7\xea\xa6\x19\x42\xf3\x7d\x04\xfb\xd3\x03\x35\x11\x2d\x3a\x62\xf1\x3d\x40\xa4\x66\xdf\x0a\x6e\xc8\x3b\x64\xad\xc7\x41\xf3\x71\x0a\x0d\xc3\xff\xe1\x86\xf6\x2b\xe2\xf4\xf1\x73\x2c\xc8\xd1\xfa\xcf\xf6\x2b\x00\x00\xff\xff\xbc\xa7\x78\x3e\xe7\x00\x00\x00") + +func vpcAdmissionWebhookYamlBytes() ([]byte, error) { + return bindataRead( + _vpcAdmissionWebhookYaml, + "vpc-admission-webhook.yaml", + ) +} + +func vpcAdmissionWebhookYaml() (*asset, error) { + bytes, err := vpcAdmissionWebhookYamlBytes() + if err != nil { + return nil, err + } + + info := bindataFileInfo{name: "vpc-admission-webhook.yaml", size: 0, mode: os.FileMode(0), modTime: time.Unix(0, 0)} + a := &asset{bytes: bytes, info: info, digest: [32]uint8{0xc0, 0x14, 0x3e, 0x68, 0x1c, 0x57, 0x26, 0x7e, 0x3b, 0xab, 0xf1, 0x55, 0x21, 0x61, 0xc3, 0xe1, 0xaf, 0x46, 0xb6, 0xf7, 0xdd, 0x11, 0x29, 0x41, 0x64, 0x57, 0xc8, 0xd4, 0xea, 0x97, 0xba, 0xff}} + return a, nil +} + +var _vpcResourceControllerDepYaml = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\xc4\x94\x4f\x6f\xdb\x3c\x0c\xc6\xef\xfe\x14\xbc\x14\x3d\xd9\x49\xfa\xbe\x6b\x31\x01\x3b\x14\x6b\xb1\x15\x18\x86\x00\x0d\x76\x67\x24\x26\x16\x2c\x4b\x1a\x45\x3b\xf1\x3e\xfd\xa0\xb5\xf9\xe3\xa6\x5b\x8b\x61\xc3\x7c\x32\x9e\x9f\xc4\x87\x24\x44\x96\x65\x59\x60\xb4\x5f\x88\x93\x0d\x5e\x01\xc6\x98\x26\xfd\xac\x68\xac\x37\x0a\x6e\x28\xba\x30\xb4\xe4\xa5\x68\x49\xd0\xa0\xa0\x2a\x00\x3c\xb6\xa4\xa0\x8f\xba\x64\x4a\xa1\x63\x4d\xa5\x0e\x5e\x38\x38\x47\xfc\xc8\x53\x44\x4d\x0a\x9a\x6e\x49\x65\x1a\x92\x50\x5b\xa4\x48\x3a\x5f\x67\x8a\xce\x6a\x4c\x0a\x66\x05\x40\x22\x47\x5a\x02\x67\x02\xd0\xa2\xe8\xfa\x13\x2e\xc9\xa5\x07\x01\x72\x4a\xbf\x32\xcb\x9f\x58\x62\x05\x4b\xd4\x0d\x79\xb3\xd3\x18\x75\xa3\x20\x09\x2e\x1d\x15\x00\x42\x6d\x74\x28\xf4\xe8\x73\x54\x4e\xfe\xdc\xc8\xf2\x55\xa6\xcf\xdb\x9e\x1a\x03\xec\x0a\xff\xf1\x4f\xdc\x5b\x4d\xd7\x5a\x87\xce\xcb\x4b\x1e\x59\x40\xeb\x89\xf7\xa9\x95\xa0\x43\xdb\xa2\x37\x87\x5c\x4b\x98\xbc\x94\x29\xf2\x3a\x1d\x5f\x28\x93\x18\x62\x96\x9a\x29\xd5\xc1\x99\x77\xd6\xaf\xc2\x9e\xdb\x16\xd7\xa4\xe0\xfc\x2c\x55\xa6\xe1\x8a\x34\x57\x67\xa9\x3a\x4b\x13\x6a\xd2\x64\x63\xbd\x09\x9b\x54\xfe\xc4\x52\xf5\xd3\xea\xa2\xba\x3c\x1f\x07\x9b\x77\xce\xcd\x83\xb3\x7a\x50\x70\xed\x36\x38\xa4\x3d\x77\xb6\x27\x4f\x29\xcd\x39\x2c\xe9\x90\x23\xc0\x0a\xad\xeb\x98\x16\xbb\x1c\x15\xbc\x39\xa2\xb5\x48\xfc\x40\x72\x7c\x01\xa0\x0e\x49\x14\xcc\x2e\xae\xaa\x69\x35\xad\x66\x23\x16\x51\x6a\x05\x93\x9a\xd0\x49\xfd\x6d\x8c\x02\x8b\x82\xcb\xd9\xd5\xd5\xdb\x91\x9e\x74\x4d\xf9\xa5\x7f\x5c\x2c\xe6\x47\xc0\x7a\x2b\x16\xdd\x0d\x39\x1c\xee\x49\x07\x6f\x92\x82\xff\xa6\x47\x27\x22\xb1\x0d\xe6\x79\x26\xb6\xa5\xd0\xc9\x1e\x1e\x8a\x7a\x69\xac\x76\x0f\x48\x77\x6c\x65\x78\x1f\xbc\xd0\x76\xd4\x80\xc8\xb6\xb7\x8e\xd6\x64\x14\x08\x77\x54\x1c\xba\xf2\x99\x64\x13\xb8\x19\xe9\xb8\x5a\xe5\x52\x86\x43\x08\x1f\x0c\x5d\x9f\xa8\x79\x62\xbf\x76\x96\xc9\xdc\x74\x6c\xfd\xfa\x5e\xd7\x64\x3a\x67\xfd\xfa\x6e\xed\xc3\x5e\xbe\xdd\x92\xee\x24\x6f\x91\x51\x13\x73\xcc\xfb\xc7\x19\x5f\x10\xb7\x69\x8c\xcb\x87\x91\xbf\xdd\x46\xa6\x94\x77\xd0\x13\x9e\x4f\x34\x34\x28\x58\x92\x60\x95\xd7\x09\x7b\x12\x4a\x95\x0d\x93\x90\x9e\x1c\x05\x08\x91\x18\xf3\x36\x81\x3b\x7f\x02\x7b\x74\x1d\x9d\xc4\xcf\x0e\xce\xfa\x6e\xfb\x6a\x5f\x64\x5d\xff\x29\x67\x6c\xcd\xe5\xff\xbf\xd7\x91\x7f\xd0\x8c\xbf\xdd\x87\xef\x01\x00\x00\xff\xff\xec\x16\x91\xef\x8f\x06\x00\x00") + +func vpcResourceControllerDepYamlBytes() ([]byte, error) { + return bindataRead( + _vpcResourceControllerDepYaml, + "vpc-resource-controller-dep.yaml", + ) +} + +func vpcResourceControllerDepYaml() (*asset, error) { + bytes, err := vpcResourceControllerDepYamlBytes() + if err != nil { + return nil, err + } + + info := bindataFileInfo{name: "vpc-resource-controller-dep.yaml", size: 0, mode: os.FileMode(0), modTime: time.Unix(0, 0)} + a := &asset{bytes: bytes, info: info, digest: [32]uint8{0x0, 0xbf, 0x11, 0xf3, 0x5f, 0x76, 0xa3, 0xb2, 0x2e, 0x2f, 0x80, 0xa7, 0x86, 0xae, 0x3f, 0xb7, 0x7e, 0x76, 0xed, 0x68, 0xfe, 0x23, 0x5c, 0x76, 0xb9, 0xd0, 0xd8, 0xed, 0xf9, 0x9d, 0x96, 0x93}} + return a, nil +} + +var _vpcResourceControllerYaml = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\xa4\x90\x31\x4f\x33\x31\x0c\x86\xf7\xfc\x8a\xa8\x7b\x5a\x7d\xdb\xa7\xdb\x80\x81\xbd\x48\xec\x3e\x9f\xdb\x9a\xe6\xe2\xc8\x76\x0e\xc1\xaf\x47\x77\xd7\xc2\x80\x44\x85\x98\xf2\xc4\xf6\x6b\x4b\x4f\x4a\x29\x40\xe5\x67\x52\x63\x29\x5d\xd4\x1e\x70\x0b\xcd\x4f\xa2\xfc\x0e\xce\x52\xb6\xe7\xff\xb6\x65\xd9\x4d\xff\xc2\x99\xcb\xd0\xc5\x87\xdc\xcc\x49\xf7\x92\x29\x8c\xe4\x30\x80\x43\x17\x62\x2c\x30\x52\x17\xa7\x8a\x49\xc9\xa4\x29\x52\x42\x29\xae\x92\x33\x69\xd0\x96\xc9\xba\x90\x22\x54\x7e\x54\x69\xd5\xe6\x4c\x8a\x9b\x4d\x88\xf1\x1a\xb8\xd4\x8a\x0c\x64\x5f\xb4\x33\x07\x6f\x6b\xa1\xca\xb0\x02\x4a\x39\xf0\x71\x84\x3a\x7f\x27\xd2\xfe\x92\x6d\x75\x00\xa7\x05\x8f\xe4\xcb\x9b\xd9\x56\x78\x05\xc7\xd3\xba\xe6\x93\x50\x69\x9e\xff\x9b\x87\x7b\x2e\x03\x97\xe3\x6f\x74\x48\xa6\x3d\x1d\xe6\xc1\xab\x90\x1f\x8e\x86\x18\xbf\xbb\xbf\x75\xc2\x5a\xff\x42\xe8\x8b\xf4\x35\xfd\x44\x3a\x31\xd2\x1d\xa2\xb4\xe2\x37\x17\xac\x7d\xab\x80\xd4\xc5\x73\xeb\x29\xd9\x9b\x39\x8d\xe1\x23\x00\x00\xff\xff\x83\x2e\x8d\x64\x35\x02\x00\x00") + +func vpcResourceControllerYamlBytes() ([]byte, error) { + return bindataRead( + _vpcResourceControllerYaml, + "vpc-resource-controller.yaml", + ) +} + +func vpcResourceControllerYaml() (*asset, error) { + bytes, err := vpcResourceControllerYamlBytes() + if err != nil { + return nil, err + } + + info := bindataFileInfo{name: "vpc-resource-controller.yaml", size: 0, mode: os.FileMode(0), modTime: time.Unix(0, 0)} + a := &asset{bytes: bytes, info: info, digest: [32]uint8{0xa8, 0xff, 0xd2, 0xc, 0x46, 0xfb, 0xe4, 0x4e, 0xb, 0x26, 0x4a, 0xa0, 0x7d, 0x73, 0x5e, 0xaf, 0x6d, 0xab, 0xfd, 0xe5, 0xc2, 0x4f, 0xed, 0xae, 0xb6, 0xd7, 0x17, 0x38, 0x68, 0xb0, 0xe8, 0x2d}} return a, nil } @@ -243,10 +348,15 @@ func AssetNames() []string { // _bindata is a table, holding each asset generator, mapped to its name. var _bindata = map[string]func() (*asset, error){ - "efa-device-plugin.yaml": efaDevicePluginYaml, - "neuron-device-plugin.yaml": neuronDevicePluginYaml, - "nvidia-device-plugin.yaml": nvidiaDevicePluginYaml, - "vpc-controller-metadata.yaml": vpcControllerMetadataYaml, + "efa-device-plugin.yaml": efaDevicePluginYaml, + "neuron-device-plugin.yaml": neuronDevicePluginYaml, + "nvidia-device-plugin.yaml": nvidiaDevicePluginYaml, + "vpc-admission-webhook-config.yaml": vpcAdmissionWebhookConfigYaml, + "vpc-admission-webhook-csr.yaml": vpcAdmissionWebhookCsrYaml, + "vpc-admission-webhook-dep.yaml": vpcAdmissionWebhookDepYaml, + "vpc-admission-webhook.yaml": vpcAdmissionWebhookYaml, + "vpc-resource-controller-dep.yaml": vpcResourceControllerDepYaml, + "vpc-resource-controller.yaml": vpcResourceControllerYaml, } // AssetDebug is true if the assets were built with the debug flag enabled. @@ -296,7 +406,12 @@ var _bintree = &bintree{nil, map[string]*bintree{ "efa-device-plugin.yaml": {efaDevicePluginYaml, map[string]*bintree{}}, "neuron-device-plugin.yaml": {neuronDevicePluginYaml, map[string]*bintree{}}, "nvidia-device-plugin.yaml": {nvidiaDevicePluginYaml, map[string]*bintree{}}, - "vpc-controller-metadata.yaml": {vpcControllerMetadataYaml, map[string]*bintree{}}, + "vpc-admission-webhook-config.yaml": {vpcAdmissionWebhookConfigYaml, map[string]*bintree{}}, + "vpc-admission-webhook-csr.yaml": {vpcAdmissionWebhookCsrYaml, map[string]*bintree{}}, + "vpc-admission-webhook-dep.yaml": {vpcAdmissionWebhookDepYaml, map[string]*bintree{}}, + "vpc-admission-webhook.yaml": {vpcAdmissionWebhookYaml, map[string]*bintree{}}, + "vpc-resource-controller-dep.yaml": {vpcResourceControllerDepYaml, map[string]*bintree{}}, + "vpc-resource-controller.yaml": {vpcResourceControllerYaml, map[string]*bintree{}}, }} // RestoreAsset restores an asset under the given directory. diff --git a/pkg/addons/assets/vpc-admission-webhook-config.yaml b/pkg/addons/assets/vpc-admission-webhook-config.yaml new file mode 100644 index 0000000000..652a257203 --- /dev/null +++ b/pkg/addons/assets/vpc-admission-webhook-config.yaml @@ -0,0 +1,20 @@ +apiVersion: admissionregistration.k8s.io/v1beta1 +kind: MutatingWebhookConfiguration +metadata: + name: vpc-admission-webhook-cfg + namespace: kube-system + labels: + app: vpc-admission-webhook +webhooks: + - name: vpc-admission-webhook.amazonaws.com + clientConfig: + service: + name: vpc-admission-webhook + namespace: kube-system + path: "/mutate" + rules: + - operations: [ "CREATE" ] + apiGroups: [""] + apiVersions: ["v1"] + resources: ["pods"] + failurePolicy: Ignore diff --git a/pkg/addons/assets/vpc-admission-webhook-csr.yaml b/pkg/addons/assets/vpc-admission-webhook-csr.yaml new file mode 100644 index 0000000000..09e4f77a6d --- /dev/null +++ b/pkg/addons/assets/vpc-admission-webhook-csr.yaml @@ -0,0 +1,11 @@ +apiVersion: certificates.k8s.io/v1beta1 +kind: CertificateSigningRequest +metadata: + name: vpc-admission-webhook.kube-system +spec: + groups: + - system:authenticated + usages: + - digital signature + - key encipherment + - server auth diff --git a/pkg/addons/assets/vpc-admission-webhook-dep.yaml b/pkg/addons/assets/vpc-admission-webhook-dep.yaml new file mode 100644 index 0000000000..2c08acab80 --- /dev/null +++ b/pkg/addons/assets/vpc-admission-webhook-dep.yaml @@ -0,0 +1,61 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: vpc-admission-webhook + namespace: kube-system + labels: + app: vpc-admission-webhook +spec: + replicas: 1 + strategy: + type: Recreate + selector: + matchLabels: + app: vpc-admission-webhook + template: + metadata: + labels: + app: vpc-admission-webhook + spec: + containers: + - name: vpc-admission-webhook + args: + - -tlsCertFile=/etc/webhook/certs/cert.pem + - -tlsKeyFile=/etc/webhook/certs/key.pem + - -OSLabelSelectorOverride=windows + - -alsologtostderr + - -v=4 + - 2>&1 + image: '%s.dkr.ecr.%s.%s/eks/vpc-admission-webhook:v0.2.6' + imagePullPolicy: Always + volumeMounts: + - name: webhook-certs + mountPath: /etc/webhook/certs + readOnly: true + hostNetwork: true + affinity: + nodeAffinity: + requiredDuringSchedulingIgnoredDuringExecution: + nodeSelectorTerms: + - matchExpressions: + - key: beta.kubernetes.io/os + operator: In + values: + - linux + - key: beta.kubernetes.io/arch + operator: In + values: + - amd64 + - matchExpressions: + - key: kubernetes.io/os + operator: In + values: + - linux + - key: kubernetes.io/arch + operator: In + values: + - amd64 + volumes: + - name: webhook-certs + secret: + secretName: vpc-admission-webhook-certs diff --git a/pkg/addons/assets/vpc-admission-webhook.yaml b/pkg/addons/assets/vpc-admission-webhook.yaml new file mode 100644 index 0000000000..b8f351fb12 --- /dev/null +++ b/pkg/addons/assets/vpc-admission-webhook.yaml @@ -0,0 +1,14 @@ +--- +apiVersion: v1 +kind: Service +metadata: + name: vpc-admission-webhook + namespace: kube-system + labels: + app: vpc-admission-webhook +spec: + ports: + - port: 443 + targetPort: 443 + selector: + app: vpc-admission-webhook diff --git a/pkg/addons/assets/vpc-controller-metadata.yaml b/pkg/addons/assets/vpc-controller-metadata.yaml deleted file mode 100644 index 93bfd78257..0000000000 --- a/pkg/addons/assets/vpc-controller-metadata.yaml +++ /dev/null @@ -1,52 +0,0 @@ ---- -apiVersion: v1 -kind: Service -metadata: - name: vpc-admission-webhook - namespace: kube-system - ---- -apiVersion: admissionregistration.k8s.io/v1beta1 -kind: MutatingWebhookConfiguration -metadata: - name: vpc-admission-webhook-cfg - namespace: kube-system - ---- -apiVersion: certificates.k8s.io/v1beta1 -kind: CertificateSigningRequest -metadata: - name: vpc-admission-webhook.kube-system - ---- -apiVersion: apps/v1 -kind: Deployment -metadata: - name: vpc-admission-webhook - namespace: kube-system - ---- -apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRole -metadata: - name: vpc-resource-controller - ---- -apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRoleBinding -metadata: - name: vpc-resource-controller - ---- -apiVersion: apps/v1 -kind: Deployment -metadata: - name: vpc-resource-controller - namespace: kube-system - ---- -apiVersion: v1 -kind: Secret -metadata: - name: vpc-admission-webhook-certs - namespace: kube-system diff --git a/pkg/addons/assets/vpc-resource-controller-dep.yaml b/pkg/addons/assets/vpc-resource-controller-dep.yaml new file mode 100644 index 0000000000..3966657e1b --- /dev/null +++ b/pkg/addons/assets/vpc-resource-controller-dep.yaml @@ -0,0 +1,64 @@ +--- +apiVersion: apps/v1 +kind: Deployment +metadata: + name: vpc-resource-controller + namespace: kube-system +spec: + replicas: 1 + selector: + matchLabels: + app: vpc-resource-controller + tier: backend + track: stable + template: + metadata: + labels: + app: vpc-resource-controller + tier: backend + track: stable + spec: + serviceAccount: vpc-resource-controller + containers: + - command: + - /vpc-resource-controller + args: + - -stderrthreshold=info + image: '%s.dkr.ecr.%s.%s/eks/windows-vpc-resource-controller:v0.2.6' + imagePullPolicy: Always + livenessProbe: + failureThreshold: 5 + httpGet: + host: 127.0.0.1 + path: /healthz + port: 61779 + scheme: HTTP + initialDelaySeconds: 30 + periodSeconds: 30 + timeoutSeconds: 5 + name: vpc-resource-controller + securityContext: + privileged: true + hostNetwork: true + affinity: + nodeAffinity: + requiredDuringSchedulingIgnoredDuringExecution: + nodeSelectorTerms: + - matchExpressions: + - key: beta.kubernetes.io/os + operator: In + values: + - linux + - key: beta.kubernetes.io/arch + operator: In + values: + - amd64 + - matchExpressions: + - key: kubernetes.io/os + operator: In + values: + - linux + - key: kubernetes.io/arch + operator: In + values: + - amd64 diff --git a/pkg/addons/assets/vpc-resource-controller.yaml b/pkg/addons/assets/vpc-resource-controller.yaml new file mode 100644 index 0000000000..91b1c9f085 --- /dev/null +++ b/pkg/addons/assets/vpc-resource-controller.yaml @@ -0,0 +1,33 @@ +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + name: vpc-resource-controller +rules: +- apiGroups: + - "" + resources: + - nodes + - nodes/status + - pods + - configmaps + verbs: + - update + - get + - list + - watch + - patch + - create +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRoleBinding +metadata: + name: vpc-resource-controller +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: ClusterRole + name: vpc-resource-controller +subjects: +- kind: ServiceAccount + name: vpc-resource-controller + namespace: kube-system diff --git a/pkg/addons/device_plugin.go b/pkg/addons/device_plugin.go index 70683fe99d..694668ad8b 100644 --- a/pkg/addons/device_plugin.go +++ b/pkg/addons/device_plugin.go @@ -71,15 +71,6 @@ type DevicePlugin interface { Deploy() error } -type typeAssertionError struct { - expected interface{} - got interface{} -} - -func (t *typeAssertionError) Error() string { - return fmt.Sprintf("expected type to be %T; got %T", t.expected, t.got) -} - func applyDevicePlugin(dp DevicePlugin) error { list, err := kubernetes.NewList(dp.Manifest()) if err != nil { diff --git a/pkg/addons/vpc_controller.go b/pkg/addons/vpc_controller.go index e6f9e059a3..4af6c3ab57 100644 --- a/pkg/addons/vpc_controller.go +++ b/pkg/addons/vpc_controller.go @@ -1,56 +1,410 @@ package addons import ( + "context" + "fmt" + "time" + + "github.com/cloudflare/cfssl/csr" "github.com/kris-nova/logger" "github.com/pkg/errors" + api "github.com/weaveworks/eksctl/pkg/apis/eksctl.io/v1alpha5" + "github.com/weaveworks/eksctl/pkg/assetutil" "github.com/weaveworks/eksctl/pkg/kubernetes" + "k8s.io/apimachinery/pkg/watch" + "k8s.io/client-go/kubernetes/typed/certificates/v1beta1" + admv1beta1 "k8s.io/api/admissionregistration/v1beta1" + appsv1 "k8s.io/api/apps/v1" + certsv1beta1 "k8s.io/api/certificates/v1beta1" + corev1 "k8s.io/api/core/v1" + apierrors "k8s.io/apimachinery/pkg/api/errors" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" ) const ( - VPCControllerInfoMessage = "you no longer need to install the VPC resource controller on Linux worker nodes to run " + - "Windows workloads in EKS clusters. You can enable Windows IP address management on the EKS control plane via " + - "a ConfigMap setting (see https://todo.com for details). eksctl will automatically patch the ConfigMap to enable " + - "Windows IP address management when a Windows nodegroup is created. For existing clusters, you can enable it manually " + - "and run `eksctl utils install-vpc-controllers` with the --delete flag to remove the worker node installation of the VPC resource controller" + vpcControllerNamespace = metav1.NamespaceSystem + vpcControllerName = "vpc-resource-controller" + webhookServiceName = "vpc-admission-webhook" + + certWaitTimeout = 45 * time.Second ) -// VPCController deletes an existing installation of VPC controller from worker nodes. +// NewVPCController creates a new VPCController +func NewVPCController(rawClient kubernetes.RawClientInterface, irsa IRSAHelper, clusterStatus *api.ClusterStatus, region string, planMode bool) *VPCController { + return &VPCController{ + rawClient: rawClient, + irsa: irsa, + clusterStatus: clusterStatus, + region: region, + planMode: planMode, + } +} + +// A VPCController deploys Windows VPC controller to a cluster type VPCController struct { - RawClient *kubernetes.RawClient - PlanMode bool + rawClient kubernetes.RawClientInterface + irsa IRSAHelper + clusterStatus *api.ClusterStatus + region string + planMode bool +} + +// Deploy deploys VPC controller to the specified cluster +func (v *VPCController) Deploy() (err error) { + defer func() { + if r := recover(); r != nil { + if ae, ok := r.(*assetutil.Error); ok { + err = ae + } else { + panic(r) + } + } + }() + + if err := v.deployVPCResourceController(); err != nil { + return err + } + + if err := v.generateCert(); err != nil { + return err + } + + return v.deployVPCWebhook() +} + +type typeAssertionError struct { + expected interface{} + got interface{} } -// Delete deletes the resources for VPC controller. -func (v *VPCController) Delete() error { - vpcControllerMetadata, err := vpcControllerMetadataYamlBytes() +func (t *typeAssertionError) Error() string { + return fmt.Sprintf("expected type to be %T; got %T", t.expected, t.got) +} + +func (v *VPCController) generateCert() error { + var ( + csrName = fmt.Sprintf("%s.%s", webhookServiceName, vpcControllerNamespace) + csrClientSet = v.rawClient.ClientSet().CertificatesV1beta1().CertificateSigningRequests() + ) + + hasApprovedCert, err := v.hasApprovedCert() + if err != nil { + return err + } + if hasApprovedCert { + // Delete existing CSR if the secret is missing + _, err := v.rawClient.ClientSet().CoreV1().Secrets(vpcControllerNamespace).Get(context.TODO(), "vpc-admission-webhook-certs", metav1.GetOptions{}) + if err != nil { + if !apierrors.IsNotFound(err) { + return err + } + if err := csrClientSet.Delete(context.TODO(), csrName, metav1.DeleteOptions{}); err != nil { + return err + } + } + return nil + } + + csrPEM, privateKey, err := generateCertReq(webhookServiceName, vpcControllerNamespace) if err != nil { - return errors.Wrap(err, "unexpected error loading manifests") + return errors.Wrap(err, "generating CSR") } - list, err := kubernetes.NewList(vpcControllerMetadata) + + manifest := assetutil.MustLoad(vpcAdmissionWebhookCsrYamlBytes) + rawExtension, err := kubernetes.NewRawExtension(manifest) if err != nil { - return errors.Wrap(err, "unexpected error parsing manifests") + return err + } + + certificateSigningRequest, ok := rawExtension.Object.(*certsv1beta1.CertificateSigningRequest) + if !ok { + return &typeAssertionError{&certsv1beta1.CertificateSigningRequest{}, rawExtension.Object} + } + + certificateSigningRequest.Spec.Request = csrPEM + certificateSigningRequest.Name = csrName + + if err := v.applyRawResource(certificateSigningRequest); err != nil { + return errors.Wrap(err, "creating CertificateSigningRequest") } + + certificateSigningRequest.Status.Conditions = []certsv1beta1.CertificateSigningRequestCondition{ + { + Type: certsv1beta1.CertificateApproved, + LastUpdateTime: metav1.NewTime(time.Now()), + Message: "This CSR was approved by eksctl", + Reason: "eksctl-approve", + }, + } + + if _, err := csrClientSet.UpdateApproval(context.TODO(), certificateSigningRequest, metav1.UpdateOptions{}); err != nil { + return errors.Wrap(err, "updating approval") + } + + logger.Info("waiting for certificate to be available") + + cert, err := watchCSRApproval(csrClientSet, csrName, certWaitTimeout) + if err != nil { + return err + } + + return v.createCertSecrets(privateKey, cert) +} + +func watchCSRApproval(csrClientSet v1beta1.CertificateSigningRequestInterface, csrName string, timeout time.Duration) ([]byte, error) { + watcher, err := csrClientSet.Watch(context.TODO(), metav1.ListOptions{ + FieldSelector: fmt.Sprintf("metadata.name=%s", csrName), + }) + + if err != nil { + return nil, err + } + + defer watcher.Stop() + + timer := time.NewTimer(timeout) + defer timer.Stop() + + for { + select { + case event, ok := <-watcher.ResultChan(): + if !ok { + return nil, errors.New("failed waiting for certificate: unexpected close of ResultChan") + } + switch event.Type { + case watch.Added, watch.Modified: + req := event.Object.(*certsv1beta1.CertificateSigningRequest) + if cert := req.Status.Certificate; cert != nil { + return cert, nil + } + logger.Warning("certificate not yet available (event: %s)", event.Type) + } + case <-timer.C: + return nil, fmt.Errorf("timed out (after %v) waiting for certificate", timeout) + } + + } +} + +func (v *VPCController) createCertSecrets(key, cert []byte) error { + secret := &corev1.Secret{ + TypeMeta: metav1.TypeMeta{ + Kind: "secret", + APIVersion: "v1", + }, + ObjectMeta: metav1.ObjectMeta{ + Name: "vpc-admission-webhook-certs", + Namespace: vpcControllerNamespace, + }, + Data: map[string][]byte{ + "key.pem": key, + "cert.pem": cert, + }, + } + + err := v.applyRawResource(secret) + if err != nil { + return errors.Wrap(err, "error creating secret") + } + return err +} + +func makePolicyDocument() map[string]interface{} { + return map[string]interface{}{ + "Version": "2012-10-17", + "Statement": []map[string]interface{}{ + { + "Effect": "Allow", + "Action": []string{ + "ec2:AssignPrivateIpAddresses", + "ec2:DescribeInstances", + "ec2:DescribeNetworkInterfaces", + "ec2:UnassignPrivateIpAddresses", + "ec2:DescribeRouteTables", + "ec2:DescribeSubnets", + }, + "Resource": "*", + }, + }, + } +} + +func (v *VPCController) deployVPCResourceController() error { + irsaEnabled, err := v.irsa.IsSupported() + if err != nil { + return err + } + if irsaEnabled { + sa := &api.ClusterIAMServiceAccount{ + ClusterIAMMeta: api.ClusterIAMMeta{ + Name: vpcControllerName, + Namespace: vpcControllerNamespace, + }, + AttachPolicy: makePolicyDocument(), + } + if err := v.irsa.CreateOrUpdate(sa); err != nil { + return errors.Wrap(err, "error enabling IRSA") + } + } else { + // If an OIDC provider isn't associated with the cluster, the VPC controller relies on the managed policy + // attached to the node role for the AWS VPC CNI plugin. + sa := kubernetes.NewServiceAccount(metav1.ObjectMeta{ + Name: vpcControllerName, + Namespace: vpcControllerNamespace, + }) + if err := v.applyRawResource(sa); err != nil { + return err + } + } + if err := v.applyResources(assetutil.MustLoad(vpcResourceControllerYamlBytes)); err != nil { + return err + } + + return v.applyDeployment(assetutil.MustLoad(vpcResourceControllerDepYamlBytes)) +} + +func (v *VPCController) deployVPCWebhook() error { + if err := v.applyResources(assetutil.MustLoad(vpcAdmissionWebhookYamlBytes)); err != nil { + return err + } + if err := v.applyDeployment(assetutil.MustLoad(vpcAdmissionWebhookDepYamlBytes)); err != nil { + return err + } + + manifest := assetutil.MustLoad(vpcAdmissionWebhookConfigYamlBytes) + rawExtension, err := kubernetes.NewRawExtension(manifest) + if err != nil { + return err + } + + mutatingWebhook, ok := rawExtension.Object.(*admv1beta1.MutatingWebhookConfiguration) + if !ok { + return &typeAssertionError{&admv1beta1.MutatingWebhookConfiguration{}, rawExtension.Object} + } + + mutatingWebhook.Webhooks[0].ClientConfig.CABundle = v.clusterStatus.CertificateAuthorityData + return v.applyRawResource(rawExtension.Object) +} + +func (v *VPCController) hasApprovedCert() (bool, error) { + csrClientSet := v.rawClient.ClientSet().CertificatesV1beta1().CertificateSigningRequests() + request, err := csrClientSet.Get(context.TODO(), fmt.Sprintf("%s.%s", webhookServiceName, vpcControllerNamespace), metav1.GetOptions{}) + if err != nil { + if !apierrors.IsNotFound(err) { + return false, err + } + return false, nil + } + + conditions := request.Status.Conditions + switch len(conditions) { + case 1: + if conditions[0].Type == certsv1beta1.CertificateApproved { + return true, nil + } + return false, fmt.Errorf("expected certificate to be approved; got %q", conditions[0].Type) + + case 0: + return false, nil + default: + return false, fmt.Errorf("unexpected number of request conditions: %d", len(conditions)) + } +} + +func (v *VPCController) applyResources(manifests []byte) error { + list, err := kubernetes.NewList(manifests) + if err != nil { + return err + } + for _, item := range list.Items { - if err := v.deleteResource(item.Object); err != nil { + if err := v.applyRawResource(item.Object); err != nil { return err } } return nil } -func (v *VPCController) deleteResource(o runtime.Object) error { - r, err := v.RawClient.NewRawResource(o) +func (v *VPCController) applyDeployment(manifests []byte) error { + rawExtension, err := kubernetes.NewRawExtension(manifests) if err != nil { - return errors.Wrap(err, "unexpected error creating raw resource") + return err + } + + deployment, ok := rawExtension.Object.(*appsv1.Deployment) + if !ok { + return &typeAssertionError{&appsv1.Deployment{}, rawExtension.Object} + } + if err := UseRegionalImage(&deployment.Spec.Template, v.region); err != nil { + return err } - msg, err := r.DeleteSync(v.PlanMode) + return v.applyRawResource(rawExtension.Object) +} + +func (v *VPCController) applyRawResource(object runtime.Object) error { + rawResource, err := v.rawClient.NewRawResource(object) if err != nil { - return errors.Wrapf(err, "error deleting resource %q", r.Info.String()) + return err + } + + switch newObject := object.(type) { + case *corev1.Service: + r, found, err := rawResource.Get() + if err != nil { + return err + } + if found { + service, ok := r.(*corev1.Service) + if !ok { + return &typeAssertionError{&corev1.Service{}, r} + } + newObject.Spec.ClusterIP = service.Spec.ClusterIP + newObject.SetResourceVersion(service.GetResourceVersion()) + } + case *admv1beta1.MutatingWebhookConfiguration: + r, found, err := rawResource.Get() + if err != nil { + return err + } + if found { + mwc, ok := r.(*admv1beta1.MutatingWebhookConfiguration) + if !ok { + return &typeAssertionError{&admv1beta1.MutatingWebhookConfiguration{}, r} + } + newObject.SetResourceVersion(mwc.GetResourceVersion()) + } } - if msg != "" { - logger.Info(msg) + + msg, err := rawResource.CreateOrReplace(v.planMode) + if err != nil { + return err } + logger.Info(msg) return nil } + +func generateCertReq(service, namespace string) ([]byte, []byte, error) { + generator := csr.Generator{ + Validator: func(request *csr.CertificateRequest) error { + // ignore validation as all required fields are being set + return nil + }, + } + + serviceCN := fmt.Sprintf("%s.%s.svc", service, namespace) + + return generator.ProcessRequest(&csr.CertificateRequest{ + KeyRequest: &csr.KeyRequest{ + A: "rsa", + S: 2048, + }, + CN: serviceCN, + Hosts: []string{ + service, + fmt.Sprintf("%s.%s", service, namespace), + serviceCN, + }, + }) +} diff --git a/pkg/apis/eksctl.io/v1alpha5/nodegroups.go b/pkg/apis/eksctl.io/v1alpha5/nodegroups.go index 548c6d5928..00382c7ca2 100644 --- a/pkg/apis/eksctl.io/v1alpha5/nodegroups.go +++ b/pkg/apis/eksctl.io/v1alpha5/nodegroups.go @@ -78,13 +78,3 @@ func (c *ClusterConfig) AllNodeGroups() []*NodeGroupBase { } return baseNodeGroups } - -// HasWindowsNodeGroup returns true if an unmanaged Windows nodegroup exists. -func (c *ClusterConfig) HasWindowsNodeGroup() bool { - for _, ng := range c.NodeGroups { - if IsWindowsImage(ng.AMIFamily) { - return true - } - } - return false -} diff --git a/pkg/ctl/create/cluster.go b/pkg/ctl/create/cluster.go index 45fbb32e77..f3d96d66f1 100644 --- a/pkg/ctl/create/cluster.go +++ b/pkg/ctl/create/cluster.go @@ -6,8 +6,6 @@ import ( "os" "strings" - "github.com/weaveworks/eksctl/pkg/addons" - "github.com/aws/amazon-ec2-instance-selector/v2/pkg/selector" "github.com/weaveworks/eksctl/pkg/kops" "github.com/weaveworks/eksctl/pkg/utils" @@ -73,8 +71,6 @@ func createClusterCmdWithRunFunc(cmd *cmdutils.Cmd, runFunc func(cmd *cmdutils.C fs.BoolVarP(¶ms.InstallWindowsVPCController, "install-vpc-controllers", "", false, "Install VPC controller that's required for Windows workloads") fs.BoolVarP(¶ms.Fargate, "fargate", "", false, "Create a Fargate profile scheduling pods in the default and kube-system namespaces onto Fargate") fs.BoolVarP(¶ms.DryRun, "dry-run", "", false, "Dry-run mode that skips cluster creation and outputs a ClusterConfig") - - _ = fs.MarkDeprecated("install-vpc-controllers", addons.VPCControllerInfoMessage) }) cmd.FlagSetGroup.InFlagSet("Initial nodegroup", func(fs *pflag.FlagSet) { @@ -194,7 +190,6 @@ func doCreateCluster(cmd *cmdutils.Cmd, ngFilter *filter.NodeGroupFilter, params if !eks.SupportsWindowsWorkloads(kubeNodeGroups) { return errors.New("running Windows workloads requires having both Windows and Linux (AmazonLinux2) node groups") } - logger.Warning(addons.VPCControllerInfoMessage) } else { eks.LogWindowsCompatibility(kubeNodeGroups, cfg.Metadata) } @@ -253,7 +248,7 @@ func doCreateCluster(cmd *cmdutils.Cmd, ngFilter *filter.NodeGroupFilter, params if err != nil { return err } - postClusterCreationTasks := ctl.CreateExtraClusterConfigTasks(cfg) + postClusterCreationTasks := ctl.CreateExtraClusterConfigTasks(cfg, params.InstallWindowsVPCController) supported, err := utils.IsMinVersion(api.Version1_18, cfg.Metadata.Version) if err != nil { diff --git a/pkg/ctl/utils/install_vpc_controllers.go b/pkg/ctl/utils/install_vpc_controllers.go index 1306f64e5e..79e3893844 100644 --- a/pkg/ctl/utils/install_vpc_controllers.go +++ b/pkg/ctl/utils/install_vpc_controllers.go @@ -4,7 +4,6 @@ import ( "github.com/kris-nova/logger" "github.com/spf13/cobra" "github.com/spf13/pflag" - "github.com/weaveworks/eksctl/pkg/addons" "github.com/weaveworks/eksctl/pkg/eks" "github.com/weaveworks/eksctl/pkg/utils/tasks" @@ -17,17 +16,13 @@ func installWindowsVPCController(cmd *cmdutils.Cmd) { cmd.ClusterConfig = cfg cmd.SetDescription("install-vpc-controllers", "Install Windows VPC controller to support running Windows workloads", "") - cmd.CobraCommand.Deprecated = addons.VPCControllerInfoMessage - - var deleteController bool cmd.CobraCommand.RunE = func(_ *cobra.Command, args []string) error { cmd.NameArg = cmdutils.GetNameArg(args) - return doInstallWindowsVPCController(cmd, deleteController) + return doInstallWindowsVPCController(cmd) } cmd.FlagSetGroup.InFlagSet("General", func(fs *pflag.FlagSet) { - fs.BoolVar(&deleteController, "delete", false, "Deletes VPC resource controller from worker nodes") cmdutils.AddClusterFlagWithDeprecated(fs, cfg.Metadata) cmdutils.AddRegionFlag(fs, &cmd.ProviderConfig) cmdutils.AddConfigFileFlag(fs, &cmd.ClusterConfigFile) @@ -38,33 +33,33 @@ func installWindowsVPCController(cmd *cmdutils.Cmd) { cmdutils.AddCommonFlagsForAWS(cmd.FlagSetGroup, &cmd.ProviderConfig, false) } -func doInstallWindowsVPCController(cmd *cmdutils.Cmd, deleteController bool) error { - if !deleteController { - logger.Warning(addons.VPCControllerInfoMessage) - return nil - } - +func doInstallWindowsVPCController(cmd *cmdutils.Cmd) error { if err := cmdutils.NewMetadataLoader(cmd).Load(); err != nil { return err } + cfg := cmd.ClusterConfig + meta := cmd.ClusterConfig.Metadata + ctl, err := cmd.NewProviderForExistingCluster() if err != nil { return err } - logger.Info("using region %s", cmd.ClusterConfig.Metadata.Region) - rawClient, err := ctl.NewRawClient(cmd.ClusterConfig) - if err != nil { + logger.Info("using region %s", meta.Region) + + if ok, err := ctl.CanUpdate(cfg); !ok { return err } - deleteControllerTask := &eks.DeleteVPCControllerTask{ - Info: "delete Windows VPC controller", - PlanMode: cmd.Plan, - RawClient: rawClient, + + vpcControllerTask := &eks.VPCControllerTask{ + Info: "install Windows VPC controller", + ClusterConfig: cfg, + ClusterProvider: ctl, + PlanMode: cmd.Plan, } taskTree := &tasks.TaskTree{ - Tasks: []tasks.Task{deleteControllerTask}, + Tasks: []tasks.Task{vpcControllerTask}, } if errs := taskTree.DoAllSync(); len(errs) > 0 { diff --git a/pkg/eks/tasks.go b/pkg/eks/tasks.go index b749d07170..b457a8b22a 100644 --- a/pkg/eks/tasks.go +++ b/pkg/eks/tasks.go @@ -6,10 +6,11 @@ import ( "time" "github.com/weaveworks/eksctl/pkg/actions/identityproviders" - "github.com/weaveworks/eksctl/pkg/windows" + "github.com/weaveworks/eksctl/pkg/actions/irsa" "github.com/kris-nova/logger" "github.com/pkg/errors" + "github.com/weaveworks/eksctl/pkg/cfn/manager" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" "k8s.io/apimachinery/pkg/runtime" @@ -39,52 +40,44 @@ func (t *clusterConfigTask) Do(errs chan error) error { return err } -// WindowsIPAMTask is a task for enabling Windows IPAM. -type WindowsIPAMTask struct { - Info string - ClientsetFunc func() (kubernetes.Interface, error) +// VPCControllerTask represents a task to install the VPC controller +type VPCControllerTask struct { + Info string + ClusterProvider *ClusterProvider + ClusterConfig *api.ClusterConfig + PlanMode bool } -// Do implements Task. -func (w *WindowsIPAMTask) Do(errCh chan error) error { - defer close(errCh) +// Describe implements Task +func (v *VPCControllerTask) Describe() string { return v.Info } - clientset, err := w.ClientsetFunc() +// Do implements Task +func (v *VPCControllerTask) Do(errCh chan error) error { + defer close(errCh) + rawClient, err := v.ClusterProvider.NewRawClient(v.ClusterConfig) if err != nil { return err } - windowsIPAM := windows.IPAM{ - Clientset: clientset, + oidc, err := v.ClusterProvider.NewOpenIDConnectManager(v.ClusterConfig) + if err != nil { + return err } - return windowsIPAM.Enable(context.TODO()) -} - -// Describe implements Task. -func (w *WindowsIPAMTask) Describe() string { - return w.Info -} -// DeleteVPCControllerTask is a task for deleting VPC controller resources. -type DeleteVPCControllerTask struct { - RawClient *kubernetes.RawClient - PlanMode bool - Info string -} + stackCollection := manager.NewStackCollection(v.ClusterProvider.Provider, v.ClusterConfig) -// Do implements Task. -func (v *DeleteVPCControllerTask) Do(errCh chan error) error { - defer close(errCh) - - vpcController := &addons.VPCController{ - RawClient: v.RawClient, - PlanMode: v.PlanMode, + clientSet, err := v.ClusterProvider.NewStdClientSet(v.ClusterConfig) + if err != nil { + return err } - return vpcController.Delete() -} + irsaManager := irsa.New(v.ClusterConfig.Metadata.Name, stackCollection, oidc, clientSet) + irsa := addons.NewIRSAHelper(oidc, stackCollection, irsaManager, v.ClusterConfig.Metadata.Name) -// Describe implements Task. -func (v *DeleteVPCControllerTask) Describe() string { - return v.Info + // TODO PlanMode doesn't work as intended + vpcController := addons.NewVPCController(rawClient, irsa, v.ClusterConfig.Status, v.ClusterProvider.Provider.Region(), v.PlanMode) + if err := vpcController.Deploy(); err != nil { + return errors.Wrap(err, "error installing VPC controller") + } + return nil } type devicePluginTask struct { @@ -195,7 +188,7 @@ func (t *restartDaemonsetTask) Do(errCh chan error) error { } // CreateExtraClusterConfigTasks returns all tasks for updating cluster configuration not depending on the control plane availability -func (c *ClusterProvider) CreateExtraClusterConfigTasks(cfg *api.ClusterConfig) *tasks.TaskTree { +func (c *ClusterProvider) CreateExtraClusterConfigTasks(cfg *api.ClusterConfig, installVPCController bool) *tasks.TaskTree { newTasks := &tasks.TaskTree{ Parallel: false, IsSubTask: true, @@ -261,12 +254,11 @@ func (c *ClusterProvider) CreateExtraClusterConfigTasks(cfg *api.ClusterConfig) newTasks.Append(identityproviders.NewAssociateProvidersTask(*cfg.Metadata, cfg.IdentityProviders, c.Provider.EKS())) } - if cfg.HasWindowsNodeGroup() { - newTasks.Append(&WindowsIPAMTask{ - Info: "enable Windows IP address management", - ClientsetFunc: func() (kubernetes.Interface, error) { - return c.NewStdClientSet(cfg) - }, + if installVPCController { + newTasks.Append(&VPCControllerTask{ + Info: "install Windows VPC controller", + ClusterConfig: cfg, + ClusterProvider: c, }) } diff --git a/pkg/kubernetes/client.go b/pkg/kubernetes/client.go index cd6494264a..10b7bf2a3e 100644 --- a/pkg/kubernetes/client.go +++ b/pkg/kubernetes/client.go @@ -245,7 +245,7 @@ func (c *RawClient) deleteObject(object runtime.RawExtension) error { if err != nil { return err } - status, err := resource.DeleteSync(false) + status, err := resource.DeleteSync() if err != nil { return err } @@ -415,7 +415,7 @@ func (r *RawResource) CreatePatchOrReplace() error { // DeleteSync attempts to delete this Kubernetes resource, or returns doing // nothing if it does not exist. It blocks until the resource has been deleted. -func (r *RawResource) DeleteSync(plan bool) (string, error) { +func (r *RawResource) DeleteSync() (string, error) { _, exists, err := r.Get() if err != nil { return "", err @@ -423,9 +423,6 @@ func (r *RawResource) DeleteSync(plan bool) (string, error) { if !exists { return "", nil } - if plan { - return r.LogAction(true, "deleted"), nil - } propagationPolicy := metav1.DeletePropagationForeground if _, err := r.Helper.DeleteWithOptions(r.Info.Namespace, r.Info.Name, &metav1.DeleteOptions{ PropagationPolicy: &propagationPolicy, diff --git a/pkg/kubernetes/client_test.go b/pkg/kubernetes/client_test.go index 5a553a9a77..aa037e04ef 100644 --- a/pkg/kubernetes/client_test.go +++ b/pkg/kubernetes/client_test.go @@ -243,7 +243,7 @@ var _ = Describe("Kubernetes client wrappers", func() { Expect(err).ToNot(HaveOccurred()) Expect(exists).To(BeTrue()) // The Kubernetes resource already exists. - status, err := rc.DeleteSync(false) + status, err := rc.DeleteSync() Expect(err).ToNot(HaveOccurred()) Expect(status).To(Equal(fmt.Sprintf("deleted %q", rc))) Expect(track).ToNot(BeNil()) diff --git a/pkg/windows/ipam.go b/pkg/windows/ipam.go deleted file mode 100644 index a2390e0028..0000000000 --- a/pkg/windows/ipam.go +++ /dev/null @@ -1,86 +0,0 @@ -package windows - -import ( - "context" - "encoding/json" - - jsonpatch "github.com/evanphx/json-patch/v5" - "github.com/kris-nova/logger" - "github.com/pkg/errors" - corev1 "k8s.io/api/core/v1" - apierrors "k8s.io/apimachinery/pkg/api/errors" - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - "k8s.io/apimachinery/pkg/types" - "k8s.io/client-go/kubernetes" - corev1client "k8s.io/client-go/kubernetes/typed/core/v1" -) - -const ( - vpcCNIName = "amazon-vpc-cni" - vpcCNINamespace = metav1.NamespaceSystem - windowsIPAMField = "enable-windows-ipam" -) - -// IPAM enables Windows IPAM in the VPC CNI ConfigMap. -type IPAM struct { - Clientset kubernetes.Interface -} - -// Enable enables Windows IPAM in the VPC CNI ConfigMap. -func (w *IPAM) Enable(ctx context.Context) error { - configMaps := w.Clientset.CoreV1().ConfigMaps(metav1.NamespaceSystem) - vpcCNIConfig, err := configMaps.Get(ctx, vpcCNIName, metav1.GetOptions{}) - if err != nil { - if !apierrors.IsNotFound(err) { - return errors.Wrapf(err, "error getting ConfigMap %q", vpcCNIName) - } - return createConfigMap(ctx, configMaps) - } - - if val, ok := vpcCNIConfig.Data[windowsIPAMField]; ok && val == "true" { - logger.Info("Windows IPAM is already enabled") - return nil - } - - patch, err := createPatch(vpcCNIConfig) - if err != nil { - return errors.Wrap(err, "error creating merge patch") - } - - _, err = configMaps.Patch(ctx, vpcCNIName, types.StrategicMergePatchType, patch, metav1.PatchOptions{}) - if err != nil { - return errors.Wrapf(err, "failed to patch resource %q", vpcCNIName) - } - return nil -} - -func createPatch(cm *corev1.ConfigMap) ([]byte, error) { - oldData, err := json.Marshal(cm) - if err != nil { - return nil, err - } - cm.Data[windowsIPAMField] = "true" - modifiedData, err := json.Marshal(cm) - if err != nil { - return nil, err - } - return jsonpatch.CreateMergePatch(oldData, modifiedData) -} - -func createConfigMap(ctx context.Context, configMaps corev1client.ConfigMapInterface) error { - cm := &corev1.ConfigMap{ - TypeMeta: metav1.TypeMeta{ - Kind: "ConfigMap", - APIVersion: "v1", - }, - ObjectMeta: metav1.ObjectMeta{ - Name: vpcCNIName, - Namespace: vpcCNINamespace, - }, - Data: map[string]string{ - windowsIPAMField: "true", - }, - } - _, err := configMaps.Create(ctx, cm, metav1.CreateOptions{}) - return err -} diff --git a/pkg/windows/ipam_test.go b/pkg/windows/ipam_test.go deleted file mode 100644 index 97ced2e57c..0000000000 --- a/pkg/windows/ipam_test.go +++ /dev/null @@ -1,97 +0,0 @@ -package windows_test - -import ( - "context" - - v1 "k8s.io/api/core/v1" - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - - . "github.com/onsi/gomega" - - . "github.com/onsi/ginkgo/extensions/table" - "github.com/weaveworks/eksctl/pkg/windows" - "k8s.io/client-go/kubernetes/fake" -) - -type ipamEntry struct { - existingConfigMapData map[string]string - - expectedConfigMapData map[string]string -} - -var _ = DescribeTable("Windows IPAM", func(e ipamEntry) { - var clientset *fake.Clientset - if e.existingConfigMapData != nil { - clientset = fake.NewSimpleClientset(&v1.ConfigMap{ - TypeMeta: metav1.TypeMeta{ - Kind: "ConfigMap", - APIVersion: "v1", - }, - ObjectMeta: metav1.ObjectMeta{ - Name: "amazon-vpc-cni", - Namespace: "kube-system", - }, - Data: e.existingConfigMapData, - }) - } else { - clientset = fake.NewSimpleClientset() - } - - ipam := &windows.IPAM{ - Clientset: clientset, - } - ctx := context.Background() - err := ipam.Enable(ctx) - Expect(err).ToNot(HaveOccurred()) - - cm, err := clientset.CoreV1().ConfigMaps("kube-system").Get(ctx, "amazon-vpc-cni", metav1.GetOptions{}) - Expect(err).ToNot(HaveOccurred()) - Expect(cm.Data).To(Equal(e.expectedConfigMapData)) - -}, - Entry("VPC CNI ConfigMap is missing", ipamEntry{ - expectedConfigMapData: map[string]string{ - "enable-windows-ipam": "true", - }, - }), - - Entry("VPC CNI ConfigMap has data", ipamEntry{ - existingConfigMapData: map[string]string{ - "VPC_CNI_1": "yes", - "VPC_CNI_2": "no", - "other": "true", - }, - expectedConfigMapData: map[string]string{ - "VPC_CNI_1": "yes", - "VPC_CNI_2": "no", - "other": "true", - "enable-windows-ipam": "true", - }, - }), - - Entry("VPC CNI ConfigMap has Windows IPAM already enabled", ipamEntry{ - existingConfigMapData: map[string]string{ - "VPC_CNI_1": "yes", - "VPC_CNI_2": "no", - "enable-windows-ipam": "true", - }, - expectedConfigMapData: map[string]string{ - "VPC_CNI_1": "yes", - "VPC_CNI_2": "no", - "enable-windows-ipam": "true", - }, - }), - - Entry("VPC CNI ConfigMap has Windows IPAM explicitly disabled", ipamEntry{ - existingConfigMapData: map[string]string{ - "VPC_CNI_1": "yes", - "VPC_CNI_2": "no", - "enable-windows-ipam": "false", - }, - expectedConfigMapData: map[string]string{ - "VPC_CNI_1": "yes", - "VPC_CNI_2": "no", - "enable-windows-ipam": "true", - }, - }), -) diff --git a/pkg/windows/windows_suite_test.go b/pkg/windows/windows_suite_test.go deleted file mode 100644 index aa7fa2b4bf..0000000000 --- a/pkg/windows/windows_suite_test.go +++ /dev/null @@ -1,11 +0,0 @@ -package windows_test - -import ( - "testing" - - "github.com/weaveworks/eksctl/pkg/testutils" -) - -func TestWindows(t *testing.T) { - testutils.RegisterAndRun(t) -} diff --git a/userdocs/src/usage/windows-worker-nodes.md b/userdocs/src/usage/windows-worker-nodes.md index 3c5998e872..96bd63ba20 100644 --- a/userdocs/src/usage/windows-worker-nodes.md +++ b/userdocs/src/usage/windows-worker-nodes.md @@ -1,15 +1,10 @@ # Windows Worker Nodes From version 1.14, Amazon EKS supports [Windows Nodes][eks-user-guide] that allow running Windows containers. -In addition to having Windows nodes, a Linux node in the cluster is required to run CoreDNS, as Microsoft doesn't support host-networking mode yet. Thus, a Windows EKS cluster will be a mixture of Windows nodes and at least one Linux node. +In addition to having Windows nodes, a Linux node in the cluster is required to run the VPC resource controller and CoreDNS, as Microsoft doesn't support host-networking mode yet. Thus, a Windows EKS cluster will be a mixed-mode cluster containing Windows nodes and at least one Linux node. The Linux nodes are critical to the functioning of the cluster, and thus, for a production-grade cluster, it's recommended to have at least two `t2.large` Linux nodes for HA. -!!!note - You no longer need to install the VPC resource controller on Linux worker nodes to run Windows workloads in EKS clusters. - You can enable Windows IP address management on the EKS control plane via a ConfigMap setting (see https://todo.com for details). - eksctl will automatically patch the ConfigMap to enable Windows IP address management when a Windows nodegroup is created. - For existing clusters, you can enable it manually, and run `eksctl utils install-vpc-controllers` with the `--delete` flag - to remove the worker node installation of the VPC resource controller. +`eksctl` provides a flag to install the VPC resource controller as part of cluster creation, and a command to install it after a cluster has been created. ## Creating a new Windows cluster @@ -31,8 +26,6 @@ nodeGroups: amiFamily: WindowsServer2019FullContainer minSize: 2 maxSize: 3 - -managedNodeGroups: - name: linux-ng instanceType: t2.large minSize: 2 @@ -40,7 +33,7 @@ managedNodeGroups: ``` ```console -eksctl create cluster -f cluster.yaml +eksctl create cluster -f cluster.yaml --install-vpc-controllers ``` @@ -49,6 +42,7 @@ To create a new cluster without using a config file, issue the following command ```console eksctl create cluster --managed=false --name=windows-cluster --node-ami-family=WindowsServer2019CoreContainer eksctl create nodegroup --cluster=windows-cluster --node-ami-family=AmazonLinux2 --nodes-min=2 --node-type=t2.large +eksctl utils install-vpc-controllers --cluster=windows-cluster --approve ``` !!!note @@ -56,10 +50,11 @@ eksctl create nodegroup --cluster=windows-cluster --node-ami-family=AmazonLinux2 ## Adding Windows support to an existing Linux cluster -To enable running Windows workloads on an existing cluster with Linux nodes (`AmazonLinux2` AMI family), you need to add a Windows nodegroup. +To enable running Windows workloads on an existing cluster with Linux nodes (`AmazonLinux2` AMI family), you need to add a Windows node group and install the Windows VPC controller: ```console eksctl create nodegroup --managed=false --cluster=existing-cluster --node-ami-family=WindowsServer2019CoreContainer +eksctl utils install-vpc-controllers --cluster=existing-cluster --approve ``` To ensure workloads are scheduled on the right OS, they must have a `nodeSelector` targeting the OS it must run on: From a9abd602ff65214a7ac4ee2199a66ba9fad5384e Mon Sep 17 00:00:00 2001 From: cpu1 Date: Thu, 23 Sep 2021 15:05:05 +0530 Subject: [PATCH 015/124] Remove redundant func --- pkg/ami/auto_resolver_test.go | 21 +++++---------------- pkg/ami/ssm_resolver_test.go | 20 ++++++++++---------- 2 files changed, 15 insertions(+), 26 deletions(-) diff --git a/pkg/ami/auto_resolver_test.go b/pkg/ami/auto_resolver_test.go index 8d7a6f2b19..596fb70115 100644 --- a/pkg/ami/auto_resolver_test.go +++ b/pkg/ami/auto_resolver_test.go @@ -8,7 +8,6 @@ import ( "github.com/stretchr/testify/mock" . "github.com/weaveworks/eksctl/pkg/ami" api "github.com/weaveworks/eksctl/pkg/apis/eksctl.io/v1alpha5" - "github.com/weaveworks/eksctl/pkg/eks" "github.com/weaveworks/eksctl/pkg/testutils/mockprovider" ) @@ -77,7 +76,7 @@ var _ = Describe("AMI Auto Resolution", func() { BeforeEach(func() { imageState = "available" - _, p = createProviders() + p = mockprovider.NewMockProvider() addMockDescribeImages(p, "amazon-eks-node-1.15-v*", expectedAmi, imageState, "2018-08-20T23:25:53.000Z", api.NodeImageFamilyAmazonLinux2) resolver := NewAutoResolver(p.MockEC2()) resolvedAmi, err = resolver.Resolve(region, version, instanceType, imageFamily) @@ -101,7 +100,7 @@ var _ = Describe("AMI Auto Resolution", func() { imageState = "available" imageFamily = "Ubuntu1804" - _, p = createProviders() + p = mockprovider.NewMockProvider() addMockDescribeImages(p, "ubuntu-eks/k8s_1.15/images/*18.04*", expectedAmi, imageState, "2018-08-20T23:25:53.000Z", api.NodeImageFamilyUbuntu1804) resolver := NewAutoResolver(p.MockEC2()) @@ -125,7 +124,7 @@ var _ = Describe("AMI Auto Resolution", func() { BeforeEach(func() { imageState = "pending" - _, p = createProviders() + p = mockprovider.NewMockProvider() addMockDescribeImagesMultiple(p, "amazon-eks-node-1.15-v*", []returnAmi{}) resolver := NewAutoResolver(p.MockEC2()) @@ -150,7 +149,7 @@ var _ = Describe("AMI Auto Resolution", func() { imageState = "available" expectedAmi = "ami-5678" - _, p = createProviders() + p = mockprovider.NewMockProvider() images := []returnAmi{ { createdDate: "2018-08-20T23:25:53.000Z", @@ -193,7 +192,7 @@ var _ = Describe("AMI Auto Resolution", func() { BeforeEach(func() { imageState = "available" - _, p = createProviders() + p = mockprovider.NewMockProvider() addMockDescribeImages(p, "amazon-eks-gpu-node-1.15-*", expectedAmi, imageState, "2018-08-20T23:25:53.000Z", api.NodeImageFamilyAmazonLinux2) resolver := NewAutoResolver(p.MockEC2()) resolvedAmi, err = resolver.Resolve(region, version, instanceType, imageFamily) @@ -216,16 +215,6 @@ var _ = Describe("AMI Auto Resolution", func() { }) }) -func createProviders() (*eks.ClusterProvider, *mockprovider.MockProvider) { - p := mockprovider.NewMockProvider() - - c := &eks.ClusterProvider{ - Provider: p, - } - - return c, p -} - func addMockDescribeImages(p *mockprovider.MockProvider, expectedNamePattern string, amiID string, amiState string, createdDate string, instanceFamily string) { p.MockEC2().On("DescribeImages", mock.MatchedBy(func(input *ec2.DescribeImagesInput) bool { diff --git a/pkg/ami/ssm_resolver_test.go b/pkg/ami/ssm_resolver_test.go index a9d745760f..6bba8b8895 100644 --- a/pkg/ami/ssm_resolver_test.go +++ b/pkg/ami/ssm_resolver_test.go @@ -42,7 +42,7 @@ var _ = Describe("AMI Auto Resolution", func() { Context("and AL2 ami is available", func() { BeforeEach(func() { - _, p = createProviders() + p = mockprovider.NewMockProvider() addMockGetParameter(p, "/aws/service/eks/optimized-ami/1.12/amazon-linux-2/recommended/image_id", expectedAmi) resolver := NewSSMResolver(p.MockSSM()) resolvedAmi, err = resolver.Resolve(region, version, instanceType, imageFamily) @@ -64,7 +64,7 @@ var _ = Describe("AMI Auto Resolution", func() { Context("and ami is NOT available", func() { BeforeEach(func() { - _, p = createProviders() + p = mockprovider.NewMockProvider() addMockFailedGetParameter(p, "/aws/service/eks/optimized-ami/1.12/amazon-linux-2/recommended/image_id") resolver := NewSSMResolver(p.MockSSM()) @@ -94,7 +94,7 @@ var _ = Describe("AMI Auto Resolution", func() { Context("and ami is available", func() { BeforeEach(func() { - _, p = createProviders() + p = mockprovider.NewMockProvider() addMockGetParameter(p, "/aws/service/eks/optimized-ami/1.12/amazon-linux-2-gpu/recommended/image_id", expectedAmi) resolver := NewSSMResolver(p.MockSSM()) resolvedAmi, err = resolver.Resolve(region, version, instanceType, imageFamily) @@ -122,7 +122,7 @@ var _ = Describe("AMI Auto Resolution", func() { Context("and ami is available", func() { BeforeEach(func() { version = "1.14" - _, p = createProviders() + p = mockprovider.NewMockProvider() }) It("should return a valid Full image for 1.14", func() { @@ -160,7 +160,7 @@ var _ = Describe("AMI Auto Resolution", func() { Context("and Ubuntu family", func() { BeforeEach(func() { - _, p = createProviders() + p = mockprovider.NewMockProvider() }) It("should return an error", func() { @@ -180,7 +180,7 @@ var _ = Describe("AMI Auto Resolution", func() { Context("and ami is available", func() { BeforeEach(func() { - _, p = createProviders() + p = mockprovider.NewMockProvider() addMockGetParameter(p, "/aws/service/bottlerocket/aws-k8s-1.15/x86_64/latest/image_id", expectedAmi) resolver := NewSSMResolver(p.MockSSM()) resolvedAmi, err = resolver.Resolve(region, version, instanceType, imageFamily) @@ -201,7 +201,7 @@ var _ = Describe("AMI Auto Resolution", func() { Context("and ami is NOT available", func() { BeforeEach(func() { - _, p = createProviders() + p = mockprovider.NewMockProvider() addMockFailedGetParameter(p, "/aws/service/bottlerocket/aws-k8s-1.15/x86_64/latest/image_id") resolver := NewSSMResolver(p.MockSSM()) @@ -229,7 +229,7 @@ var _ = Describe("AMI Auto Resolution", func() { Context("and ami is available", func() { BeforeEach(func() { - _, p = createProviders() + p = mockprovider.NewMockProvider() addMockGetParameter(p, "/aws/service/bottlerocket/aws-k8s-1.15/arm64/latest/image_id", expectedAmi) resolver := NewSSMResolver(p.MockSSM()) resolvedAmi, err = resolver.Resolve(region, version, instanceType, imageFamily) @@ -250,7 +250,7 @@ var _ = Describe("AMI Auto Resolution", func() { Context("and ami is NOT available", func() { BeforeEach(func() { - _, p = createProviders() + p = mockprovider.NewMockProvider() addMockFailedGetParameter(p, "/aws/service/bottlerocket/aws-k8s-1.15/arm64/latest/image_id") resolver := NewSSMResolver(p.MockSSM()) @@ -278,7 +278,7 @@ var _ = Describe("AMI Auto Resolution", func() { }) }) -func addMockGetParameter(p *mockprovider.MockProvider, name string, amiID string) { +func addMockGetParameter(p *mockprovider.MockProvider, name, amiID string) { p.MockSSM().On("GetParameter", mock.MatchedBy(func(input *ssm.GetParameterInput) bool { return *input.Name == name From 6dbe7ffdab4d5104145fc157f15808111216fb25 Mon Sep 17 00:00:00 2001 From: cpu1 Date: Thu, 23 Sep 2021 16:02:56 +0530 Subject: [PATCH 016/124] Move package --- pkg/actions/nodegroup/create.go | 4 ++-- pkg/ami/auto_resolver.go | 6 +++--- pkg/ami/ssm_resolver.go | 8 ++++---- pkg/eks/instance_selection_test.go | 3 +-- pkg/eks/tasks.go | 8 ++++---- pkg/utils/instance/instance.go | 32 ++++++++++++++++++++++++++++++ pkg/utils/utils.go | 27 ------------------------- 7 files changed, 46 insertions(+), 42 deletions(-) create mode 100644 pkg/utils/instance/instance.go diff --git a/pkg/actions/nodegroup/create.go b/pkg/actions/nodegroup/create.go index 57205cc409..3bd92939f6 100644 --- a/pkg/actions/nodegroup/create.go +++ b/pkg/actions/nodegroup/create.go @@ -14,7 +14,7 @@ import ( "github.com/weaveworks/eksctl/pkg/eks" "github.com/weaveworks/eksctl/pkg/kubernetes" "github.com/weaveworks/eksctl/pkg/printers" - "github.com/weaveworks/eksctl/pkg/utils" + instanceutils "github.com/weaveworks/eksctl/pkg/utils/instance" "github.com/weaveworks/eksctl/pkg/utils/tasks" "github.com/weaveworks/eksctl/pkg/vpc" @@ -278,7 +278,7 @@ func (m *Manager) checkARMSupport(ctl *eks.ClusterProvider, clientSet kubernetes if err != nil { return err } - if api.ClusterHasInstanceType(cfg, utils.IsARMInstanceType) { + if api.ClusterHasInstanceType(cfg, instanceutils.IsARMInstanceType) { upToDate, err := defaultaddons.DoAddonsSupportMultiArch(clientSet, rawClient, kubernetesVersion, ctl.Provider.Region()) if err != nil { return err diff --git a/pkg/ami/auto_resolver.go b/pkg/ami/auto_resolver.go index 790bfa68e9..3acfeccf3d 100644 --- a/pkg/ami/auto_resolver.go +++ b/pkg/ami/auto_resolver.go @@ -6,7 +6,7 @@ import ( "github.com/aws/aws-sdk-go/service/ec2/ec2iface" "github.com/kris-nova/logger" api "github.com/weaveworks/eksctl/pkg/apis/eksctl.io/v1alpha5" - "github.com/weaveworks/eksctl/pkg/utils" + instanceutils "github.com/weaveworks/eksctl/pkg/utils/instance" ) const ( @@ -71,7 +71,7 @@ func (r *AutoResolver) Resolve(region, version, instanceType, imageFamily string imageClasses := MakeImageSearchPatterns(version)[imageFamily] namePattern := imageClasses[ImageClassGeneral] - if utils.IsGPUInstanceType(instanceType) { + if instanceutils.IsGPUInstanceType(instanceType) { var ok bool namePattern, ok = imageClasses[ImageClassGPU] if !ok { @@ -80,7 +80,7 @@ func (r *AutoResolver) Resolve(region, version, instanceType, imageFamily string } } - if utils.IsARMInstanceType(instanceType) { + if instanceutils.IsARMInstanceType(instanceType) { var ok bool namePattern, ok = imageClasses[ImageClassARM] if !ok { diff --git a/pkg/ami/ssm_resolver.go b/pkg/ami/ssm_resolver.go index 792b0d1f75..9b63352bff 100644 --- a/pkg/ami/ssm_resolver.go +++ b/pkg/ami/ssm_resolver.go @@ -10,8 +10,8 @@ import ( "github.com/kris-nova/logger" api "github.com/weaveworks/eksctl/pkg/apis/eksctl.io/v1alpha5" - "github.com/weaveworks/eksctl/pkg/utils" + instanceutils "github.com/weaveworks/eksctl/pkg/utils/instance" ) // SSMResolver resolves the AMI to the defaults for the region @@ -86,7 +86,7 @@ func MakeManagedSSMParameterName(version, imageFamily, amiType string) (string, // instanceEC2ArchName returns the name of the architecture as used by EC2 // resources. func instanceEC2ArchName(instanceType string) string { - if utils.IsARMInstanceType(instanceType) { + if instanceutils.IsARMInstanceType(instanceType) { return "arm64" } return "x86_64" @@ -94,11 +94,11 @@ func instanceEC2ArchName(instanceType string) string { func imageType(imageFamily, instanceType string) string { family := utils.ToKebabCase(imageFamily) - if utils.IsGPUInstanceType(instanceType) { + if instanceutils.IsGPUInstanceType(instanceType) { return family + "-gpu" } - if utils.IsARMInstanceType(instanceType) { + if instanceutils.IsARMInstanceType(instanceType) { return family + "-arm64" } return family diff --git a/pkg/eks/instance_selection_test.go b/pkg/eks/instance_selection_test.go index 6ff6cf8e05..4f1677c9b3 100644 --- a/pkg/eks/instance_selection_test.go +++ b/pkg/eks/instance_selection_test.go @@ -4,7 +4,6 @@ import ( . "github.com/onsi/ginkgo/extensions/table" . "github.com/onsi/gomega" api "github.com/weaveworks/eksctl/pkg/apis/eksctl.io/v1alpha5" - "github.com/weaveworks/eksctl/pkg/eks" ) type instanceTypeCase struct { @@ -42,7 +41,7 @@ var _ = DescribeTable("Instance type selection", func(t instanceTypeCase) { } for _, np := range []api.NodePool{ng, mng} { - instanceType := eks.SelectInstanceType(np) + instanceType := api.SelectInstanceType(np) Expect(instanceType).To(Equal(t.expectedInstanceType)) } }, diff --git a/pkg/eks/tasks.go b/pkg/eks/tasks.go index b457a8b22a..48ff4d7145 100644 --- a/pkg/eks/tasks.go +++ b/pkg/eks/tasks.go @@ -19,7 +19,7 @@ import ( "github.com/weaveworks/eksctl/pkg/addons" "github.com/weaveworks/eksctl/pkg/fargate" iamoidc "github.com/weaveworks/eksctl/pkg/iam/oidc" - "github.com/weaveworks/eksctl/pkg/utils" + instanceutils "github.com/weaveworks/eksctl/pkg/utils/instance" "github.com/weaveworks/eksctl/pkg/utils/tasks" api "github.com/weaveworks/eksctl/pkg/apis/eksctl.io/v1alpha5" @@ -272,16 +272,16 @@ func (c *ClusterProvider) ClusterTasksForNodeGroups(cfg *api.ClusterConfig, inst IsSubTask: false, } var needsNvidiaButNotNeuron = func(t string) bool { - return utils.IsGPUInstanceType(t) && !utils.IsInferentiaInstanceType(t) + return instanceutils.IsGPUInstanceType(t) && !instanceutils.IsInferentiaInstanceType(t) } var haveNeuronInstanceType, haveNvidiaInstanceType, efaEnabled bool for _, ng := range cfg.NodeGroups { - haveNeuronInstanceType = haveNeuronInstanceType || api.HasInstanceType(ng, utils.IsInferentiaInstanceType) + haveNeuronInstanceType = haveNeuronInstanceType || api.HasInstanceType(ng, instanceutils.IsInferentiaInstanceType) haveNvidiaInstanceType = haveNvidiaInstanceType || api.HasInstanceType(ng, needsNvidiaButNotNeuron) efaEnabled = efaEnabled || api.IsEnabled(ng.EFAEnabled) } for _, ng := range cfg.ManagedNodeGroups { - haveNeuronInstanceType = haveNeuronInstanceType || api.HasInstanceTypeManaged(ng, utils.IsInferentiaInstanceType) + haveNeuronInstanceType = haveNeuronInstanceType || api.HasInstanceTypeManaged(ng, instanceutils.IsInferentiaInstanceType) haveNvidiaInstanceType = haveNvidiaInstanceType || api.HasInstanceTypeManaged(ng, needsNvidiaButNotNeuron) efaEnabled = efaEnabled || api.IsEnabled(ng.EFAEnabled) } diff --git a/pkg/utils/instance/instance.go b/pkg/utils/instance/instance.go new file mode 100644 index 0000000000..98e554b1ef --- /dev/null +++ b/pkg/utils/instance/instance.go @@ -0,0 +1,32 @@ +package instance + +import ( + "strings" +) + +// IsARMInstanceType returns true if the instance type is ARM architecture +func IsARMInstanceType(instanceType string) bool { + return strings.HasPrefix(instanceType, "a1") || + strings.HasPrefix(instanceType, "t4g") || + strings.HasPrefix(instanceType, "m6g") || + strings.HasPrefix(instanceType, "m6gd") || + strings.HasPrefix(instanceType, "c6g") || + strings.HasPrefix(instanceType, "c6gd") || + strings.HasPrefix(instanceType, "r6g") || + strings.HasPrefix(instanceType, "r6gd") +} + +// IsGPUInstanceType returns true if the instance type is GPU optimised +func IsGPUInstanceType(instanceType string) bool { + return strings.HasPrefix(instanceType, "p2") || + strings.HasPrefix(instanceType, "p3") || + strings.HasPrefix(instanceType, "p4") || + strings.HasPrefix(instanceType, "g3") || + strings.HasPrefix(instanceType, "g4") || + strings.HasPrefix(instanceType, "inf1") +} + +// IsInferentiaInstanceType returns true if the instance type requires AWS Neuron +func IsInferentiaInstanceType(instanceType string) bool { + return strings.HasPrefix(instanceType, "inf1") +} diff --git a/pkg/utils/utils.go b/pkg/utils/utils.go index 1de713e33b..1ebd47c3aa 100644 --- a/pkg/utils/utils.go +++ b/pkg/utils/utils.go @@ -9,33 +9,6 @@ import ( "github.com/pkg/errors" ) -// IsARMInstanceType returns true if the instance type is ARM architecture -func IsARMInstanceType(instanceType string) bool { - return strings.HasPrefix(instanceType, "a1") || - strings.HasPrefix(instanceType, "t4g") || - strings.HasPrefix(instanceType, "m6g") || - strings.HasPrefix(instanceType, "m6gd") || - strings.HasPrefix(instanceType, "c6g") || - strings.HasPrefix(instanceType, "c6gd") || - strings.HasPrefix(instanceType, "r6g") || - strings.HasPrefix(instanceType, "r6gd") -} - -// IsGPUInstanceType returns true if the instance type is GPU optimised -func IsGPUInstanceType(instanceType string) bool { - return strings.HasPrefix(instanceType, "p2") || - strings.HasPrefix(instanceType, "p3") || - strings.HasPrefix(instanceType, "p4") || - strings.HasPrefix(instanceType, "g3") || - strings.HasPrefix(instanceType, "g4") || - strings.HasPrefix(instanceType, "inf1") -} - -// IsInferentiaInstanceType returns true if the instance type requires AWS Neuron -func IsInferentiaInstanceType(instanceType string) bool { - return strings.HasPrefix(instanceType, "inf1") -} - var matchFirstCap = regexp.MustCompile("([0-9]+|[A-Z])") // ToKebabCase turns a CamelCase string into a kebab-case string From a31115fa444830942fde61cfe3606b8ca8fc364e Mon Sep 17 00:00:00 2001 From: cpu1 Date: Thu, 23 Sep 2021 16:04:51 +0530 Subject: [PATCH 017/124] Validate support for GPU instances --- pkg/apis/eksctl.io/v1alpha5/instance.go | 32 ++++++++++++++ pkg/apis/eksctl.io/v1alpha5/types.go | 51 +++++++++++------------ pkg/apis/eksctl.io/v1alpha5/validation.go | 13 ++++-- pkg/cfn/builder/managed_nodegroup.go | 8 ++-- pkg/eks/api.go | 30 +------------ 5 files changed, 72 insertions(+), 62 deletions(-) create mode 100644 pkg/apis/eksctl.io/v1alpha5/instance.go diff --git a/pkg/apis/eksctl.io/v1alpha5/instance.go b/pkg/apis/eksctl.io/v1alpha5/instance.go new file mode 100644 index 0000000000..407de19633 --- /dev/null +++ b/pkg/apis/eksctl.io/v1alpha5/instance.go @@ -0,0 +1,32 @@ +package v1alpha5 + +import ( + instanceutils "github.com/weaveworks/eksctl/pkg/utils/instance" +) + +// SelectInstanceType determines which instanceType is relevant for selecting an AMI +// If the nodegroup has mixed instances it will prefer a GPU instance type over a general class one +// This is to make sure that the AMI that is selected later is valid for all the types +func SelectInstanceType(np NodePool) string { + var instanceTypes []string + switch ng := np.(type) { + case *NodeGroup: + if ng.InstancesDistribution != nil { + instanceTypes = ng.InstancesDistribution.InstanceTypes + } + case *ManagedNodeGroup: + instanceTypes = ng.InstanceTypes + } + + hasMixedInstances := len(instanceTypes) > 0 + if hasMixedInstances { + for _, instanceType := range instanceTypes { + if instanceutils.IsGPUInstanceType(instanceType) { + return instanceType + } + } + return instanceTypes[0] + } + + return np.BaseNodeGroup().InstanceType +} diff --git a/pkg/apis/eksctl.io/v1alpha5/types.go b/pkg/apis/eksctl.io/v1alpha5/types.go index 3f2260f7cc..f65be77e0e 100644 --- a/pkg/apis/eksctl.io/v1alpha5/types.go +++ b/pkg/apis/eksctl.io/v1alpha5/types.go @@ -727,9 +727,9 @@ func NewClusterVPC() *ClusterVPC { CIDR: &cidr, }, ManageSharedNodeSecurityGroupRules: Enabled(), - NAT: DefaultClusterNAT(), - AutoAllocateIPv6: Disabled(), - ClusterEndpoints: &ClusterEndpoints{}, + NAT: DefaultClusterNAT(), + AutoAllocateIPv6: Disabled(), + ClusterEndpoints: &ClusterEndpoints{}, } } @@ -776,18 +776,18 @@ func NewNodeGroup() *NodeGroup { VolumeSize: &DefaultNodeVolumeSize, IAM: &NodeGroupIAM{ WithAddonPolicies: NodeGroupIAMAddonPolicies{ - ImageBuilder: Disabled(), - AutoScaler: Disabled(), - ExternalDNS: Disabled(), - CertManager: Disabled(), - AppMesh: Disabled(), - AppMeshPreview: Disabled(), - EBS: Disabled(), - FSX: Disabled(), - EFS: Disabled(), + ImageBuilder: Disabled(), + AutoScaler: Disabled(), + ExternalDNS: Disabled(), + CertManager: Disabled(), + AppMesh: Disabled(), + AppMeshPreview: Disabled(), + EBS: Disabled(), + FSX: Disabled(), + EFS: Disabled(), AWSLoadBalancerController: Disabled(), - XRay: Disabled(), - CloudWatch: Disabled(), + XRay: Disabled(), + CloudWatch: Disabled(), }, }, ScalingConfig: &ScalingConfig{}, @@ -822,22 +822,21 @@ func NewManagedNodeGroup() *ManagedNodeGroup { SSH: &NodeGroupSSH{ Allow: Disabled(), PublicKeyName: &publicKey, - EnableSSM: Disabled(), }, IAM: &NodeGroupIAM{ WithAddonPolicies: NodeGroupIAMAddonPolicies{ - ImageBuilder: Disabled(), - AutoScaler: Disabled(), - ExternalDNS: Disabled(), - CertManager: Disabled(), - AppMesh: Disabled(), - AppMeshPreview: Disabled(), - EBS: Disabled(), - FSX: Disabled(), - EFS: Disabled(), + ImageBuilder: Disabled(), + AutoScaler: Disabled(), + ExternalDNS: Disabled(), + CertManager: Disabled(), + AppMesh: Disabled(), + AppMeshPreview: Disabled(), + EBS: Disabled(), + FSX: Disabled(), + EFS: Disabled(), AWSLoadBalancerController: Disabled(), - XRay: Disabled(), - CloudWatch: Disabled(), + XRay: Disabled(), + CloudWatch: Disabled(), }, }, ScalingConfig: &ScalingConfig{}, diff --git a/pkg/apis/eksctl.io/v1alpha5/validation.go b/pkg/apis/eksctl.io/v1alpha5/validation.go index 207f3671d4..5d2bd40cdb 100644 --- a/pkg/apis/eksctl.io/v1alpha5/validation.go +++ b/pkg/apis/eksctl.io/v1alpha5/validation.go @@ -7,6 +7,8 @@ import ( "strconv" "strings" + instanceutils "github.com/weaveworks/eksctl/pkg/utils/instance" + "github.com/aws/aws-sdk-go/aws" "github.com/aws/aws-sdk-go/aws/arn" "github.com/kris-nova/logger" @@ -212,7 +214,8 @@ func PrivateOnly(ces *ClusterEndpoints) bool { return !*ces.PublicAccess && *ces.PrivateAccess } -func validateNodeGroupBase(ng *NodeGroupBase, path string) error { +func validateNodeGroupBase(np NodePool, path string) error { + ng := np.BaseNodeGroup() if ng.VolumeSize == nil { errCantSet := func(field string) error { return fmt.Errorf("%s.%s cannot be set without %s.volumeSize", path, field, path) @@ -279,6 +282,10 @@ func validateNodeGroupBase(ng *NodeGroupBase, path string) error { } } + if instanceutils.IsGPUInstanceType(SelectInstanceType(np)) && ng.AMIFamily != NodeImageFamilyAmazonLinux2 { + return errors.Errorf("GPU instance types are not supported for %s", ng.AMIFamily) + } + return nil } @@ -369,7 +376,7 @@ func validateNodeGroupName(name string) error { // ValidateNodeGroup checks compatible fields of a given nodegroup func ValidateNodeGroup(i int, ng *NodeGroup) error { path := fmt.Sprintf("nodeGroups[%d]", i) - if err := validateNodeGroupBase(ng.NodeGroupBase, path); err != nil { + if err := validateNodeGroupBase(ng, path); err != nil { return err } @@ -593,7 +600,7 @@ func ValidateManagedNodeGroup(ng *ManagedNodeGroup, index int) error { path := fmt.Sprintf("managedNodeGroups[%d]", index) - if err := validateNodeGroupBase(ng.NodeGroupBase, path); err != nil { + if err := validateNodeGroupBase(ng, path); err != nil { return err } diff --git a/pkg/cfn/builder/managed_nodegroup.go b/pkg/cfn/builder/managed_nodegroup.go index fe50c7f915..98c86da9f2 100644 --- a/pkg/cfn/builder/managed_nodegroup.go +++ b/pkg/cfn/builder/managed_nodegroup.go @@ -14,7 +14,7 @@ import ( api "github.com/weaveworks/eksctl/pkg/apis/eksctl.io/v1alpha5" "github.com/weaveworks/eksctl/pkg/nodebootstrap" - "github.com/weaveworks/eksctl/pkg/utils" + instanceutils "github.com/weaveworks/eksctl/pkg/utils/instance" "github.com/weaveworks/eksctl/pkg/vpc" ) @@ -215,7 +215,7 @@ func mapTaints(taints []api.NodeGroupTaint) ([]*gfneks.Nodegroup_Taints, error) func selectManagedInstanceType(ng *api.ManagedNodeGroup) string { if len(ng.InstanceTypes) > 0 { for _, instanceType := range ng.InstanceTypes { - if utils.IsGPUInstanceType(instanceType) { + if instanceutils.IsGPUInstanceType(instanceType) { return instanceType } } @@ -260,10 +260,10 @@ func validateLaunchTemplate(launchTemplateData *ec2.ResponseLaunchTemplateData, } func getAMIType(instanceType string) string { - if utils.IsGPUInstanceType(instanceType) { + if instanceutils.IsGPUInstanceType(instanceType) { return eks.AMITypesAl2X8664Gpu } - if utils.IsARMInstanceType(instanceType) { + if instanceutils.IsARMInstanceType(instanceType) { return eks.AMITypesAl2Arm64 } return eks.AMITypesAl2X8664 diff --git a/pkg/eks/api.go b/pkg/eks/api.go index 274d262ecc..2cfee9c18d 100644 --- a/pkg/eks/api.go +++ b/pkg/eks/api.go @@ -46,7 +46,6 @@ import ( ekscreds "github.com/weaveworks/eksctl/pkg/credentials" "github.com/weaveworks/eksctl/pkg/kubernetes" kubewrapper "github.com/weaveworks/eksctl/pkg/kubernetes" - "github.com/weaveworks/eksctl/pkg/utils" "github.com/weaveworks/eksctl/pkg/version" ) @@ -340,7 +339,7 @@ func ResolveAMI(provider api.ClusterProvider, version string, np api.NodePool) e return errors.Errorf("invalid AMI value: %q", ng.AMI) } - instanceType := SelectInstanceType(np) + instanceType := api.SelectInstanceType(np) id, err := resolver.Resolve(provider.Region(), version, instanceType, ng.AMIFamily) if err != nil { return errors.Wrap(err, "unable to determine AMI to use") @@ -352,33 +351,6 @@ func ResolveAMI(provider api.ClusterProvider, version string, np api.NodePool) e return nil } -// SelectInstanceType determines which instanceType is relevant for selecting an AMI -// If the nodegroup has mixed instances it will prefer a GPU instance type over a general class one -// This is to make sure that the AMI that is selected later is valid for all the types -func SelectInstanceType(np api.NodePool) string { - var instanceTypes []string - switch ng := np.(type) { - case *api.NodeGroup: - if ng.InstancesDistribution != nil { - instanceTypes = ng.InstancesDistribution.InstanceTypes - } - case *api.ManagedNodeGroup: - instanceTypes = ng.InstanceTypes - } - - hasMixedInstances := len(instanceTypes) > 0 - if hasMixedInstances { - for _, instanceType := range instanceTypes { - if utils.IsGPUInstanceType(instanceType) { - return instanceType - } - } - return instanceTypes[0] - } - - return np.BaseNodeGroup().InstanceType -} - func errTooFewAvailabilityZones(azs []string) error { return fmt.Errorf("only %d zones specified %v, %d are required (can be non-unique)", len(azs), azs, az.MinRequiredAvailabilityZones) } From 6daaef0eadbb1c24844d686a2b0e3f4e4b89ba2b Mon Sep 17 00:00:00 2001 From: cpu1 Date: Thu, 23 Sep 2021 16:05:09 +0530 Subject: [PATCH 018/124] Add test for GPU instance support --- .../eksctl.io/v1alpha5/gpu_validation_test.go | 91 +++++++++++++++++++ pkg/apis/eksctl.io/v1alpha5/types.go | 50 +++++----- 2 files changed, 116 insertions(+), 25 deletions(-) create mode 100644 pkg/apis/eksctl.io/v1alpha5/gpu_validation_test.go diff --git a/pkg/apis/eksctl.io/v1alpha5/gpu_validation_test.go b/pkg/apis/eksctl.io/v1alpha5/gpu_validation_test.go new file mode 100644 index 0000000000..984023d3a9 --- /dev/null +++ b/pkg/apis/eksctl.io/v1alpha5/gpu_validation_test.go @@ -0,0 +1,91 @@ +package v1alpha5_test + +import ( + "fmt" + + . "github.com/onsi/ginkgo" + . "github.com/onsi/ginkgo/extensions/table" + . "github.com/onsi/gomega" + + api "github.com/weaveworks/eksctl/pkg/apis/eksctl.io/v1alpha5" +) + +var _ = Describe("GPU instance support", func() { + + type gpuInstanceEntry struct { + gpuInstanceType string + amiFamily string + + expectUnsupportedErr bool + } + + assertValidationError := func(e gpuInstanceEntry, err error) { + if e.expectUnsupportedErr { + Expect(err).To(HaveOccurred()) + Expect(err).To(MatchError(ContainSubstring(fmt.Sprintf("GPU instance types are not supported for %s", e.amiFamily)))) + return + } + Expect(err).ToNot(HaveOccurred()) + } + + DescribeTable("managed nodegroups", func(e gpuInstanceEntry) { + mng := api.NewManagedNodeGroup() + mng.InstanceType = e.gpuInstanceType + mng.AMIFamily = e.amiFamily + mng.InstanceSelector = &api.InstanceSelector{} + assertValidationError(e, api.ValidateManagedNodeGroup(mng, 0)) + }, + Entry("AL2", gpuInstanceEntry{ + gpuInstanceType: "asdf", + amiFamily: api.NodeImageFamilyAmazonLinux2, + }), + Entry("Bottlerocket", gpuInstanceEntry{ + amiFamily: api.NodeImageFamilyBottlerocket, + gpuInstanceType: "g4dn.xlarge", + expectUnsupportedErr: true, + }), + Entry("Ubuntu2004", gpuInstanceEntry{ + amiFamily: api.NodeImageFamilyUbuntu2004, + gpuInstanceType: "g4dn.xlarge", + expectUnsupportedErr: true, + }), + ) + + DescribeTable("unmanaged nodegroups", func(e gpuInstanceEntry) { + ng := api.NewNodeGroup() + ng.InstanceType = e.gpuInstanceType + ng.AMIFamily = e.amiFamily + assertValidationError(e, api.ValidateNodeGroup(0, ng)) + + }, + Entry("AL2", gpuInstanceEntry{ + gpuInstanceType: "g4dn.xlarge", + amiFamily: api.NodeImageFamilyAmazonLinux2, + }), + Entry("Bottlerocket", gpuInstanceEntry{ + amiFamily: api.NodeImageFamilyBottlerocket, + gpuInstanceType: "g4dn.xlarge", + expectUnsupportedErr: true, + }), + Entry("Ubuntu2004", gpuInstanceEntry{ + amiFamily: api.NodeImageFamilyUbuntu2004, + gpuInstanceType: "g4dn.xlarge", + expectUnsupportedErr: true, + }), + Entry("Windows2004", gpuInstanceEntry{ + amiFamily: api.NodeImageFamilyWindowsServer2004CoreContainer, + gpuInstanceType: "p2.xlarge", + expectUnsupportedErr: true, + }), + Entry("Windows2019Core", gpuInstanceEntry{ + amiFamily: api.NodeImageFamilyWindowsServer2019CoreContainer, + gpuInstanceType: "g3.8xlarge", + expectUnsupportedErr: true, + }), + Entry("Windows2019Full", gpuInstanceEntry{ + amiFamily: api.NodeImageFamilyWindowsServer2019FullContainer, + gpuInstanceType: "p3.2xlarge", + expectUnsupportedErr: true, + }), + ) +}) diff --git a/pkg/apis/eksctl.io/v1alpha5/types.go b/pkg/apis/eksctl.io/v1alpha5/types.go index f65be77e0e..1a9c225499 100644 --- a/pkg/apis/eksctl.io/v1alpha5/types.go +++ b/pkg/apis/eksctl.io/v1alpha5/types.go @@ -727,9 +727,9 @@ func NewClusterVPC() *ClusterVPC { CIDR: &cidr, }, ManageSharedNodeSecurityGroupRules: Enabled(), - NAT: DefaultClusterNAT(), - AutoAllocateIPv6: Disabled(), - ClusterEndpoints: &ClusterEndpoints{}, + NAT: DefaultClusterNAT(), + AutoAllocateIPv6: Disabled(), + ClusterEndpoints: &ClusterEndpoints{}, } } @@ -776,18 +776,18 @@ func NewNodeGroup() *NodeGroup { VolumeSize: &DefaultNodeVolumeSize, IAM: &NodeGroupIAM{ WithAddonPolicies: NodeGroupIAMAddonPolicies{ - ImageBuilder: Disabled(), - AutoScaler: Disabled(), - ExternalDNS: Disabled(), - CertManager: Disabled(), - AppMesh: Disabled(), - AppMeshPreview: Disabled(), - EBS: Disabled(), - FSX: Disabled(), - EFS: Disabled(), + ImageBuilder: Disabled(), + AutoScaler: Disabled(), + ExternalDNS: Disabled(), + CertManager: Disabled(), + AppMesh: Disabled(), + AppMeshPreview: Disabled(), + EBS: Disabled(), + FSX: Disabled(), + EFS: Disabled(), AWSLoadBalancerController: Disabled(), - XRay: Disabled(), - CloudWatch: Disabled(), + XRay: Disabled(), + CloudWatch: Disabled(), }, }, ScalingConfig: &ScalingConfig{}, @@ -825,18 +825,18 @@ func NewManagedNodeGroup() *ManagedNodeGroup { }, IAM: &NodeGroupIAM{ WithAddonPolicies: NodeGroupIAMAddonPolicies{ - ImageBuilder: Disabled(), - AutoScaler: Disabled(), - ExternalDNS: Disabled(), - CertManager: Disabled(), - AppMesh: Disabled(), - AppMeshPreview: Disabled(), - EBS: Disabled(), - FSX: Disabled(), - EFS: Disabled(), + ImageBuilder: Disabled(), + AutoScaler: Disabled(), + ExternalDNS: Disabled(), + CertManager: Disabled(), + AppMesh: Disabled(), + AppMeshPreview: Disabled(), + EBS: Disabled(), + FSX: Disabled(), + EFS: Disabled(), AWSLoadBalancerController: Disabled(), - XRay: Disabled(), - CloudWatch: Disabled(), + XRay: Disabled(), + CloudWatch: Disabled(), }, }, ScalingConfig: &ScalingConfig{}, From 4bcff91151570a1a15a2a0d8d07ae33799500380 Mon Sep 17 00:00:00 2001 From: cpu1 Date: Mon, 27 Sep 2021 18:16:32 +0530 Subject: [PATCH 019/124] Fix integration test --- integration/tests/instance_selector/instance_selector_test.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/integration/tests/instance_selector/instance_selector_test.go b/integration/tests/instance_selector/instance_selector_test.go index d113869ff6..f6168b71a3 100644 --- a/integration/tests/instance_selector/instance_selector_test.go +++ b/integration/tests/instance_selector/instance_selector_test.go @@ -9,12 +9,12 @@ import ( . "github.com/onsi/ginkgo/extensions/table" . "github.com/onsi/gomega" "github.com/pkg/errors" - "github.com/weaveworks/eksctl/pkg/utils" "github.com/weaveworks/eksctl/integration/tests" api "github.com/weaveworks/eksctl/pkg/apis/eksctl.io/v1alpha5" "github.com/weaveworks/eksctl/pkg/eks" "github.com/weaveworks/eksctl/pkg/testutils" + instanceutils "github.com/weaveworks/eksctl/pkg/utils/instance" . "github.com/onsi/ginkgo" ) @@ -58,7 +58,7 @@ var _ = Describe("(Integration) [Instance Selector test]", func() { }, Entry("non-GPU instances", func(instanceTypes []string) { for _, instanceType := range instanceTypes { - Expect(instanceType).ToNot(Satisfy(utils.IsGPUInstanceType)) + Expect(instanceType).ToNot(Satisfy(instanceutils.IsGPUInstanceType)) } }, "--instance-selector-vcpus=8", "--instance-selector-memory=32", From a1d46cf66ecd724522463353be06f4920baf5950 Mon Sep 17 00:00:00 2001 From: Jake Klein Date: Tue, 19 Oct 2021 12:38:54 +0100 Subject: [PATCH 020/124] Bump go releaser (#4348) * bump goreleaser to 0.182.1 * bump build image --- .github/workflows/ci.yaml | 2 +- .github/workflows/integration-tests.yaml | 2 +- .github/workflows/release-candidate.yaml | 2 +- .github/workflows/release.yaml | 2 +- .github/workflows/tag-release.yaml | 2 +- .github/workflows/update-generated.yaml | 2 +- Dockerfile | 2 +- build/docker/build_image_manifest | 2 +- build/docker/image_tag | 2 +- go.mod | 84 +++++--- go.sum | 244 +++++++++++++++++------ 11 files changed, 245 insertions(+), 101 deletions(-) diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index a274a42e21..70952c0fc0 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -10,7 +10,7 @@ jobs: lint: name: Lint runs-on: ubuntu-latest - container: weaveworks/eksctl-build:a6c29f81a85a7f438c60686b01d74bec7b0dfb82 + container: weaveworks/eksctl-build:ff2eff428ff2b334c713fd07916a10db37f60d29 steps: - name: Checkout uses: actions/checkout@v2 diff --git a/.github/workflows/integration-tests.yaml b/.github/workflows/integration-tests.yaml index 805b5787bb..a18bd15b1d 100644 --- a/.github/workflows/integration-tests.yaml +++ b/.github/workflows/integration-tests.yaml @@ -10,7 +10,7 @@ jobs: name: Run integration tests environment: "Integration tests" runs-on: ubuntu-latest - container: weaveworks/eksctl-build:a6c29f81a85a7f438c60686b01d74bec7b0dfb82 + container: weaveworks/eksctl-build:ff2eff428ff2b334c713fd07916a10db37f60d29 env: SSH: "/root/.ssh" steps: diff --git a/.github/workflows/release-candidate.yaml b/.github/workflows/release-candidate.yaml index 46d142803c..fb34633960 100644 --- a/.github/workflows/release-candidate.yaml +++ b/.github/workflows/release-candidate.yaml @@ -11,7 +11,7 @@ jobs: rc: name: Trigger release candidate build runs-on: ubuntu-latest - container: weaveworks/eksctl-build:a6c29f81a85a7f438c60686b01d74bec7b0dfb82 + container: weaveworks/eksctl-build:ff2eff428ff2b334c713fd07916a10db37f60d29 steps: - uses: actions/github-script@v3 name: Get integration tests status diff --git a/.github/workflows/release.yaml b/.github/workflows/release.yaml index 6074f9ecda..4abf29e579 100644 --- a/.github/workflows/release.yaml +++ b/.github/workflows/release.yaml @@ -7,7 +7,7 @@ jobs: rc: name: Trigger release build runs-on: ubuntu-latest - container: weaveworks/eksctl-build:a6c29f81a85a7f438c60686b01d74bec7b0dfb82 + container: weaveworks/eksctl-build:ff2eff428ff2b334c713fd07916a10db37f60d29 steps: - name: Checkout uses: actions/checkout@v2 diff --git a/.github/workflows/tag-release.yaml b/.github/workflows/tag-release.yaml index dbac9c9231..061e34419c 100644 --- a/.github/workflows/tag-release.yaml +++ b/.github/workflows/tag-release.yaml @@ -18,7 +18,7 @@ jobs: name: Tag release from version environment: release runs-on: ubuntu-latest - container: weaveworks/eksctl-build:a6c29f81a85a7f438c60686b01d74bec7b0dfb82 + container: weaveworks/eksctl-build:ff2eff428ff2b334c713fd07916a10db37f60d29 steps: - name: Checkout uses: actions/checkout@v2 diff --git a/.github/workflows/update-generated.yaml b/.github/workflows/update-generated.yaml index b1afd2acbf..95fdcd9deb 100644 --- a/.github/workflows/update-generated.yaml +++ b/.github/workflows/update-generated.yaml @@ -55,7 +55,7 @@ jobs: update_aws_node: name: Update aws-node and open PR runs-on: ubuntu-latest - container: weaveworks/eksctl-build:a6c29f81a85a7f438c60686b01d74bec7b0dfb82 + container: weaveworks/eksctl-build:ff2eff428ff2b334c713fd07916a10db37f60d29 env: UPDATE_BRANCH: update-aws-node GOPRIVATE: "" diff --git a/Dockerfile b/Dockerfile index ca446e6777..90383b61d1 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,4 +1,4 @@ -ARG BUILD_IMAGE=/weaveworks/eksctl-build:a6c29f81a85a7f438c60686b01d74bec7b0dfb82 +ARG BUILD_IMAGE=/weaveworks/eksctl-build:ff2eff428ff2b334c713fd07916a10db37f60d29 FROM $BUILD_IMAGE as build WORKDIR /src diff --git a/build/docker/build_image_manifest b/build/docker/build_image_manifest index a6c29f81a8..ff2eff428f 100644 --- a/build/docker/build_image_manifest +++ b/build/docker/build_image_manifest @@ -2,7 +2,7 @@ "github.com/cloudflare/cfssl v1.6.1" "github.com/cloudflare/cfssl v1.6.1" "github.com/golangci/golangci-lint v1.42.0" -"github.com/goreleaser/goreleaser v0.177.0" +"github.com/goreleaser/goreleaser v0.182.1" "github.com/kevinburke/go-bindata v3.22.0+incompatible" "github.com/onsi/ginkgo v1.16.4" "github.com/vektra/mockery v1.1.2" diff --git a/build/docker/image_tag b/build/docker/image_tag index 6b26cce9de..d6c0fab08b 100644 --- a/build/docker/image_tag +++ b/build/docker/image_tag @@ -1 +1 @@ -a6c29f81a85a7f438c60686b01d74bec7b0dfb82 +ff2eff428ff2b334c713fd07916a10db37f60d29 diff --git a/go.mod b/go.mod index 559e24b0d5..c6e835409d 100644 --- a/go.mod +++ b/go.mod @@ -7,19 +7,19 @@ go 1.17 require ( 4d63.com/gochecknoglobals v0.0.0-20201008074935-acfc0b28355a // indirect - cloud.google.com/go v0.81.0 // indirect - cloud.google.com/go/storage v1.15.0 // indirect + cloud.google.com/go v0.94.0 // indirect + cloud.google.com/go/storage v1.16.1 // indirect code.gitea.io/sdk/gitea v0.15.0 // indirect github.com/AlekSi/pointer v1.1.0 // indirect github.com/Antonboom/errname v0.1.3 // indirect github.com/Azure/azure-pipeline-go v0.2.3 // indirect - github.com/Azure/azure-sdk-for-go v54.0.0+incompatible // indirect - github.com/Azure/azure-storage-blob-go v0.13.0 // indirect + github.com/Azure/azure-sdk-for-go v57.0.0+incompatible // indirect + github.com/Azure/azure-storage-blob-go v0.14.0 // indirect github.com/Azure/go-autorest v14.2.0+incompatible // indirect - github.com/Azure/go-autorest/autorest v0.11.18 // indirect - github.com/Azure/go-autorest/autorest/adal v0.9.13 // indirect - github.com/Azure/go-autorest/autorest/azure/auth v0.5.7 // indirect - github.com/Azure/go-autorest/autorest/azure/cli v0.4.2 // indirect + github.com/Azure/go-autorest/autorest v0.11.20 // indirect + github.com/Azure/go-autorest/autorest/adal v0.9.15 // indirect + github.com/Azure/go-autorest/autorest/azure/auth v0.5.8 // indirect + github.com/Azure/go-autorest/autorest/azure/cli v0.4.3 // indirect github.com/Azure/go-autorest/autorest/date v0.3.0 // indirect github.com/Azure/go-autorest/autorest/to v0.4.0 // indirect github.com/Azure/go-autorest/autorest/validation v0.3.1 // indirect @@ -89,7 +89,7 @@ require ( github.com/fluxcd/go-git-providers v0.2.0 github.com/fluxcd/helm-operator/pkg/install v0.0.0-20200729150005-1467489f7ee4 // helm-operator 1.2.0 github.com/form3tech-oss/jwt-go v3.2.3+incompatible // indirect - github.com/fsnotify/fsnotify v1.4.9 // indirect + github.com/fsnotify/fsnotify v1.5.1 // indirect github.com/fzipp/gocyclo v0.3.1 // indirect github.com/ghodss/yaml v1.0.0 // indirect github.com/github-release/github-release v0.10.0 @@ -118,7 +118,7 @@ require ( github.com/gofrs/flock v0.8.1 github.com/gogo/protobuf v1.3.2 // indirect github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect - github.com/golang/mock v1.5.0 // indirect + github.com/golang/mock v1.6.0 // indirect github.com/golang/protobuf v1.5.2 // indirect github.com/golang/snappy v0.0.3 // indirect github.com/golangci/check v0.0.0-20180506172741-cfe4005ccda2 // indirect @@ -141,15 +141,15 @@ require ( github.com/google/gofuzz v1.1.0 // indirect github.com/google/rpmpack v0.0.0-20210410105602-e20c988a6f5a // indirect github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 // indirect - github.com/google/uuid v1.2.0 + github.com/google/uuid v1.3.0 github.com/google/wire v0.5.0 // indirect - github.com/googleapis/gax-go/v2 v2.0.5 // indirect + github.com/googleapis/gax-go/v2 v2.1.0 // indirect github.com/googleapis/gnostic v0.4.1 // indirect github.com/gophercloud/gophercloud v0.11.1-0.20200518183226-7aec46f32c19 // indirect github.com/gordonklaus/ineffassign v0.0.0-20210225214923-2e10b2664254 // indirect github.com/goreleaser/chglog v0.1.2 // indirect github.com/goreleaser/fileglob v1.2.0 // indirect - github.com/goreleaser/goreleaser v0.177.0 + github.com/goreleaser/goreleaser v0.182.1 github.com/goreleaser/nfpm/v2 v2.6.0 // indirect github.com/gorilla/websocket v1.4.2 // indirect github.com/gostaticanalysis/analysisutil v0.4.1 // indirect @@ -182,7 +182,6 @@ require ( github.com/jmespath/go-jmespath v0.4.0 // indirect github.com/jonboulle/clockwork v0.2.2 // indirect github.com/json-iterator/go v1.1.11 // indirect - github.com/jstemmer/go-junit-report v0.9.1 // indirect github.com/julz/importas v0.0.0-20210419104244-841f0c0fe66d // indirect github.com/justinbarrick/go-k8s-portforward v1.0.4-0.20200904152830-b575325c1855 github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51 @@ -311,27 +310,26 @@ require ( go.hein.dev/go-version v0.1.0 // indirect go.opencensus.io v0.23.0 // indirect go.starlark.net v0.0.0-20200306205701-8dd3e2ee1dd5 // indirect - go.uber.org/atomic v1.7.0 // indirect + go.uber.org/atomic v1.9.0 // indirect go.uber.org/multierr v1.7.0 // indirect - go.uber.org/zap v1.17.0 // indirect - gocloud.dev v0.23.0 // indirect - golang.org/x/crypto v0.0.0-20210513164829-c07d793c2f9a // indirect - golang.org/x/lint v0.0.0-20210508222113-6edffad5e616 // indirect - golang.org/x/mod v0.4.2 // indirect - golang.org/x/net v0.0.0-20210614182718-04defd469f4e // indirect - golang.org/x/oauth2 v0.0.0-20210628180205-a41e5a781914 // indirect + go.uber.org/zap v1.19.0 // indirect + gocloud.dev v0.24.0 // indirect + golang.org/x/crypto v0.0.0-20210817164053-32db794688a5 // indirect + golang.org/x/mod v0.5.0 // indirect + golang.org/x/net v0.0.0-20210825183410-e898025ed96a // indirect + golang.org/x/oauth2 v0.0.0-20210819190943-2bc19b11175f // indirect golang.org/x/sync v0.0.0-20210220032951-036812b2e83c // indirect - golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c // indirect + golang.org/x/sys v0.0.0-20210831042530-f4d43177bf5e // indirect golang.org/x/term v0.0.0-20210220032956-6a3ed077a48d // indirect - golang.org/x/text v0.3.6 // indirect - golang.org/x/time v0.0.0-20210220033141-f8bda1e9f3ba // indirect + golang.org/x/text v0.3.7 // indirect + golang.org/x/time v0.0.0-20210723032227-1f47c861a9ac // indirect golang.org/x/tools v0.1.5 golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 // indirect - google.golang.org/api v0.46.0 // indirect + google.golang.org/api v0.56.0 // indirect google.golang.org/appengine v1.6.7 // indirect - google.golang.org/genproto v0.0.0-20210602131652-f16073e35f0c // indirect - google.golang.org/grpc v1.38.0 // indirect - google.golang.org/protobuf v1.26.0 // indirect + google.golang.org/genproto v0.0.0-20210831024726-fe130286e0e2 // indirect + google.golang.org/grpc v1.40.0 // indirect + google.golang.org/protobuf v1.27.1 // indirect gopkg.in/cheggaaa/pb.v1 v1.0.28 // indirect gopkg.in/gcfg.v1 v1.2.3 // indirect gopkg.in/inf.v0 v0.9.1 // indirect @@ -339,7 +337,7 @@ require ( gopkg.in/square/go-jose.v2 v2.3.1 // indirect gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 // indirect gopkg.in/warnings.v0 v0.1.2 // indirect - gopkg.in/yaml.v2 v2.4.0 // indirect + gopkg.in/yaml.v2 v2.4.0 gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b // indirect honnef.co/go/tools v0.2.1 // indirect k8s.io/api v0.21.2 @@ -373,16 +371,36 @@ require ( ) require ( + cloud.google.com/go/kms v0.1.0 // indirect + github.com/DisgoOrg/disgohook v1.4.3 // indirect + github.com/DisgoOrg/log v1.1.0 // indirect + github.com/DisgoOrg/restclient v1.2.7 // indirect + github.com/atc0005/go-teams-notify/v2 v2.6.0 // indirect + github.com/aws/aws-sdk-go-v2 v1.9.0 // indirect + github.com/aws/aws-sdk-go-v2/config v1.7.0 // indirect + github.com/aws/aws-sdk-go-v2/credentials v1.4.0 // indirect + github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.5.0 // indirect + github.com/aws/aws-sdk-go-v2/internal/ini v1.2.2 // indirect + github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.3.0 // indirect + github.com/aws/aws-sdk-go-v2/service/kms v1.5.0 // indirect + github.com/aws/aws-sdk-go-v2/service/sso v1.4.0 // indirect + github.com/aws/aws-sdk-go-v2/service/sts v1.7.0 // indirect + github.com/aws/smithy-go v1.8.0 // indirect github.com/census-instrumentation/opencensus-proto v0.3.0 // indirect + github.com/cespare/xxhash v1.1.0 // indirect github.com/cncf/udpa/go v0.0.0-20210322005330-6414d713912e // indirect + github.com/cncf/xds/go v0.0.0-20210312221358-fbca930ec8ed // indirect github.com/coreos/go-systemd/v22 v22.3.2 // indirect - github.com/envoyproxy/go-control-plane v0.9.9-0.20210217033140-668b12f5399d // indirect + github.com/envoyproxy/go-control-plane v0.9.9-0.20210512163311-63b5d3c536b0 // indirect github.com/envoyproxy/protoc-gen-validate v0.6.1 // indirect github.com/fullstorydev/grpcurl v1.8.1 // indirect + github.com/go-telegram-bot-api/telegram-bot-api v4.6.4+incompatible // indirect + github.com/golang-jwt/jwt/v4 v4.0.0 // indirect github.com/jhump/protoreflect v1.8.2 // indirect github.com/rivo/uniseg v0.2.0 // indirect github.com/slack-go/slack v0.9.4 // indirect - github.com/vartanbeno/go-reddit/v2 v2.0.1 // indirect + github.com/technoweenie/multipartstreamer v1.0.1 // indirect + github.com/vartanbeno/go-reddit/v2 v2.0.0 // indirect go.etcd.io/etcd/api/v3 v3.5.0 // indirect go.etcd.io/etcd/client/pkg/v3 v3.5.0 // indirect go.etcd.io/etcd/client/v2 v2.305.0 // indirect @@ -393,6 +411,8 @@ require ( go.etcd.io/etcd/server/v3 v3.5.0-alpha.0 // indirect go.etcd.io/etcd/tests/v3 v3.5.0-alpha.0 // indirect go.etcd.io/etcd/v3 v3.5.0-alpha.0 // indirect + gopkg.in/alexcesaro/quotedprintable.v3 v3.0.0-20150716171945-2caba252f4dc // indirect + gopkg.in/mail.v2 v2.3.1 // indirect ) replace ( diff --git a/go.sum b/go.sum index c155a80ccb..e7fa3c3df2 100644 --- a/go.sum +++ b/go.sum @@ -28,8 +28,19 @@ cloud.google.com/go v0.74.0/go.mod h1:VV1xSbzvo+9QJOxLDaJfTjx5e+MePCpCWwvftOeQmW cloud.google.com/go v0.75.0/go.mod h1:VGuuCn7PG0dwsd5XPVm2Mm3wlh3EL55/79EKB6hlPTY= cloud.google.com/go v0.78.0/go.mod h1:QjdrLG0uq+YwhjoVOLsS1t7TW8fs36kLs4XO5R5ECHg= cloud.google.com/go v0.79.0/go.mod h1:3bzgcEeQlzbuEAYu4mrWhKqWjmpprinYgKJLgKHnbb8= -cloud.google.com/go v0.81.0 h1:at8Tk2zUz63cLPR0JPWm5vp77pEZmzxEQBEfRKn1VV8= cloud.google.com/go v0.81.0/go.mod h1:mk/AM35KwGk/Nm2YSeZbxXdrNK3KZOYHmLkOqC2V6E0= +cloud.google.com/go v0.82.0/go.mod h1:vlKccHJGuFBFufnAnuB08dfEH9Y3H7dzDzRECFdC2TA= +cloud.google.com/go v0.83.0/go.mod h1:Z7MJUsANfY0pYPdw0lbnivPx4/vhy/e2FEkSkF7vAVY= +cloud.google.com/go v0.84.0/go.mod h1:RazrYuxIK6Kb7YrzzhPoLmCVzl7Sup4NrbKPg8KHSUM= +cloud.google.com/go v0.87.0/go.mod h1:TpDYlFy7vuLzZMMZ+B6iRiELaY7z/gJPaqbMx6mlWcY= +cloud.google.com/go v0.88.0/go.mod h1:dnKwfYbP9hQhefiUvpbcAyoGSHUrOxR20JVElLiUvEY= +cloud.google.com/go v0.89.0/go.mod h1:kRX0mNRHe0e2rC6oNakvwQqzyDmg57xJ+SZU1eT2aDQ= +cloud.google.com/go v0.90.0/go.mod h1:kRX0mNRHe0e2rC6oNakvwQqzyDmg57xJ+SZU1eT2aDQ= +cloud.google.com/go v0.92.2/go.mod h1:8utlLll2EF5XMAV15woO4lSbWQlk8rer9aLOfLh7+YI= +cloud.google.com/go v0.92.3/go.mod h1:8utlLll2EF5XMAV15woO4lSbWQlk8rer9aLOfLh7+YI= +cloud.google.com/go v0.93.3/go.mod h1:8utlLll2EF5XMAV15woO4lSbWQlk8rer9aLOfLh7+YI= +cloud.google.com/go v0.94.0 h1:QDB2MZHqjTt0hGKnoEWyG/iWykue/lvkLdogLgrg10U= +cloud.google.com/go v0.94.0/go.mod h1:qAlAugsXlC+JWO+Bke5vCtc9ONxjQT3drlTTnAplMW4= cloud.google.com/go/bigquery v1.0.1/go.mod h1:i/xbL2UlR5RvWAURpBYZTtm/cXjCha9lbfbpx4poX+o= cloud.google.com/go/bigquery v1.3.0/go.mod h1:PjpwJnslEMmckchkHFfq+HTD2DmtT67aNFKH1/VBDHE= cloud.google.com/go/bigquery v1.4.0/go.mod h1:S8dzgnTigyfTmLBfrtrhyYhwRxG72rYxvftPBK2Dvzc= @@ -40,12 +51,16 @@ cloud.google.com/go/datastore v1.0.0/go.mod h1:LXYbyblFSglQ5pkeyhO+Qmw7ukd3C+pD7 cloud.google.com/go/datastore v1.1.0/go.mod h1:umbIZjpQpHh4hmRpGhH4tLFup+FVzqBi1b3c64qFpCk= cloud.google.com/go/firestore v1.1.0/go.mod h1:ulACoGHTpvq5r8rxGJ4ddJZBZqakUQqClKRT5SZwBmk= cloud.google.com/go/firestore v1.5.0/go.mod h1:c4nNYR1qdq7eaZ+jSc5fonrQN2k3M7sWATcYTiakjEo= +cloud.google.com/go/kms v0.1.0 h1:VXAb5OzejDcyhFzIDeZ5n5AUdlsFnCyexuascIwWMj0= +cloud.google.com/go/kms v0.1.0/go.mod h1:8Qp8PCAypHg4FdmlyW1QRAv09BGQ9Uzh7JnmIZxPk+c= +cloud.google.com/go/monitoring v0.1.0/go.mod h1:Hpm3XfzJv+UTiXzCG5Ffp0wijzHTC7Cv4eR7o3x/fEE= cloud.google.com/go/pubsub v1.0.1/go.mod h1:R0Gpsv3s54REJCy4fxDixWD93lHJMoZTyQ2kNxGRt3I= cloud.google.com/go/pubsub v1.1.0/go.mod h1:EwwdRX2sKPjnvnqCa270oGRyludottCI76h+R3AArQw= cloud.google.com/go/pubsub v1.2.0/go.mod h1:jhfEVHT8odbXTkndysNHCcx0awwzvfOlguIAii9o8iA= cloud.google.com/go/pubsub v1.3.1/go.mod h1:i+ucay31+CNRpDW4Lu78I4xXG+O1r/MAHgjpRVR+TSU= cloud.google.com/go/pubsub v1.5.0/go.mod h1:ZEwJccE3z93Z2HWvstpri00jOg7oO4UZDtKhwDwqF0w= -cloud.google.com/go/pubsub v1.10.3/go.mod h1:FUcc28GpGxxACoklPsE1sCtbkY4Ix+ro7yvw+h82Jn4= +cloud.google.com/go/pubsub v1.16.0/go.mod h1:6A8EfoWZ/lUvCWStKGwAWauJZSiuV0Mkmu6WilK/TxQ= +cloud.google.com/go/secretmanager v0.1.0/go.mod h1:3nGKHvnzDUVit7U0S9KAKJ4aOsO1xtwRG+7ey5LK1bM= cloud.google.com/go/spanner v1.7.0/go.mod h1:sd3K2gZ9Fd0vMPLXzeCrF6fq4i63Q7aTLW/lBIfBkIk= cloud.google.com/go/spanner v1.17.0/go.mod h1:+17t2ixFwRG4lWRwE+5kipDR9Ef07Jkmc8z0IbMDKUs= cloud.google.com/go/storage v1.0.0/go.mod h1:IhtSnM/ZTZV8YYJWCY8RULGVqBDmpoyjwiyrjsg+URw= @@ -53,8 +68,9 @@ cloud.google.com/go/storage v1.5.0/go.mod h1:tpKbwo567HUNpVclU5sGELwQWBDZ8gh0Zeo cloud.google.com/go/storage v1.6.0/go.mod h1:N7U0C8pVQ/+NIKOBQyamJIeKQKkZ+mxpohlUTyfDhBk= cloud.google.com/go/storage v1.8.0/go.mod h1:Wv1Oy7z6Yz3DshWRJFhqM/UCfaWIRTdp0RXyy7KQOVs= cloud.google.com/go/storage v1.10.0/go.mod h1:FLPqc6j+Ki4BU591ie1oL6qBQGu2Bl/tZ9ullr3+Kg0= -cloud.google.com/go/storage v1.15.0 h1:Ljj+ZXVEhCr/1+4ZhvtteN1ND7UUsNTlduGclLh8GO0= -cloud.google.com/go/storage v1.15.0/go.mod h1:mjjQMoxxyGH7Jr8K5qrx6N2O0AHsczI61sMNn03GIZI= +cloud.google.com/go/storage v1.16.1 h1:sMEIc4wxvoY3NXG7Rn9iP7jb/2buJgWR1vNXCR/UPfs= +cloud.google.com/go/storage v1.16.1/go.mod h1:LaNorbty3ehnU3rEjXSNV/NRgQA0O8Y+uh6bPe5UOk4= +cloud.google.com/go/trace v0.1.0/go.mod h1:wxEwsoeRVPbeSkt7ZC9nWCgmoKQRAoySN7XHW2AmI7g= code.gitea.io/gitea-vet v0.2.1/go.mod h1:zcNbT/aJEmivCAhfmkHOlT645KNOf9W2KnkLgFjGGfE= code.gitea.io/sdk/gitea v0.11.3/go.mod h1:z3uwDV/b9Ls47NGukYM9XhnHtqPh/J+t40lsUrR6JDY= code.gitea.io/sdk/gitea v0.15.0 h1:tsNhxDM/2N1Ohv1Xq5UWrht/esg0WmtRj4wsHVHriTg= @@ -65,6 +81,7 @@ contrib.go.opencensus.io/exporter/ocagent v0.5.0/go.mod h1:ImxhfLRpxoYiSq891pBrL contrib.go.opencensus.io/exporter/stackdriver v0.12.1/go.mod h1:iwB6wGarfphGGe/e5CWqyUk/cLzKnWsOKPVW3no6OTw= contrib.go.opencensus.io/exporter/stackdriver v0.13.4/go.mod h1:aXENhDJ1Y4lIg4EUaVTwzvYETVNZk10Pu26tevFKLUc= contrib.go.opencensus.io/exporter/stackdriver v0.13.5/go.mod h1:aXENhDJ1Y4lIg4EUaVTwzvYETVNZk10Pu26tevFKLUc= +contrib.go.opencensus.io/exporter/stackdriver v0.13.8/go.mod h1:huNtlWx75MwO7qMs0KrMxPZXzNNWebav1Sq/pm02JdQ= contrib.go.opencensus.io/integrations/ocsql v0.1.4/go.mod h1:8DsSdjz3F+APR+0z0WkU1aRorQCFfRxvqjUUPMbF3fE= contrib.go.opencensus.io/integrations/ocsql v0.1.7/go.mod h1:8DsSdjz3F+APR+0z0WkU1aRorQCFfRxvqjUUPMbF3fE= contrib.go.opencensus.io/resource v0.1.1/go.mod h1:F361eGI91LCmW1I/Saf+rX0+OFcigGlFvXwEGEnkRLA= @@ -75,6 +92,7 @@ github.com/Antonboom/errname v0.1.3 h1:qKV8gSzPzBqrG/q0dgraZXJCymWt6KuD9+Y7K7xtz github.com/Antonboom/errname v0.1.3/go.mod h1:jRXo3m0E0EuCnK3wbsSVH3X55Z4iTDLl6ZfCxwFj4TM= github.com/Azure/azure-amqp-common-go/v2 v2.1.0/go.mod h1:R8rea+gJRuJR6QxTir/XuEd+YuKoUiazDC/N96FiDEU= github.com/Azure/azure-amqp-common-go/v3 v3.1.0/go.mod h1:PBIGdzcO1teYoufTKMcGibdKaYZv4avS+O6LNIp8bq0= +github.com/Azure/azure-amqp-common-go/v3 v3.1.1/go.mod h1:YsDaPfaO9Ub2XeSKdIy2DfwuiQlHQCauHJwSqtrkECI= github.com/Azure/azure-pipeline-go v0.2.1/go.mod h1:UGSo8XybXnIGZ3epmeBw7Jdz+HiUVpqIlpz/HKHylF4= github.com/Azure/azure-pipeline-go v0.2.3 h1:7U9HBg1JFK3jHl5qmo4CTZKFTVgMwdFHMVtCdfBE21U= github.com/Azure/azure-pipeline-go v0.2.3/go.mod h1:x841ezTBIMG6O3lAcl8ATHnsOPVl2bqk7S3ta6S6u4k= @@ -82,16 +100,16 @@ github.com/Azure/azure-sdk-for-go v29.0.0+incompatible/go.mod h1:9XXNKU+eRnpl9mo github.com/Azure/azure-sdk-for-go v30.1.0+incompatible/go.mod h1:9XXNKU+eRnpl9moKnB4QOLf1HestfXbmab5FXxiDBjc= github.com/Azure/azure-sdk-for-go v43.0.0+incompatible/go.mod h1:9XXNKU+eRnpl9moKnB4QOLf1HestfXbmab5FXxiDBjc= github.com/Azure/azure-sdk-for-go v51.1.0+incompatible/go.mod h1:9XXNKU+eRnpl9moKnB4QOLf1HestfXbmab5FXxiDBjc= -github.com/Azure/azure-sdk-for-go v54.0.0+incompatible h1:Bq3L9LF0DHCexlT0fccwxgrOMfjHx8LGz+d+L7gGQv4= -github.com/Azure/azure-sdk-for-go v54.0.0+incompatible/go.mod h1:9XXNKU+eRnpl9moKnB4QOLf1HestfXbmab5FXxiDBjc= +github.com/Azure/azure-sdk-for-go v57.0.0+incompatible h1:isVki3PbIFrwKvKdVP1byxo73/pt+Nn174YxW1k4PNw= +github.com/Azure/azure-sdk-for-go v57.0.0+incompatible/go.mod h1:9XXNKU+eRnpl9moKnB4QOLf1HestfXbmab5FXxiDBjc= github.com/Azure/azure-service-bus-go v0.9.1/go.mod h1:yzBx6/BUGfjfeqbRZny9AQIbIe3AcV9WZbAdpkoXOa0= -github.com/Azure/azure-service-bus-go v0.10.11/go.mod h1:AWw9eTTWZVZyvgpPahD1ybz3a8/vT3GsJDS8KYex55U= +github.com/Azure/azure-service-bus-go v0.10.16/go.mod h1:MlkLwGGf1ewcx5jZadn0gUEty+tTg0RaElr6bPf+QhI= github.com/Azure/azure-storage-blob-go v0.8.0/go.mod h1:lPI3aLPpuLTeUwh1sViKXFxwl2B6teiRqI0deQUvsw0= -github.com/Azure/azure-storage-blob-go v0.13.0 h1:lgWHvFh+UYBNVQLFHXkvul2f6yOPA9PIH82RTG2cSwc= -github.com/Azure/azure-storage-blob-go v0.13.0/go.mod h1:pA9kNqtjUeQF2zOSu4s//nUdBD+e64lEuc4sVnuOfNs= +github.com/Azure/azure-storage-blob-go v0.14.0 h1:1BCg74AmVdYwO3dlKwtFU1V0wU2PZdREkXvAmZJRUlM= +github.com/Azure/azure-storage-blob-go v0.14.0/go.mod h1:SMqIBi+SuiQH32bvyjngEewEeXoPfKMgWlBDaYf6fck= github.com/Azure/go-amqp v0.13.0/go.mod h1:qj+o8xPCz9tMSbQ83Vp8boHahuRDl5mkNHyt1xlxUTs= -github.com/Azure/go-amqp v0.13.4/go.mod h1:wbpCKA8tR5MLgRyIu+bb+S6ECdIDdYJ0NlpFE9xsBPI= -github.com/Azure/go-amqp v0.13.7/go.mod h1:wbpCKA8tR5MLgRyIu+bb+S6ECdIDdYJ0NlpFE9xsBPI= +github.com/Azure/go-amqp v0.13.11/go.mod h1:D5ZrjQqB1dyp1A+G73xeL/kNn7D5qHJIIsNNps7YNmk= +github.com/Azure/go-amqp v0.13.12/go.mod h1:D5ZrjQqB1dyp1A+G73xeL/kNn7D5qHJIIsNNps7YNmk= github.com/Azure/go-ansiterm v0.0.0-20170929234023-d6e3b3328b78/go.mod h1:LmzpDX56iTiv29bbRTIsUNlaFfuhWRQBWjQdVyAevI8= github.com/Azure/go-autorest v12.0.0+incompatible/go.mod h1:r+4oMnoxhatjLLJ6zxSWATqVooLgysK6ZNox3g/xq24= github.com/Azure/go-autorest v14.2.0+incompatible h1:V5VMDjClD3GiElqLWO7mz2MxNAK/vTfRHdAubSIPRgs= @@ -102,20 +120,23 @@ github.com/Azure/go-autorest/autorest v0.11.3/go.mod h1:JFgpikqFJ/MleTTxwepExTKn github.com/Azure/go-autorest/autorest v0.11.4/go.mod h1:JFgpikqFJ/MleTTxwepExTKnFUKKszPS8UavbQYUMuw= github.com/Azure/go-autorest/autorest v0.11.12/go.mod h1:eipySxLmqSyC5s5k1CLupqet0PSENBEDP93LQ9a8QYw= github.com/Azure/go-autorest/autorest v0.11.17/go.mod h1:eipySxLmqSyC5s5k1CLupqet0PSENBEDP93LQ9a8QYw= -github.com/Azure/go-autorest/autorest v0.11.18 h1:90Y4srNYrwOtAgVo3ndrQkTYn6kf1Eg/AjTFJ8Is2aM= github.com/Azure/go-autorest/autorest v0.11.18/go.mod h1:dSiJPy22c3u0OtOKDNttNgqpNFY/GeWa7GH/Pz56QRA= +github.com/Azure/go-autorest/autorest v0.11.20 h1:s8H1PbCZSqg/DH7JMlOz6YMig6htWLNPsjDdlLqCx3M= +github.com/Azure/go-autorest/autorest v0.11.20/go.mod h1:o3tqFY+QR40VOlk+pV4d77mORO64jOXSgEnPQgLK6JY= github.com/Azure/go-autorest/autorest/adal v0.5.0/go.mod h1:8Z9fGy2MpX0PvDjB1pEgQTmVqjGhiHBW7RJJEciWzS0= github.com/Azure/go-autorest/autorest/adal v0.8.2/go.mod h1:ZjhuQClTqx435SRJ2iMlOxPYt3d2C/T/7TiQCVZSn3Q= github.com/Azure/go-autorest/autorest/adal v0.9.0/go.mod h1:/c022QCutn2P7uY+/oQWWNcK9YU+MH96NgK+jErpbcg= -github.com/Azure/go-autorest/autorest/adal v0.9.2/go.mod h1:/3SMAM86bP6wC9Ev35peQDUeqFZBMH07vvUOmg4z/fE= github.com/Azure/go-autorest/autorest/adal v0.9.5/go.mod h1:B7KF7jKIeC9Mct5spmyCB/A8CG/sEz1vwIRGv/bbw7A= github.com/Azure/go-autorest/autorest/adal v0.9.11/go.mod h1:nBKAnTomx8gDtl+3ZCJv2v0KACFHWTB2drffI1B68Pk= -github.com/Azure/go-autorest/autorest/adal v0.9.13 h1:Mp5hbtOePIzM8pJVRa3YLrWWmZtoxRXqUEzCfJt3+/Q= github.com/Azure/go-autorest/autorest/adal v0.9.13/go.mod h1:W/MM4U6nLxnIskrw4UwWzlHfGjwUS50aOsc/I3yuU8M= -github.com/Azure/go-autorest/autorest/azure/auth v0.5.7 h1:8DQB8yl7aLQuP+nuR5e2RO6454OvFlSTXXaNHshc16s= -github.com/Azure/go-autorest/autorest/azure/auth v0.5.7/go.mod h1:AkzUsqkrdmNhfP2i54HqINVQopw0CLDnvHpJ88Zz1eI= -github.com/Azure/go-autorest/autorest/azure/cli v0.4.2 h1:dMOmEJfkLKW/7JsokJqkyoYSgmR08hi9KrhjZb+JALY= +github.com/Azure/go-autorest/autorest/adal v0.9.14/go.mod h1:W/MM4U6nLxnIskrw4UwWzlHfGjwUS50aOsc/I3yuU8M= +github.com/Azure/go-autorest/autorest/adal v0.9.15 h1:X+p2GF0GWyOiSmqohIaEeuNFNDY4I4EOlVuUQvFdWMk= +github.com/Azure/go-autorest/autorest/adal v0.9.15/go.mod h1:tGMin8I49Yij6AQ+rvV+Xa/zwxYQB5hmsd6DkfAx2+A= +github.com/Azure/go-autorest/autorest/azure/auth v0.5.8 h1:TzPg6B6fTZ0G1zBf3T54aI7p3cAT6u//TOXGPmFMOXg= +github.com/Azure/go-autorest/autorest/azure/auth v0.5.8/go.mod h1:kxyKZTSfKh8OVFWPAgOgQ/frrJgeYQJPyR5fLFmXko4= github.com/Azure/go-autorest/autorest/azure/cli v0.4.2/go.mod h1:7qkJkT+j6b+hIpzMOwPChJhTqS8VbsqqgULzMNRugoM= +github.com/Azure/go-autorest/autorest/azure/cli v0.4.3 h1:DOhB+nXkF7LN0JfBGB5YtCF6QLK8mLe4psaHF7ZQEKM= +github.com/Azure/go-autorest/autorest/azure/cli v0.4.3/go.mod h1:yAQ2b6eP/CmLPnmLvxtT1ALIY3OR1oFcCqVBi8vHiTc= github.com/Azure/go-autorest/autorest/date v0.1.0/go.mod h1:plvfp3oPSKwf2DNjlBjWF/7vwR+cUD/ELuzDCXwHUVA= github.com/Azure/go-autorest/autorest/date v0.2.0/go.mod h1:vcORJHLJEh643/Ioh9+vPmf1Ij9AEBM5FuBIXLmIy0g= github.com/Azure/go-autorest/autorest/date v0.3.0 h1:7gUk1U5M/CQbp9WoqinNzJar+8KY+LPI6wiWrP/myHw= @@ -143,12 +164,18 @@ github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03 github.com/BurntSushi/toml v0.4.1 h1:GaI7EiDXDRfa8VshkTj7Fym7ha+y8/XxIgD2okUIjLw= github.com/BurntSushi/toml v0.4.1/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ= github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= +github.com/DisgoOrg/disgohook v1.4.3 h1:JtZiV0jAku9NZRYD6wVH7tWY1617rh4tRqn4ihTUJRc= +github.com/DisgoOrg/disgohook v1.4.3/go.mod h1:aHNyBHq1pBbdWrkCq3ZCSBeavUoGWZAAT4+609EcrvU= +github.com/DisgoOrg/log v1.1.0 h1:a6hLfVSDuTFJc5AKQ8FDYQ5TASnwk3tciUyXThm1CR4= +github.com/DisgoOrg/log v1.1.0/go.mod h1:Qihgz6fax3JCfuO7vxVavL0LyHS0sUdQ9OmykQ2fiQs= +github.com/DisgoOrg/restclient v1.2.7 h1:A8ltFP+8O2q9ZTk/vRmlQRvH2cbcnaacUV2uXWFcONQ= +github.com/DisgoOrg/restclient v1.2.7/go.mod h1:2pc/htya/5kjxvWNYya98sb8B4mexobxmWvhTiWPt94= github.com/Djarvur/go-err113 v0.0.0-20210108212216-aea10b59be24 h1:sHglBQTwgx+rWPdisA5ynNEsoARbiCBOyGcJM4/OzsM= github.com/Djarvur/go-err113 v0.0.0-20210108212216-aea10b59be24/go.mod h1:4UJr5HIiMZrwgkSPdsjy2uOQExX/WEILpIrO9UPGuXs= github.com/GeertJohan/go.incremental v1.0.0/go.mod h1:6fAjUhbVuX1KcMD3c8TEgVUqmo4seqhv0i0kdATSkM0= github.com/GeertJohan/go.rice v1.0.2/go.mod h1:af5vUNlDNkCjOZeSGFgIJxDje9qdjsO6hshx0gTmZt4= github.com/GoogleCloudPlatform/cloudsql-proxy v0.0.0-20191009163259-e802c2cb94ae/go.mod h1:mjwGPas4yKduTyubHvD1Atl9r1rUq8DfVy+gkVvZ+oo= -github.com/GoogleCloudPlatform/cloudsql-proxy v1.22.0/go.mod h1:mAm5O/zik2RFmcpigNjg6nMotDL8ZXJaxKzgGVcSMFA= +github.com/GoogleCloudPlatform/cloudsql-proxy v1.24.0/go.mod h1:3tx938GhY4FC+E1KT/jNjDw7Z5qxAEtIiERJ2sXjnII= github.com/GoogleCloudPlatform/k8s-cloud-provider v0.0.0-20200415212048-7901bc822317 h1:JhyuWIqYrstW7KHMjk/fTqU0xtMpBOHuiTA2FVc7L4E= github.com/GoogleCloudPlatform/k8s-cloud-provider v0.0.0-20200415212048-7901bc822317/go.mod h1:DF8FZRxMHMGv/vP2lQP6h+dYzzjpuRn24VeRiYn3qjQ= github.com/JeffAshton/win_pdh v0.0.0-20161109143554-76bb4ee9f0ab/go.mod h1:3VYc5hodBMJ5+l/7J4xAyMeuM2PNuepvHlGs8yilUCA= @@ -178,6 +205,7 @@ github.com/Microsoft/go-winio v0.4.16/go.mod h1:XB6nPKklQyQ7GC9LdcBEcBl8PF76WugX github.com/Microsoft/hcsshim v0.8.10-0.20200715222032-5eafd1556990/go.mod h1:ay/0dTb7NsG8QMDfsRfLHgZo/6xAJShLe1+ePPflihk= github.com/NYTimes/gziphandler v0.0.0-20170623195520-56545f4a5d46/go.mod h1:3wb06e3pkSAbeQ52E9H9iFoQsEEwGN64994WTCIhntQ= github.com/NYTimes/gziphandler v1.1.1/go.mod h1:n/CVRwUEOgIxrgPvAQhUUr9oeUtvrhMomdKFjzJNB0c= +github.com/OneOfOne/xxhash v1.2.2 h1:KMrpdQIwFcEqXDklaen+P1axHaj9BSKzvpUUfnHldSE= github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU= github.com/OpenPeeDeeP/depguard v1.0.1 h1:VlW4R6jmBIv3/u1JNlawEvJMM4J+dPORPaZasQee8Us= github.com/OpenPeeDeeP/depguard v1.0.1/go.mod h1:xsIw86fROiiwelg+jB2uM9PiKihMMmUx/1V+TNhjQvM= @@ -247,6 +275,8 @@ github.com/ashanbrown/forbidigo v1.2.0 h1:RMlEFupPCxQ1IogYOQUnIQwGEUGK8g5vAPMRyJ github.com/ashanbrown/forbidigo v1.2.0/go.mod h1:vVW7PEdqEFqapJe95xHkTfB1+XvZXBFg8t0sG2FIxmI= github.com/ashanbrown/makezero v0.0.0-20210520155254-b6261585ddde h1:YOsoVXsZQPA9aOTy1g0lAJv5VzZUvwQuZqug8XPeqfM= github.com/ashanbrown/makezero v0.0.0-20210520155254-b6261585ddde/go.mod h1:oG9Dnez7/ESBqc4EdrdNlryeo7d0KcW1ftXHm7nU/UU= +github.com/atc0005/go-teams-notify/v2 v2.6.0 h1:YegKDWbjlatR0fP2yHsQYXzTcUGNJXhm1/OiCgbyysc= +github.com/atc0005/go-teams-notify/v2 v2.6.0/go.mod h1:xo6GejLDHn3tWBA181F8LrllIL0xC1uRsRxq7YNXaaY= github.com/auth0/go-jwt-middleware v0.0.0-20170425171159-5493cabe49f7/go.mod h1:LWMyo4iOLWXHGdBki7NIht1kHru/0wM179h+d3g8ATM= github.com/aws/amazon-ec2-instance-selector/v2 v2.0.1/go.mod h1:juzWzDAyOHbufrohZ77l2VW+CEgtXIm2SzrTVMmfJy8= github.com/aws/amazon-ec2-instance-selector/v2 v2.0.3-0.20210303155736-3e43512d88f8 h1:qR505xKnVxbA/jNh61AoQRnbWlL0b5a58ZgU79AX+VM= @@ -267,10 +297,33 @@ github.com/aws/aws-sdk-go v1.31.12/go.mod h1:5zCpMtNQVjRREroY7sYe8lOMRSxkhG6MZve github.com/aws/aws-sdk-go v1.35.24/go.mod h1:tlPOdRjfxPBpNIwqDj61rmsnA85v9jc0Ps9+muhnW+k= github.com/aws/aws-sdk-go v1.36.0/go.mod h1:hcU610XS61/+aQV88ixoOzUoG7v3b31pl2zKMmprdro= github.com/aws/aws-sdk-go v1.36.30/go.mod h1:hcU610XS61/+aQV88ixoOzUoG7v3b31pl2zKMmprdro= -github.com/aws/aws-sdk-go v1.38.35/go.mod h1:hcU610XS61/+aQV88ixoOzUoG7v3b31pl2zKMmprdro= +github.com/aws/aws-sdk-go v1.37.0/go.mod h1:hcU610XS61/+aQV88ixoOzUoG7v3b31pl2zKMmprdro= +github.com/aws/aws-sdk-go v1.40.34/go.mod h1:585smgzpB/KqRA+K3y/NL/oYRqQvpNJYvLm+LY1U59Q= github.com/aws/aws-sdk-go v1.40.38 h1:kl3iIW0h/JEBFjSBcAxDsiRbKMPz4aI5FJIHMCAQ+J0= github.com/aws/aws-sdk-go v1.40.38/go.mod h1:585smgzpB/KqRA+K3y/NL/oYRqQvpNJYvLm+LY1U59Q= github.com/aws/aws-sdk-go-v2 v0.18.0/go.mod h1:JWVYvqSMppoMJC0x5wdwiImzgXTI9FuZwxzkQq9wy+g= +github.com/aws/aws-sdk-go-v2 v1.9.0 h1:+S+dSqQCN3MSU5vJRu1HqHrq00cJn6heIMU7X9hcsoo= +github.com/aws/aws-sdk-go-v2 v1.9.0/go.mod h1:cK/D0BBs0b/oWPIcX/Z/obahJK1TT7IPVjy53i/mX/4= +github.com/aws/aws-sdk-go-v2/config v1.7.0 h1:J2cZ7qe+3IpqBEXnHUrFrOjoB9BlsXg7j53vxcl5IVg= +github.com/aws/aws-sdk-go-v2/config v1.7.0/go.mod h1:w9+nMZ7soXCe5nT46Ri354SNhXDQ6v+V5wqDjnZE+GY= +github.com/aws/aws-sdk-go-v2/credentials v1.4.0 h1:kmvesfjY861FzlCU9mvAfe01D9aeXcG2ZuC+k9F2YLM= +github.com/aws/aws-sdk-go-v2/credentials v1.4.0/go.mod h1:dgGR+Qq7Wjcd4AOAW5Rf5Tnv3+x7ed6kETXyS9WCuAY= +github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.5.0 h1:OxTAgH8Y4BXHD6PGCJ8DHx2kaZPCQfSTqmDsdRZFezE= +github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.5.0/go.mod h1:CpNzHK9VEFUCknu50kkB8z58AH2B5DvPP7ea1LHve/Y= +github.com/aws/aws-sdk-go-v2/internal/ini v1.2.2 h1:d95cddM3yTm4qffj3P6EnP+TzX1SSkWaQypXSgT/hpA= +github.com/aws/aws-sdk-go-v2/internal/ini v1.2.2/go.mod h1:BQV0agm+JEhqR+2RT5e1XTFIDcAAV0eW6z2trp+iduw= +github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.3.0 h1:VNJ5NLBteVXEwE2F1zEXVmyIH58mZ6kIQGJoC7C+vkg= +github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.3.0/go.mod h1:R1KK+vY8AfalhG1AOu5e35pOD2SdoPKQCFLTvnxiohk= +github.com/aws/aws-sdk-go-v2/service/kms v1.5.0 h1:10e9mzaaYIIePEuxUzW5YJ8LKHNG/NX63evcvS3ux9U= +github.com/aws/aws-sdk-go-v2/service/kms v1.5.0/go.mod h1:w7JuP9Oq1IKMFQPkNe3V6s9rOssXzOVEMNEqK1L1bao= +github.com/aws/aws-sdk-go-v2/service/secretsmanager v1.6.0/go.mod h1:B+7C5UKdVq1ylkI/A6O8wcurFtaux0R1njePNPtKwoA= +github.com/aws/aws-sdk-go-v2/service/ssm v1.10.0/go.mod h1:4dXS5YNqI3SNbetQ7X7vfsMlX6ZnboJA2dulBwJx7+g= +github.com/aws/aws-sdk-go-v2/service/sso v1.4.0 h1:sHXMIKYS6YiLPzmKSvDpPmOpJDHxmAUgbiF49YNVztg= +github.com/aws/aws-sdk-go-v2/service/sso v1.4.0/go.mod h1:+1fpWnL96DL23aXPpMGbsmKe8jLTEfbjuQoA4WS1VaA= +github.com/aws/aws-sdk-go-v2/service/sts v1.7.0 h1:1at4e5P+lvHNl2nUktdM2/v+rpICg/QSEr9TO/uW9vU= +github.com/aws/aws-sdk-go-v2/service/sts v1.7.0/go.mod h1:0qcSMCyASQPN2sk/1KQLQ2Fh6yq8wm0HSDAimPhzCoM= +github.com/aws/smithy-go v1.8.0 h1:AEwwwXQZtUwP5Mz506FeXXrKBe0jA8gVM+1gEcSRooc= +github.com/aws/smithy-go v1.8.0/go.mod h1:SObp3lf9smib00L/v3U2eAKG8FyQ7iLrJnQiAmR5n+E= github.com/awslabs/goformation/v4 v4.15.5 h1:q3lm7oj4yqqJ76ZcaFThUACT3MQLD6yBcJRKuZ6g87w= github.com/awslabs/goformation/v4 v4.15.5/go.mod h1:wB5lKZf1J0MYH1Lt4B9w3opqz0uIjP7MMCAcib3QkwA= github.com/aybabtme/rgbterm v0.0.0-20170906152045-cc83f3b3ce59/go.mod h1:q/89r3U2H7sSsE2t6Kca0lfwTK8JdoNGS/yzM/4iH5I= @@ -281,6 +334,8 @@ github.com/bazelbuild/buildtools v0.0.0-20190917191645-69366ca98f89 h1:3B/ZE1a6e github.com/bazelbuild/buildtools v0.0.0-20190917191645-69366ca98f89/go.mod h1:5JP0TXzWDHXv8qvxRC4InIazwdyDseBDbzESUMKk1yU= github.com/bazelbuild/rules_go v0.0.0-20190719190356-6dae44dc5cab h1:wzbawlkLtl2ze9w/312NHZ84c7kpUCtlkD8HgFY27sw= github.com/bazelbuild/rules_go v0.0.0-20190719190356-6dae44dc5cab/go.mod h1:MC23Dc/wkXEyk3Wpq6lCqz0ZAYOZDw2DR5y3N1q2i7M= +github.com/benbjohnson/clock v1.1.0 h1:Q92kusRqC1XV2MjkWETPvjJVqKetz1OzxZB7mHJLju8= +github.com/benbjohnson/clock v1.1.0/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA= github.com/benjamintf1/unmarshalledmatchers v0.0.0-20190408201839-bb1c1f34eaea h1:NhnqtoeNnEBu36bfeP2CZq/d5bJxzJBtChscvM7v5Cg= github.com/benjamintf1/unmarshalledmatchers v0.0.0-20190408201839-bb1c1f34eaea/go.mod h1:jfBxQAPihPj5l6sipcapjHruLizHrt3RKuppDE97K+g= github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= @@ -364,6 +419,8 @@ github.com/cncf/udpa/go v0.0.0-20200629203442-efcf912fb354/go.mod h1:WmhPx2Nbnht github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= github.com/cncf/udpa/go v0.0.0-20210322005330-6414d713912e h1:xjKi0OrdbKVCLWRoF2SGNnv9todhp+zQlvRHhsb14R4= github.com/cncf/udpa/go v0.0.0-20210322005330-6414d713912e/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= +github.com/cncf/xds/go v0.0.0-20210312221358-fbca930ec8ed h1:OZmjad4L3H8ncOIR8rnb5MREYqG8ixi5+WbeUsquF0c= +github.com/cncf/xds/go v0.0.0-20210312221358-fbca930ec8ed/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= github.com/cockroachdb/datadriven v0.0.0-20190809214429-80d97fb3cbaa/go.mod h1:zn76sxSg3SzpJ0PPJaLDCu+Bu0Lg3sKTORVIj19EIF8= github.com/cockroachdb/datadriven v0.0.0-20200714090401-bf6692d28da5 h1:xD/lrqdvwsc+O2bjSSi3YqY73Ke3LAiSCx49aCesA0E= github.com/cockroachdb/datadriven v0.0.0-20200714090401-bf6692d28da5/go.mod h1:h6jFvWxBdQXxjopDMZyH2UVceIRfR84bdzbkoKrsWNo= @@ -403,7 +460,6 @@ github.com/coreos/go-systemd v0.0.0-20190620071333-e64a0ec8b42a h1:W8b4lQ4tFF21a github.com/coreos/go-systemd v0.0.0-20190620071333-e64a0ec8b42a/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= github.com/coreos/go-systemd/v22 v22.0.0/go.mod h1:xO0FLkIi5MaZafQlIrOotqXZ90ih+1atmu1JpKERPPk= github.com/coreos/go-systemd/v22 v22.1.0/go.mod h1:xO0FLkIi5MaZafQlIrOotqXZ90ih+1atmu1JpKERPPk= -github.com/coreos/go-systemd/v22 v22.3.1/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc= github.com/coreos/go-systemd/v22 v22.3.2 h1:D9/bQk5vlXQFZ6Kwuu6zaiXJ9oTPe68++AzAJc1DzSI= github.com/coreos/go-systemd/v22 v22.3.2/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc= github.com/coreos/pkg v0.0.0-20160727233714-3ac0863d7acf/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA= @@ -480,8 +536,9 @@ github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.m github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98= github.com/envoyproxy/go-control-plane v0.9.7/go.mod h1:cwu0lG7PUMfa9snN8LXBig5ynNVH9qI8YYLbd1fK2po= github.com/envoyproxy/go-control-plane v0.9.9-0.20201210154907-fd9021fe5dad/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk= -github.com/envoyproxy/go-control-plane v0.9.9-0.20210217033140-668b12f5399d h1:QyzYnTnPE15SQyUeqU6qLbWxMkwyAyu+vGksa0b7j00= github.com/envoyproxy/go-control-plane v0.9.9-0.20210217033140-668b12f5399d/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk= +github.com/envoyproxy/go-control-plane v0.9.9-0.20210512163311-63b5d3c536b0 h1:dulLQAYQFYtG5MTplgNGHWuV2D+OBD+Z8lmDBmbLg+s= +github.com/envoyproxy/go-control-plane v0.9.9-0.20210512163311-63b5d3c536b0/go.mod h1:hliV/p42l8fGbc6Y9bQ70uLwIvmJyVE5k4iMKlh8wCQ= github.com/envoyproxy/protoc-gen-validate v0.0.14/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= github.com/envoyproxy/protoc-gen-validate v0.3.0-java/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= @@ -524,8 +581,9 @@ github.com/fortytw2/leaktest v1.3.0/go.mod h1:jDsjWgpAGjm2CA7WthBh/CdZYEPF31XHqu github.com/franela/goblin v0.0.0-20200105215937-c9ffbefa60db/go.mod h1:7dvUGVsVBjqR7JHJk0brhHOZYGmfBYOrK0ZhYMEtBr4= github.com/franela/goreq v0.0.0-20171204163338-bcd34c9993f8/go.mod h1:ZhphrRTfi2rbfLwlschooIH4+wKKDR4Pdxhh+TRoA20= github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= -github.com/fsnotify/fsnotify v1.4.9 h1:hsms1Qyu0jgnwNXIxa+/V/PDsU6CfLf6CNO8H7IWoS4= github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ= +github.com/fsnotify/fsnotify v1.5.1 h1:mZcQUHVQUQWoPXXtuf9yuEXKudkV2sx1E06UadKWpgI= +github.com/fsnotify/fsnotify v1.5.1/go.mod h1:T3375wBYaZdLLcVNkcVbzGHY7f1l/uK5T5Ai1i3InKU= github.com/fullsailor/pkcs7 v0.0.0-20180422025557-ae226422660e/go.mod h1:KnogPXtdwXqoenmZCw6S+25EAm2MkxbG0deNDu4cbSA= github.com/fullstorydev/grpcurl v1.6.0/go.mod h1:ZQ+ayqbKMJNhzLmbpCiurTVlaK2M/3nqZCxaQ2Ze/sM= github.com/fullstorydev/grpcurl v1.8.0/go.mod h1:Mn2jWbdMrQGJQ8UD62uNyMumT2acsZUCkZIqFxsQf1o= @@ -649,6 +707,8 @@ github.com/go-sql-driver/mysql v1.5.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LB github.com/go-sql-driver/mysql v1.6.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg= github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0/go.mod h1:fyg7847qk6SyHyPtNmDHnmrv/HOrqktSC+C9fM+CJOE= +github.com/go-telegram-bot-api/telegram-bot-api v4.6.4+incompatible h1:2cauKuaELYAEARXRkq2LrJ0yDDv1rW7+wrTEdVL3uaU= +github.com/go-telegram-bot-api/telegram-bot-api v4.6.4+incompatible/go.mod h1:qf9acutJ8cwBUhm1bqgz6Bei9/C/c93FPDljKWwsOgM= github.com/go-test/deep v1.0.2-0.20181118220953-042da051cf31/go.mod h1:wGDj63lr65AM2AQyKZd/NYHGb0R+1RLqB8NKt3aSFNA= github.com/go-test/deep v1.0.3/go.mod h1:wGDj63lr65AM2AQyKZd/NYHGb0R+1RLqB8NKt3aSFNA= github.com/go-test/deep v1.0.4 h1:u2CU3YKy9I2pmu9pX0eq50wCgjfGIt539SqR7FbHiho= @@ -696,6 +756,8 @@ github.com/gogo/protobuf v1.3.1/go.mod h1:SlYgWuQ5SjCEi6WLHjHCa1yvBfUnHcTbrrZtXP github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= github.com/goji/httpauth v0.0.0-20160601135302-2da839ab0f4d/go.mod h1:nnjvkQ9ptGaCkuDUx6wNykzzlUixGxvkme+H/lnzb+A= +github.com/golang-jwt/jwt/v4 v4.0.0 h1:RAqyYixv1p7uEnocuy8P1nru5wprCh/MH2BIlW5z5/o= +github.com/golang-jwt/jwt/v4 v4.0.0/go.mod h1:/xlHOz8bRuivTWchD4jCa+NbatV+wEUSzwAxVc6locg= github.com/golang-sql/civil v0.0.0-20190719163853-cb61b32ac6fe/go.mod h1:8vg3r2VgvsThLBIFL93Qb5yWzgyZWhEmBwUJWevAkK0= github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0/go.mod h1:E/TSTwGwJL78qG/PmXZO1EjYhfJinVAhrmmHX6Z8B9k= github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= @@ -714,8 +776,9 @@ github.com/golang/mock v1.4.0/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt github.com/golang/mock v1.4.1/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= github.com/golang/mock v1.4.3/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= github.com/golang/mock v1.4.4/go.mod h1:l3mdAwkq5BuhzHwde/uurv3sEJeZMXNpwsxVWU71h+4= -github.com/golang/mock v1.5.0 h1:jlYHihg//f7RRwuPfptm04yp4s7O6Kw8EZiVYIGcH0g= github.com/golang/mock v1.5.0/go.mod h1:CWnOUgYIOo4TcNZ0wHX3YZCqsaM1I1Jvs6v3mP3KVu8= +github.com/golang/mock v1.6.0 h1:ErTB+efbowRARo13NNdxyJji2egdxLGQhRaY+DUumQc= +github.com/golang/mock v1.6.0/go.mod h1:p6yTPP+5HYm5mzsMV8JkE6ZKdX+/wYM6Hr+LicevLPs= github.com/golang/protobuf v1.0.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.1.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= @@ -796,11 +859,11 @@ github.com/google/go-licenses v0.0.0-20210329231322-ce1d9163b77d/go.mod h1:+TYOm github.com/google/go-querystring v1.0.0 h1:Xkwi/a1rcvNg1PPYe5vI8GbeBY/jrVuDX5ASuANWTrk= github.com/google/go-querystring v1.0.0/go.mod h1:odCYkC5MyYFN7vkCjXpyrEuKhc/BUO6wN/zVPAxq5ck= github.com/google/go-replayers/grpcreplay v0.1.0/go.mod h1:8Ig2Idjpr6gifRd6pNVggX6TC1Zw6Jx74AKp7QNH2QE= -github.com/google/go-replayers/grpcreplay v1.0.0 h1:B5kVOzJ1hBgnevTgIWhSTatQ3608yu/2NnU0Ta1d0kY= -github.com/google/go-replayers/grpcreplay v1.0.0/go.mod h1:8Ig2Idjpr6gifRd6pNVggX6TC1Zw6Jx74AKp7QNH2QE= +github.com/google/go-replayers/grpcreplay v1.1.0 h1:S5+I3zYyZ+GQz68OfbURDdt/+cSMqCK1wrvNx7WBzTE= +github.com/google/go-replayers/grpcreplay v1.1.0/go.mod h1:qzAvJ8/wi57zq7gWqaE6AwLM6miiXUQwP1S+I9icmhk= github.com/google/go-replayers/httpreplay v0.1.0/go.mod h1:YKZViNhiGgqdBlUbI2MwGpq4pXxNmhJLPHQ7cv2b5no= -github.com/google/go-replayers/httpreplay v0.1.2 h1:HCfx+dQzwN9XbGTHF8qJ+67WN8glL9FTWV5rraCJ/jU= -github.com/google/go-replayers/httpreplay v0.1.2/go.mod h1:YKZViNhiGgqdBlUbI2MwGpq4pXxNmhJLPHQ7cv2b5no= +github.com/google/go-replayers/httpreplay v1.0.0 h1:8SmT8fUYM4nueF+UnXIX8LJxNTb1vpPuknXz+yTWzL4= +github.com/google/go-replayers/httpreplay v1.0.0/go.mod h1:LJhKoTwS5Wy5Ld/peq8dFFG5OfJyHEz7ft+DsTUv25M= 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= @@ -809,8 +872,9 @@ github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXi github.com/google/martian v2.1.1-0.20190517191504-25dcb96d9e51+incompatible h1:xmapqc1AyLoB+ddYT6r04bD9lIjlOqGaREovi0SzFaE= github.com/google/martian v2.1.1-0.20190517191504-25dcb96d9e51+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs= github.com/google/martian/v3 v3.0.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0= -github.com/google/martian/v3 v3.1.0 h1:wCKgOCHuUEVfsaQLpPSJb7VdYCdTVZQAuOdYm1yc/60= github.com/google/martian/v3 v3.1.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0= +github.com/google/martian/v3 v3.2.1 h1:d8MncMlErDFTwQGBK1xhv026j9kqhvw1Qv9IbWT1VLQ= +github.com/google/martian/v3 v3.2.1/go.mod h1:oBOf6HBosgwRXnUGWUB05QECsc6uvmMiJ3+6W4l/CUk= github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= github.com/google/pprof v0.0.0-20190515194954-54271f7e092f/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= github.com/google/pprof v0.0.0-20191218002539-d4f498aebedc/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= @@ -824,6 +888,11 @@ github.com/google/pprof v0.0.0-20201203190320-1bf35d6f28c2/go.mod h1:kpwsk12EmLe github.com/google/pprof v0.0.0-20201218002935-b9804c9f04c2/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= github.com/google/pprof v0.0.0-20210122040257-d980be63207e/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= github.com/google/pprof v0.0.0-20210226084205-cbba55b83ad5/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= +github.com/google/pprof v0.0.0-20210506205249-923b5ab0fc1a/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= +github.com/google/pprof v0.0.0-20210601050228-01bbb1931b22/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= +github.com/google/pprof v0.0.0-20210609004039-a478d1d731e9/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= +github.com/google/pprof v0.0.0-20210715191844-86eeefc3e471/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= +github.com/google/pprof v0.0.0-20210720184732-4bb14d4b1be1/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= github.com/google/rpmpack v0.0.0-20191226140753-aa36bfddb3a0/go.mod h1:RaTPr0KUf2K7fnZYLNDrr8rxAamWs3iNywJLtQ2AzBg= github.com/google/rpmpack v0.0.0-20210410105602-e20c988a6f5a h1:XC048Fc/OB2rUl/BxruopEl2u/EP6cJNFveVxI1cvdk= @@ -838,16 +907,18 @@ github.com/google/uuid v0.0.0-20161128191214-064e2069ce9c/go.mod h1:TIyPZe4Mgqvf 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/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= -github.com/google/uuid v1.2.0 h1:qJYtXnJRWmpe7m/3XlyhrsLrEURqHRM2kxzoxXqyUDs= github.com/google/uuid v1.2.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I= +github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/wire v0.3.0/go.mod h1:i1DMg/Lu8Sz5yYl25iOdmc5CT5qusaa+zmRWs16741s= github.com/google/wire v0.5.0 h1:I7ELFeVBr3yfPIcc8+MWvrjk+3VjbcSzoXm3JVa+jD8= github.com/google/wire v0.5.0/go.mod h1:ngWDr9Qvq3yZA10YrxfyGELY/AFWGVpy9c1LTRi1EoU= github.com/googleapis/gax-go v2.0.2+incompatible h1:silFMLAnr330+NRuag/VjIGF7TLp/LBrV2CJKFLWEww= github.com/googleapis/gax-go v2.0.2+incompatible/go.mod h1:SFVmujtThgffbyetf+mdk2eWhX2bMyUtNHzFKcPA9HY= github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg= -github.com/googleapis/gax-go/v2 v2.0.5 h1:sjZBwGj9Jlw33ImPtvFviGYvseOtDM7hkSKB7+Tv3SM= github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk= +github.com/googleapis/gax-go/v2 v2.1.0 h1:6DWmvNpomjL1+3liNSZbVns3zsYzzCjm6pRBO1tLeso= +github.com/googleapis/gax-go/v2 v2.1.0/go.mod h1:Q3nei7sK6ybPYH7twZdmQpAd1MKb7pfu6SK+H1/DsU0= github.com/googleapis/gnostic v0.3.1/go.mod h1:on+2t9HRStVgn95RSsFWFz+6Q0Snyqv1awfrALZdbtU= github.com/googleapis/gnostic v0.4.1 h1:DLJCy1n/vrD4HPjOvYcT8aYQXpPIzoRZONaYwyycI+I= github.com/googleapis/gnostic v0.4.1/go.mod h1:LRhVm6pbyptWbWbuZ38d1eyptfvIytN3ir6b65WBswg= @@ -867,8 +938,8 @@ github.com/goreleaser/chglog v0.1.2/go.mod h1:tTZsFuSZK4epDXfjMkxzcGbrIOXprf0JFp github.com/goreleaser/fileglob v1.2.0 h1:OErqbdzeg/eibfDGPHDQDN8jL5u1jNyxA5IQzNPLLoU= github.com/goreleaser/fileglob v1.2.0/go.mod h1:rFyb2pXaK3YdnYnSjn6lifw0h2Q6s8OfOsx6I6bXkKE= github.com/goreleaser/goreleaser v0.134.0/go.mod h1:ZT6Y2rSYa6NxQzIsdfWWNWAlYGXGbreo66NmE+3X3WQ= -github.com/goreleaser/goreleaser v0.177.0 h1:pPjL2NGfrLY5mqEK+3Nk6IgZtPyU9zB9mFxKeF3MU8w= -github.com/goreleaser/goreleaser v0.177.0/go.mod h1:9RAcbZOoMQIfDgvTORBho/LBN4aRU4NGaZBLTaoIcbs= +github.com/goreleaser/goreleaser v0.182.1 h1:cKRlHfbMxejiyMCNACsl82slFXEW+k9RggADv6/Akqg= +github.com/goreleaser/goreleaser v0.182.1/go.mod h1:DDAKfIsyz8N8HTGYxGT9OvLW2XMLaS5Gr8/O3fSasKw= github.com/goreleaser/nfpm v1.2.1 h1:AEnu9XVmupRDTR930Z2rAs31Mj6sLIPxFcR9ESYvgDA= github.com/goreleaser/nfpm v1.2.1/go.mod h1:TtWrABZozuLOttX2uDlYyECfQX7x5XYkVxhjYcR6G9w= github.com/goreleaser/nfpm/v2 v2.6.0 h1:bwDU9o4/CVTSpqASJA7+r+rkqpTGamQKYHMRH3wDlRE= @@ -1045,7 +1116,6 @@ github.com/json-iterator/go v1.1.10/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/ github.com/json-iterator/go v1.1.11 h1:uVUAXhF2To8cbw/3xN3pxj6kk7TYKs98NIrTqPlMWAQ= github.com/json-iterator/go v1.1.11/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU= -github.com/jstemmer/go-junit-report v0.9.1 h1:6QPYqodiu3GuPL+7mfx+NwDdp2eTkp9IfEUpgAwUN0o= github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/XSXhF0NWZEnDohbsk= github.com/jtolds/gls v4.20.0+incompatible h1:xdiiI2gbIgH/gLH7ADydsJ1uDOEzR8yvV7C0MuV77Wo= github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU= @@ -1082,7 +1152,7 @@ github.com/kisom/goutils v1.4.3/go.mod h1:Lp5qrquG7yhYnWzZCI/68Pa/GpFynw//od6EkG github.com/klauspost/compress v1.10.3/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs= github.com/klauspost/compress v1.10.7/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs= github.com/klauspost/compress v1.11.0/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs= -github.com/klauspost/compress v1.12.2/go.mod h1:8dP1Hq4DHOhN9w426knH3Rhby4rFm6D8eO+e+Dq5Gzg= +github.com/klauspost/compress v1.13.5/go.mod h1:/3/Vjq9QcHkK5uEr5lBEmyoZ1iFhe47etQ6QUkpK6sk= github.com/klauspost/cpuid v1.2.0/go.mod h1:Pj4uuM528wm8OyEC2QMXAi2YiTZ96dNQPGgoMS4s3ek= github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= github.com/konsorten/go-windows-terminal-sequences v1.0.2/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= @@ -1132,7 +1202,6 @@ github.com/lib/pq v1.1.1/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo= github.com/lib/pq v1.2.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo= github.com/lib/pq v1.8.0/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o= github.com/lib/pq v1.9.0/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o= -github.com/lib/pq v1.10.0/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o= github.com/lib/pq v1.10.1/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o= github.com/lib/pq v1.10.2/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o= github.com/libopenstorage/openstorage v1.0.0/go.mod h1:Sp1sIObHjat1BeXhfMqLZ14wnOzEhNx2YQedreMcUyc= @@ -1543,6 +1612,7 @@ github.com/sonatard/noctx v0.0.1/go.mod h1:9D2D/EoULe8Yy2joDHJj7bv3sZoq9AaSb8B4l github.com/sony/gobreaker v0.4.1/go.mod h1:ZKptC7FHNvhBz7dN2LGjPVBz2sZJmc0/PkyDJOjmxWY= github.com/sourcegraph/go-diff v0.6.1 h1:hmA1LzxW0n1c3Q4YbrFgg4P99GSnebYa3x8gr0HZqLQ= github.com/sourcegraph/go-diff v0.6.1/go.mod h1:iBszgVvyxdc8SFZ7gm69go2KDdt3ag071iBaWPF6cjs= +github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72 h1:qLC7fQah7D6K1B0ujays3HV9gkFtllcxhzImRR7ArPQ= github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA= github.com/spf13/afero v1.1.1/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B0CQ= github.com/spf13/afero v1.1.2/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B0CQ= @@ -1611,6 +1681,8 @@ github.com/subosito/gotenv v1.2.0/go.mod h1:N0PQaV/YGNqwC0u51sEeR/aUtSLEXKX9iv69 github.com/syndtr/gocapability v0.0.0-20180916011248-d98352740cb2/go.mod h1:hkRG7XYTFWNJGYcbNJQlaLq0fg1yr4J4t/NcTQtrfww= github.com/tdakkota/asciicheck v0.0.0-20200416200610-e657995f937b h1:HxLVTlqcHhFAz3nWUcuvpH7WuOMv8LQoCWmruLfFH2U= github.com/tdakkota/asciicheck v0.0.0-20200416200610-e657995f937b/go.mod h1:yHp0ai0Z9gUljN3o0xMhYJnH/IcvkdTBOX2fmJ93JEM= +github.com/technoweenie/multipartstreamer v1.0.1 h1:XRztA5MXiR1TIRHxH2uNxXxaIkKQDeX7m2XsSOlQEnM= +github.com/technoweenie/multipartstreamer v1.0.1/go.mod h1:jNVxdtShOxzAsukZwTSw6MDx5eUJoiEBsSvzDU9uzog= github.com/tetafro/godot v1.4.8 h1:rhuUH+tBrx24yVAr6Ox3/UxcsiUPPJcGhinfLdbdew0= github.com/tetafro/godot v1.4.8/go.mod h1:LR3CJpxDVGlYOWn3ZZg1PgNZdTUvzsZWu8xaEohUpn8= github.com/thecodeteam/goscaleio v0.1.0/go.mod h1:68sdkZAsK8bvEwBlbQnlLS+xU+hvLYM/iQ8KXej1AwM= @@ -1674,8 +1746,8 @@ github.com/valyala/fasthttp v1.16.0/go.mod h1:YOKImeEosDdBPnxc0gy7INqi3m1zK6A+xl github.com/valyala/fasttemplate v1.0.1/go.mod h1:UQGH1tvbgY+Nz5t2n7tXsz52dQxojPUpymEIMZ47gx8= github.com/valyala/quicktemplate v1.6.3/go.mod h1:fwPzK2fHuYEODzJ9pkw0ipCPNHZ2tD5KW4lOuSdPKzY= github.com/valyala/tcplisten v0.0.0-20161114210144-ceec8f93295a/go.mod h1:v3UYOV9WzVtRmSR+PDvWpU/qWl4Wa5LApYYX4ZtKbio= -github.com/vartanbeno/go-reddit/v2 v2.0.1 h1:P6ITpf5YHjdy7DHZIbUIDn/iNAoGcEoDQnMa+L4vutw= -github.com/vartanbeno/go-reddit/v2 v2.0.1/go.mod h1:758/S10hwZSLm43NPtwoNQdZFSg3sjB5745Mwjb0ANI= +github.com/vartanbeno/go-reddit/v2 v2.0.0 h1:fxYMqx5lhbmJ3yYRN1nnQC/gecRB3xpUS2BbG7GLpsk= +github.com/vartanbeno/go-reddit/v2 v2.0.0/go.mod h1:758/S10hwZSLm43NPtwoNQdZFSg3sjB5745Mwjb0ANI= github.com/vektah/gqlparser v1.1.2/go.mod h1:1ycwN7Ij5njmMkPPAOaRFY4rET2Enx7IkVv3vaXspKw= github.com/vektra/mockery v1.1.2 h1:uc0Yn67rJpjt8U/mAZimdCKn9AeA97BOkjpmtBSlfP4= github.com/vektra/mockery v1.1.2/go.mod h1:VcfZjKaFOPO+MpN4ZvwPjs4c48lkq1o3Ym8yHZJu0jU= @@ -1786,16 +1858,21 @@ go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= go.opencensus.io v0.22.3/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= go.opencensus.io v0.22.4/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= go.opencensus.io v0.22.5/go.mod h1:5pWMHQbX5EPX2/62yrJeAkowc+lfs/XD7Uxpq3pI6kk= +go.opencensus.io v0.22.6/go.mod h1:XItmlyltB5F7CS4xOC1DcqMoFqwtC6OG2xF7mCv7P7E= go.opencensus.io v0.23.0 h1:gqCw0LfLxScz8irSi8exQc7fyQ0fKQU/qnC/X8+V/1M= go.opencensus.io v0.23.0/go.mod h1:XItmlyltB5F7CS4xOC1DcqMoFqwtC6OG2xF7mCv7P7E= +go.opentelemetry.io/proto/otlp v0.7.0/go.mod h1:PqfVotwruBrMGOCsRd/89rSnXhoiJIqeYNgFYFoEGnI= go.starlark.net v0.0.0-20200306205701-8dd3e2ee1dd5 h1:+FNtrFTmVw0YZGpBGX56XDee331t6JAXeK2bcyhLOOc= go.starlark.net v0.0.0-20200306205701-8dd3e2ee1dd5/go.mod h1:nmDLcffg48OtT/PSW0Hg7FvpRQsQh5OSqIylirxKC7o= go.uber.org/atomic v1.3.2/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= go.uber.org/atomic v1.5.0/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ= go.uber.org/atomic v1.6.0/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ= -go.uber.org/atomic v1.7.0 h1:ADUqmZGgLDDfbSL9ZmPxKTybcoEYHgpYfELNoN+7hsw= go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= +go.uber.org/atomic v1.9.0 h1:ECmE8Bn/WFTYwEW/bpKD3M8VtR/zQVbavAoalC1PYyE= +go.uber.org/atomic v1.9.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= +go.uber.org/goleak v1.1.10 h1:z+mqJhf6ss6BSfSM671tgKyZBFPTTJM+HLxnhPC3wu0= +go.uber.org/goleak v1.1.10/go.mod h1:8a7PlsEVH3e/a/GLqe5IIrQx6GzcnRmZEufDUTk4A7A= go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0= go.uber.org/multierr v1.3.0/go.mod h1:VgVr7evmIr6uPjLBxg28wmKNXyqE9akIJ5XnfpiKl+4= go.uber.org/multierr v1.4.0/go.mod h1:VgVr7evmIr6uPjLBxg28wmKNXyqE9akIJ5XnfpiKl+4= @@ -1807,11 +1884,13 @@ go.uber.org/tools v0.0.0-20190618225709-2cfd321de3ee/go.mod h1:vJERXedbb3MVM5f9E go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q= go.uber.org/zap v1.13.0/go.mod h1:zwrFLgMcdUuIBviXEYEH1YKNaOBnKXsx2IPda5bBwHM= go.uber.org/zap v1.16.0/go.mod h1:MA8QOfq0BHJwdXa996Y4dYkAqRKB8/1K1QMMZVaNZjQ= -go.uber.org/zap v1.17.0 h1:MTjgFu6ZLKvY6Pvaqk97GlxNBuMpV4Hy/3P6tRGlI2U= go.uber.org/zap v1.17.0/go.mod h1:MXVU+bhUf/A7Xi2HNOnopQOrmycQ5Ih87HtOu4q5SSo= +go.uber.org/zap v1.18.1/go.mod h1:xg/QME4nWcxGxrpdeYfq7UvYrLh66cuVKdrbD1XF/NI= +go.uber.org/zap v1.19.0 h1:mZQZefskPPCMIBCSEH0v2/iUqqLrYtaeqwD6FUGUnFE= +go.uber.org/zap v1.19.0/go.mod h1:xg/QME4nWcxGxrpdeYfq7UvYrLh66cuVKdrbD1XF/NI= gocloud.dev v0.19.0/go.mod h1:SmKwiR8YwIMMJvQBKLsC3fHNyMwXLw3PMDO+VVteJMI= -gocloud.dev v0.23.0 h1:u/6F8slWwaZPgGpjpNp0jzH+1P/M2ri7qEP3lFgbqBE= -gocloud.dev v0.23.0/go.mod h1:zklCCIIo1N9ELkU2S2E7tW8P8eeMU7oGLeQCXdDwx9Q= +gocloud.dev v0.24.0 h1:cNtHD07zQQiv02OiwwDyVMuHmR7iQt2RLkzoAgz7wBs= +gocloud.dev v0.24.0/go.mod h1:uA+als++iBX5ShuG4upQo/3Zoz49iIPlYUWHV5mM8w8= golang.org/dl v0.0.0-20190829154251-82a15e2f2ead/go.mod h1:IUMfjQLJQd4UTqG1Z90tenwKoCX93Gn3MAQJMOSBsDQ= golang.org/x/crypto v0.0.0-20180501155221-613d6eafa307/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= @@ -1846,8 +1925,9 @@ golang.org/x/crypto v0.0.0-20201221181555-eec23a3978ad/go.mod h1:jdWPYTVW3xRLrWP golang.org/x/crypto v0.0.0-20210220033148-5ea612d1eb83/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I= golang.org/x/crypto v0.0.0-20210322153248-0c34fe9e7dc2/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4= golang.org/x/crypto v0.0.0-20210506145944-38f3c27a63bf/go.mod h1:P+XmwS30IXTQdn5tA2iutPOUgjI07+tq3H3K9MVA1s8= -golang.org/x/crypto v0.0.0-20210513164829-c07d793c2f9a h1:kr2P4QFmQr29mSLA43kwrOcgcReGTfbE9N577tCTuBc= golang.org/x/crypto v0.0.0-20210513164829-c07d793c2f9a/go.mod h1:P+XmwS30IXTQdn5tA2iutPOUgjI07+tq3H3K9MVA1s8= +golang.org/x/crypto v0.0.0-20210817164053-32db794688a5 h1:HWj/xjIHfjYU5nVXpTM0s39J9CbLn7Cc5a7IC5rwsMQ= +golang.org/x/crypto v0.0.0-20210817164053-32db794688a5/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/exp v0.0.0-20180321215751-8460e604b9de/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20180807140117-3d87b88a115f/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= @@ -1893,8 +1973,9 @@ golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.3.1-0.20200828183125-ce943fd02449/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.4.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.4.1/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= -golang.org/x/mod v0.4.2 h1:Gz96sIWK3OalVv/I/qNygP42zyoKp3xptRVCWRFEBvo= golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/mod v0.5.0 h1:UG21uOlmZabA4fW5i7ZX6bjw1xELEGg/ZLgZq9auk/Q= +golang.org/x/mod v0.5.0/go.mod h1:5OXOZSfqPIIbmVBIIKWRFfZjPR0E5r58TLhUjH0a2Ro= golang.org/x/net v0.0.0-20180218175443-cbe0f9307d01/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180811021610-c39426892332/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= @@ -1962,13 +2043,13 @@ golang.org/x/net v0.0.0-20210326060303-6b1517762897/go.mod h1:uSPa2vr4CLtc/ILN5o golang.org/x/net v0.0.0-20210331212208-0fccb6fa2b5c/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM= golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM= golang.org/x/net v0.0.0-20210410081132-afb366fc7cd1/go.mod h1:9tjilg8BloeKEkVJvy7fQ90B1CfIiPueXVOjqfkSzI8= -golang.org/x/net v0.0.0-20210420210106-798c2154c571/go.mod h1:72T/g9IO56b78aLF+1Kcs5dz7/ng1VjMUvfKvpfy+jM= golang.org/x/net v0.0.0-20210428140749-89ef3d95e781/go.mod h1:OJAsFXCWl8Ukc7SiCT/9KSuxbyM7479/AVlXFRxuMCk= golang.org/x/net v0.0.0-20210503060351-7fd8e65b6420/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= -golang.org/x/net v0.0.0-20210505214959-0714010a04ed/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20210510120150-4163338589ed/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= -golang.org/x/net v0.0.0-20210614182718-04defd469f4e h1:XpT3nA5TvE525Ne3hInMh6+GETgn27Zfm9dxsThnX2Q= golang.org/x/net v0.0.0-20210614182718-04defd469f4e/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= +golang.org/x/net v0.0.0-20210726213435-c6fcb2dbf985/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= +golang.org/x/net v0.0.0-20210825183410-e898025ed96a h1:bRuuGXV8wwSdGTB+CtJf+FjgO1APK1CoO39T4BN/XBw= +golang.org/x/net v0.0.0-20210825183410-e898025ed96a/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/oauth2 v0.0.0-20180227000427-d7d64896b5ff/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20181106182150-f42d05182288/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= @@ -1980,14 +2061,18 @@ golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4Iltr golang.org/x/oauth2 v0.0.0-20200902213428-5d25da1a8d43/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= golang.org/x/oauth2 v0.0.0-20201109201403-9fd604954f58/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= golang.org/x/oauth2 v0.0.0-20201208152858-08078c50e5b5/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= +golang.org/x/oauth2 v0.0.0-20210126194326-f9ce19ea3013/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= golang.org/x/oauth2 v0.0.0-20210218202405-ba52d332ba99/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= golang.org/x/oauth2 v0.0.0-20210220000619-9bb904979d93/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= golang.org/x/oauth2 v0.0.0-20210313182246-cd4f82c27b84/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= golang.org/x/oauth2 v0.0.0-20210402161424-2e8d93401602/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= golang.org/x/oauth2 v0.0.0-20210413134643-5e61552d6c78/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= golang.org/x/oauth2 v0.0.0-20210427180440-81ed05c6b58c/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= -golang.org/x/oauth2 v0.0.0-20210628180205-a41e5a781914 h1:3B43BWw0xEBsLZ/NO1VALz6fppU3481pik+2Ksv45z8= +golang.org/x/oauth2 v0.0.0-20210514164344-f6687ab2804c/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= golang.org/x/oauth2 v0.0.0-20210628180205-a41e5a781914/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= +golang.org/x/oauth2 v0.0.0-20210805134026-6f1e6394065a/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= +golang.org/x/oauth2 v0.0.0-20210819190943-2bc19b11175f h1:Qmd2pbz05z7z6lm0DrgQVVPuBm92jqujBKMHMOlOQEw= +golang.org/x/oauth2 v0.0.0-20210819190943-2bc19b11175f/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= @@ -2104,16 +2189,20 @@ golang.org/x/sys v0.0.0-20210324051608-47abb6519492/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210403161142-5e06dd20ab57/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210412220455-f1c623a9e750/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210420072515-93ed5bcd2bfe/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210420205809-ac73e9fd8988/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210426230700-d19ff857e887/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210503080704-8803ae5d1324/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210503173754-0981d6026fa6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210511113859-b0526f3d8744/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c h1:F1jZWGFhYfh0Ci55sIpILtKKK8p3i2/krTr0H1rg74I= +golang.org/x/sys v0.0.0-20210514084401-e8d321eab015/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210603125802-9665404d3644/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210616094352-59db8d763f22/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210806184541-e5e7981a1069/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210823070655-63515b42dcdf/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210831042530-f4d43177bf5e h1:XMgFehsDnnLGtjvjOfqWSUzt0alpTR1RSEuznObga2c= +golang.org/x/sys v0.0.0-20210831042530-f4d43177bf5e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210220032956-6a3ed077a48d h1:SZxvLBoTP5yHO3Frd4z4vrF+DBX9vMVanchswa69toE= @@ -2127,16 +2216,18 @@ golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.4/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.3.6 h1:aRYxNxv6iGQlyVaZmk6ZgYEDa+Jg18DxebPSrd6bg1M= golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.3.7 h1:olpwvP2KacW1ZWvsR7uQhoyTYvKAupfQrRGBFM352Gk= +golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= golang.org/x/time v0.0.0-20180412165947-fbb02b2291d2/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20200416051211-89c76fbcd5d1/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20200630173020-3af7569d3a1e/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= -golang.org/x/time v0.0.0-20210220033141-f8bda1e9f3ba h1:O8mE0/t419eoIwhTFpKVkHiTs/Igowgfkj25AcZrtiE= golang.org/x/time v0.0.0-20210220033141-f8bda1e9f3ba/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +golang.org/x/time v0.0.0-20210723032227-1f47c861a9ac h1:7zkz7BUtwNFFqcowJ+RIgu2MaV/MapERkDIy+mwPyjs= +golang.org/x/time v0.0.0-20210723032227-1f47c861a9ac/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/tools v0.0.0-20180221164845-07fd8470d635/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20180525024113-a5b4c53f6e8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20180828015842-6cd1fcedba52/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= @@ -2254,6 +2345,7 @@ golang.org/x/tools v0.0.0-20210105154028-b0ab187a4818/go.mod h1:emZCQorbCU4vsT4f golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.0.0-20210108195828-e2f9c7f1fc8e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0= +golang.org/x/tools v0.1.1/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/tools v0.1.2/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/tools v0.1.3/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/tools v0.1.4/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= @@ -2295,13 +2387,22 @@ google.golang.org/api v0.29.0/go.mod h1:Lcubydp8VUV7KeIHD9z2Bys/sm/vGKnG1UHuDBSr google.golang.org/api v0.30.0/go.mod h1:QGmEvQ87FHZNiUVJkT14jQNYJ4ZJjdRF23ZXz5138Fc= google.golang.org/api v0.35.0/go.mod h1:/XrVsuzM0rZmrsbjJutiuftIzeuTQcEeaYcSk/mQ1dg= google.golang.org/api v0.36.0/go.mod h1:+z5ficQTmoYpPn8LCUNVpK5I7hwkpjbcgqA7I34qYtE= +google.golang.org/api v0.37.0/go.mod h1:fYKFpnQN0DsDSKRVRcQSDQNtqWPfM9i+zNPxepjRCQ8= google.golang.org/api v0.40.0/go.mod h1:fYKFpnQN0DsDSKRVRcQSDQNtqWPfM9i+zNPxepjRCQ8= google.golang.org/api v0.41.0/go.mod h1:RkxM5lITDfTzmyKFPt+wGrCJbVfniCr2ool8kTBzRTU= google.golang.org/api v0.43.0/go.mod h1:nQsDGjRXMo4lvh5hP0TKqF244gqhGcr/YSIykhUk/94= google.golang.org/api v0.44.0/go.mod h1:EBOGZqzyhtvMDoxwS97ctnh0zUmYY6CxqXsc1AvkYD8= google.golang.org/api v0.45.0/go.mod h1:ISLIJCedJolbZvDfAk+Ctuq5hf+aJ33WgtUsfyFoLXA= -google.golang.org/api v0.46.0 h1:jkDWHOBIoNSD0OQpq4rtBVu+Rh325MPjXG1rakAp8JU= google.golang.org/api v0.46.0/go.mod h1:ceL4oozhkAiTID8XMmJBsIxID/9wMXJVVFXPg4ylg3I= +google.golang.org/api v0.47.0/go.mod h1:Wbvgpq1HddcWVtzsVLyfLp8lDg6AA241LmgIL59tHXo= +google.golang.org/api v0.48.0/go.mod h1:71Pr1vy+TAZRPkPs/xlCf5SsU8WjuAWv1Pfjbtukyy4= +google.golang.org/api v0.50.0/go.mod h1:4bNT5pAuq5ji4SRZm+5QIkjny9JAyVD/3gaSihNefaw= +google.golang.org/api v0.51.0/go.mod h1:t4HdrdoNgyN5cbEfm7Lum0lcLDLiise1F8qDKX00sOU= +google.golang.org/api v0.52.0/go.mod h1:Him/adpjt0sxtkWViy0b6xyKW/SD71CwdJ7HqJo7SrU= +google.golang.org/api v0.54.0/go.mod h1:7C4bFFOvVDGXjfDTAsgGwDgAxRDeQ4X8NvUedIt6z3k= +google.golang.org/api v0.55.0/go.mod h1:38yMfeP1kfjsl8isn0tliTjIb1rJXcQi4UXlbqivdVE= +google.golang.org/api v0.56.0 h1:08F9XVYTLOGeSQb3xI9C0gXMuQanhdGed0cWFhDozbI= +google.golang.org/api v0.56.0/go.mod h1:38yMfeP1kfjsl8isn0tliTjIb1rJXcQi4UXlbqivdVE= google.golang.org/appengine v1.0.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= google.golang.org/appengine v1.2.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= @@ -2362,6 +2463,7 @@ google.golang.org/genproto v0.0.0-20201201144952-b05cb90ed32e/go.mod h1:FWY/as6D google.golang.org/genproto v0.0.0-20201210142538-e3217bee35cc/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20201214200347-8c77b98c765d/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20210108203827-ffc7fda8c3d7/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20210126160654-44e461bb6506/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20210222152913-aa3ee6e6a81c/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20210303154014-9728d6b83eeb/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20210310155132-4ce2db91004e/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= @@ -2369,13 +2471,26 @@ google.golang.org/genproto v0.0.0-20210319143718-93e7006c17a6/go.mod h1:FWY/as6D google.golang.org/genproto v0.0.0-20210331142528-b7513248f0ba/go.mod h1:9lPAdzaEmUacj36I+k7YKbEc5CXzPIeORRgDAUOu28A= google.golang.org/genproto v0.0.0-20210402141018-6c239bbf2bb1/go.mod h1:9lPAdzaEmUacj36I+k7YKbEc5CXzPIeORRgDAUOu28A= google.golang.org/genproto v0.0.0-20210413151531-c14fb6ef47c3/go.mod h1:P3QM42oQyzQSnHPnZ/vqoCdDmzH28fzWByN9asMeM8A= -google.golang.org/genproto v0.0.0-20210420162539-3c870d7478d2/go.mod h1:P3QM42oQyzQSnHPnZ/vqoCdDmzH28fzWByN9asMeM8A= -google.golang.org/genproto v0.0.0-20210423144448-3a41ef94ed2b/go.mod h1:P3QM42oQyzQSnHPnZ/vqoCdDmzH28fzWByN9asMeM8A= google.golang.org/genproto v0.0.0-20210429181445-86c259c2b4ab/go.mod h1:P3QM42oQyzQSnHPnZ/vqoCdDmzH28fzWByN9asMeM8A= -google.golang.org/genproto v0.0.0-20210506142907-4a47615972c2/go.mod h1:P3QM42oQyzQSnHPnZ/vqoCdDmzH28fzWByN9asMeM8A= google.golang.org/genproto v0.0.0-20210510173355-fb37daa5cd7a/go.mod h1:P3QM42oQyzQSnHPnZ/vqoCdDmzH28fzWByN9asMeM8A= -google.golang.org/genproto v0.0.0-20210602131652-f16073e35f0c h1:wtujag7C+4D6KMoulW9YauvK2lgdvCMS260jsqqBXr0= +google.golang.org/genproto v0.0.0-20210513213006-bf773b8c8384/go.mod h1:P3QM42oQyzQSnHPnZ/vqoCdDmzH28fzWByN9asMeM8A= +google.golang.org/genproto v0.0.0-20210517163617-5e0236093d7a/go.mod h1:P3QM42oQyzQSnHPnZ/vqoCdDmzH28fzWByN9asMeM8A= google.golang.org/genproto v0.0.0-20210602131652-f16073e35f0c/go.mod h1:UODoCrxHCcBojKKwX1terBiRUaqAsFqJiF615XL43r0= +google.golang.org/genproto v0.0.0-20210604141403-392c879c8b08/go.mod h1:UODoCrxHCcBojKKwX1terBiRUaqAsFqJiF615XL43r0= +google.golang.org/genproto v0.0.0-20210608205507-b6d2f5bf0d7d/go.mod h1:UODoCrxHCcBojKKwX1terBiRUaqAsFqJiF615XL43r0= +google.golang.org/genproto v0.0.0-20210624195500-8bfb893ecb84/go.mod h1:SzzZ/N+nwJDaO1kznhnlzqS8ocJICar6hYhVyhi++24= +google.golang.org/genproto v0.0.0-20210713002101-d411969a0d9a/go.mod h1:AxrInvYm1dci+enl5hChSFPOmmUF1+uAa/UsgNRWd7k= +google.golang.org/genproto v0.0.0-20210716133855-ce7ef5c701ea/go.mod h1:AxrInvYm1dci+enl5hChSFPOmmUF1+uAa/UsgNRWd7k= +google.golang.org/genproto v0.0.0-20210721163202-f1cecdd8b78a/go.mod h1:ob2IJxKrgPT52GcgX759i1sleT07tiKowYBGbczaW48= +google.golang.org/genproto v0.0.0-20210722135532-667f2b7c528f/go.mod h1:ob2IJxKrgPT52GcgX759i1sleT07tiKowYBGbczaW48= +google.golang.org/genproto v0.0.0-20210728212813-7823e685a01f/go.mod h1:ob2IJxKrgPT52GcgX759i1sleT07tiKowYBGbczaW48= +google.golang.org/genproto v0.0.0-20210805201207-89edb61ffb67/go.mod h1:ob2IJxKrgPT52GcgX759i1sleT07tiKowYBGbczaW48= +google.golang.org/genproto v0.0.0-20210813162853-db860fec028c/go.mod h1:cFeNkxwySK631ADgubI+/XFU/xp8FD5KIVV4rj8UC5w= +google.golang.org/genproto v0.0.0-20210821163610-241b8fcbd6c8/go.mod h1:eFjDcFEctNawg4eG61bRv87N7iHBWyVhJu7u1kqDUXY= +google.golang.org/genproto v0.0.0-20210825212027-de86158e7fda/go.mod h1:eFjDcFEctNawg4eG61bRv87N7iHBWyVhJu7u1kqDUXY= +google.golang.org/genproto v0.0.0-20210828152312-66f60bf46e71/go.mod h1:eFjDcFEctNawg4eG61bRv87N7iHBWyVhJu7u1kqDUXY= +google.golang.org/genproto v0.0.0-20210831024726-fe130286e0e2 h1:NHN4wOCScVzKhPenJ2dt+BTs3X/XkBVI/Rh4iDt55T8= +google.golang.org/genproto v0.0.0-20210831024726-fe130286e0e2/go.mod h1:eFjDcFEctNawg4eG61bRv87N7iHBWyVhJu7u1kqDUXY= google.golang.org/grpc v1.8.0/go.mod h1:yo6s7OP7yaDglbqo1J04qKzAhqBH6lvTonzMVmEdcZw= google.golang.org/grpc v1.14.0/go.mod h1:yo6s7OP7yaDglbqo1J04qKzAhqBH6lvTonzMVmEdcZw= google.golang.org/grpc v1.17.0/go.mod h1:6QZJwpn2B+Zp71q/5VxRsJ6NXXVCE5NRUHRo+f3cWCs= @@ -2407,8 +2522,12 @@ google.golang.org/grpc v1.35.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAG google.golang.org/grpc v1.36.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= google.golang.org/grpc v1.36.1/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= google.golang.org/grpc v1.37.0/go.mod h1:NREThFqKR1f3iQ6oBuvc5LadQuXVGo9rkm5ZGrQdJfM= -google.golang.org/grpc v1.38.0 h1:/9BgsAsa5nWe26HqOlvlgJnqBuktYOLCgjCPqsa56W0= +google.golang.org/grpc v1.37.1/go.mod h1:NREThFqKR1f3iQ6oBuvc5LadQuXVGo9rkm5ZGrQdJfM= google.golang.org/grpc v1.38.0/go.mod h1:NREThFqKR1f3iQ6oBuvc5LadQuXVGo9rkm5ZGrQdJfM= +google.golang.org/grpc v1.39.0/go.mod h1:PImNr+rS9TWYb2O4/emRugxiyHZ5JyHW5F+RPnDzfrE= +google.golang.org/grpc v1.39.1/go.mod h1:PImNr+rS9TWYb2O4/emRugxiyHZ5JyHW5F+RPnDzfrE= +google.golang.org/grpc v1.40.0 h1:AGJ0Ih4mHjSeibYkFGh1dD9KJ/eOtZ93I6hoHhukQ5Q= +google.golang.org/grpc v1.40.0/go.mod h1:ogyxbiOoUXAkP+4+xa6PZSE9DZgIHtSpzjDTB9KAK34= google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.1.0/go.mod h1:6Kw0yEErY5E/yWrBtf03jp27GLLJujG4z/JK95pnjjw= google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= @@ -2422,9 +2541,12 @@ google.golang.org/protobuf v1.24.0/go.mod h1:r/3tXBNzIEhYS9I1OUVjXDlt8tc493IdKGj google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c= google.golang.org/protobuf v1.25.1-0.20200805231151-a709e31e5d12/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c= google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= -google.golang.org/protobuf v1.26.0 h1:bxAC2xTBsZGibn2RTntX0oH50xLsqy1OxA9tTL3p/lk= google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= +google.golang.org/protobuf v1.27.1 h1:SnqbnDw1V7RiZcXPx5MEeqPv2s79L9i7BJUlG/+RurQ= +google.golang.org/protobuf v1.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= +gopkg.in/alexcesaro/quotedprintable.v3 v3.0.0-20150716171945-2caba252f4dc h1:2gGKlE2+asNV9m7xrywl36YYNnBG5ZQ0r/BOOxqPpmk= +gopkg.in/alexcesaro/quotedprintable.v3 v3.0.0-20150716171945-2caba252f4dc/go.mod h1:m7x9LTH6d71AHyAX77c9yqWCCa3UKHcVEj9y7hAtKDk= gopkg.in/asn1-ber.v1 v1.0.0-20181015200546-f715ec2f112d/go.mod h1:cuepJuh7vyXfUyUwEgHQXw849cJrilpS5NeIjOWESAw= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= @@ -2448,6 +2570,8 @@ gopkg.in/ini.v1 v1.51.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= gopkg.in/ini.v1 v1.57.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= gopkg.in/ini.v1 v1.62.0 h1:duBzk771uxoUuOlyRLkHsygud9+5lrlGjdFBb4mSKDU= gopkg.in/ini.v1 v1.62.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= +gopkg.in/mail.v2 v2.3.1 h1:WYFn/oANrAGP2C0dcV6/pbkPzv8yGzqTjPmTeO7qoXk= +gopkg.in/mail.v2 v2.3.1/go.mod h1:htwXN1Qh09vZJ1NVKxQqHPBaCBbzKhp5GzuJEA4VJWw= gopkg.in/mcuadros/go-syslog.v2 v2.2.1/go.mod h1:l5LPIyOOyIdQquNg+oU6Z3524YwrcqEm0aKH+5zpt2U= gopkg.in/natefinch/lumberjack.v2 v2.0.0/go.mod h1:l0ndWWf7gzL7RNwBG7wST/UCcT4T24xpD6X8LsfU/+k= gopkg.in/resty.v1 v1.12.0/go.mod h1:mDo4pnntr5jdWRML875a/NmxYqAlA73dVijT2AXvQQo= From 74b4d0d1f66027528074949ee5936f483b81d514 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 19 Oct 2021 16:52:35 +0000 Subject: [PATCH 021/124] Bump mkdocs from 1.1 to 1.2.3 in /userdocs (#4349) Bumps [mkdocs](https://github.com/mkdocs/mkdocs) from 1.1 to 1.2.3. - [Release notes](https://github.com/mkdocs/mkdocs/releases) - [Commits](https://github.com/mkdocs/mkdocs/compare/1.1...1.2.3) --- updated-dependencies: - dependency-name: mkdocs dependency-type: direct:production ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- userdocs/requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/userdocs/requirements.txt b/userdocs/requirements.txt index f965b22972..88c403fcee 100644 --- a/userdocs/requirements.txt +++ b/userdocs/requirements.txt @@ -1,4 +1,4 @@ -mkdocs == 1.1 +mkdocs == 1.2.3 mkdocs-material == 5.3.3 mkdocs-redirects pymdown-extensions == 7.1 From dfe71b66f6d3407a351b475f4df6aaebd680441a Mon Sep 17 00:00:00 2001 From: weaveworksbot Date: Thu, 21 Oct 2021 05:03:44 +0000 Subject: [PATCH 022/124] Update aws-node --- pkg/addons/default/assets.go | 6 ++--- pkg/addons/default/assets/aws-node.yaml | 30 +++++++++++++++++-------- 2 files changed, 24 insertions(+), 12 deletions(-) diff --git a/pkg/addons/default/assets.go b/pkg/addons/default/assets.go index 9018ff08d3..7655c06350 100644 --- a/pkg/addons/default/assets.go +++ b/pkg/addons/default/assets.go @@ -1,6 +1,6 @@ // Code generated by go-bindata. DO NOT EDIT. // sources: -// assets/aws-node.yaml (6.768kB) +// assets/aws-node.yaml (7.015kB) // assets/coredns-1.17.json (10.228kB) // assets/coredns-1.18.json (10.212kB) // assets/coredns-1.19.json (10.163kB) @@ -74,7 +74,7 @@ func (fi bindataFileInfo) Sys() interface{} { return nil } -var _awsNodeYaml = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\xec\x59\x41\x93\xe2\xba\x11\xbe\xf3\x2b\xa6\x54\x95\x4b\xaa\x6c\x60\xb3\xbb\xd9\x37\x55\x39\xb0\xe0\x21\xae\x07\x86\x32\x30\xfb\x5e\x2e\x2e\x21\xf7\x18\x05\x59\xf2\x93\x64\x86\x79\xa9\xfc\xf7\x94\x84\x0d\x36\xd8\xc0\x6c\xb6\x92\x1c\x72\x9a\x19\xa9\xfb\xeb\xd6\xa7\xee\x56\xbb\xc7\x71\x9c\x0e\xc2\x19\x7d\x06\xa9\xa8\xe0\xe8\xf1\x01\xc9\x35\x26\x2e\xce\xf5\x46\x48\xfa\x3b\xd6\x54\x70\x77\xfb\x45\xb9\x54\x74\x77\x7d\xd4\x41\x5b\xca\x63\x23\x36\x64\xb9\xd2\x20\x43\xc1\xe0\x2b\xe5\x31\xe5\x09\xea\xa0\x14\x34\x8e\xb1\xc6\xe8\xb1\xf3\xf0\x80\x38\x4e\xc1\x88\xe2\x57\xe5\x70\x11\x03\xea\x20\x29\x18\x84\xf0\x72\xd8\xc7\x19\x1d\x4b\x91\x67\x57\xad\x22\x23\xd9\x60\x14\xb5\x58\x50\xf9\xfa\xef\x40\xb4\x42\x8f\x1d\xe7\xa4\xb8\x00\xb9\xa3\x04\x06\x84\x88\x9c\xeb\x16\xdd\x62\x51\x65\x98\xd8\x9d\x6d\xbe\x06\x47\xbd\x29\x0d\x29\xea\xfc\x10\xa6\xee\xa2\x28\x67\x50\x78\x5f\x12\xa4\xac\xb0\xf3\x80\x88\x8c\xad\x09\x9c\xe2\xdf\x05\xc7\xaf\xca\x25\x22\xb5\x8e\x4b\x50\x22\x97\x04\x8e\xa2\xc0\x29\x11\xfc\x85\x26\xca\xee\xef\x40\xae\x8f\x7b\x09\x58\x0a\x9c\x07\xc4\xa8\x2a\x7f\x7d\xc5\x9a\x6c\x50\xa3\xd9\x66\x0b\x99\x88\x55\xa1\x7b\xa4\xad\xc1\xd8\xa5\x89\x93\x0f\xf7\x1b\x33\xe4\xbc\x13\xdc\xfe\x96\x67\x31\xd6\xd0\x6c\x09\xf6\x1a\xb8\xb9\x4c\xd5\x6c\xf3\x8f\xf7\xd8\x6b\x88\x0b\x9c\xd1\x13\xf4\x29\x24\xd6\xa0\x71\x2d\x2e\x72\xa5\x45\x1a\x16\x56\x47\xf0\x42\x39\x35\x41\xd4\x1a\x24\xa7\x2b\x75\x5b\x02\x01\xa9\x0c\xc8\x41\x29\x29\x33\xab\x3d\x66\xec\xad\x59\xe9\x4a\x8a\x79\x81\x3f\xb4\x46\xd0\x61\x3d\x63\xb9\xc4\xac\x6e\xbe\xd8\x52\x94\x27\x39\xc3\xb2\xb6\x69\x91\x15\x11\x19\x54\x62\xbf\x24\xf2\x40\xf6\xe3\x29\x68\x8c\xcc\xae\x8f\x59\xb6\x31\xd4\x1c\x50\x41\xee\xc0\xb8\xa2\x65\x0e\xc5\x92\x16\x12\x27\x50\xae\x35\x52\x9e\xa9\x7a\xd6\x8d\x30\xa4\x82\x2f\x4c\x20\x9c\xd1\xc9\xf0\x1a\xd8\xe9\xdc\x5f\x94\x83\xb3\xac\xb1\x12\xbc\xa3\x3c\x54\x98\x57\xc0\x80\x68\x21\x4b\x0b\xa9\x09\x94\x49\xd5\xe8\x15\xb3\x1a\xd2\x8c\x99\x88\x2d\x95\xab\xae\xdb\x15\x56\x47\x6a\xc7\x32\xae\x94\x4e\xd9\xbf\xf0\x8b\x0d\xb1\xb7\xaa\xae\x11\x1e\x5c\xae\xdb\x74\xf8\x2d\xa7\x12\xe2\x51\x2e\x29\x4f\x16\x64\x03\x71\xce\x28\x4f\xfc\x84\x8b\xe3\xb2\xb7\x07\x92\xdb\xa0\xad\xea\x16\xb8\x8b\x82\x88\x25\xc8\x54\x9d\x09\x38\x05\x2f\xde\x3e\x93\xa0\x4e\x71\x71\x26\xb3\x85\x37\x73\x2c\x93\x3a\xae\xe1\x5b\x72\xd0\x60\xf3\x49\x14\x51\x58\xb3\x2a\x32\x90\xd8\x52\xff\x80\x7c\xde\x20\xb0\xc3\x2c\x87\x4b\x4b\x45\x6e\xf3\x7c\x7f\xae\x73\xd5\x07\x2c\x0f\x15\xe7\x47\x7a\x81\xd3\xf8\xf3\xc7\x4b\x1d\xb3\x23\xd3\xcb\x9d\x93\x7f\xb0\x3d\xcb\xf1\x2e\x11\x69\x96\x6b\x70\xf4\x5b\x06\x37\xdc\x0c\x84\x7e\xb7\xa7\x2f\x58\x26\xb6\xb6\x9e\xad\xbf\xe3\x5e\xff\xcb\x57\xfa\xff\xdb\x3c\xd9\x3d\xbb\x4d\x44\x04\xd7\x98\x72\x90\x27\x79\xdb\x55\xec\x2a\xea\x95\x22\x3e\x18\x8d\xfc\xa5\x3f\x0b\x06\x93\xc8\x0b\xfc\x68\x39\x18\x2f\xaa\x0e\x1c\x4c\x1b\xc1\x7f\xfc\x13\x35\xea\x7f\x5b\x44\xcf\xf3\x61\x34\x0c\xfc\x28\x98\x8d\xbc\x68\x3e\x0b\x97\xd1\x62\x35\x37\x3f\x9b\x91\xcc\x5b\x70\x15\xcb\x38\x32\x5d\xae\x9a\xb5\x7f\xea\xf5\xfa\x57\xb5\x7f\xfe\xb2\xb0\xde\x0c\x67\xc1\x93\x3f\x5e\x85\x5e\x14\xce\x9f\xfc\xc9\xd2\x0b\x9b\x01\x5f\x30\x53\xd7\xfd\x39\x22\xae\x16\xcb\xd9\x34\x0a\xbc\xe5\xb7\x59\xf8\x73\x34\x7c\x1a\xff\xbb\x88\xde\x2f\x4b\x2f\x0c\x06\x93\x45\x30\x68\x21\xeb\x7e\xac\xc9\x6c\x3c\xf1\x9e\xbd\x49\x33\xce\xc8\xfb\xba\x1a\xdf\x8b\x13\x3d\xf9\x13\xaf\x19\xa7\xbb\x11\x4a\x77\x77\x58\x76\x99\x48\xba\xe6\xd9\x92\x22\xd7\x10\x3b\xc0\x69\x97\x66\x38\x8d\x5d\x26\x92\xbb\x0c\x85\x83\x60\x34\x9b\xfa\x7f\xf3\xda\x4f\x9f\x49\x7e\x1f\xd6\xb3\xb7\xfc\xeb\x3c\xf4\x9e\xfc\x5f\x9a\x81\x80\xd3\x9b\x38\xf3\xc9\x6a\xec\x07\xb7\xce\xdf\x72\xf4\x8c\xe5\x09\xe5\x77\x9d\xbd\x62\xe7\xbb\x2e\x6c\xe4\x2f\x06\x5f\x27\x5e\xe4\x07\xcb\x70\xb6\x98\x7b\x43\x93\xbf\xef\x8d\x9e\x12\x64\xea\x2d\x43\x7f\xd8\x92\xf3\xb7\xd5\xcb\x5c\x08\xbd\xc5\x6c\x15\x0e\xbd\x68\x1e\xce\x9e\xfd\x85\x3f\x0b\xfc\xe0\xdd\xd9\xe1\x05\x16\x73\x3e\x1b\x99\x12\xf0\xbd\xda\x36\x0a\xa2\x91\x37\xf1\xc6\x83\xef\x61\x66\xfa\xeb\xa1\x90\x05\x83\x69\x43\x0c\x3c\x49\x91\x9e\xf7\x4c\x2f\x14\x58\x5c\x7e\x1d\x5f\xee\xcc\xb1\xde\x18\x60\xd3\xd4\xb9\xa6\xbf\x0a\x8c\xa5\x26\xd3\xdf\x06\xe1\xb4\x28\xc3\xe1\xd8\x6b\xc9\x89\xe6\xea\x67\x55\x8b\xb3\xdf\xa9\x8d\x68\x7a\x68\xce\xd1\xe7\xde\x87\x8f\xbd\x7e\xff\xe3\x9f\x3e\x7e\xfa\xe0\xc6\x5b\xe9\x02\x91\x6e\xae\x9c\x57\x50\xda\xf9\x70\xf6\x9e\x1d\xfe\x72\x4c\xf3\x4a\x38\x7d\xdc\xf5\xdd\x9f\xdc\x2a\x2a\xa3\x3b\xe0\xa0\xd4\x5c\x8a\x35\xd4\x5b\x53\xd8\x57\xda\xda\x62\x8d\x88\x34\xc5\xa6\xf5\x3f\x6f\x47\xba\x38\xcb\xba\x89\xcc\x88\xb3\x01\xcc\xf4\xc6\xc9\x2c\xe0\xb9\x98\x83\xe3\x58\xfe\xe5\xf1\x53\xaf\xf7\xa9\x5f\x3b\xb2\xfd\x2a\xc3\x6c\x04\x0c\xbf\x2d\x80\x08\x1e\x2b\xf4\xf8\xf0\xb9\x57\xe9\xa1\x1b\x3e\x15\x8a\xad\x4c\x48\xad\xea\x2f\xe6\xf1\x61\x9d\x0b\xa9\x0d\x52\xff\xf3\x9f\xbf\x54\x0d\x96\x70\x29\x68\x49\x49\xa5\x27\x42\x12\x70\x4c\xff\x77\x39\xe9\x57\x3d\xad\x7e\x4b\x57\x96\x7f\xcb\x41\xe9\xf3\x16\x04\x91\x2c\xb7\x41\xd5\x4b\x2b\xa7\x55\x40\x72\x49\xf5\xdb\x50\x70\x0d\x7b\x5d\x47\x22\x38\xc3\x6b\xca\xa8\xa6\x17\x0d\x0d\xc2\x71\xc3\x91\x03\x6f\x19\x0d\x46\x53\xbf\x92\xc7\x68\x27\x58\x9e\xc2\x54\xe4\xfc\xfc\x92\x52\xb3\x56\x26\xdc\xe1\xad\x12\x99\xee\x12\x4e\xbb\x6b\x5a\x6b\xad\x8e\xd7\x45\x38\x75\xd6\x94\x3b\x31\x95\xe8\x06\x14\x68\x62\xa1\x38\x68\x37\x6e\x05\xe3\xa0\xef\x01\x6b\x7e\x48\x1a\x51\x99\x48\x6e\x20\x1a\x30\x99\xf3\xee\x65\x28\x57\x60\x64\x7e\xeb\x94\x25\x4c\x2c\xc8\x16\xa4\xda\xd0\xd4\x55\x82\x6c\x1b\xd1\x4e\x32\x57\x00\x0d\xd8\x5e\xe3\x35\x03\xe5\xb2\x36\xa4\x42\xc0\xa9\x0a\x20\xc3\x51\x00\xfa\x55\xc8\x6d\x75\xa6\x50\x04\xf1\xf0\x7d\x5d\x6e\xf9\x5c\x2d\x87\xf3\xc8\x1b\x84\x93\x5f\xa3\x91\x37\x5d\xb5\xf4\x0a\x67\x4f\xc3\x0f\x29\x93\x8e\x71\xfa\xb2\x56\x56\x2b\xd0\x2e\x23\x47\xc9\x7b\xb3\x29\x93\x74\x47\x19\x24\xf5\xb9\xcb\x7f\x24\x47\x8c\x6d\x61\x1d\x63\x58\xa9\xa0\x10\x3c\x8c\x55\x6c\x08\x3a\x44\x52\x4d\x09\x66\x47\x0d\x55\x1b\xe6\x06\x2d\xd5\x17\x69\x90\x29\xe5\x76\x2e\x3b\x96\x98\xc0\x1c\x24\x15\x71\xa5\x5c\xf5\x8e\x92\x82\x99\x8f\xa7\xda\xc7\xaa\x53\xff\xa4\xf2\xf6\xd4\xd4\xad\x4e\x8d\x95\x9a\xb4\x21\xe0\xc0\x46\x8d\xd9\x92\x9f\x46\x6a\xae\x11\x73\x1b\xb2\xa5\x8c\x5c\x2b\x22\xb7\x41\x6f\xa6\xee\x95\xc4\xbd\x8d\xde\x9e\xc7\x57\xb3\xf8\x3e\xb7\x6f\x54\x41\xfb\xe1\x6c\x92\x98\x4a\x3b\x96\x7a\x9b\xc9\xa1\x84\xda\x04\xa3\xad\x52\xde\x4f\x5b\x63\xe1\x7c\x8f\xe5\x4a\x71\x2d\x86\xd7\x0b\x2d\xb1\x86\xa4\x1c\xcf\x21\x29\x18\xa3\x3c\x59\x1d\x26\xdb\xc7\xe9\x5e\x8a\xf7\x2b\x8e\x77\x98\x32\xc3\xdf\xe1\x39\xfd\x43\x31\x07\x2c\x1d\x08\x6b\xaa\x4d\x83\xd4\xda\x0c\xf5\xfc\xbf\x26\x37\xff\x79\x71\x75\x44\xea\xba\x6e\xe7\x5f\x01\x00\x00\xff\xff\xaf\xc1\xd4\x65\x70\x1a\x00\x00") +var _awsNodeYaml = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\xec\x58\xdf\x8f\xe2\x38\x12\x7e\xe7\xaf\x68\x59\xba\x97\x93\x12\xe8\xd9\x99\xb9\xde\x96\xf6\x81\x81\x34\x17\x2d\x04\x14\xa0\x67\xf7\x5e\x22\xe3\x54\x07\x1f\x8e\x9d\xb5\x1d\x9a\xde\xd3\xfd\xef\x27\x9b\x04\x12\x48\x80\x9e\xdb\xbb\x91\x4e\xf7\xd4\x8d\x5d\xf5\x7d\xe5\x2f\x55\xe5\x1f\x8e\xe3\x74\x10\xce\xe8\x33\x48\x45\x05\x47\x8f\x77\x68\x7b\x8f\x3a\x68\x43\x79\x6c\x7e\xcc\x41\x6e\x29\x81\x3e\x21\x22\xe7\x1a\x75\x50\x0a\x1a\xc7\x58\x63\xf4\xd8\xb9\xbb\x43\x1c\xa7\x60\xcc\xf0\xab\x72\xb8\x88\x01\x95\x83\x2a\xc3\xc4\xce\x6c\xf2\x15\x38\xea\x4d\x69\x48\x51\xa7\x81\x4d\xae\x30\x71\x71\xae\xd7\x42\xd2\xdf\xb1\xa6\x82\xbb\x9b\x07\xe5\x52\xd1\xad\xc5\x31\x60\xb9\xd2\x20\x43\xc1\xe0\x0b\xe5\x31\xe5\xc9\x0d\xb1\x20\x29\x18\x84\xf0\xb2\x9f\xc7\x19\x1d\x49\x91\x67\x17\x59\xed\x02\x1a\x48\x51\x0b\x83\xca\x57\x7f\x07\xa2\x15\x7a\xec\x38\x77\xad\xaa\x7d\x27\xa5\x6e\x92\x28\x67\x50\x44\x5f\x0a\xa4\xac\xb1\x73\x87\x88\x8c\x2d\x05\x4e\xf1\xef\x82\xe3\x57\xe5\x12\x91\xda\xc0\x25\x28\x91\x4b\x02\x07\x53\xe0\x94\x08\xfe\x42\x13\x65\xe7\xb7\x20\x57\x87\xb9\x04\xac\x04\xce\x1d\x62\x54\x95\xff\xbe\x62\x4d\xd6\xa8\x91\xb6\x99\xe1\xa0\x55\x03\xc3\x39\xee\x91\xf8\x76\x86\x4c\xc4\xff\x31\x6c\xa3\xf6\x3b\xc1\xed\x7f\x79\x16\x63\x0d\xcd\x4c\xb0\xd3\xc0\x4d\x76\xa8\x66\xce\x3f\xdf\xc2\xd7\x90\x68\x38\xa3\x47\xe8\x63\x8e\xad\x40\xe3\x5a\xa2\xe5\x4a\x8b\x34\x2c\x58\x87\xf0\x42\x39\x35\x59\xd9\x9a\x75\xc7\x1c\x71\x5b\x32\x0b\xa9\x0c\xc8\xde\x29\x29\x4b\xb5\x3d\x09\x6d\x46\x58\xeb\x4a\xcd\x7a\x81\x3f\xb0\x24\x68\x3f\x9e\xb1\x5c\x62\x56\xa7\x2f\xa6\x14\xe5\x49\xce\xb0\xac\x4d\x5a\x64\x45\x44\x06\x95\x62\x2a\x85\xdc\x8b\x5d\x49\xc8\x7d\xbf\xc4\x2c\x5b\x1b\x69\xf6\xa8\x20\xb7\x60\x42\xd1\x32\x87\x62\x48\x0b\x89\x13\x28\xc7\x1a\x25\xcf\x54\xbd\x8c\x87\x18\x52\xc1\xe7\x70\xde\x73\x19\x5e\x01\x3b\xae\xfb\x41\x39\x38\xcb\x1a\x5b\xcb\x3b\xfa\x4d\x45\x79\x05\x0c\x88\x16\xb2\x64\x48\x4d\xa2\x8c\xab\xa4\x17\x68\x35\xa4\x19\x33\x19\x5b\x3a\x57\x43\xb7\x23\xac\x8e\xd4\x8e\x65\x42\x29\x83\xb2\xbf\xf0\x8b\x4d\xb1\xb7\xaa\xaf\x31\xee\x9f\x8f\xdb\x72\xf8\x2d\xa7\x12\xe2\x61\x2e\x29\x4f\xe6\x64\x0d\x71\xce\x28\x4f\xfc\x84\x8b\xc3\xb0\xb7\x03\x92\xdb\xa4\xad\xfa\x16\xb8\xf3\x42\x88\x05\xc8\x54\x9d\x18\x38\x85\x2e\xde\x2e\x93\xa0\x8e\x79\x71\x62\xb3\x81\x37\xb3\x2c\x53\x3a\xae\xd1\x5b\x72\xd0\x60\xeb\x49\x14\x59\x58\x63\x15\x19\x48\x6c\xa5\xbf\x43\x3e\x6f\x30\xd8\x62\x96\xc3\x39\x53\x51\xdb\x3c\xdf\x9d\xfa\x5c\x8c\x01\xcb\x7d\xc7\xf9\x23\xa3\xc0\x69\xfc\xf9\xe3\xb9\x8f\x99\x91\xe9\xf9\xcc\x31\x3e\xd8\x9c\xd4\x78\x97\x88\x34\xcb\x35\x38\xfa\x2d\x83\x2b\x61\x06\x42\xbf\x3b\xd2\x17\x2c\x13\xdb\x5b\x4f\xc6\xdf\xf1\x5d\xbf\xf3\x27\xfd\xff\xd7\x3c\xf2\x9e\x7c\x4d\x44\x04\xd7\x98\x72\x90\x47\x7b\x7b\x4c\xd9\x56\xdc\x2b\x4d\xbc\x3f\x1c\xfa\x0b\x7f\x1a\xf4\xc7\x91\x17\xf8\xd1\xa2\x3f\x9a\x57\x03\xd8\x53\x1b\xc3\x7f\xfc\x13\x35\xfa\x7f\x9d\x47\xcf\xb3\x41\x34\x08\xfc\x28\x98\x0e\xbd\x68\x36\x0d\x17\xd1\x7c\x39\x33\x7f\x9b\x91\xcc\x5e\x70\x11\xcb\x04\x32\x59\x2c\x9b\xbd\x7f\xec\xf5\xee\x2f\x7a\xff\xfc\x30\xb7\xd1\x0c\xa6\xc1\x93\x3f\x5a\x86\x5e\x14\xce\x9e\xfc\xf1\xc2\x0b\x9b\x01\x5f\x30\x53\x97\xe3\x39\x20\x2e\xe7\x8b\xe9\x24\x0a\xbc\xc5\xd7\x69\xf8\x73\x34\x78\x1a\xfd\xbb\x88\xde\x2f\x0b\x2f\x0c\xfa\xe3\x79\xd0\x6f\x11\xeb\x76\xac\xf1\x74\x34\xf6\x9e\xbd\x71\x33\xce\xd0\xfb\xb2\x1c\xdd\x8a\x13\x3d\xf9\x63\xaf\x19\xa7\xbb\x16\x4a\x77\xb7\x58\x76\x99\x48\xba\x66\xdb\x92\x22\xd7\x10\x3b\xc0\x69\x97\x66\x38\x8d\x5d\x26\x92\x9b\x88\xc2\x7e\x30\x9c\x4e\xfc\xbf\x79\xed\xab\xcf\x24\xbf\x0d\xeb\xd9\x5b\xfc\x75\x16\x7a\x4f\xfe\x2f\xcd\x40\xc0\xe9\x55\x9c\xd9\x78\x39\xf2\x83\x6b\xeb\x6f\x59\x7a\xc6\xf2\x84\xf2\x9b\xd6\x5e\xe1\xf9\xa6\x0f\x36\xf4\xe7\xfd\x2f\x63\x2f\xf2\x83\x45\x38\x9d\xcf\xbc\x81\xa9\xdf\xf7\x66\x4f\x09\x32\xf1\x16\xa1\x3f\x68\xa9\xf9\xeb\xee\x65\x2d\x84\xde\x7c\xba\x0c\x07\x5e\x34\x0b\xa7\xcf\xfe\xdc\x9f\x06\x7e\xf0\xee\xea\xf0\x02\x8b\x39\x9b\x0e\x4d\x0b\xf8\x56\x6f\x9b\x05\xd1\xd0\x1b\x7b\xa3\xfe\xb7\x28\x33\xf9\x75\xdf\xc8\x82\xfe\xa4\x21\x07\x9e\xa4\x48\x4f\xcf\x4c\x2f\x14\x58\x5c\x5e\xb7\xcf\x67\x66\x58\xaf\x0d\xb0\x39\xd4\xb9\xe6\x7c\x15\x18\xa6\x26\xea\xaf\xfd\x70\x52\xb4\xe1\x70\xe4\xb5\xd4\x44\x73\xf7\xb3\xae\xc5\xda\x6f\xf4\x46\x34\xdd\x1f\xce\xd1\xe7\xde\x87\x8f\xbd\xfb\xfb\x8f\x3f\x7c\xfc\xf4\xc1\x8d\x37\xd2\x05\x22\xdd\x5c\x39\xaf\xa0\xb4\xf3\xe1\x64\x3f\xdb\xff\x72\xcc\xe1\x95\x70\xfa\xb8\xbd\x77\x7f\x74\x7f\xa8\xa0\x32\xba\x05\x0e\x4a\xcd\xa4\x58\x41\xfd\x68\x0a\xbb\xca\xb1\xb6\x18\x23\x22\x4d\xb1\x39\xfa\x9f\x1e\x47\xba\x38\xcb\xba\x89\xcc\x88\xb3\x06\xcc\xf4\xda\xc9\x2c\xe0\xa9\x99\x83\xe3\x58\xfe\xf4\xf8\xa9\xd7\xfb\x74\x7f\x3e\x49\x04\xe7\x40\xb4\xa3\x69\x0a\x22\xd7\x3f\x7d\x50\xe7\x36\x86\xa2\x79\x1e\xd9\x9b\x1d\x66\x43\x60\xf8\x6d\x0e\x44\xf0\x58\xa1\xc7\xbb\xcf\xbd\xaa\x4d\xe1\x7a\x9c\xfe\x54\x39\xa5\x37\x5c\x46\x8a\xa9\x4c\x48\xad\xea\x7b\xf2\x61\xeb\x9e\x09\xa9\x0d\xcf\xfd\xe7\xbf\x3c\x54\xa9\x4a\xb8\x14\xb4\xa4\xa4\x12\x2a\x92\x80\x63\xfa\xbf\xad\xfa\x7d\x75\xb5\xd5\x1b\x7f\x65\xf8\xb7\x1c\x94\x3e\x3d\x28\x21\x92\xe5\x36\xf5\x7b\x69\x45\x31\x05\x24\x97\x54\xbf\x0d\x04\xd7\xb0\xd3\x75\x24\x82\x33\xbc\xa2\x8c\x6a\x7a\x76\xec\x42\x38\x6e\x90\x2d\xf0\x16\x51\x7f\x38\xf1\x2b\xdd\x06\x6d\x05\xcb\x53\x98\x88\x9c\x9f\x7e\xe8\xd4\x8c\x95\x6d\x61\xbf\xa3\x8a\x4c\x77\x09\xa7\xdd\x15\xad\x1d\x00\x0f\x9f\x9c\x70\xea\xac\x28\x77\x62\x2a\xd1\x15\x28\xd0\xc4\x42\x71\xd0\x6e\xdc\x0a\xc6\x41\xdf\x02\xd6\xbc\xdd\x35\xa2\x32\x91\x5c\x41\x34\x60\x32\xe7\xdd\xf3\x72\xa8\xc0\xc8\xfc\xda\x2a\x4b\x98\x58\x90\x0d\x48\xb5\xa6\xa9\xab\x04\xd9\x34\xa2\x1d\x6d\x2e\x00\x1a\xb0\x9d\xc6\x2b\x06\xca\x65\x6d\x48\x85\x81\x53\x35\x40\x46\xa3\x00\xf4\xab\x90\x9b\xea\xcb\x47\x91\xc4\x83\xf7\x9d\xc5\xcb\x4d\x75\x31\x98\x45\x5e\x3f\x1c\xff\x1a\x0d\xbd\xc9\xb2\xe5\x44\x73\xb2\x81\xfd\x21\xcd\xdc\x31\x41\x9f\x77\xf4\x6a\x17\xdb\x66\xe4\x60\x79\x6b\x35\x65\x92\x6e\x29\x83\xa4\xfe\x3a\xf4\x5f\xa9\x11\xc3\x2d\x6c\x60\x0c\x2b\x15\x14\x86\xfb\xc7\x1f\x9b\x82\x0e\x91\x54\x53\x82\xd9\xc1\x43\xd5\xde\xb0\x83\x96\x0e\x8e\x34\xc8\x94\x72\xfb\x1c\x3d\x92\x98\xc0\x0c\x24\x15\x71\xa5\x5d\xf5\x0e\x96\x82\x99\x2b\x5e\xed\x4a\xed\xd4\x2f\x7e\xde\x8e\x9a\xbe\xd5\xa9\xa9\x52\xb3\x36\x02\xec\xd5\xa8\x29\x5b\xea\xd3\x28\xcd\x25\x61\xae\x43\xb6\xb4\x91\x4b\x4d\xe4\x3a\xe8\xd5\xd2\xbd\x50\xb8\xd7\xd1\xdb\xeb\xf8\x62\x15\xdf\x16\xf6\x95\x2e\x68\xaf\xf7\xa6\x88\xa9\xb4\x8f\x67\x6f\x53\x39\x90\x50\x7b\x67\x69\xeb\x94\xb7\xcb\xd6\xd8\x38\xdf\xc3\x5c\x69\xae\xc5\x13\xfb\x5c\x4b\xac\x21\x29\x1f\x11\x91\x14\x8c\x51\x9e\x2c\xf7\xef\xef\x87\x37\xc8\x14\xef\x96\x1c\x6f\x31\x65\x46\xbf\xfd\x76\xfa\xa7\xe2\xb5\xb2\x0c\x20\xac\xb9\x76\x5c\xd7\xed\xfc\x2b\x00\x00\xff\xff\x52\x34\x51\xce\x67\x1b\x00\x00") func awsNodeYamlBytes() ([]byte, error) { return bindataRead( @@ -90,7 +90,7 @@ func awsNodeYaml() (*asset, error) { } info := bindataFileInfo{name: "aws-node.yaml", size: 0, mode: os.FileMode(0), modTime: time.Unix(0, 0)} - a := &asset{bytes: bytes, info: info, digest: [32]uint8{0x15, 0x7a, 0x4, 0xf3, 0x4e, 0x9c, 0x52, 0x8b, 0x4, 0xa4, 0x1c, 0xee, 0xfc, 0xd4, 0x7e, 0x41, 0x58, 0x5, 0xc8, 0x90, 0xb4, 0xaa, 0x3, 0x3c, 0xce, 0x9d, 0x1d, 0x53, 0x8, 0xe9, 0x20, 0xc0}} + a := &asset{bytes: bytes, info: info, digest: [32]uint8{0x7c, 0x85, 0xa8, 0x9e, 0xb6, 0x21, 0xf, 0x46, 0x9a, 0x6f, 0x36, 0xe9, 0xb2, 0x10, 0xc9, 0x3d, 0x4e, 0x97, 0xf5, 0xf5, 0x23, 0xb7, 0x14, 0x6e, 0x77, 0x70, 0xd4, 0x7b, 0xe, 0x62, 0xbe, 0x50}} return a, nil } diff --git a/pkg/addons/default/assets/aws-node.yaml b/pkg/addons/default/assets/aws-node.yaml index acf37ed900..638400f8dc 100644 --- a/pkg/addons/default/assets/aws-node.yaml +++ b/pkg/addons/default/assets/aws-node.yaml @@ -1,4 +1,10 @@ --- +"apiVersion": "v1" +"kind": "ServiceAccount" +"metadata": + "name": "aws-node" + "namespace": "kube-system" +--- "apiVersion": "rbac.authorization.k8s.io/v1" "kind": "ClusterRoleBinding" "metadata": @@ -28,12 +34,19 @@ - "apiGroups": - "" "resources": - - "pods" - "namespaces" "verbs": - "list" - "watch" - "get" +- "apiGroups": + - "" + "resources": + - "pods" + "verbs": + - "list" + - "watch" + - "get" - "apiGroups": - "" "resources": @@ -159,13 +172,16 @@ "value": "1" - "name": "WARM_PREFIX_TARGET" "value": "1" - "image": "602401143452.dkr.ecr.us-west-2.amazonaws.com/amazon-k8s-cni:v1.9.1" + "image": "602401143452.dkr.ecr.us-west-2.amazonaws.com/amazon-k8s-cni:v1.9.3" "livenessProbe": "exec": "command": - "/app/grpc-health-probe" - "-addr=:50051" + - "-connect-timeout=2s" + - "-rpc-timeout=2s" "initialDelaySeconds": 60 + "timeoutSeconds": 5 "name": "aws-node" "ports": - "containerPort": 61678 @@ -175,6 +191,8 @@ "command": - "/app/grpc-health-probe" - "-addr=:50051" + - "-connect-timeout=2s" + - "-rpc-timeout=2s" "initialDelaySeconds": 1 "resources": "requests": @@ -201,7 +219,7 @@ - "env": - "name": "DISABLE_TCP_EARLY_DEMUX" "value": "false" - "image": "602401143452.dkr.ecr.us-west-2.amazonaws.com/amazon-k8s-cni-init:v1.9.1" + "image": "602401143452.dkr.ecr.us-west-2.amazonaws.com/amazon-k8s-cni-init:v1.9.3" "name": "aws-vpc-cni-init" "securityContext": "privileged": true @@ -238,10 +256,4 @@ "rollingUpdate": "maxUnavailable": "10%" "type": "RollingUpdate" ---- -"apiVersion": "v1" -"kind": "ServiceAccount" -"metadata": - "name": "aws-node" - "namespace": "kube-system" ... From 775647a9bca7f65c4106d63c7e595bf3f062b0a6 Mon Sep 17 00:00:00 2001 From: Gergely Brautigam <182850+Skarlso@users.noreply.github.com> Date: Thu, 21 Oct 2021 14:36:20 +0200 Subject: [PATCH 023/124] Add iamidentitymapping delete and get commands (#4346) * Add accounts to delete and get * Simplified and unified the display by extending the interface in an ugly way * Update pkg/authconfigmap/authconfigmap.go Co-authored-by: Chetan Patwal * Addressed comments Co-authored-by: Chetan Patwal --- pkg/authconfigmap/authconfigmap.go | 38 +++++++----- pkg/authconfigmap/authconfigmap_test.go | 69 +++++++++++++++++++++ pkg/ctl/create/iamidentitymapping.go | 2 +- pkg/ctl/delete/iamidentitymapping.go | 30 ++++++--- pkg/ctl/get/iamidentitymapping.go | 5 +- pkg/iam/mapping.go | 37 +++++++++++ userdocs/src/usage/iam-identity-mappings.md | 18 +++++- 7 files changed, 171 insertions(+), 28 deletions(-) diff --git a/pkg/authconfigmap/authconfigmap.go b/pkg/authconfigmap/authconfigmap.go index 246863e7d1..6550406989 100644 --- a/pkg/authconfigmap/authconfigmap.go +++ b/pkg/authconfigmap/authconfigmap.go @@ -108,20 +108,19 @@ func (a *AuthConfigMap) RemoveAccount(account string) error { return err } - var newAccounts []string found := false - for _, acc := range accounts { + for i, acc := range accounts { if acc == account { found = true - continue + accounts = append(accounts[:i], accounts[i+1:]...) + break } - newAccounts = append(newAccounts, acc) } if !found { return fmt.Errorf("account %q not found in auth ConfigMap", account) } logger.Info("removing account %q from auth ConfigMap", account) - return a.setAccounts(newAccounts) + return a.setAccounts(accounts) } func (a *AuthConfigMap) accounts() ([]string, error) { @@ -150,7 +149,7 @@ func (a *AuthConfigMap) AddIdentity(identity iam.Identity) error { // AddIdentityIfNotPresent adds the specified identity if the predicate exists(identity) returns false for all entries func (a *AuthConfigMap) AddIdentityIfNotPresent(identity iam.Identity, exists func(iam.Identity) bool) error { - identities, err := a.Identities() + identities, err := a.GetIdentities() if err != nil { return err } @@ -175,7 +174,7 @@ func (a *AuthConfigMap) AddIdentityIfNotPresent(identity iam.Identity, exists fu // If `all` is true it will remove all of them and not return an // error if it cannot be found. func (a *AuthConfigMap) RemoveIdentity(arnToDelete string, all bool) error { - identities, err := a.Identities() + identities, err := a.GetIdentities() if err != nil { return err } @@ -199,8 +198,8 @@ func (a *AuthConfigMap) RemoveIdentity(arnToDelete string, all bool) error { return a.setIdentities(newidentities) } -// Identities returns a list of iam users and roles that are currently in the (cached) configmap. -func (a *AuthConfigMap) Identities() ([]iam.Identity, error) { +// GetIdentities returns a list of iam users and roles that are currently in the (cached) configmap. +func (a *AuthConfigMap) GetIdentities() ([]iam.Identity, error) { var roles []iam.RoleIdentity if err := yaml.Unmarshal([]byte(a.cm.Data[rolesData]), &roles); err != nil { return nil, errors.Wrapf(err, "unmarshalling %q", rolesData) @@ -211,12 +210,20 @@ func (a *AuthConfigMap) Identities() ([]iam.Identity, error) { return nil, errors.Wrapf(err, "unmarshalling %q", usersData) } - all := make([]iam.Identity, len(users)+len(roles)) - for i, r := range roles { - all[i] = r + var accounts []string + if err := yaml.Unmarshal([]byte(a.cm.Data[accountsData]), &accounts); err != nil { + return nil, errors.Wrapf(err, "unmarshalling %q", accountsData) + } + + var all []iam.Identity + for _, r := range roles { + all = append(all, r) } - for i, u := range users { - all[i+len(roles)] = u + for _, u := range users { + all = append(all, u) + } + for _, a := range accounts { + all = append(all, iam.AccountIdentity{KubernetesAccount: a}) } return all, nil } @@ -230,6 +237,9 @@ func (a *AuthConfigMap) setIdentities(identities []iam.Identity) error { roles = append(roles, identity) case iam.ResourceTypeUser: users = append(users, identity) + case iam.ResourceTypeAccount: + // skip, this is handled separately by AddAccount + continue default: return errors.Errorf("cannot determine if %q refers to a user or role during setIdentities preprocessing", identity.ARN()) } diff --git a/pkg/authconfigmap/authconfigmap_test.go b/pkg/authconfigmap/authconfigmap_test.go index a0374c9fde..6d893e94c8 100644 --- a/pkg/authconfigmap/authconfigmap_test.go +++ b/pkg/authconfigmap/authconfigmap_test.go @@ -13,6 +13,7 @@ import ( . "github.com/onsi/ginkgo" . "github.com/onsi/gomega" + . "github.com/weaveworks/eksctl/pkg/authconfigmap" "github.com/weaveworks/eksctl/pkg/iam" ) @@ -368,6 +369,74 @@ var _ = Describe("AuthConfigMap{}", func() { Expect(cm.Data["mapUsers"]).To(MatchYAML(expectedUsers)) }) }) + Describe("GetIdentities()", func() { + + var ( + client *mockClient + existing *corev1.ConfigMap + acm *AuthConfigMap + addAndSave func(account string) *corev1.ConfigMap + ) + + BeforeEach(func() { + existing = &corev1.ConfigMap{ + ObjectMeta: ObjectMeta(), + Data: map[string]string{}, + } + existing.UID = "123456" + client = &mockClient{} + acm = New(client, existing) + addAndSave = func(account string) *corev1.ConfigMap { + client.reset() + err := acm.AddAccount(account) + Expect(err).NotTo(HaveOccurred()) + + err = acm.Save() + Expect(err).NotTo(HaveOccurred()) + Expect(client.created).To(BeNil()) + Expect(client.updated).NotTo(BeNil()) + + return client.updated + } + }) + + It("should list accounts as identities", func() { + cm := addAndSave(accountA) + Expect(cm.Data["mapAccounts"]).To(MatchYAML(makeExpectedAccounts(accountA))) + identities, err := acm.GetIdentities() + Expect(err).ToNot(HaveOccurred()) + Expect(identities).To(ContainElement(iam.AccountIdentity{KubernetesAccount: accountA})) + }) + When("the list of identities can consist of different identities", func() { + It("handles all of them well", func() { + err := acm.AddAccount(accountA) + Expect(err).NotTo(HaveOccurred()) + err = acm.AddIdentity(mustIdentity(userA, userAUsername, userAGroups)) + Expect(err).NotTo(HaveOccurred()) + err = acm.AddIdentity(mustIdentity(roleA, RoleNodeGroupUsername, RoleNodeGroupGroups)) + Expect(err).NotTo(HaveOccurred()) + identities, err := acm.GetIdentities() + Expect(err).ToNot(HaveOccurred()) + Expect(identities).To(ConsistOf( + iam.AccountIdentity{KubernetesAccount: accountA}, + iam.UserIdentity{ + UserARN: userA, + KubernetesIdentity: iam.KubernetesIdentity{ + KubernetesUsername: userAUsername, + KubernetesGroups: userAGroups, + }, + }, + iam.RoleIdentity{ + RoleARN: roleA, + KubernetesIdentity: iam.KubernetesIdentity{ + KubernetesUsername: RoleNodeGroupUsername, + KubernetesGroups: RoleNodeGroupGroups, + }, + }), + ) + }) + }) + }) Describe("RemoveIdentity()", func() { existing := &corev1.ConfigMap{ ObjectMeta: ObjectMeta(), diff --git a/pkg/ctl/create/iamidentitymapping.go b/pkg/ctl/create/iamidentitymapping.go index d5579f941d..cb598bd71e 100644 --- a/pkg/ctl/create/iamidentitymapping.go +++ b/pkg/ctl/create/iamidentitymapping.go @@ -125,7 +125,7 @@ func doCreateIAMIdentityMapping(cmd *cmdutils.Cmd, options iamIdentityMappingOpt } // Check whether role already exists. - identities, err := acm.Identities() + identities, err := acm.GetIdentities() if err != nil { return err } diff --git a/pkg/ctl/delete/iamidentitymapping.go b/pkg/ctl/delete/iamidentitymapping.go index f97bffa80c..77024e5d60 100644 --- a/pkg/ctl/delete/iamidentitymapping.go +++ b/pkg/ctl/delete/iamidentitymapping.go @@ -1,6 +1,8 @@ package delete import ( + "fmt" + "github.com/kris-nova/logger" "github.com/spf13/cobra" "github.com/spf13/pflag" @@ -15,14 +17,15 @@ func deleteIAMIdentityMappingCmd(cmd *cmdutils.Cmd) { cmd.ClusterConfig = cfg var ( - arn string - all bool + arn string + all bool + account string ) cmd.SetDescription("iamidentitymapping", "Delete a IAM identity mapping", "") cmd.CobraCommand.RunE = func(_ *cobra.Command, args []string) error { - return doDeleteIAMIdentityMapping(cmd, arn, all) + return doDeleteIAMIdentityMapping(cmd, arn, account, all) } cmd.FlagSetGroup.InFlagSet("General", func(fs *pflag.FlagSet) { @@ -32,12 +35,13 @@ func deleteIAMIdentityMappingCmd(cmd *cmdutils.Cmd) { cmdutils.AddRegionFlag(fs, &cmd.ProviderConfig) cmdutils.AddConfigFileFlag(fs, &cmd.ClusterConfigFile) cmdutils.AddTimeoutFlag(fs, &cmd.ProviderConfig.WaitTimeout) + fs.StringVar(&account, "account", "", "Account ID to delete") }) cmdutils.AddCommonFlagsForAWS(cmd.FlagSetGroup, &cmd.ProviderConfig, false) } -func doDeleteIAMIdentityMapping(cmd *cmdutils.Cmd, arn string, all bool) error { +func doDeleteIAMIdentityMapping(cmd *cmdutils.Cmd, arn, account string, all bool) error { if err := cmdutils.NewMetadataLoader(cmd).Load(); err != nil { return err } @@ -50,8 +54,8 @@ func doDeleteIAMIdentityMapping(cmd *cmdutils.Cmd, arn string, all bool) error { } cmdutils.LogRegionAndVersionInfo(cfg.Metadata) - if arn == "" { - return cmdutils.ErrMustBeSet("--arn") + if arn == "" && account == "" || arn != "" && account != "" { + return fmt.Errorf("either --arn or --account must be set") } if cfg.Metadata.Name == "" { return cmdutils.ErrMustBeSet(cmdutils.ClusterNameFlag(cmd)) @@ -69,15 +73,23 @@ func doDeleteIAMIdentityMapping(cmd *cmdutils.Cmd, arn string, all bool) error { return err } - if err := acm.RemoveIdentity(arn, all); err != nil { - return err + switch { + case account != "": + if err := acm.RemoveAccount(account); err != nil { + return err + } + case arn != "": + if err := acm.RemoveIdentity(arn, all); err != nil { + return err + } } + if err := acm.Save(); err != nil { return err } // Check whether we have more roles that match - identities, err := acm.Identities() + identities, err := acm.GetIdentities() if err != nil { return err } diff --git a/pkg/ctl/get/iamidentitymapping.go b/pkg/ctl/get/iamidentitymapping.go index 35a6a214f8..2db7fe7fcb 100644 --- a/pkg/ctl/get/iamidentitymapping.go +++ b/pkg/ctl/get/iamidentitymapping.go @@ -77,7 +77,7 @@ func doGetIAMIdentityMapping(cmd *cmdutils.Cmd, params *getCmdParams, arn string if err != nil { return err } - identities, err := acm.Identities() + identities, err := acm.GetIdentities() if err != nil { return err } @@ -119,4 +119,7 @@ func addIAMIdentityMappingTableColumns(printer *printers.TablePrinter) { printer.AddColumn("GROUPS", func(r iam.Identity) string { return strings.Join(r.Groups(), ",") }) + printer.AddColumn("ACCOUNT", func(r iam.Identity) string { + return r.Account() + }) } diff --git a/pkg/iam/mapping.go b/pkg/iam/mapping.go index 934d912446..0defb12b0c 100644 --- a/pkg/iam/mapping.go +++ b/pkg/iam/mapping.go @@ -5,6 +5,11 @@ import ( "fmt" ) +const ( + // ResourceTypeAccount is the resource type of Accounts + ResourceTypeAccount = "account" +) + var ( // ErrNeitherUserNorRole is the error returned when an identity is missing both UserARN // and RoleARN. @@ -21,6 +26,7 @@ type Identity interface { Type() string Username() string Groups() []string + Account() string } // KubernetesIdentity represents a kubernetes identity to be used in iam mappings @@ -41,6 +47,27 @@ type RoleIdentity struct { KubernetesIdentity } +// AccountIdentity represents a mapping from an IAM role to a kubernetes identity +type AccountIdentity struct { + KubernetesAccount string `json:"account,omitempty"` + KubernetesIdentity +} + +// ARN returns the ARN of the iam mapping +func (a AccountIdentity) ARN() string { + return "" +} + +// Account returns the Account of the iam mapping +func (a AccountIdentity) Account() string { + return a.KubernetesAccount +} + +// Type returns the resource type of the iam mapping +func (a AccountIdentity) Type() string { + return ResourceTypeAccount +} + // Username returns the Kubernetes username func (k KubernetesIdentity) Username() string { return k.KubernetesUsername @@ -61,11 +88,21 @@ func (u UserIdentity) Type() string { return ResourceTypeUser } +// Account returns the Account of the iam mapping +func (u UserIdentity) Account() string { + return "" +} + // ARN returns the ARN of the iam mapping func (r RoleIdentity) ARN() string { return r.RoleARN } +// Account returns the Account of the iam mapping +func (r RoleIdentity) Account() string { + return "" +} + // Type returns the resource type of the iam mapping func (r RoleIdentity) Type() string { return ResourceTypeRole diff --git a/userdocs/src/usage/iam-identity-mappings.md b/userdocs/src/usage/iam-identity-mappings.md index a35a8c1dc9..dc950d74aa 100644 --- a/userdocs/src/usage/iam-identity-mappings.md +++ b/userdocs/src/usage/iam-identity-mappings.md @@ -21,12 +21,24 @@ Create an identity mapping: eksctl create iamidentitymapping --cluster my-cluster-1 --arn arn:aws:iam::123456:role/testing --group system:masters --username admin ``` -Delete a mapping: +Delete an identity mapping: ```bash eksctl delete iamidentitymapping --cluster my-cluster-1 --arn arn:aws:iam::123456:role/testing ``` !!!note - Above command deletes a single mapping FIFO unless `--all` is given in which case it removes all matching. Will warn if - more mappings matching this role are found. +Above command deletes a single mapping FIFO unless `--all` is given in which case it removes all matching. Will warn if +more mappings matching this role are found. + +Create an account mapping: + +```bash + eksctl create iamidentitymapping --cluster my-cluster-1 --account user-account +``` + +Delete an account mapping: + +```bash + eksctl delete iamidentitymapping --cluster my-cluster-1 --account user-account +``` From a95e31ac1f0582e02e808f9fe9a3c66dd7f7155f Mon Sep 17 00:00:00 2001 From: Gergely Brautigam <182850+Skarlso@users.noreply.github.com> Date: Fri, 22 Oct 2021 10:19:55 +0200 Subject: [PATCH 024/124] Fix integration test timeout (#4361) --- integration/tests/params.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/integration/tests/params.go b/integration/tests/params.go index a6c1632506..08d04d1df3 100644 --- a/integration/tests/params.go +++ b/integration/tests/params.go @@ -94,7 +94,7 @@ func (p *Params) GenerateCommands() { p.EksctlGetCmd = p.EksctlCmd. WithArgs("get"). - WithTimeout(1 * time.Minute) + WithTimeout(2 * time.Minute) p.EksctlSetLabelsCmd = p.EksctlCmd. WithArgs("set", "labels"). From 822e5d8b19b8665559df09f2843ff336c98d7442 Mon Sep 17 00:00:00 2001 From: Niki <18622989+nikimanoledaki@users.noreply.github.com> Date: Fri, 22 Oct 2021 15:11:40 +0200 Subject: [PATCH 025/124] Add release notes for 0.71 (#4362) * Adding release notes for 0.71.0 * Update docs/release_notes/0.71.0.md * Add breaking change Co-authored-by: Chetan Patwal --- docs/release_notes/0.71.0.md | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) create mode 100644 docs/release_notes/0.71.0.md diff --git a/docs/release_notes/0.71.0.md b/docs/release_notes/0.71.0.md new file mode 100644 index 0000000000..d5b65cc2ea --- /dev/null +++ b/docs/release_notes/0.71.0.md @@ -0,0 +1,21 @@ +# Release 0.71.0 + +## Breaking Changes +- [Breaking] Remove incomplete support for GPU instance types in Bottlerocket and Windows nodegroups ([#4238](https://github.com/weaveworks/eksctl/issues/4238)) + +## Features + +- Add iamidentitymapping delete and get commands (#4346) + +## Improvements + +- Move from io/ioutil to io and os packages (#4333) + +## Bug Fixes + +- Validate support for GPU instance types (#4243) +- Wait for addons to be healthy only if there are nodegroups when creating a cluster (#4332) + +## Acknowledgments +Weaveworks would like to sincerely thank: + @Juneezee From 3f1b9b6bebbe7cffd83ea52bfd1a8814546e0add Mon Sep 17 00:00:00 2001 From: Weaveworks Bot Date: Mon, 25 Oct 2021 07:35:00 -0400 Subject: [PATCH 026/124] Prepare for next development iteration (#4365) --- pkg/version/release.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkg/version/release.go b/pkg/version/release.go index 1fd11dd635..f6d556e291 100644 --- a/pkg/version/release.go +++ b/pkg/version/release.go @@ -3,7 +3,7 @@ package version // This file was generated by release_generate.go; DO NOT EDIT. // Version is the version number in semver format X.Y.Z -var Version = "0.71.0" +var Version = "0.72.0" // PreReleaseID can be empty for releases, "rc.X" for release candidates and "dev" for snapshots var PreReleaseID = "dev" From 0a855404ee81acfa1e6a49dbefe5e86ee3343144 Mon Sep 17 00:00:00 2001 From: Jake Klein Date: Thu, 28 Oct 2021 15:05:30 +0100 Subject: [PATCH 027/124] Use go:embed instead of go-bindata (#4370) * use go embed in authconfigmap * use go:embed in nodebootstrap * use go:embed in addons * use go:embed for schema * remove bindata from makefile & tools * update build image * fix linter/failing test Co-authored-by: Chetan Patwal --- .github/workflows/ci.yaml | 2 +- .github/workflows/integration-tests.yaml | 2 +- .github/workflows/release-candidate.yaml | 2 +- .github/workflows/release.yaml | 2 +- .github/workflows/tag-release.yaml | 2 +- .github/workflows/update-generated.yaml | 2 +- .requirements | 1 - Dockerfile | 2 +- Makefile | 14 +- build/docker/build_image_manifest | 3 +- build/docker/image_tag | 2 +- go.mod | 1 - go.sum | 2 - pkg/addons/assets.go | 458 ----------------- pkg/addons/default/assets.go | 389 -------------- pkg/addons/default/assets_test.go | 17 +- pkg/addons/default/aws_node.go | 8 +- pkg/addons/default/coredns.go | 14 +- pkg/addons/default/generate.go | 3 - pkg/addons/default/helpers.go | 8 +- pkg/addons/device_plugin.go | 19 +- pkg/addons/generate.go | 3 - pkg/addons/vpc_controller.go | 33 +- pkg/apis/eksctl.io/v1alpha5/generate.go | 10 +- pkg/apis/eksctl.io/v1alpha5/schema.go | 274 ---------- pkg/authconfigmap/assets.go | 274 ---------- pkg/authconfigmap/service_access.go | 8 +- pkg/ctl/utils/schema.go | 7 +- pkg/nodebootstrap/al2.go | 7 +- pkg/nodebootstrap/assets/assets.go | 38 ++ .../scripts}/10-eksctl.al2.conf | 0 .../scripts}/bootstrap.al2.sh | 0 .../scripts}/bootstrap.helper.sh | 0 .../scripts}/bootstrap.ubuntu.sh | 0 .../assets => assets/scripts}/efa.al2.sh | 0 .../scripts}/efa.managed.boothook | 0 .../scripts}/install-ssm.al2.sh | 0 .../assets => assets/scripts}/kubelet.yaml | 0 pkg/nodebootstrap/bindata/assets.go | 485 ------------------ pkg/nodebootstrap/legacy/al2.go | 19 +- .../scripts}/bootstrap.legacy.al2.sh | 0 .../scripts}/bootstrap.legacy.ubuntu.sh | 0 pkg/nodebootstrap/legacy/ubuntu.go | 10 +- pkg/nodebootstrap/legacy/userdata.go | 45 +- pkg/nodebootstrap/managed_al2.go | 7 +- pkg/nodebootstrap/ubuntu.go | 3 +- pkg/nodebootstrap/userdata.go | 36 +- tools.go | 3 +- 48 files changed, 183 insertions(+), 2032 deletions(-) delete mode 100644 pkg/addons/assets.go delete mode 100644 pkg/addons/default/assets.go delete mode 100644 pkg/addons/default/generate.go delete mode 100644 pkg/addons/generate.go delete mode 100644 pkg/apis/eksctl.io/v1alpha5/schema.go delete mode 100644 pkg/authconfigmap/assets.go create mode 100644 pkg/nodebootstrap/assets/assets.go rename pkg/nodebootstrap/{bindata/assets => assets/scripts}/10-eksctl.al2.conf (100%) rename pkg/nodebootstrap/{bindata/assets => assets/scripts}/bootstrap.al2.sh (100%) rename pkg/nodebootstrap/{bindata/assets => assets/scripts}/bootstrap.helper.sh (100%) rename pkg/nodebootstrap/{bindata/assets => assets/scripts}/bootstrap.ubuntu.sh (100%) rename pkg/nodebootstrap/{bindata/assets => assets/scripts}/efa.al2.sh (100%) rename pkg/nodebootstrap/{bindata/assets => assets/scripts}/efa.managed.boothook (100%) rename pkg/nodebootstrap/{bindata/assets => assets/scripts}/install-ssm.al2.sh (100%) rename pkg/nodebootstrap/{bindata/assets => assets/scripts}/kubelet.yaml (100%) delete mode 100644 pkg/nodebootstrap/bindata/assets.go rename pkg/nodebootstrap/{bindata/assets => legacy/scripts}/bootstrap.legacy.al2.sh (100%) rename pkg/nodebootstrap/{bindata/assets => legacy/scripts}/bootstrap.legacy.ubuntu.sh (100%) diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index 70952c0fc0..c47f415353 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -10,7 +10,7 @@ jobs: lint: name: Lint runs-on: ubuntu-latest - container: weaveworks/eksctl-build:ff2eff428ff2b334c713fd07916a10db37f60d29 + container: weaveworks/eksctl-build:83999a3391d78ed18a2e6093328d1122c927956f steps: - name: Checkout uses: actions/checkout@v2 diff --git a/.github/workflows/integration-tests.yaml b/.github/workflows/integration-tests.yaml index a18bd15b1d..07afa27a3d 100644 --- a/.github/workflows/integration-tests.yaml +++ b/.github/workflows/integration-tests.yaml @@ -10,7 +10,7 @@ jobs: name: Run integration tests environment: "Integration tests" runs-on: ubuntu-latest - container: weaveworks/eksctl-build:ff2eff428ff2b334c713fd07916a10db37f60d29 + container: weaveworks/eksctl-build:83999a3391d78ed18a2e6093328d1122c927956f env: SSH: "/root/.ssh" steps: diff --git a/.github/workflows/release-candidate.yaml b/.github/workflows/release-candidate.yaml index fb34633960..060c6c3935 100644 --- a/.github/workflows/release-candidate.yaml +++ b/.github/workflows/release-candidate.yaml @@ -11,7 +11,7 @@ jobs: rc: name: Trigger release candidate build runs-on: ubuntu-latest - container: weaveworks/eksctl-build:ff2eff428ff2b334c713fd07916a10db37f60d29 + container: weaveworks/eksctl-build:83999a3391d78ed18a2e6093328d1122c927956f steps: - uses: actions/github-script@v3 name: Get integration tests status diff --git a/.github/workflows/release.yaml b/.github/workflows/release.yaml index 4abf29e579..b334ecf2eb 100644 --- a/.github/workflows/release.yaml +++ b/.github/workflows/release.yaml @@ -7,7 +7,7 @@ jobs: rc: name: Trigger release build runs-on: ubuntu-latest - container: weaveworks/eksctl-build:ff2eff428ff2b334c713fd07916a10db37f60d29 + container: weaveworks/eksctl-build:83999a3391d78ed18a2e6093328d1122c927956f steps: - name: Checkout uses: actions/checkout@v2 diff --git a/.github/workflows/tag-release.yaml b/.github/workflows/tag-release.yaml index 061e34419c..5f77d3ed0b 100644 --- a/.github/workflows/tag-release.yaml +++ b/.github/workflows/tag-release.yaml @@ -18,7 +18,7 @@ jobs: name: Tag release from version environment: release runs-on: ubuntu-latest - container: weaveworks/eksctl-build:ff2eff428ff2b334c713fd07916a10db37f60d29 + container: weaveworks/eksctl-build:83999a3391d78ed18a2e6093328d1122c927956f steps: - name: Checkout uses: actions/checkout@v2 diff --git a/.github/workflows/update-generated.yaml b/.github/workflows/update-generated.yaml index 95fdcd9deb..fa9bbaaacb 100644 --- a/.github/workflows/update-generated.yaml +++ b/.github/workflows/update-generated.yaml @@ -55,7 +55,7 @@ jobs: update_aws_node: name: Update aws-node and open PR runs-on: ubuntu-latest - container: weaveworks/eksctl-build:ff2eff428ff2b334c713fd07916a10db37f60d29 + container: weaveworks/eksctl-build:83999a3391d78ed18a2e6093328d1122c927956f env: UPDATE_BRANCH: update-aws-node GOPRIVATE: "" diff --git a/.requirements b/.requirements index e02e5f2ad4..5683496f7e 100644 --- a/.requirements +++ b/.requirements @@ -3,7 +3,6 @@ github.com/cloudflare/cfssl/cmd/cfssl@v1.5.0 github.com/cloudflare/cfssl/cmd/cfssljson@v1.5.0 github.com/golangci/golangci-lint/cmd/golangci-lint github.com/goreleaser/goreleaser -github.com/kevinburke/go-bindata/go-bindata github.com/onsi/ginkgo/ginkgo@v1.16.4 github.com/vektra/mockery/cmd/mockery github.com/github-release/github-release diff --git a/Dockerfile b/Dockerfile index 90383b61d1..60427db242 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,4 +1,4 @@ -ARG BUILD_IMAGE=/weaveworks/eksctl-build:ff2eff428ff2b334c713fd07916a10db37f60d29 +ARG BUILD_IMAGE=/weaveworks/eksctl-build:83999a3391d78ed18a2e6093328d1122c927956f FROM $BUILD_IMAGE as build WORKDIR /src diff --git a/Makefile b/Makefile index 2d0379382c..99203c2687 100644 --- a/Makefile +++ b/Makefile @@ -16,16 +16,8 @@ generated_code_deep_copy_helper := pkg/apis/eksctl.io/v1alpha5/zz_generated.deep generated_code_aws_sdk_mocks := $(wildcard pkg/eks/mocks/*API.go) conditionally_generated_files := \ - userdocs/src/usage/schema.json \ $(generated_code_deep_copy_helper) $(generated_code_aws_sdk_mocks) -all_generated_files := \ - pkg/nodebootstrap/bindata/assets.go \ - pkg/addons/default/assets.go \ - pkg/addons/assets.go \ - pkg/apis/eksctl.io/v1alpha5 \ - $(conditionally_generated_files) - .DEFAULT_GOAL := help ##@ Utility @@ -172,10 +164,6 @@ delete-integration-test-dev-cluster: build ## Delete the test cluster for use wh ## not present, the generation of assets will not fail but will not contain it. .PHONY: generate-always generate-always: pkg/addons/default/assets/aws-node.yaml ## Generate code (required for every build) - @# go-bindata targets must run every time, as dependencies are too complex to declare in make: - @# - deleting an asset is breaks the dependencies - @# - different version of go-bindata generate different code - @go-bindata -v go generate ./pkg/apis/eksctl.io/v1alpha5/generate.go go generate ./pkg/nodebootstrap go generate ./pkg/addons/default/generate.go @@ -193,7 +181,7 @@ generate-all: generate-always $(conditionally_generated_files) ## Re-generate al .PHONY: check-all-generated-files-up-to-date check-all-generated-files-up-to-date: generate-all ## Run the generate all command and verify there is no new diff - git diff --quiet -- $(all_generated_files) || (git --no-pager diff $(all_generated_files); echo "HINT: to fix this, run 'git commit $(all_generated_files) --message \"Update generated files\"'"; exit 1) + git diff --quiet -- $(conditionally_generated_files) || (git --no-pager diff $(conditionally_generated_files); echo "HINT: to fix this, run 'git commit $(conditionally_generated_files) --message \"Update generated files\"'"; exit 1) ### Update maxpods.go from AWS .PHONY: update-maxpods diff --git a/build/docker/build_image_manifest b/build/docker/build_image_manifest index ff2eff428f..83999a3391 100644 --- a/build/docker/build_image_manifest +++ b/build/docker/build_image_manifest @@ -3,7 +3,6 @@ "github.com/cloudflare/cfssl v1.6.1" "github.com/golangci/golangci-lint v1.42.0" "github.com/goreleaser/goreleaser v0.182.1" -"github.com/kevinburke/go-bindata v3.22.0+incompatible" "github.com/onsi/ginkgo v1.16.4" "github.com/vektra/mockery v1.1.2" "github.com/github-release/github-release v0.10.0" @@ -15,5 +14,5 @@ "k8s.io/code-generator v0.21.2" "sigs.k8s.io/mdtoc v1.0.1" 100644 blob a73dcb54fd6215c023ffea7f781e313b41841135 build/docker/Dockerfile -100644 blob e02e5f2ad4516bd586dd870006e14a8a5a168093 .requirements +100644 blob 5683496f7ee0443658a663785d87e404096459d6 .requirements 100755 blob c1129ff1ff85ac2c53f908a577675ea59a9325a7 build/scripts/install-build-deps.sh diff --git a/build/docker/image_tag b/build/docker/image_tag index d6c0fab08b..387232386a 100644 --- a/build/docker/image_tag +++ b/build/docker/image_tag @@ -1 +1 @@ -ff2eff428ff2b334c713fd07916a10db37f60d29 +83999a3391d78ed18a2e6093328d1122c927956f diff --git a/go.mod b/go.mod index c6e835409d..66e8f8b882 100644 --- a/go.mod +++ b/go.mod @@ -185,7 +185,6 @@ require ( github.com/julz/importas v0.0.0-20210419104244-841f0c0fe66d // indirect github.com/justinbarrick/go-k8s-portforward v1.0.4-0.20200904152830-b575325c1855 github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51 - github.com/kevinburke/go-bindata v3.22.0+incompatible github.com/kevinburke/rest v0.0.0-20210106114233-22cd0577e450 // indirect github.com/kevinburke/ssh_config v1.1.0 // indirect github.com/kisielk/errcheck v1.6.0 // indirect diff --git a/go.sum b/go.sum index e7fa3c3df2..2bccb422f5 100644 --- a/go.sum +++ b/go.sum @@ -1132,8 +1132,6 @@ github.com/k0kubun/pp v2.3.0+incompatible/go.mod h1:GWse8YhT0p8pT4ir3ZgBbfZild3t github.com/karrick/godirwalk v1.7.5/go.mod h1:2c9FRhkDxdIbgkOnCEvnSWs71Bhugbl46shStcFDJ34= github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51 h1:Z9n2FFNUXsshfwJMBgNA0RU6/i7WVaAegv3PtuIHPMs= github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51/go.mod h1:CzGEWj7cYgsdH8dAjBGEr58BoE7ScuLd+fwFZ44+/x8= -github.com/kevinburke/go-bindata v3.22.0+incompatible h1:/JmqEhIWQ7GRScV0WjX/0tqBrC5D21ALg0H0U/KZ/ts= -github.com/kevinburke/go-bindata v3.22.0+incompatible/go.mod h1:/pEEZ72flUW2p0yi30bslSp9YqD9pysLxunQDdb2CPM= github.com/kevinburke/rest v0.0.0-20210106114233-22cd0577e450 h1:Lr2sEj5wWzk82b/L8LsLzsCxywQaOpcr0ti/qcfzCOk= github.com/kevinburke/rest v0.0.0-20210106114233-22cd0577e450/go.mod h1:pD+iEcdAGVXld5foVN4e24zb/6fnb60tgZPZ3P/3T/I= github.com/kevinburke/ssh_config v0.0.0-20190725054713-01f96b0aa0cd/go.mod h1:CT57kijsi8u/K/BOFA39wgDQJ9CxiF4nAY/ojJ6r6mM= diff --git a/pkg/addons/assets.go b/pkg/addons/assets.go deleted file mode 100644 index 5baaf0a456..0000000000 --- a/pkg/addons/assets.go +++ /dev/null @@ -1,458 +0,0 @@ -// Code generated by go-bindata. DO NOT EDIT. -// sources: -// assets/efa-device-plugin.yaml (3.084kB) -// assets/neuron-device-plugin.yaml (3.623kB) -// assets/nvidia-device-plugin.yaml (2.369kB) -// assets/vpc-admission-webhook-config.yaml (524B) -// assets/vpc-admission-webhook-csr.yaml (234B) -// assets/vpc-admission-webhook-dep.yaml (1.675kB) -// assets/vpc-admission-webhook.yaml (231B) -// assets/vpc-resource-controller-dep.yaml (1.679kB) -// assets/vpc-resource-controller.yaml (565B) - -package addons - -import ( - "bytes" - "compress/gzip" - "crypto/sha256" - "fmt" - "io" - "io/ioutil" - "os" - "path/filepath" - "strings" - "time" -) - -func bindataRead(data []byte, name string) ([]byte, error) { - gz, err := gzip.NewReader(bytes.NewBuffer(data)) - if err != nil { - return nil, fmt.Errorf("read %q: %w", name, err) - } - - var buf bytes.Buffer - _, err = io.Copy(&buf, gz) - clErr := gz.Close() - - if err != nil { - return nil, fmt.Errorf("read %q: %w", name, err) - } - if clErr != nil { - return nil, err - } - - return buf.Bytes(), nil -} - -type asset struct { - bytes []byte - info os.FileInfo - digest [sha256.Size]byte -} - -type bindataFileInfo struct { - name string - size int64 - mode os.FileMode - modTime time.Time -} - -func (fi bindataFileInfo) Name() string { - return fi.name -} -func (fi bindataFileInfo) Size() int64 { - return fi.size -} -func (fi bindataFileInfo) Mode() os.FileMode { - return fi.mode -} -func (fi bindataFileInfo) ModTime() time.Time { - return fi.modTime -} -func (fi bindataFileInfo) IsDir() bool { - return false -} -func (fi bindataFileInfo) Sys() interface{} { - return nil -} - -var _efaDevicePluginYaml = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\xec\x56\x4d\x8f\xdb\x36\x10\xbd\xfb\x57\x0c\x1c\xec\xad\x92\xba\xd9\x5d\x20\x50\x4f\xc6\xc6\x2d\x82\x6e\xb6\x41\x9d\xb4\x87\xa2\x87\x31\x39\xb2\x08\x53\x24\xcb\x19\xd9\xeb\xfe\xfa\x82\xb2\xac\x58\xce\x3a\xeb\x5e\x72\x8a\x2f\x16\xc8\xf7\xe6\xcd\x0c\x1f\x3f\xb2\x2c\x9b\x60\x30\x7f\x50\x64\xe3\x5d\x09\x18\x02\x17\x9b\xeb\xc9\xda\x38\x5d\xc2\x5b\xa4\xc6\xbb\x05\xc9\xa4\x21\x41\x8d\x82\xe5\x04\xc0\x61\x43\x25\xe0\x96\x33\xaa\x30\x5b\xbf\xe1\x4c\xd3\xc6\x28\xca\x82\x6d\x57\xc6\x65\xba\x63\x31\x49\x8f\xe5\x80\x8a\x4a\x58\xb7\x4b\xca\x78\xc7\x42\xcd\x84\x03\xa9\x14\x8a\xc9\x92\x12\x1f\xd3\x37\x40\x83\xa2\xea\x07\x5c\x92\xe5\xfd\xc0\x41\xeb\xbc\xd8\x04\xa0\x0d\x1a\x85\x16\x12\x51\x68\xb5\xdb\x13\x65\x17\xa8\x84\xdf\xbd\xb5\xc6\xad\x3e\x75\x80\x09\x80\x50\x13\x2c\x0a\xf5\x6a\x47\x25\xa5\xdf\x2b\xf8\x58\x1b\x06\x74\xce\x0b\x8a\xf1\x0e\x0c\x83\xa6\x10\x49\xa1\x90\xce\xe1\x57\x0a\x02\x35\x45\x82\xca\x47\x58\xa2\x5a\x6f\x31\x6a\x50\xbe\x09\x28\x66\x69\xac\x91\xdd\x10\x6b\x41\x04\xb5\x48\xe0\xb2\x28\x52\xe5\xd1\x91\x10\xe7\xc6\x17\xda\x2b\x2e\x04\x79\xcd\x05\xea\xc6\x38\xc3\x42\x31\x53\xb6\x4d\xff\xc5\xaa\xc5\x88\x4e\x88\x74\xc6\xaa\x26\xdd\xa6\x0a\x32\x15\x8d\x18\x85\x36\x43\xad\xbd\xcb\x82\xd7\x5c\xf4\x52\x9f\xf3\x1d\x9a\x06\xd0\x53\x29\xe6\x68\x43\x8d\xf9\x38\x83\x21\x5a\xf0\xba\x84\xe9\xb4\xa7\xd9\x51\xe7\x5f\x5c\xe7\x0e\x77\x58\xc8\xee\x9b\x62\x9a\x9e\x29\xe5\x5b\x27\x25\x68\xaa\xb0\xb5\xd2\xcf\x8a\xb7\x14\x4f\xf3\xcc\x60\x4d\xbb\x12\xee\xfb\x84\x66\xa9\x3a\xfe\xcd\xd9\xdd\x80\x00\xf0\x21\xf1\x7c\x2c\x61\xfe\x64\x58\xf8\x94\x8c\x5b\xce\xb1\xc1\x7f\xbd\xcb\x95\x6f\x0a\xaa\xf0\x12\x32\x00\x55\x15\x29\x29\xe1\xd1\x2f\xfa\x6e\x0d\x8b\xf7\x1e\xe3\x1a\x24\xb9\x21\x78\x0d\xc8\x80\x70\xe8\x19\xa0\xd6\x99\x77\x3f\xc1\xb6\x26\x07\xe4\x70\x69\x49\xff\x00\x52\xd3\x29\x64\x88\x36\x2c\x06\x44\x4a\x3d\x22\x4e\x1f\xbe\x8d\x8a\xb8\xb3\xd2\x09\x31\x89\x32\xb0\x07\xa9\x51\x52\xe4\x1d\x28\xfc\x1c\x6e\x49\x89\xde\xc7\xd4\x80\x95\x50\x04\x84\x0a\x8d\x6d\x23\xe5\xdf\xde\x81\x21\x1a\x1f\x8d\xec\xee\x2d\x32\x3f\x76\xa6\x99\xee\xf7\x79\xe6\xbc\xa6\x81\x7a\xf0\x19\x56\x95\x71\x46\x76\x47\x4e\xf3\x9a\x66\x5f\x8c\xa6\x22\xe6\x3f\xcf\x80\xdb\x10\x7c\x14\xd2\x60\x1c\x0b\x3a\x45\x5c\x0e\x95\xa5\x5a\xf2\x13\x0b\xcc\xfe\x5c\xcc\xef\x5f\x17\x69\xab\xb3\x14\x9f\x98\xe2\x2f\xad\xd1\x94\xac\x91\xd7\xd2\xd8\x57\xc9\xcf\x87\x58\x59\x3a\x2b\x8e\x7d\x11\xe9\x9f\xd6\x44\xd2\x6f\xdb\x68\xdc\x6a\x31\xb4\xe0\xdd\xca\xf9\x61\x78\xfe\x44\xaa\x4d\x66\x3e\x4e\x77\x5f\xc8\xa2\x3f\xd3\x3e\x52\x6c\x78\x3c\x9d\x3c\xdb\x1d\x72\xf3\xa7\x10\x89\x79\xbc\x19\x8e\x51\x9d\xb3\xa7\x4b\x92\xd3\xbd\x3b\x4a\x7b\xfa\x0c\xf7\xd8\xf3\xef\xdc\xb3\x80\x0d\xda\x96\x9e\x15\xde\x8b\xab\x3b\x97\x5f\xbf\x79\xb2\x18\x57\xf4\x55\x50\x3a\x42\xed\x59\xc4\xea\x56\xbf\x04\x31\x37\xe4\xf2\xd7\xb7\x2f\x48\x75\xa8\x17\x02\xb9\xea\xfa\xe5\x40\xcd\x9d\xbe\x40\xae\xb9\xbb\x00\x14\x6e\x2e\x09\x15\x2f\x12\x8c\x17\x09\xde\xea\x73\xa0\xff\x67\xaa\xe4\xd1\xef\xa6\xfa\x6e\xaa\x33\xa6\xaa\x3d\xcb\x23\xc9\xd6\xc7\x75\x09\x12\xdb\xc3\xb8\xf2\x4e\xd0\x38\x8a\xa3\xeb\xdb\x34\xb8\x4a\xe7\xfd\x15\xe7\x7a\x1d\x73\x52\x31\xbf\xe2\xfc\x8a\x0b\x4a\x97\xcb\xb9\xa7\x43\xb9\xf9\x31\xbf\xc9\x6f\x8e\x9d\x76\xc9\x63\x63\xff\x63\x52\x6d\x77\xdd\x78\x27\xf4\x24\x63\xc7\xa1\xb5\x7e\xfb\x21\x9a\x8d\xb1\xb4\xa2\x39\x2b\xb4\xdd\x9b\xa3\x84\x0a\x2d\x8f\x1b\xa1\x30\x60\xf7\x6a\x33\x5f\xfa\x56\x47\x1f\x4a\xf8\x6b\x3a\x7b\x78\x98\xfe\x7d\x34\xb7\xf1\xb6\x6d\xe8\x7d\x7a\xe0\x9c\x70\xb2\xbe\x84\x73\x69\xa7\x5f\x93\x78\x1f\x50\xea\x12\x8a\x0d\xc6\xc2\x9a\x65\x77\x35\x5b\x92\x62\xc4\x3b\xdc\x47\x7b\xb9\x51\xc7\xbf\xae\x92\x56\xaf\x13\x18\x29\x87\x8b\x24\xff\x0b\x00\x00\xff\xff\xf5\xa9\x92\x60\x0c\x0c\x00\x00") - -func efaDevicePluginYamlBytes() ([]byte, error) { - return bindataRead( - _efaDevicePluginYaml, - "efa-device-plugin.yaml", - ) -} - -func efaDevicePluginYaml() (*asset, error) { - bytes, err := efaDevicePluginYamlBytes() - if err != nil { - return nil, err - } - - info := bindataFileInfo{name: "efa-device-plugin.yaml", size: 0, mode: os.FileMode(0), modTime: time.Unix(0, 0)} - a := &asset{bytes: bytes, info: info, digest: [32]uint8{0xf, 0x88, 0xf3, 0x33, 0x57, 0xdb, 0x84, 0xb8, 0x9e, 0x87, 0x8d, 0x16, 0xec, 0x91, 0x23, 0x4, 0xcc, 0x1d, 0x9f, 0x58, 0x2a, 0xa8, 0xee, 0x6b, 0xa7, 0xe9, 0xd6, 0x14, 0xbf, 0x16, 0x57, 0xeb}} - return a, nil -} - -var _neuronDevicePluginYaml = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\xe4\x56\x4d\x73\xdb\x36\x10\xbd\xeb\x57\xec\x28\xd7\x92\xac\xfb\x35\x19\xf6\xe4\x38\x4a\x26\xd3\xc4\xf1\x44\x4d\x2f\x9d\x4e\x67\x05\x2c\x29\x54\x20\x80\x02\x0b\xd9\xca\xaf\xef\x80\xa4\x68\xd2\x66\x58\xa7\xd3\x9e\xca\x13\x29\xec\xbe\x5d\x3c\xbc\x7d\x50\x96\x65\xab\x83\x32\xb2\x84\x2b\x1d\x03\x93\xff\x60\x35\xad\xd0\xa9\x5f\xc8\x07\x65\x4d\x09\x7e\x87\x22\xc7\xc8\x7b\xeb\xd5\x27\x64\x65\x4d\x7e\x78\x1e\x72\x65\x8b\xe3\xc5\xaa\x21\x46\x89\x8c\xe5\x0a\xc0\x60\x43\x25\x18\x8a\xde\x9a\x4c\xd2\x51\x09\xca\x9c\x8e\xb5\x32\x2b\x1f\x35\x85\x14\x93\x01\x3a\xf5\xda\xdb\xe8\xda\xcf\xf4\x64\xb0\x5e\xb7\xaf\x9e\x82\x8d\x5e\xd0\x68\xc5\x58\x49\xa1\xfd\x3a\x92\xdf\x8d\x16\x6a\xe2\xe1\x5d\xab\x70\xff\x71\x8b\x2c\xf6\x5f\x5e\x88\x8e\x64\x78\xb6\x92\xf0\x84\x4c\xc3\xa7\xfb\x67\xf8\xce\xca\x59\xf4\xe8\xe4\x1c\xfa\x7f\xb3\xc9\x96\xcd\x22\x30\x72\x9c\x6d\x66\x5a\xbd\x6f\x2d\x09\x64\x2c\x87\xe3\x45\xaf\x97\x2d\xf9\x74\xc4\x97\x42\xd8\x68\xf8\xa9\x4a\xe8\x16\x83\x43\x41\x25\x1c\xe2\x8e\xb2\x70\x0a\x4c\xcd\x6a\x56\x88\x2f\x94\x91\xca\xd4\xff\xba\x1e\x3f\xdb\x85\xb7\x9a\x3e\x50\x95\xd2\xcf\xd4\x2e\x54\x5c\x01\x3c\x9e\x9d\xc5\xc2\x21\xee\xfe\x20\xc1\xfd\x2c\xcc\x12\x99\xd8\x5f\x6c\x7d\x91\xc2\x67\xb0\x67\x76\xa1\x2c\x8a\xb4\xe2\x0d\x31\xb5\xdc\x48\x2b\x42\x21\xac\x11\xe4\x38\x14\x74\xc7\x64\x64\x76\x1f\x52\x08\xdb\xb8\xc8\x94\x05\xb6\x1e\x6b\xca\x0c\x71\x31\x29\x1c\x8a\xc9\x29\xa0\x73\xa1\x18\xb4\xf0\x12\xa9\xb1\x66\x4b\x4f\x95\x41\x26\xdb\x84\xd0\x0a\xfc\x33\xbb\x09\x8e\x44\x42\x09\xa4\x49\xb0\xf5\x9d\x4e\x9b\xa4\xd1\xb7\xb8\x23\x3d\x08\x77\xa9\x4c\xd2\x79\x27\xe4\x2d\x7b\x64\xaa\x4f\x5d\x16\x9f\x1c\x95\xf0\xc1\x6a\xad\x4c\xfd\xf1\x3c\x84\x4c\x8d\xd3\xc8\xd4\x97\x1a\x6d\x25\x3d\x68\x8c\xe5\xf6\xf8\x87\xd2\x00\x41\xec\x49\x46\x4d\x3e\x47\xed\xf6\x98\x4f\x59\x17\x5e\xb1\x12\xa8\x33\x67\x65\x79\x9e\x4c\x00\x3d\xe9\xff\xef\x77\x00\x70\x26\xa3\x7d\x9f\xe8\x65\x41\x26\x00\x6c\x35\xf9\x87\x2d\x67\x70\xa0\x53\x09\x57\x7d\x6f\x97\x52\x5a\x13\xde\x1b\x7d\x1a\x22\x00\xac\x4b\x79\xd6\x97\xb0\xb9\x53\xa1\x77\xc6\x51\x32\xde\x86\x1c\x1b\xfc\x64\x4d\x2e\x6c\x53\x74\x2d\x3c\x25\x1f\x80\xaa\x8a\x04\x97\x70\x6d\xb7\x3d\x77\xfd\xe2\x33\x78\x87\xfe\x00\xbc\x57\x21\xf9\x25\x60\x00\x84\x33\x83\x80\x52\x66\xd6\xfc\x08\xb7\x7b\x32\x40\x06\x77\x9a\xe4\x57\xc0\x7b\x7a\x18\x32\xa0\x0d\x47\x93\xbc\x90\xfc\x91\xc2\xbd\x29\x42\x65\xfd\xc3\xc4\xd6\xa4\x21\x58\xe0\x3d\x72\x42\x3e\x81\xc0\x7b\xb8\x1d\xa5\xf4\x1e\x53\x02\x56\x4c\x1e\x10\x2a\x54\x3a\x7a\xca\x87\xb8\x2d\xd1\xd2\x0c\x32\x86\x43\x28\x50\x36\xca\xa8\xe4\x19\x99\xe8\xbc\xa3\xa8\x23\x7a\x34\x4c\x24\xb3\xbe\x8a\x32\x75\x36\x28\x08\xd3\x31\x25\x1d\x85\xa2\x2f\xe5\xbc\xb2\x5e\xf1\xe9\x4a\x63\x08\xd7\xad\x84\xd6\xdd\xec\x64\xc9\xe9\x87\xd4\xb3\xea\xb0\xaa\x94\x51\x7c\x1a\xe9\xce\x4a\xba\x7c\xf4\x6b\xba\x3b\xfe\x8c\xca\x93\x7c\x19\xbd\x32\xf5\x76\xe8\xe6\x4d\x6d\xec\xf0\xf3\xe6\x8e\x44\x4c\xd2\x1a\x67\x76\x98\xdb\x7e\x64\x7f\x26\xdf\x84\xe9\x72\x52\x50\x3b\xc3\x9b\x3b\xe7\x29\x84\xa9\x34\xc7\x51\xad\xce\xd6\x3b\xe2\x87\x43\xa5\x4c\x60\x34\x82\xb2\x34\xc4\xeb\x99\xdc\xb1\xfc\xde\x98\xd9\x80\x23\xea\x48\xb3\x85\xbb\xe2\xca\x54\x17\xf9\x9d\x46\x5f\xd3\x72\xcc\x37\x4f\x09\xfa\xe1\x49\x48\xdf\xcd\x46\x7d\x19\x5d\x89\xfd\xff\x25\x5d\xc2\x1a\x46\x65\xc8\x4f\x8c\x4e\x35\x58\xa7\xb1\x70\x71\xa7\x95\xc8\x49\xf8\x1c\x6f\x43\x6f\x57\xc5\x9c\x71\x96\x17\xf9\xf7\xf9\xb7\xf9\xd7\x63\xa2\x5a\x94\x9b\xa8\xf5\x8d\xd5\x4a\x9c\x4a\xb8\xd4\xb7\x78\x1a\x7b\x5a\x67\xe0\x87\xe7\x21\x9b\x35\x71\xc1\x7e\x6c\x80\xe6\x38\x65\x32\xeb\xf3\x7f\xfa\xf8\x62\x73\xf5\xfe\xfa\xd5\x9b\xd7\xab\x19\xfa\x4b\x28\x88\xc5\xc8\x52\xda\x57\x4d\x9c\x0b\x6b\xaa\x59\xc0\xeb\xf7\x2f\x37\xbf\x5f\x5f\xbe\xdb\xcc\xe1\xbd\xf2\xb6\x79\x7c\xa2\x95\x22\x2d\xfb\x7f\x40\xb3\x6b\x37\xc8\xfb\xb2\xbd\x8f\xf2\x24\xb6\xe4\x3b\xa3\xd0\x40\x22\xb6\x9e\x64\x0d\xd3\x1d\x4f\x51\x50\x6b\x7b\x7b\xe3\xd5\x51\x69\xaa\x69\x13\x04\xea\xf6\x6e\x2a\xa1\x42\x1d\xa6\xe7\x2d\xd0\xe1\x4e\x69\xc5\xea\xb1\xee\xa4\xb7\xae\x84\x5f\xd7\x97\x6f\xdf\xae\x7f\x1b\xad\x1d\xad\x8e\x0d\xbd\x4b\xb7\x62\x98\x67\x78\xee\x8e\x3c\x3f\x4d\xca\xeb\x76\x57\x1c\xd1\x17\x5a\xed\xce\x0c\x3f\xf8\x27\x34\x0b\xad\x4c\x85\x59\x83\x6e\x01\xd5\xc7\x73\xcd\xae\xd3\x89\x54\x97\x1b\xdc\xdb\xd0\xa1\x4c\xe0\xdd\x17\x75\xbb\xd0\xe9\x22\x7c\x6a\xfb\xaf\x00\x00\x00\xff\xff\xb8\x35\xe9\xa2\x27\x0e\x00\x00") - -func neuronDevicePluginYamlBytes() ([]byte, error) { - return bindataRead( - _neuronDevicePluginYaml, - "neuron-device-plugin.yaml", - ) -} - -func neuronDevicePluginYaml() (*asset, error) { - bytes, err := neuronDevicePluginYamlBytes() - if err != nil { - return nil, err - } - - info := bindataFileInfo{name: "neuron-device-plugin.yaml", size: 0, mode: os.FileMode(0), modTime: time.Unix(0, 0)} - a := &asset{bytes: bytes, info: info, digest: [32]uint8{0xfd, 0x74, 0x40, 0xab, 0xb9, 0x89, 0x7d, 0xb8, 0x93, 0xb5, 0xea, 0x8f, 0x3d, 0x97, 0x97, 0xa2, 0x7c, 0xd4, 0xde, 0xb3, 0x44, 0xa0, 0xd3, 0xf9, 0xa4, 0xde, 0x3b, 0x6, 0xdc, 0xc6, 0x8d, 0x8c}} - return a, nil -} - -var _nvidiaDevicePluginYaml = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\xd4\x55\x41\x8f\xdb\x36\x13\xbd\xeb\x57\x3c\xd8\x97\x04\x58\x49\x9b\x9c\xbe\x28\xf8\x0e\xee\xee\x16\x35\xb2\xb1\x83\xf5\x26\x41\x50\xf4\x30\x26\xc7\x12\x61\x8a\x64\x49\xca\x5e\xfd\xfb\x82\xb2\xd6\x6b\xa5\x40\x93\x53\x81\xea\x62\x43\x7a\x33\xf3\xe6\xbd\x19\x72\x8e\x1b\xeb\x7a\xaf\xea\x26\xe2\x95\x78\x8d\xb7\xd7\x6f\xde\x5d\x61\xf5\x65\x79\xbb\x5c\xe0\x66\xfd\xf0\x69\xfd\xb0\x78\x5c\xae\x57\x05\xb0\xd0\x1a\x03\x30\xc0\x73\x60\x7f\x60\x59\x64\xf3\x6c\x8e\x7b\x25\xd8\x04\x96\xe8\x8c\x64\x8f\xd8\x30\x16\x8e\x44\xc3\xcf\x5f\xae\xf0\x85\x7d\x50\xd6\xe0\x6d\x71\x8d\x57\x09\x30\x1b\x3f\xcd\x5e\xbf\xcf\xe6\xe8\x6d\x87\x96\x7a\x18\x1b\xd1\x05\x46\x6c\x54\xc0\x4e\x69\x06\x3f\x09\x76\x11\xca\x40\xd8\xd6\x69\x45\x46\x30\x8e\x2a\x36\x43\x99\x31\x49\x91\xcd\xf1\x6d\x4c\x61\xb7\x91\x94\x01\x41\x58\xd7\xc3\xee\x2e\x71\xa0\x38\x10\x4e\x4f\x13\xa3\xab\xca\xf2\x78\x3c\x16\x34\x90\x2d\xac\xaf\x4b\x7d\x02\x86\xf2\x7e\x79\x73\xb7\xda\xdc\xe5\x6f\x8b\xeb\x21\xe4\xb3\xd1\x1c\x52\xe3\x7f\x76\xca\xb3\xc4\xb6\x07\x39\xa7\x95\xa0\xad\x66\x68\x3a\xc2\x7a\x50\xed\x99\x25\xa2\x4d\x7c\x8f\x5e\x45\x65\xea\x2b\x04\xbb\x8b\x47\xf2\x9c\xcd\x21\x55\x88\x5e\x6d\xbb\x38\x11\xeb\x99\x9d\x0a\x13\x80\x35\x20\x83\xd9\x62\x83\xe5\x66\x86\x5f\x16\x9b\xe5\xe6\x2a\x9b\xe3\xeb\xf2\xf1\xb7\xf5\xe7\x47\x7c\x5d\x3c\x3c\x2c\x56\x8f\xcb\xbb\x0d\xd6\x0f\xb8\x59\xaf\x6e\x97\xc9\xa8\x0d\xd6\xbf\x62\xb1\xfa\x86\x0f\xcb\xd5\xed\x15\x58\xc5\x86\x3d\xf8\xc9\xf9\xc4\xdf\x7a\xa8\x24\xe3\x60\x1d\x36\xcc\x13\x02\x3b\x7b\x22\x14\x1c\x0b\xb5\x53\x02\x9a\x4c\xdd\x51\xcd\xa8\xed\x81\xbd\x51\xa6\x86\x63\xdf\xaa\x90\xcc\x0c\x20\x23\xb3\x39\xb4\x6a\x55\xa4\x38\xbc\xf9\x5b\x53\x45\x96\x91\x53\xa3\xfd\x55\xd2\x2c\x94\x87\x37\xd9\x5e\x19\x59\xe1\x96\xb8\xb5\x66\xc3\x31\x6b\x39\x92\xa4\x48\x55\x06\x18\x6a\xb9\x82\x39\x28\xa9\x28\x97\x7c\x50\x82\x73\xa7\xbb\x5a\x99\x5c\x0e\x01\x81\xe3\x08\x0b\x8e\x04\x57\xd8\x77\x5b\xce\x43\x1f\x22\xb7\x59\xe2\x9e\xb2\x04\xd6\x2c\xa2\xf5\xe9\x3f\xd0\x52\x14\xcd\x3d\x6d\x59\x87\xd3\x8b\x7f\x2e\x13\x32\xa0\x73\x92\x22\x6f\xa2\xa7\xc8\x75\x7f\x8a\x8a\xbd\xe3\x0a\x0f\x56\x6b\x65\xea\xcf\x03\x20\x03\x22\xb7\x4e\x53\xe4\xb1\xd4\x45\x2b\xe9\x99\xe3\x31\x4d\x33\x19\x63\x4f\x2a\x0d\x3e\xb3\xf3\x2c\x28\xb2\x2c\xf0\x21\x0d\x78\xc3\xfe\xa4\xff\x96\xc4\xfe\x48\x5e\x0e\xf3\x4e\x51\x6d\x95\x56\xb1\x3f\xe7\x4a\x96\xa5\xd1\x0d\x55\x59\xa6\xb6\xbd\xe1\xc8\xa1\x50\xb6\x94\x56\x84\x32\x52\xd8\x87\x92\x64\xab\x8c\x0a\x91\x7d\x2e\x74\x97\x7e\xcb\xba\x23\x4f\x26\x32\xcb\x3c\x88\x86\x65\x97\x3a\xc8\x45\x9a\x51\x41\x3a\x27\x29\xad\xc9\x9d\x95\xa1\x1c\x4b\xbd\xf0\x3d\x2b\x06\x8c\xa1\xec\x0b\xd2\xae\xa1\x62\xca\xe0\x9c\xcd\x59\x59\x61\x36\x1b\xc3\xf4\x44\xf6\x1f\x0b\x0f\x3c\x7b\x38\x48\x6e\x35\xfb\x29\x8f\x51\xd1\x97\x2f\xff\x0d\x45\x73\xec\xb9\xaf\x70\x33\x22\x16\x09\x10\xd6\x46\xf7\x67\x65\xac\x4b\x0d\x59\x5f\xe1\xee\x49\x85\x18\xa6\x81\x27\xc5\x0a\x61\xdb\xb2\x76\xdd\x8f\x82\x00\xde\xed\x58\xc4\x0a\x2b\xbb\x19\x6d\x3b\xf7\xfc\x91\xfc\xfe\x74\xc8\x3a\x2b\x41\x21\x1d\x97\x23\x2d\x90\x94\xb9\x35\xef\x71\x6c\xd8\x80\x4d\x3a\xdf\xe4\xd5\xb0\xd2\xdf\x41\xce\xd9\xce\x53\xf1\x7c\x2f\x0c\x17\x84\xed\xbc\xe0\x30\x38\xf0\x5d\x60\x2a\x1a\x10\x2c\x62\x43\x31\x65\xee\x21\xe8\x25\xdd\x96\x53\xf8\x98\x53\x82\x76\x91\x3d\x08\x3b\x52\xba\xf3\x5c\xfc\xfb\xc6\x39\xaf\xac\x57\xb1\xbf\xd1\x14\xc2\x6a\x98\xde\xd9\xe9\xb4\xc9\x8d\x95\x7c\x0e\x7d\x1e\x78\x61\x4d\xba\x83\xd8\x9f\x27\x36\x87\x6a\xa9\x1e\xa6\x5e\xf8\xc4\xf0\xe4\x65\xb9\xff\x5f\x98\x6e\x40\x75\xb8\x2e\xde\x15\xd7\x3f\xb3\x2b\x22\xfa\x33\x8c\x7c\x1d\x2a\xfc\x3e\xcb\xf3\xa4\x52\x6e\x4d\xae\x8c\x8a\x39\x7b\x6f\xfd\xff\x77\xa4\x03\xcf\xfe\x78\x59\x62\x16\xdd\xd0\x8e\x35\x91\x9f\xe2\xcb\x62\x02\xa4\xb5\x3d\x7e\xf2\xea\xa0\x34\xd7\x7c\x17\x04\xe9\x61\xc1\x2a\x0c\x49\x2e\x90\x82\x1c\x0d\x8b\xa4\x38\x5c\x66\x00\xa4\xb7\x2e\x71\x59\xdc\xdf\x5f\x14\x3d\x58\xdd\xb5\xfc\xd1\x76\x26\x4e\xf0\xf9\xd8\xe2\xa4\xb7\x49\xbe\x36\xc5\x7c\xa2\xd8\x54\x28\x0f\xe4\x4b\xad\xb6\x83\xdd\x9a\x63\x39\x89\x7a\x9e\xfc\x53\xa9\x8b\x2a\x3f\xaa\xd1\xd8\x70\x2a\x30\xa9\xeb\x7e\xaa\x64\xf6\x57\x00\x00\x00\xff\xff\xaf\x6c\xf5\xd9\x41\x09\x00\x00") - -func nvidiaDevicePluginYamlBytes() ([]byte, error) { - return bindataRead( - _nvidiaDevicePluginYaml, - "nvidia-device-plugin.yaml", - ) -} - -func nvidiaDevicePluginYaml() (*asset, error) { - bytes, err := nvidiaDevicePluginYamlBytes() - if err != nil { - return nil, err - } - - info := bindataFileInfo{name: "nvidia-device-plugin.yaml", size: 0, mode: os.FileMode(0), modTime: time.Unix(0, 0)} - a := &asset{bytes: bytes, info: info, digest: [32]uint8{0x49, 0x34, 0xa1, 0xba, 0x6, 0x98, 0xf5, 0x96, 0x4d, 0x79, 0xa1, 0x9a, 0x47, 0x9, 0x3e, 0x2d, 0x8e, 0x64, 0x45, 0xf5, 0x9d, 0xcf, 0x3f, 0xf6, 0x8d, 0x97, 0x94, 0xa3, 0x59, 0xec, 0x4a, 0x29}} - return a, nil -} - -var _vpcAdmissionWebhookConfigYaml = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\x7c\x91\x4f\x6b\xf3\x30\x0c\xc6\xef\xf9\x14\x22\xf7\xa4\xf4\xf6\xe2\xdb\x4b\x29\x63\x87\xc1\x18\x63\x3b\x8c\x1d\x14\x47\x4d\x45\x62\xcb\x58\x76\x4a\xf7\xe9\x47\xfe\xb4\xac\xb0\xd5\x17\xdb\x7a\xa4\xdf\x63\xc9\x18\xf8\x8d\xa2\xb2\x78\x03\xd8\x3a\xd6\xe9\x18\xa9\x63\x4d\x11\x13\x8b\xaf\xfb\x7f\x5a\xb3\x6c\xc6\x6d\x43\x09\xb7\x45\xcf\xbe\x35\xf0\x94\x13\x26\xf6\xdd\x3b\x35\x47\x91\x7e\x27\xfe\xc0\x5d\x5e\x2a\x0a\x47\x09\x5b\x4c\x68\x0a\x00\x8f\x8e\x0c\x8c\xc1\x56\x57\x7a\x75\x5a\x8a\x2a\x7b\xe8\xd6\x0c\x0d\x68\xc9\x40\x9f\x1b\xaa\xf4\xac\x89\x5c\x01\x30\x60\x43\x83\x4e\x10\x00\x0c\xe1\x0f\x4a\xb1\xee\x73\x62\x75\xcf\xaf\x46\x87\x5f\xe2\xf1\xa4\xb5\x15\x37\x63\xed\xc0\xe4\xd3\xf2\xfa\xc5\x08\x40\x29\x8e\x6c\xe9\x72\xbd\xdb\xc2\x4d\xce\xaf\x4d\x2c\x2b\x60\x3a\x1a\x28\x37\x6e\x1a\x1b\x95\x73\x3c\xe6\x81\xf4\xe2\x52\x81\x04\x5a\xc6\xa7\x06\x3e\xa0\xdc\xbd\xec\xff\xbf\xee\x4b\xf8\xbc\x32\x30\xf0\x43\x94\x1c\x26\xbd\x2c\x6f\xe2\xeb\x0f\xce\xca\xb8\xfd\xa1\x45\x52\xc9\xd1\xd2\xac\x04\x69\x75\xd5\x0e\xc8\x43\x8e\xf4\x2c\x03\xdb\xb3\x81\xc7\xce\x4b\xa4\xe2\x3b\x00\x00\xff\xff\x49\xee\x9e\x02\x0c\x02\x00\x00") - -func vpcAdmissionWebhookConfigYamlBytes() ([]byte, error) { - return bindataRead( - _vpcAdmissionWebhookConfigYaml, - "vpc-admission-webhook-config.yaml", - ) -} - -func vpcAdmissionWebhookConfigYaml() (*asset, error) { - bytes, err := vpcAdmissionWebhookConfigYamlBytes() - if err != nil { - return nil, err - } - - info := bindataFileInfo{name: "vpc-admission-webhook-config.yaml", size: 0, mode: os.FileMode(0), modTime: time.Unix(0, 0)} - a := &asset{bytes: bytes, info: info, digest: [32]uint8{0x7d, 0x11, 0x23, 0x17, 0x2f, 0xdc, 0x4e, 0x18, 0xaa, 0xc8, 0x66, 0xee, 0xf3, 0xc1, 0x85, 0x63, 0xb1, 0xe3, 0x53, 0x57, 0x80, 0x96, 0xe6, 0x54, 0x26, 0x46, 0x6b, 0x3f, 0x17, 0x20, 0x31, 0x8}} - return a, nil -} - -var _vpcAdmissionWebhookCsrYaml = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\x44\x8d\x4b\x4e\xc4\x30\x10\x44\xf7\x3e\x45\x5f\x20\x41\xb3\x43\xde\x72\x03\x90\xd8\x77\xec\xc2\x69\x19\x7f\x70\xb7\x83\xe6\xf6\x28\x13\xa4\xd9\x95\xaa\x9e\x5e\x71\x97\x4f\x0c\x95\x56\x3d\x05\x0c\x93\x2f\x09\x6c\xd0\x35\xbf\xea\x2a\xed\xe5\xb8\x6d\x30\xbe\xb9\x2c\x35\x7a\x7a\x7b\x12\x1f\x92\xaa\xd4\xf4\x8e\x9f\x09\x35\x57\x60\x1c\xd9\xd8\x3b\xa2\xca\x05\x9e\x8e\x1e\x16\x8e\x45\xf4\x94\x2f\xbf\xd8\xf6\xd6\xf2\x9a\xe7\x86\x45\xef\x6a\x28\x4e\x3b\xc2\xc9\xa7\xd1\x66\xd7\x33\x2d\x74\x4d\x9e\xa7\xed\xa8\xf6\x78\x8a\x8e\x68\x2a\x27\xfc\x23\x51\x92\x18\x7f\x93\x4a\xaa\x6c\x73\xe0\xd1\x66\xdc\x09\x35\x48\xdf\x31\x0a\xaa\x5d\x36\x8c\x03\x83\x4e\x9b\xfb\x0b\x00\x00\xff\xff\xf1\x7d\x42\x97\xea\x00\x00\x00") - -func vpcAdmissionWebhookCsrYamlBytes() ([]byte, error) { - return bindataRead( - _vpcAdmissionWebhookCsrYaml, - "vpc-admission-webhook-csr.yaml", - ) -} - -func vpcAdmissionWebhookCsrYaml() (*asset, error) { - bytes, err := vpcAdmissionWebhookCsrYamlBytes() - if err != nil { - return nil, err - } - - info := bindataFileInfo{name: "vpc-admission-webhook-csr.yaml", size: 0, mode: os.FileMode(0), modTime: time.Unix(0, 0)} - a := &asset{bytes: bytes, info: info, digest: [32]uint8{0x56, 0xf4, 0x54, 0x57, 0xf8, 0xbd, 0x8a, 0x1a, 0x67, 0xb2, 0x29, 0x18, 0xe2, 0x44, 0x8a, 0xc2, 0x7f, 0x44, 0x26, 0x4c, 0x52, 0xe0, 0x70, 0xe0, 0xc8, 0x5a, 0x74, 0x76, 0x2, 0xcd, 0x3e, 0xa}} - return a, nil -} - -var _vpcAdmissionWebhookDepYaml = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\xc4\x54\xc1\x6e\xdb\x3a\x10\xbc\xfb\x2b\xf6\x92\x97\x93\xa5\x97\xa0\xc8\x81\x40\x0a\x04\x4d\x0a\x04\x6d\x93\xa0\x29\x7a\x5f\x53\x13\x99\x10\x45\xb2\xe4\x4a\x8e\xfe\xbe\xa0\xad\xa4\xb6\x1c\x37\x39\x14\xad\x0e\x3e\xec\xec\xcc\x2c\x87\x5e\x72\x30\xdf\x11\x93\xf1\x4e\x11\x87\x90\xca\xfe\x64\xd6\x18\x57\x29\xba\x44\xb0\x7e\x68\xe1\x64\xd6\x42\xb8\x62\x61\x35\x23\x72\xdc\x42\x51\x1f\xf4\x9c\xab\xd6\xa4\xcc\x9c\xaf\xb0\x58\x7a\xdf\x8c\x68\x0a\xac\xa1\xa8\xe9\x16\x98\xa7\x21\x09\xda\x19\x91\xe5\x05\x6c\xca\x02\x94\x7d\x0e\x29\xa4\x00\x9d\x9b\x22\x82\x35\x9a\x93\xa2\x93\x19\x51\x92\xc8\x82\x7a\xd8\xd0\x65\x08\x50\xf4\x15\x3a\x82\x05\x19\x86\x85\x16\x1f\x37\x70\xcb\xa2\x97\x9f\xb7\xec\x7e\x6b\x48\x24\x68\x83\x65\xc1\xc8\xde\x3a\x6a\xfe\xec\x8e\xd0\x2b\x52\x44\x4f\xf3\xe7\x4f\x7b\x27\x6c\x1c\xe2\x16\x7d\xfe\x4a\x7e\xcf\x36\xb1\xde\x62\x6d\x98\x73\xb1\xe9\x03\xa2\x7c\x34\x16\xe7\x25\x44\x97\x23\xaf\xd4\x88\x92\xd6\xbf\x45\x58\xa7\x3d\xa5\x7d\xc2\x70\x88\xd5\x60\x78\x89\x74\x7b\xbf\x8e\xf0\x7e\x8c\xf6\xb6\x47\x8c\xa6\xc2\xf9\xca\xb8\xca\xaf\xd2\xb4\x9d\x6d\xf2\xd6\xd7\xe2\x93\x54\x88\x71\x0a\xf7\xe7\xef\x26\xa5\xd3\xf7\xff\x9d\x6c\x95\x4c\xcb\x35\x14\x1d\x1f\xa5\xa2\x6a\x62\x01\x1d\x8b\xa3\x54\x1c\xa5\x12\x4d\x2a\x5f\x0c\x4b\xf5\xff\x17\xa7\xc5\xd9\xf1\x54\xe4\xae\xb3\xf6\xce\x5b\xa3\x07\x45\x17\x76\xc5\xc3\xf6\xac\xbd\xb7\x5d\x8b\x2f\xbe\x73\xb2\x17\xef\xe6\x62\x46\xf5\xf9\x3a\x9c\x9d\x0e\xa2\x36\xf3\xee\x58\x96\x8a\xf6\x83\x9c\xf4\x46\x70\x75\xeb\xec\xa0\x48\x62\x87\x11\x5c\xfa\x24\x37\x90\x95\x8f\xcd\x4e\x9d\x1f\x1e\x8c\x33\x32\xfc\x1a\xc9\xf9\x0a\x17\x7b\xd5\x2c\xfb\xa3\x33\x11\xd5\x65\x17\x8d\xab\xef\xf5\x12\x55\x67\x8d\xab\xaf\x6b\xe7\x9f\xcb\x57\x8f\xd0\x9d\xe4\x95\xde\x19\x2a\x6b\x3e\xdd\xe7\x37\xc4\x76\x2f\x81\xf5\xe6\x5c\x3d\x86\x88\x75\xd2\x13\x3c\x77\x34\x18\x14\x2d\x20\x5c\xe4\xed\x8e\x0e\x82\x54\x18\x5f\xfa\xe9\xf1\x89\x7c\x40\xe4\xbc\x94\x74\xed\xf6\xc0\x9e\x6d\x87\x3d\xfd\xec\x60\x8d\xeb\x1e\xdf\xec\xcb\x51\x2f\xff\x94\x33\xb7\xd5\xd9\xf4\x5f\xfa\xc6\x44\xfe\x41\x18\x7f\x27\x87\xcd\xbe\xbc\xf0\x7e\x1d\x5a\x93\x94\x5f\x65\xd9\x95\xdd\xd4\x6e\x0e\xbf\x7b\xa3\xca\xcf\x00\x00\x00\xff\xff\x52\xd4\x1b\x58\x8b\x06\x00\x00") - -func vpcAdmissionWebhookDepYamlBytes() ([]byte, error) { - return bindataRead( - _vpcAdmissionWebhookDepYaml, - "vpc-admission-webhook-dep.yaml", - ) -} - -func vpcAdmissionWebhookDepYaml() (*asset, error) { - bytes, err := vpcAdmissionWebhookDepYamlBytes() - if err != nil { - return nil, err - } - - info := bindataFileInfo{name: "vpc-admission-webhook-dep.yaml", size: 0, mode: os.FileMode(0), modTime: time.Unix(0, 0)} - a := &asset{bytes: bytes, info: info, digest: [32]uint8{0x3b, 0x48, 0x71, 0x63, 0xbb, 0x59, 0xcc, 0xd5, 0x1b, 0x30, 0xc7, 0x1c, 0x5e, 0xf2, 0x65, 0x72, 0xff, 0xa9, 0x4d, 0x14, 0x6c, 0xce, 0x49, 0xa8, 0x6f, 0x4d, 0x8e, 0x19, 0xf7, 0xee, 0xfa, 0x8c}} - return a, nil -} - -var _vpcAdmissionWebhookYaml = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\x84\x8c\x31\xae\xc2\x40\x0c\x05\xfb\x3d\x85\x2f\xe0\xe2\xeb\xa7\xf2\x29\x90\x90\xe8\x9d\xcd\x13\xac\x92\xcd\x5a\x6b\x13\xc4\xed\x51\x22\x0a\x1a\x44\x67\xf9\xcd\x0c\x33\x27\xb5\x72\x41\xf7\xd2\x56\xa1\xed\x2f\xcd\x65\x9d\x84\xce\xe8\x5b\xc9\x48\x15\xa1\x93\x86\x4a\x22\x5a\xb5\x42\x68\xb3\xcc\x3a\xd5\xe2\xbb\xc1\x0f\x8c\xb7\xd6\xe6\xf7\xea\xa6\x19\x42\xf3\x7d\x04\xfb\xd3\x03\x35\x11\x2d\x3a\x62\xf1\x3d\x40\xa4\x66\xdf\x0a\x6e\xc8\x3b\x64\xad\xc7\x41\xf3\x71\x0a\x0d\xc3\xff\xe1\x86\xf6\x2b\xe2\xf4\xf1\x73\x2c\xc8\xd1\xfa\xcf\xf6\x2b\x00\x00\xff\xff\xbc\xa7\x78\x3e\xe7\x00\x00\x00") - -func vpcAdmissionWebhookYamlBytes() ([]byte, error) { - return bindataRead( - _vpcAdmissionWebhookYaml, - "vpc-admission-webhook.yaml", - ) -} - -func vpcAdmissionWebhookYaml() (*asset, error) { - bytes, err := vpcAdmissionWebhookYamlBytes() - if err != nil { - return nil, err - } - - info := bindataFileInfo{name: "vpc-admission-webhook.yaml", size: 0, mode: os.FileMode(0), modTime: time.Unix(0, 0)} - a := &asset{bytes: bytes, info: info, digest: [32]uint8{0xc0, 0x14, 0x3e, 0x68, 0x1c, 0x57, 0x26, 0x7e, 0x3b, 0xab, 0xf1, 0x55, 0x21, 0x61, 0xc3, 0xe1, 0xaf, 0x46, 0xb6, 0xf7, 0xdd, 0x11, 0x29, 0x41, 0x64, 0x57, 0xc8, 0xd4, 0xea, 0x97, 0xba, 0xff}} - return a, nil -} - -var _vpcResourceControllerDepYaml = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\xc4\x94\x4f\x6f\xdb\x3c\x0c\xc6\xef\xfe\x14\xbc\x14\x3d\xd9\x49\xfa\xbe\x6b\x31\x01\x3b\x14\x6b\xb1\x15\x18\x86\x00\x0d\x76\x67\x24\x26\x16\x2c\x4b\x1a\x45\x3b\xf1\x3e\xfd\xa0\xb5\xf9\xe3\xa6\x5b\x8b\x61\xc3\x7c\x32\x9e\x9f\xc4\x87\x24\x44\x96\x65\x59\x60\xb4\x5f\x88\x93\x0d\x5e\x01\xc6\x98\x26\xfd\xac\x68\xac\x37\x0a\x6e\x28\xba\x30\xb4\xe4\xa5\x68\x49\xd0\xa0\xa0\x2a\x00\x3c\xb6\xa4\xa0\x8f\xba\x64\x4a\xa1\x63\x4d\xa5\x0e\x5e\x38\x38\x47\xfc\xc8\x53\x44\x4d\x0a\x9a\x6e\x49\x65\x1a\x92\x50\x5b\xa4\x48\x3a\x5f\x67\x8a\xce\x6a\x4c\x0a\x66\x05\x40\x22\x47\x5a\x02\x67\x02\xd0\xa2\xe8\xfa\x13\x2e\xc9\xa5\x07\x01\x72\x4a\xbf\x32\xcb\x9f\x58\x62\x05\x4b\xd4\x0d\x79\xb3\xd3\x18\x75\xa3\x20\x09\x2e\x1d\x15\x00\x42\x6d\x74\x28\xf4\xe8\x73\x54\x4e\xfe\xdc\xc8\xf2\x55\xa6\xcf\xdb\x9e\x1a\x03\xec\x0a\xff\xf1\x4f\xdc\x5b\x4d\xd7\x5a\x87\xce\xcb\x4b\x1e\x59\x40\xeb\x89\xf7\xa9\x95\xa0\x43\xdb\xa2\x37\x87\x5c\x4b\x98\xbc\x94\x29\xf2\x3a\x1d\x5f\x28\x93\x18\x62\x96\x9a\x29\xd5\xc1\x99\x77\xd6\xaf\xc2\x9e\xdb\x16\xd7\xa4\xe0\xfc\x2c\x55\xa6\xe1\x8a\x34\x57\x67\xa9\x3a\x4b\x13\x6a\xd2\x64\x63\xbd\x09\x9b\x54\xfe\xc4\x52\xf5\xd3\xea\xa2\xba\x3c\x1f\x07\x9b\x77\xce\xcd\x83\xb3\x7a\x50\x70\xed\x36\x38\xa4\x3d\x77\xb6\x27\x4f\x29\xcd\x39\x2c\xe9\x90\x23\xc0\x0a\xad\xeb\x98\x16\xbb\x1c\x15\xbc\x39\xa2\xb5\x48\xfc\x40\x72\x7c\x01\xa0\x0e\x49\x14\xcc\x2e\xae\xaa\x69\x35\xad\x66\x23\x16\x51\x6a\x05\x93\x9a\xd0\x49\xfd\x6d\x8c\x02\x8b\x82\xcb\xd9\xd5\xd5\xdb\x91\x9e\x74\x4d\xf9\xa5\x7f\x5c\x2c\xe6\x47\xc0\x7a\x2b\x16\xdd\x0d\x39\x1c\xee\x49\x07\x6f\x92\x82\xff\xa6\x47\x27\x22\xb1\x0d\xe6\x79\x26\xb6\xa5\xd0\xc9\x1e\x1e\x8a\x7a\x69\xac\x76\x0f\x48\x77\x6c\x65\x78\x1f\xbc\xd0\x76\xd4\x80\xc8\xb6\xb7\x8e\xd6\x64\x14\x08\x77\x54\x1c\xba\xf2\x99\x64\x13\xb8\x19\xe9\xb8\x5a\xe5\x52\x86\x43\x08\x1f\x0c\x5d\x9f\xa8\x79\x62\xbf\x76\x96\xc9\xdc\x74\x6c\xfd\xfa\x5e\xd7\x64\x3a\x67\xfd\xfa\x6e\xed\xc3\x5e\xbe\xdd\x92\xee\x24\x6f\x91\x51\x13\x73\xcc\xfb\xc7\x19\x5f\x10\xb7\x69\x8c\xcb\x87\x91\xbf\xdd\x46\xa6\x94\x77\xd0\x13\x9e\x4f\x34\x34\x28\x58\x92\x60\x95\xd7\x09\x7b\x12\x4a\x95\x0d\x93\x90\x9e\x1c\x05\x08\x91\x18\xf3\x36\x81\x3b\x7f\x02\x7b\x74\x1d\x9d\xc4\xcf\x0e\xce\xfa\x6e\xfb\x6a\x5f\x64\x5d\xff\x29\x67\x6c\xcd\xe5\xff\xbf\xd7\x91\x7f\xd0\x8c\xbf\xdd\x87\xef\x01\x00\x00\xff\xff\xec\x16\x91\xef\x8f\x06\x00\x00") - -func vpcResourceControllerDepYamlBytes() ([]byte, error) { - return bindataRead( - _vpcResourceControllerDepYaml, - "vpc-resource-controller-dep.yaml", - ) -} - -func vpcResourceControllerDepYaml() (*asset, error) { - bytes, err := vpcResourceControllerDepYamlBytes() - if err != nil { - return nil, err - } - - info := bindataFileInfo{name: "vpc-resource-controller-dep.yaml", size: 0, mode: os.FileMode(0), modTime: time.Unix(0, 0)} - a := &asset{bytes: bytes, info: info, digest: [32]uint8{0x0, 0xbf, 0x11, 0xf3, 0x5f, 0x76, 0xa3, 0xb2, 0x2e, 0x2f, 0x80, 0xa7, 0x86, 0xae, 0x3f, 0xb7, 0x7e, 0x76, 0xed, 0x68, 0xfe, 0x23, 0x5c, 0x76, 0xb9, 0xd0, 0xd8, 0xed, 0xf9, 0x9d, 0x96, 0x93}} - return a, nil -} - -var _vpcResourceControllerYaml = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\xa4\x90\x31\x4f\x33\x31\x0c\x86\xf7\xfc\x8a\xa8\x7b\x5a\x7d\xdb\xa7\xdb\x80\x81\xbd\x48\xec\x3e\x9f\xdb\x9a\xe6\xe2\xc8\x76\x0e\xc1\xaf\x47\x77\xd7\xc2\x80\x44\x85\x98\xf2\xc4\xf6\x6b\x4b\x4f\x4a\x29\x40\xe5\x67\x52\x63\x29\x5d\xd4\x1e\x70\x0b\xcd\x4f\xa2\xfc\x0e\xce\x52\xb6\xe7\xff\xb6\x65\xd9\x4d\xff\xc2\x99\xcb\xd0\xc5\x87\xdc\xcc\x49\xf7\x92\x29\x8c\xe4\x30\x80\x43\x17\x62\x2c\x30\x52\x17\xa7\x8a\x49\xc9\xa4\x29\x52\x42\x29\xae\x92\x33\x69\xd0\x96\xc9\xba\x90\x22\x54\x7e\x54\x69\xd5\xe6\x4c\x8a\x9b\x4d\x88\xf1\x1a\xb8\xd4\x8a\x0c\x64\x5f\xb4\x33\x07\x6f\x6b\xa1\xca\xb0\x02\x4a\x39\xf0\x71\x84\x3a\x7f\x27\xd2\xfe\x92\x6d\x75\x00\xa7\x05\x8f\xe4\xcb\x9b\xd9\x56\x78\x05\xc7\xd3\xba\xe6\x93\x50\x69\x9e\xff\x9b\x87\x7b\x2e\x03\x97\xe3\x6f\x74\x48\xa6\x3d\x1d\xe6\xc1\xab\x90\x1f\x8e\x86\x18\xbf\xbb\xbf\x75\xc2\x5a\xff\x42\xe8\x8b\xf4\x35\xfd\x44\x3a\x31\xd2\x1d\xa2\xb4\xe2\x37\x17\xac\x7d\xab\x80\xd4\xc5\x73\xeb\x29\xd9\x9b\x39\x8d\xe1\x23\x00\x00\xff\xff\x83\x2e\x8d\x64\x35\x02\x00\x00") - -func vpcResourceControllerYamlBytes() ([]byte, error) { - return bindataRead( - _vpcResourceControllerYaml, - "vpc-resource-controller.yaml", - ) -} - -func vpcResourceControllerYaml() (*asset, error) { - bytes, err := vpcResourceControllerYamlBytes() - if err != nil { - return nil, err - } - - info := bindataFileInfo{name: "vpc-resource-controller.yaml", size: 0, mode: os.FileMode(0), modTime: time.Unix(0, 0)} - a := &asset{bytes: bytes, info: info, digest: [32]uint8{0xa8, 0xff, 0xd2, 0xc, 0x46, 0xfb, 0xe4, 0x4e, 0xb, 0x26, 0x4a, 0xa0, 0x7d, 0x73, 0x5e, 0xaf, 0x6d, 0xab, 0xfd, 0xe5, 0xc2, 0x4f, 0xed, 0xae, 0xb6, 0xd7, 0x17, 0x38, 0x68, 0xb0, 0xe8, 0x2d}} - return a, nil -} - -// Asset loads and returns the asset for the given name. -// It returns an error if the asset could not be found or -// could not be loaded. -func Asset(name string) ([]byte, error) { - canonicalName := strings.Replace(name, "\\", "/", -1) - if f, ok := _bindata[canonicalName]; ok { - a, err := f() - if err != nil { - return nil, fmt.Errorf("Asset %s can't read by error: %v", name, err) - } - return a.bytes, nil - } - return nil, fmt.Errorf("Asset %s not found", name) -} - -// AssetString returns the asset contents as a string (instead of a []byte). -func AssetString(name string) (string, error) { - data, err := Asset(name) - return string(data), err -} - -// MustAsset is like Asset but panics when Asset would return an error. -// It simplifies safe initialization of global variables. -func MustAsset(name string) []byte { - a, err := Asset(name) - if err != nil { - panic("asset: Asset(" + name + "): " + err.Error()) - } - - return a -} - -// MustAssetString is like AssetString but panics when Asset would return an -// error. It simplifies safe initialization of global variables. -func MustAssetString(name string) string { - return string(MustAsset(name)) -} - -// AssetInfo loads and returns the asset info for the given name. -// It returns an error if the asset could not be found or -// could not be loaded. -func AssetInfo(name string) (os.FileInfo, error) { - canonicalName := strings.Replace(name, "\\", "/", -1) - if f, ok := _bindata[canonicalName]; ok { - a, err := f() - if err != nil { - return nil, fmt.Errorf("AssetInfo %s can't read by error: %v", name, err) - } - return a.info, nil - } - return nil, fmt.Errorf("AssetInfo %s not found", name) -} - -// AssetDigest returns the digest of the file with the given name. It returns an -// error if the asset could not be found or the digest could not be loaded. -func AssetDigest(name string) ([sha256.Size]byte, error) { - canonicalName := strings.Replace(name, "\\", "/", -1) - if f, ok := _bindata[canonicalName]; ok { - a, err := f() - if err != nil { - return [sha256.Size]byte{}, fmt.Errorf("AssetDigest %s can't read by error: %v", name, err) - } - return a.digest, nil - } - return [sha256.Size]byte{}, fmt.Errorf("AssetDigest %s not found", name) -} - -// Digests returns a map of all known files and their checksums. -func Digests() (map[string][sha256.Size]byte, error) { - mp := make(map[string][sha256.Size]byte, len(_bindata)) - for name := range _bindata { - a, err := _bindata[name]() - if err != nil { - return nil, err - } - mp[name] = a.digest - } - return mp, nil -} - -// AssetNames returns the names of the assets. -func AssetNames() []string { - names := make([]string, 0, len(_bindata)) - for name := range _bindata { - names = append(names, name) - } - return names -} - -// _bindata is a table, holding each asset generator, mapped to its name. -var _bindata = map[string]func() (*asset, error){ - "efa-device-plugin.yaml": efaDevicePluginYaml, - "neuron-device-plugin.yaml": neuronDevicePluginYaml, - "nvidia-device-plugin.yaml": nvidiaDevicePluginYaml, - "vpc-admission-webhook-config.yaml": vpcAdmissionWebhookConfigYaml, - "vpc-admission-webhook-csr.yaml": vpcAdmissionWebhookCsrYaml, - "vpc-admission-webhook-dep.yaml": vpcAdmissionWebhookDepYaml, - "vpc-admission-webhook.yaml": vpcAdmissionWebhookYaml, - "vpc-resource-controller-dep.yaml": vpcResourceControllerDepYaml, - "vpc-resource-controller.yaml": vpcResourceControllerYaml, -} - -// AssetDebug is true if the assets were built with the debug flag enabled. -const AssetDebug = false - -// AssetDir returns the file names below a certain -// directory embedded in the file by go-bindata. -// For example if you run go-bindata on data/... and data contains the -// following hierarchy: -// data/ -// foo.txt -// img/ -// a.png -// b.png -// then AssetDir("data") would return []string{"foo.txt", "img"}, -// AssetDir("data/img") would return []string{"a.png", "b.png"}, -// AssetDir("foo.txt") and AssetDir("notexist") would return an error, and -// AssetDir("") will return []string{"data"}. -func AssetDir(name string) ([]string, error) { - node := _bintree - if len(name) != 0 { - canonicalName := strings.Replace(name, "\\", "/", -1) - pathList := strings.Split(canonicalName, "/") - for _, p := range pathList { - node = node.Children[p] - if node == nil { - return nil, fmt.Errorf("Asset %s not found", name) - } - } - } - if node.Func != nil { - return nil, fmt.Errorf("Asset %s not found", name) - } - rv := make([]string, 0, len(node.Children)) - for childName := range node.Children { - rv = append(rv, childName) - } - return rv, nil -} - -type bintree struct { - Func func() (*asset, error) - Children map[string]*bintree -} - -var _bintree = &bintree{nil, map[string]*bintree{ - "efa-device-plugin.yaml": {efaDevicePluginYaml, map[string]*bintree{}}, - "neuron-device-plugin.yaml": {neuronDevicePluginYaml, map[string]*bintree{}}, - "nvidia-device-plugin.yaml": {nvidiaDevicePluginYaml, map[string]*bintree{}}, - "vpc-admission-webhook-config.yaml": {vpcAdmissionWebhookConfigYaml, map[string]*bintree{}}, - "vpc-admission-webhook-csr.yaml": {vpcAdmissionWebhookCsrYaml, map[string]*bintree{}}, - "vpc-admission-webhook-dep.yaml": {vpcAdmissionWebhookDepYaml, map[string]*bintree{}}, - "vpc-admission-webhook.yaml": {vpcAdmissionWebhookYaml, map[string]*bintree{}}, - "vpc-resource-controller-dep.yaml": {vpcResourceControllerDepYaml, map[string]*bintree{}}, - "vpc-resource-controller.yaml": {vpcResourceControllerYaml, map[string]*bintree{}}, -}} - -// RestoreAsset restores an asset under the given directory. -func RestoreAsset(dir, name string) error { - data, err := Asset(name) - if err != nil { - return err - } - info, err := AssetInfo(name) - if err != nil { - return err - } - err = os.MkdirAll(_filePath(dir, filepath.Dir(name)), os.FileMode(0755)) - if err != nil { - return err - } - err = ioutil.WriteFile(_filePath(dir, name), data, info.Mode()) - if err != nil { - return err - } - return os.Chtimes(_filePath(dir, name), info.ModTime(), info.ModTime()) -} - -// RestoreAssets restores an asset under the given directory recursively. -func RestoreAssets(dir, name string) error { - children, err := AssetDir(name) - // File - if err != nil { - return RestoreAsset(dir, name) - } - // Dir - for _, child := range children { - err = RestoreAssets(dir, filepath.Join(name, child)) - if err != nil { - return err - } - } - return nil -} - -func _filePath(dir, name string) string { - canonicalName := strings.Replace(name, "\\", "/", -1) - return filepath.Join(append([]string{dir}, strings.Split(canonicalName, "/")...)...) -} diff --git a/pkg/addons/default/assets.go b/pkg/addons/default/assets.go deleted file mode 100644 index 7655c06350..0000000000 --- a/pkg/addons/default/assets.go +++ /dev/null @@ -1,389 +0,0 @@ -// Code generated by go-bindata. DO NOT EDIT. -// sources: -// assets/aws-node.yaml (7.015kB) -// assets/coredns-1.17.json (10.228kB) -// assets/coredns-1.18.json (10.212kB) -// assets/coredns-1.19.json (10.163kB) -// assets/coredns-1.20.json (10.393kB) -// assets/coredns-1.21.json (10.486kB) - -package defaultaddons - -import ( - "bytes" - "compress/gzip" - "crypto/sha256" - "fmt" - "io" - "io/ioutil" - "os" - "path/filepath" - "strings" - "time" -) - -func bindataRead(data []byte, name string) ([]byte, error) { - gz, err := gzip.NewReader(bytes.NewBuffer(data)) - if err != nil { - return nil, fmt.Errorf("read %q: %w", name, err) - } - - var buf bytes.Buffer - _, err = io.Copy(&buf, gz) - clErr := gz.Close() - - if err != nil { - return nil, fmt.Errorf("read %q: %w", name, err) - } - if clErr != nil { - return nil, err - } - - return buf.Bytes(), nil -} - -type asset struct { - bytes []byte - info os.FileInfo - digest [sha256.Size]byte -} - -type bindataFileInfo struct { - name string - size int64 - mode os.FileMode - modTime time.Time -} - -func (fi bindataFileInfo) Name() string { - return fi.name -} -func (fi bindataFileInfo) Size() int64 { - return fi.size -} -func (fi bindataFileInfo) Mode() os.FileMode { - return fi.mode -} -func (fi bindataFileInfo) ModTime() time.Time { - return fi.modTime -} -func (fi bindataFileInfo) IsDir() bool { - return false -} -func (fi bindataFileInfo) Sys() interface{} { - return nil -} - -var _awsNodeYaml = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\xec\x58\xdf\x8f\xe2\x38\x12\x7e\xe7\xaf\x68\x59\xba\x97\x93\x12\xe8\xd9\x99\xb9\xde\x96\xf6\x81\x81\x34\x17\x2d\x04\x14\xa0\x67\xf7\x5e\x22\xe3\x54\x07\x1f\x8e\x9d\xb5\x1d\x9a\xde\xd3\xfd\xef\x27\x9b\x04\x12\x48\x80\x9e\xdb\xbb\x91\x4e\xf7\xd4\x8d\x5d\xf5\x7d\xe5\x2f\x55\xe5\x1f\x8e\xe3\x74\x10\xce\xe8\x33\x48\x45\x05\x47\x8f\x77\x68\x7b\x8f\x3a\x68\x43\x79\x6c\x7e\xcc\x41\x6e\x29\x81\x3e\x21\x22\xe7\x1a\x75\x50\x0a\x1a\xc7\x58\x63\xf4\xd8\xb9\xbb\x43\x1c\xa7\x60\xcc\xf0\xab\x72\xb8\x88\x01\x95\x83\x2a\xc3\xc4\xce\x6c\xf2\x15\x38\xea\x4d\x69\x48\x51\xa7\x81\x4d\xae\x30\x71\x71\xae\xd7\x42\xd2\xdf\xb1\xa6\x82\xbb\x9b\x07\xe5\x52\xd1\xad\xc5\x31\x60\xb9\xd2\x20\x43\xc1\xe0\x0b\xe5\x31\xe5\xc9\x0d\xb1\x20\x29\x18\x84\xf0\xb2\x9f\xc7\x19\x1d\x49\x91\x67\x17\x59\xed\x02\x1a\x48\x51\x0b\x83\xca\x57\x7f\x07\xa2\x15\x7a\xec\x38\x77\xad\xaa\x7d\x27\xa5\x6e\x92\x28\x67\x50\x44\x5f\x0a\xa4\xac\xb1\x73\x87\x88\x8c\x2d\x05\x4e\xf1\xef\x82\xe3\x57\xe5\x12\x91\xda\xc0\x25\x28\x91\x4b\x02\x07\x53\xe0\x94\x08\xfe\x42\x13\x65\xe7\xb7\x20\x57\x87\xb9\x04\xac\x04\xce\x1d\x62\x54\x95\xff\xbe\x62\x4d\xd6\xa8\x91\xb6\x99\xe1\xa0\x55\x03\xc3\x39\xee\x91\xf8\x76\x86\x4c\xc4\xff\x31\x6c\xa3\xf6\x3b\xc1\xed\x7f\x79\x16\x63\x0d\xcd\x4c\xb0\xd3\xc0\x4d\x76\xa8\x66\xce\x3f\xdf\xc2\xd7\x90\x68\x38\xa3\x47\xe8\x63\x8e\xad\x40\xe3\x5a\xa2\xe5\x4a\x8b\x34\x2c\x58\x87\xf0\x42\x39\x35\x59\xd9\x9a\x75\xc7\x1c\x71\x5b\x32\x0b\xa9\x0c\xc8\xde\x29\x29\x4b\xb5\x3d\x09\x6d\x46\x58\xeb\x4a\xcd\x7a\x81\x3f\xb0\x24\x68\x3f\x9e\xb1\x5c\x62\x56\xa7\x2f\xa6\x14\xe5\x49\xce\xb0\xac\x4d\x5a\x64\x45\x44\x06\x95\x62\x2a\x85\xdc\x8b\x5d\x49\xc8\x7d\xbf\xc4\x2c\x5b\x1b\x69\xf6\xa8\x20\xb7\x60\x42\xd1\x32\x87\x62\x48\x0b\x89\x13\x28\xc7\x1a\x25\xcf\x54\xbd\x8c\x87\x18\x52\xc1\xe7\x70\xde\x73\x19\x5e\x01\x3b\xae\xfb\x41\x39\x38\xcb\x1a\x5b\xcb\x3b\xfa\x4d\x45\x79\x05\x0c\x88\x16\xb2\x64\x48\x4d\xa2\x8c\xab\xa4\x17\x68\x35\xa4\x19\x33\x19\x5b\x3a\x57\x43\xb7\x23\xac\x8e\xd4\x8e\x65\x42\x29\x83\xb2\xbf\xf0\x8b\x4d\xb1\xb7\xaa\xaf\x31\xee\x9f\x8f\xdb\x72\xf8\x2d\xa7\x12\xe2\x61\x2e\x29\x4f\xe6\x64\x0d\x71\xce\x28\x4f\xfc\x84\x8b\xc3\xb0\xb7\x03\x92\xdb\xa4\xad\xfa\x16\xb8\xf3\x42\x88\x05\xc8\x54\x9d\x18\x38\x85\x2e\xde\x2e\x93\xa0\x8e\x79\x71\x62\xb3\x81\x37\xb3\x2c\x53\x3a\xae\xd1\x5b\x72\xd0\x60\xeb\x49\x14\x59\x58\x63\x15\x19\x48\x6c\xa5\xbf\x43\x3e\x6f\x30\xd8\x62\x96\xc3\x39\x53\x51\xdb\x3c\xdf\x9d\xfa\x5c\x8c\x01\xcb\x7d\xc7\xf9\x23\xa3\xc0\x69\xfc\xf9\xe3\xb9\x8f\x99\x91\xe9\xf9\xcc\x31\x3e\xd8\x9c\xd4\x78\x97\x88\x34\xcb\x35\x38\xfa\x2d\x83\x2b\x61\x06\x42\xbf\x3b\xd2\x17\x2c\x13\xdb\x5b\x4f\xc6\xdf\xf1\x5d\xbf\xf3\x27\xfd\xff\xd7\x3c\xf2\x9e\x7c\x4d\x44\x04\xd7\x98\x72\x90\x47\x7b\x7b\x4c\xd9\x56\xdc\x2b\x4d\xbc\x3f\x1c\xfa\x0b\x7f\x1a\xf4\xc7\x91\x17\xf8\xd1\xa2\x3f\x9a\x57\x03\xd8\x53\x1b\xc3\x7f\xfc\x13\x35\xfa\x7f\x9d\x47\xcf\xb3\x41\x34\x08\xfc\x28\x98\x0e\xbd\x68\x36\x0d\x17\xd1\x7c\x39\x33\x7f\x9b\x91\xcc\x5e\x70\x11\xcb\x04\x32\x59\x2c\x9b\xbd\x7f\xec\xf5\xee\x2f\x7a\xff\xfc\x30\xb7\xd1\x0c\xa6\xc1\x93\x3f\x5a\x86\x5e\x14\xce\x9e\xfc\xf1\xc2\x0b\x9b\x01\x5f\x30\x53\x97\xe3\x39\x20\x2e\xe7\x8b\xe9\x24\x0a\xbc\xc5\xd7\x69\xf8\x73\x34\x78\x1a\xfd\xbb\x88\xde\x2f\x0b\x2f\x0c\xfa\xe3\x79\xd0\x6f\x11\xeb\x76\xac\xf1\x74\x34\xf6\x9e\xbd\x71\x33\xce\xd0\xfb\xb2\x1c\xdd\x8a\x13\x3d\xf9\x63\xaf\x19\xa7\xbb\x16\x4a\x77\xb7\x58\x76\x99\x48\xba\x66\xdb\x92\x22\xd7\x10\x3b\xc0\x69\x97\x66\x38\x8d\x5d\x26\x92\x9b\x88\xc2\x7e\x30\x9c\x4e\xfc\xbf\x79\xed\xab\xcf\x24\xbf\x0d\xeb\xd9\x5b\xfc\x75\x16\x7a\x4f\xfe\x2f\xcd\x40\xc0\xe9\x55\x9c\xd9\x78\x39\xf2\x83\x6b\xeb\x6f\x59\x7a\xc6\xf2\x84\xf2\x9b\xd6\x5e\xe1\xf9\xa6\x0f\x36\xf4\xe7\xfd\x2f\x63\x2f\xf2\x83\x45\x38\x9d\xcf\xbc\x81\xa9\xdf\xf7\x66\x4f\x09\x32\xf1\x16\xa1\x3f\x68\xa9\xf9\xeb\xee\x65\x2d\x84\xde\x7c\xba\x0c\x07\x5e\x34\x0b\xa7\xcf\xfe\xdc\x9f\x06\x7e\xf0\xee\xea\xf0\x02\x8b\x39\x9b\x0e\x4d\x0b\xf8\x56\x6f\x9b\x05\xd1\xd0\x1b\x7b\xa3\xfe\xb7\x28\x33\xf9\x75\xdf\xc8\x82\xfe\xa4\x21\x07\x9e\xa4\x48\x4f\xcf\x4c\x2f\x14\x58\x5c\x5e\xb7\xcf\x67\x66\x58\xaf\x0d\xb0\x39\xd4\xb9\xe6\x7c\x15\x18\xa6\x26\xea\xaf\xfd\x70\x52\xb4\xe1\x70\xe4\xb5\xd4\x44\x73\xf7\xb3\xae\xc5\xda\x6f\xf4\x46\x34\xdd\x1f\xce\xd1\xe7\xde\x87\x8f\xbd\xfb\xfb\x8f\x3f\x7c\xfc\xf4\xc1\x8d\x37\xd2\x05\x22\xdd\x5c\x39\xaf\xa0\xb4\xf3\xe1\x64\x3f\xdb\xff\x72\xcc\xe1\x95\x70\xfa\xb8\xbd\x77\x7f\x74\x7f\xa8\xa0\x32\xba\x05\x0e\x4a\xcd\xa4\x58\x41\xfd\x68\x0a\xbb\xca\xb1\xb6\x18\x23\x22\x4d\xb1\x39\xfa\x9f\x1e\x47\xba\x38\xcb\xba\x89\xcc\x88\xb3\x06\xcc\xf4\xda\xc9\x2c\xe0\xa9\x99\x83\xe3\x58\xfe\xf4\xf8\xa9\xd7\xfb\x74\x7f\x3e\x49\x04\xe7\x40\xb4\xa3\x69\x0a\x22\xd7\x3f\x7d\x50\xe7\x36\x86\xa2\x79\x1e\xd9\x9b\x1d\x66\x43\x60\xf8\x6d\x0e\x44\xf0\x58\xa1\xc7\xbb\xcf\xbd\xaa\x4d\xe1\x7a\x9c\xfe\x54\x39\xa5\x37\x5c\x46\x8a\xa9\x4c\x48\xad\xea\x7b\xf2\x61\xeb\x9e\x09\xa9\x0d\xcf\xfd\xe7\xbf\x3c\x54\xa9\x4a\xb8\x14\xb4\xa4\xa4\x12\x2a\x92\x80\x63\xfa\xbf\xad\xfa\x7d\x75\xb5\xd5\x1b\x7f\x65\xf8\xb7\x1c\x94\x3e\x3d\x28\x21\x92\xe5\x36\xf5\x7b\x69\x45\x31\x05\x24\x97\x54\xbf\x0d\x04\xd7\xb0\xd3\x75\x24\x82\x33\xbc\xa2\x8c\x6a\x7a\x76\xec\x42\x38\x6e\x90\x2d\xf0\x16\x51\x7f\x38\xf1\x2b\xdd\x06\x6d\x05\xcb\x53\x98\x88\x9c\x9f\x7e\xe8\xd4\x8c\x95\x6d\x61\xbf\xa3\x8a\x4c\x77\x09\xa7\xdd\x15\xad\x1d\x00\x0f\x9f\x9c\x70\xea\xac\x28\x77\x62\x2a\xd1\x15\x28\xd0\xc4\x42\x71\xd0\x6e\xdc\x0a\xc6\x41\xdf\x02\xd6\xbc\xdd\x35\xa2\x32\x91\x5c\x41\x34\x60\x32\xe7\xdd\xf3\x72\xa8\xc0\xc8\xfc\xda\x2a\x4b\x98\x58\x90\x0d\x48\xb5\xa6\xa9\xab\x04\xd9\x34\xa2\x1d\x6d\x2e\x00\x1a\xb0\x9d\xc6\x2b\x06\xca\x65\x6d\x48\x85\x81\x53\x35\x40\x46\xa3\x00\xf4\xab\x90\x9b\xea\xcb\x47\x91\xc4\x83\xf7\x9d\xc5\xcb\x4d\x75\x31\x98\x45\x5e\x3f\x1c\xff\x1a\x0d\xbd\xc9\xb2\xe5\x44\x73\xb2\x81\xfd\x21\xcd\xdc\x31\x41\x9f\x77\xf4\x6a\x17\xdb\x66\xe4\x60\x79\x6b\x35\x65\x92\x6e\x29\x83\xa4\xfe\x3a\xf4\x5f\xa9\x11\xc3\x2d\x6c\x60\x0c\x2b\x15\x14\x86\xfb\xc7\x1f\x9b\x82\x0e\x91\x54\x53\x82\xd9\xc1\x43\xd5\xde\xb0\x83\x96\x0e\x8e\x34\xc8\x94\x72\xfb\x1c\x3d\x92\x98\xc0\x0c\x24\x15\x71\xa5\x5d\xf5\x0e\x96\x82\x99\x2b\x5e\xed\x4a\xed\xd4\x2f\x7e\xde\x8e\x9a\xbe\xd5\xa9\xa9\x52\xb3\x36\x02\xec\xd5\xa8\x29\x5b\xea\xd3\x28\xcd\x25\x61\xae\x43\xb6\xb4\x91\x4b\x4d\xe4\x3a\xe8\xd5\xd2\xbd\x50\xb8\xd7\xd1\xdb\xeb\xf8\x62\x15\xdf\x16\xf6\x95\x2e\x68\xaf\xf7\xa6\x88\xa9\xb4\x8f\x67\x6f\x53\x39\x90\x50\x7b\x67\x69\xeb\x94\xb7\xcb\xd6\xd8\x38\xdf\xc3\x5c\x69\xae\xc5\x13\xfb\x5c\x4b\xac\x21\x29\x1f\x11\x91\x14\x8c\x51\x9e\x2c\xf7\xef\xef\x87\x37\xc8\x14\xef\x96\x1c\x6f\x31\x65\x46\xbf\xfd\x76\xfa\xa7\xe2\xb5\xb2\x0c\x20\xac\xb9\x76\x5c\xd7\xed\xfc\x2b\x00\x00\xff\xff\x52\x34\x51\xce\x67\x1b\x00\x00") - -func awsNodeYamlBytes() ([]byte, error) { - return bindataRead( - _awsNodeYaml, - "aws-node.yaml", - ) -} - -func awsNodeYaml() (*asset, error) { - bytes, err := awsNodeYamlBytes() - if err != nil { - return nil, err - } - - info := bindataFileInfo{name: "aws-node.yaml", size: 0, mode: os.FileMode(0), modTime: time.Unix(0, 0)} - a := &asset{bytes: bytes, info: info, digest: [32]uint8{0x7c, 0x85, 0xa8, 0x9e, 0xb6, 0x21, 0xf, 0x46, 0x9a, 0x6f, 0x36, 0xe9, 0xb2, 0x10, 0xc9, 0x3d, 0x4e, 0x97, 0xf5, 0xf5, 0x23, 0xb7, 0x14, 0x6e, 0x77, 0x70, 0xd4, 0x7b, 0xe, 0x62, 0xbe, 0x50}} - return a, nil -} - -var _coredns117Json = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\xec\x5a\x5f\x73\x1b\xb9\x0d\x7f\xf7\xa7\xd8\xd9\x99\xbc\x9d\x64\x29\x8e\xdd\x9c\xdf\x7c\xb6\x9b\xf3\x34\x76\x35\xb6\x73\x2f\xcd\xcd\x0d\xc5\x85\x24\x56\x5c\x82\x05\xb9\xb2\x75\x19\x7f\xf7\x0e\xf7\x8f\xb4\x7f\xc8\x95\xe4\x3a\x9d\x74\xa6\x7a\x48\xd6\x24\x00\x62\x01\xfc\x40\x80\xdc\x6f\x47\x51\x14\x33\x2d\x7e\x03\x32\x02\x55\x7c\x1e\xc5\xab\x71\xfc\x93\x1b\x15\x16\x52\x13\x9f\x47\xff\x38\x8a\xa2\x28\xfa\x96\xff\x1b\x22\xce\x67\x96\x42\x25\x6e\xec\x01\x68\x25\x38\x6c\x27\x52\xb0\x2c\x61\x96\xc5\xe7\x1b\x31\x4e\x90\x52\x68\x99\x15\xa8\x4c\x63\x22\x8a\x62\x4d\x98\x82\x5d\x40\x66\x86\x02\x8f\x35\x92\x75\x72\x7f\x1e\x9f\x9e\x6c\x84\x7a\xe8\x0c\x27\xa6\xc1\x51\x5a\xca\x20\xde\x10\xbe\x6c\x79\x62\xc9\xa6\x20\x3b\xeb\xc1\xd2\x0c\x59\xca\xfe\x44\xc5\x9e\xcc\x90\x63\x7a\xcc\x31\xd5\xa8\x40\xe5\x0b\x2f\xb3\x29\x0c\x12\x65\x9a\x8b\x2f\x3f\x9a\x01\xd3\xba\x87\x20\x9b\x02\x29\xb0\x90\x6b\xc7\x65\x66\x2c\xd0\xc0\x94\xd6\xa9\xd4\xec\x61\x51\x2c\xcd\xe9\x2e\x91\xe0\xea\xee\xc1\xff\x46\x15\x91\x47\x87\x7c\xce\x68\xc6\xb7\x04\x66\x6d\x2c\xa4\x95\xa4\x8d\x9c\xd8\x68\xe0\x4d\xf7\x38\xab\x6f\xdd\x5f\xfc\xea\x46\xab\x2d\xdd\x7e\xf3\x92\x3b\x3e\x8f\x4e\x4f\xda\xe3\x84\x16\x39\x4a\xc7\xf6\xe5\x6a\xd2\x66\xb3\x8c\xe6\x60\x27\x15\x73\x6d\xf2\xe5\xa7\xbd\xf4\x18\x58\xae\x5f\xa3\xcb\xe3\xe5\x21\xba\x6c\x9e\x7f\xaf\x19\xdb\x80\x04\x6e\x91\xda\xc1\xe5\x8b\x13\xaf\x27\x0d\x18\x07\xab\x8b\xd9\x4c\x28\x61\xd7\x8e\xe1\x0e\x55\x3d\x42\x62\xbb\x2e\x02\xfc\xb2\x08\xa6\x9b\xc9\xc6\x93\x47\x35\x69\x87\x63\xf5\x82\x73\xcc\x94\x3d\x10\xb2\xff\x31\xb0\x38\x12\xec\x85\xab\xde\xc8\xef\x4a\xd9\x1d\xf8\x07\x9a\xab\x6b\x0a\x87\xc9\x99\x90\xf9\x02\xc3\xf3\xd3\x93\xe8\xdb\x57\xe5\x26\x80\x08\xc9\x14\xcf\x0b\x60\xd2\x2e\x8a\xe7\x2d\xb2\xa3\x32\x13\x0c\x25\x72\x26\x23\xa1\x06\x2c\x49\x68\xc8\x48\xb3\x48\xe8\xb3\xe2\xa1\x94\x16\x45\x1a\x13\x13\x09\x65\x80\x67\x04\xd5\x60\xa6\x8d\x25\x60\x69\xf5\xf7\x8c\x49\x69\x17\x84\xd9\x7c\xe1\x97\x57\x10\xbe\x14\xff\x6d\xb3\x66\x74\xee\x72\x6a\x31\x3a\x43\x7a\x62\x94\x44\xc3\xe8\x18\x2c\x3f\x26\x30\x28\x57\x43\x8e\x6a\x56\xcc\x73\xc6\x17\x10\x9d\x8c\x8a\xbf\x24\xa2\x2e\x9e\x08\x24\xb2\xa4\x1a\x65\xc9\x94\x49\xa6\x38\x7c\x55\x2f\x5f\x55\x37\xcf\x54\x71\x77\x89\x6a\x26\xe6\xb7\x4c\xff\x3f\xe4\x6a\x21\xc7\xb4\x36\xc7\x3e\x98\x5e\x81\x96\xb8\x4e\xe1\x07\x86\xe8\x5b\xed\x63\xaf\x31\x6d\xdf\x36\x46\x38\x27\x30\xe6\x0a\x58\x22\x85\x82\x07\xe0\xa8\x12\x67\x85\xb3\xd1\xa8\xb6\x06\x81\x96\x82\x33\x37\xf1\xbe\x31\xbc\x12\xce\x3b\xbf\x0a\x63\x91\xd6\x9f\x45\x2a\x9c\x59\xc6\xa3\x3d\x12\x7f\xca\x2c\x5f\x7c\xf6\x19\xfd\x75\x66\xdf\x15\xa8\xf5\x8d\xa9\xb1\xaf\x58\x62\x16\xe6\xeb\xb6\x7e\x84\x52\x0a\x35\xff\xa2\x13\x66\xa1\xab\x61\xca\x9e\x1f\x32\x9a\xe7\x46\x7f\x7f\xfa\xae\xad\x4a\xca\x9e\xbf\x28\xb6\x62\x42\xb2\x69\x9e\x06\xc7\xa1\xdd\x7a\xb3\x6b\xdd\x37\x16\xf4\xea\x6a\x21\xd5\xb2\xab\x8e\x3f\xd8\xa3\xfe\x32\xb2\xc7\xce\x99\x85\x41\xa5\x15\xf0\xf7\x71\x83\xeb\xa5\xf5\xa6\x9c\x20\x97\xff\x28\x52\x30\x96\xa5\xce\xfc\x2a\x93\xb2\x45\xe6\x85\x57\x8f\x0e\x3b\x7c\xbd\xdb\xdb\x75\x7f\xb7\x4d\xde\x01\x42\x61\xab\x6d\x69\xd1\x51\x52\x61\x02\x17\xe1\xf9\x1c\x0b\xff\xca\x04\x41\x72\x95\x91\x50\xf3\x07\xbe\x80\x24\x73\xfe\xbc\x99\x2b\xdc\x0c\x5f\x3f\x03\xcf\x6c\x91\xcf\xba\x32\xca\x75\x1e\x4a\xc4\x3c\x02\xa5\xed\x1a\x73\xfb\xf3\xb1\x47\x1b\x60\x5d\x3f\x6b\x2a\x0a\xa6\xb0\x84\x3e\x29\xb9\xa4\x25\xe4\x65\xd6\x14\x2c\x1b\x36\x73\x16\x76\xfd\xd1\xe0\x44\x0d\xc4\x0a\xd0\xc7\x37\xaa\x9f\x76\xc5\x64\x06\xfd\x5a\xe6\x74\x52\xa8\xec\x39\xee\xa1\xf9\x3d\x38\xf7\x12\x56\xe0\x95\x06\x60\xc4\x17\xff\x7d\x13\xb0\x34\x39\xfb\xd0\x2b\xca\x11\x51\x7a\xf6\xe1\x95\x76\x0a\xcc\xf8\x39\x7c\xd4\x5d\xca\x36\x55\xc7\x17\xb1\xc6\xe4\x42\x59\xd1\x0f\x2f\x4d\x30\x03\x3a\x04\x5f\x3e\x5b\xfa\xbd\x9d\x6b\x50\xae\xee\x40\x17\x00\x67\xb4\xc9\x63\x0f\xfe\x3d\xad\x45\x7a\x10\x10\xfb\x23\x71\x1b\x8b\x55\xd6\xdb\x11\x04\x07\x44\xdf\xfe\xf1\x17\x85\x32\x6d\xfb\x17\x8e\xb0\x70\x8c\x85\xb9\x82\xe8\x8d\x2d\x6a\x94\x38\x5f\xff\xad\xb4\x4d\x03\xa2\x0b\x34\x36\x2f\x9b\xfc\xc1\xeb\x17\x1a\x3f\x81\x98\x2f\x8a\x22\x66\xe4\xa1\xe8\x6a\xdf\xd6\xfa\xa5\x7f\xb7\x44\x65\x99\x50\x40\x3e\x6b\x7b\xc2\x9e\xd1\x3c\xe4\x97\x78\xe0\xda\x0f\xaf\x6b\xe3\xbc\x49\x29\x77\xce\xe3\x4d\x33\xd6\xd5\xbd\xcb\x1c\x8b\x94\x15\x55\xcd\x3b\x33\x4c\x96\x34\x04\x4e\xc3\x77\x66\xf8\xce\x1c\xc3\xd2\x54\x32\xcf\x57\xe3\xe1\xd9\xf0\x6c\x00\x4b\x33\xcd\x84\x4c\x86\x63\x8f\x1e\x85\xa8\x49\x26\xe5\x04\xa5\xe0\xb9\x8b\x6e\x66\x77\x68\x27\x04\xa6\x5e\xac\xd7\x58\xa4\x58\x81\x02\x63\x26\x84\xd3\x6e\xd5\x55\x12\xcd\x98\x90\x19\xc1\xe3\x82\xc0\x2c\x50\xba\x1e\xe0\xd4\x6b\x86\x85\xb5\xfa\x13\xd8\x20\x4c\x63\xcd\xec\xc2\xa9\x75\x5c\x34\xa3\x01\x9c\x54\x67\x24\x1f\x47\x1f\x47\x01\x0a\xc3\x17\x50\x54\xe8\xbf\x3e\x3e\x4e\x7c\x21\xe7\x0d\xb8\xd8\xe5\x1c\xc1\xe4\x15\x48\xb6\xae\x17\xdf\x5e\x62\x0d\x24\x30\xd9\x92\x8d\xfd\x64\x26\xe3\x1c\x8c\xa9\x9b\x67\xec\x25\xb4\x22\x05\xcc\xec\x56\xe0\x69\x37\x7b\x7b\x7c\x14\xee\x45\xb6\x9a\x7a\x8e\xc7\xaa\x5f\xc0\x15\x1b\x64\x4c\xfc\x07\x52\x9d\xe5\xfd\x4b\x47\xbe\x73\xb4\x7d\xdd\xf1\x86\xaa\x79\x8e\xda\xbc\xea\x3d\x5e\xbe\xb9\x7a\x3f\x8f\x77\x2a\x98\x82\x25\xc1\xf7\xb2\x5f\x48\xc1\xbd\x92\x09\x01\x4b\xc4\x6b\xf0\xec\x7d\x81\xff\x01\x3c\x7f\x77\x88\x8e\xf7\x82\x28\x81\xc1\x8c\x38\xf8\x1a\xae\xa8\xc8\xb3\xa9\xb0\xa1\xd9\xbc\xa3\x4c\x91\xf2\x8c\x3d\xfe\xcb\xe8\x56\xec\x6f\x00\xd7\x06\x81\xe9\x13\xcd\x75\x96\xcb\x1d\x8d\xd2\x90\x7f\xb6\xab\x07\x17\xdf\xcb\x0c\xf9\xb9\xa0\xb0\xeb\x4b\x54\x16\x9e\x43\x71\x13\x33\x29\xf1\x69\x42\x62\x25\x24\xcc\xe1\xda\x70\x26\x59\x59\x44\xce\x98\x34\xe0\x7d\x51\xce\x34\x9b\x0a\x29\xac\x08\x5a\xd9\x89\x4e\x92\x9e\xb2\x2a\xbe\xbb\x7e\xfc\xe3\x97\x9b\xbb\xab\x3f\x1e\xae\xef\x7f\xbb\xb9\xbc\xf6\xd7\x2a\x1e\x64\xe5\xdc\x09\xa1\xee\x93\xce\xa4\x0c\x08\x3c\xc0\x9d\x2c\xf9\xbb\x92\xeb\x7b\x44\xfb\x57\x21\xa1\x3c\x5a\x3a\x8f\x2c\x65\xb0\x97\x0f\x2c\x50\x2a\x54\x6e\xcf\x5b\x30\xc6\x55\x04\x15\x48\x13\x58\x1d\xd7\xa6\x07\x12\xe7\xbe\xcd\xc4\x23\x61\x53\x4f\x38\x9d\x7c\x3c\x2b\x94\x59\x0a\xb7\x98\xa9\x43\xf7\xa1\xd4\xf1\x6c\x54\xac\xd5\x51\xa1\x60\xdd\x6e\x87\x6a\x26\xe6\x83\x62\xe5\x10\x71\x65\xcf\x90\x05\x0f\xcb\xfc\x4d\x5d\x6d\x1a\xdc\x71\x2a\x1d\x1d\xc9\x1b\x54\xb5\xad\x80\x74\xfb\xdd\xd6\x25\x57\x30\x63\x99\x6c\x57\x77\xb1\x26\x81\x39\x16\x25\x33\xe6\xae\xd4\xa7\x08\xa7\x41\x75\xfb\xc7\x49\x58\xc1\x99\x6c\xf3\x12\x18\xcb\xc8\x6e\xd7\xb8\x90\x4f\x6c\xdd\x39\xff\x33\x45\x53\x08\x54\x89\x4f\x0a\x55\x06\x9b\x89\x0e\x47\x37\x41\xb4\x2b\x76\xd3\xbc\x03\x0a\x9f\x3e\x36\x09\xef\x7a\x8b\xa4\x7a\x4c\x7f\x22\xc6\x61\xd2\xda\x37\x4e\x46\x6d\x06\x94\xae\xa3\x0b\xf4\x91\x9e\xce\x01\x66\x33\xe0\xb6\xb8\x26\x2b\xbb\x65\x2f\x52\xca\xbe\x52\x61\x02\x03\x42\x09\xad\x83\x8e\x94\x39\xcf\xb4\x83\xa6\x13\xa4\x1e\x05\x4a\xc1\x97\xa5\x4f\x2f\x92\x04\x95\xc9\x63\xdf\xa3\x45\xbd\x5f\xbd\x7e\x16\x6e\x03\x39\x28\x02\x0b\xd4\xed\x6b\x9a\x54\xdb\xf5\x95\x20\x8f\xbb\xa3\x1d\x68\xd9\xe7\xc5\xf9\xe6\xf6\x26\xb0\xdf\x94\x61\x79\x8b\x89\x5b\xe6\xc3\x7b\x7f\x8d\xd0\xfc\xc2\xa0\xfd\x0b\x1e\x50\x54\x66\xaf\x9a\xbe\x60\xf3\x5c\xd5\x4a\xe1\xf6\x30\x0a\x1d\xf2\x78\xf5\x6d\xb7\x05\x07\xf6\x12\xf5\xe4\xd9\xef\xfa\x23\xdf\x4c\xf5\xb4\xcf\x45\x12\x4d\x19\x1f\xb2\xcc\x2e\x90\xc4\x9f\x39\xa6\x86\xcb\x8f\x79\xb4\xfb\x6e\x97\xca\xdb\xe4\x7b\x94\x87\x7e\xb4\xf1\x43\x5c\x2f\x4d\x11\xad\xb1\xc4\xb4\x16\x6a\x5e\xbd\xfd\xa0\x0c\xc1\x1d\x17\x79\x45\x7a\x3e\x6f\x79\x74\x7b\xa1\x44\x99\x6c\x61\xae\xf1\x76\x4c\x8b\x4f\x84\x99\xee\x46\x71\x5c\x77\x71\x23\x9c\x1a\xa5\x6b\x8b\x09\x54\xa2\x51\xb8\x1d\xdd\x9f\x7a\x3d\xdf\x59\x24\x9d\xb1\xcd\x75\x99\x09\xeb\xb0\x02\x9a\x7a\xd6\x97\xc2\x74\xb6\xb5\x27\x66\xf9\xa2\x21\xc9\x67\xd1\xef\x6a\x16\x97\xba\x0f\x7f\x99\x39\xd8\x80\xda\x47\xf5\x91\xef\x84\xa4\x5f\x84\x4a\x5c\x3c\x1e\x06\xa8\x86\x41\x3c\x4b\x37\x8f\xe8\x33\x8b\x59\x75\x7b\xf7\xd6\x1f\x3d\xfd\xf0\xc8\x44\x09\xf7\x30\x6b\x59\xb3\x0c\xbc\x5e\xcf\xd5\xaf\x96\xfb\x52\xe0\x01\xca\x98\x6c\xfa\x4f\xe0\xb6\x27\x53\xec\xf8\xe0\x26\xda\x75\xec\xb4\xf3\x12\xbc\x13\xd6\x47\x25\x4c\x36\x4b\x7f\x76\xe0\x3e\x7a\x39\xfa\x77\x00\x00\x00\xff\xff\x85\x7f\x10\xa7\xf4\x27\x00\x00") - -func coredns117JsonBytes() ([]byte, error) { - return bindataRead( - _coredns117Json, - "coredns-1.17.json", - ) -} - -func coredns117Json() (*asset, error) { - bytes, err := coredns117JsonBytes() - if err != nil { - return nil, err - } - - info := bindataFileInfo{name: "coredns-1.17.json", size: 0, mode: os.FileMode(0), modTime: time.Unix(0, 0)} - a := &asset{bytes: bytes, info: info, digest: [32]uint8{0x9d, 0x70, 0x23, 0x87, 0xb4, 0xbb, 0xaf, 0x6f, 0x43, 0xc2, 0xf2, 0xe, 0xd2, 0xc1, 0x68, 0x9c, 0xb8, 0x1c, 0xf1, 0x3, 0xac, 0x82, 0xf4, 0x54, 0x6d, 0x63, 0xf3, 0x36, 0xa2, 0x7c, 0xa2, 0x1}} - return a, nil -} - -var _coredns118Json = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\xec\x5a\x5f\x6f\x1b\x39\x0e\x7f\xcf\xa7\x18\x0c\xd0\xb7\xb5\x63\x37\x4d\xb7\x9b\xb7\x6c\x92\xeb\x06\xd7\xe4\x8c\x24\xdd\x97\xeb\x62\x21\x6b\x68\x5b\x67\x8d\xa8\xa3\x34\x4e\xdc\x22\xdf\xfd\xa0\xf9\x63\xcf\x1f\x69\x6c\xe7\xd2\x43\x0f\x58\x3f\xb4\x13\x89\xa4\x38\x24\x7f\x14\x29\xcd\xb7\xa3\x28\x8a\x99\x16\xbf\x03\x19\x81\x2a\x3e\x8b\xe2\xd5\x38\xfe\xc9\x8d\x0a\x0b\xa9\x89\xcf\xa2\x7f\x1e\x45\x51\x14\x7d\xcb\xff\x0d\x11\xe7\x33\x4b\xa1\x12\x37\x76\x0f\xb4\x12\x1c\xb6\x13\x29\x58\x96\x30\xcb\xe2\xb3\x8d\x18\x27\x48\x29\xb4\xcc\x0a\x54\xa6\x31\x11\x45\xb1\x26\x4c\xc1\x2e\x20\x33\x43\x81\xc7\x1a\xc9\x3a\xb9\xbf\x8c\x4f\x4f\x36\x42\x3d\x74\x86\x13\xd3\xe0\x28\x2d\x65\x10\x6f\x08\x9f\xb7\x3c\xb1\x64\x53\x90\x9d\xf5\x60\x69\x86\x2c\x65\x5f\x51\xb1\x47\x33\xe4\x98\x1e\x73\x4c\x35\x2a\x50\xf9\xc2\xcb\x6c\x0a\x83\x44\x99\xe6\xe2\xcb\x0f\x66\xc0\xb4\xee\x21\xc8\xa6\x40\x0a\x2c\xe4\xda\x71\x99\x19\x0b\x34\x30\xa5\x75\x2a\x35\x7b\x58\x14\x4b\x73\xba\x0b\x24\xb8\xbc\xbd\xf7\xbf\x51\x45\xe4\xd1\x21\x9f\x33\x9a\xf1\x2d\x81\x59\x1b\x0b\x69\x25\x69\x23\x27\x36\x1a\x78\xd3\x3d\xce\xea\x5b\xf7\x17\xbf\xba\xd1\x6a\x4b\xb7\xdf\xbc\xe4\x8e\xcf\xa2\xd3\x93\xf6\x38\xa1\x45\x8e\xd2\xb1\x7d\xbe\x9c\xb4\xd9\x2c\xa3\x39\xd8\x49\xc5\x5c\x9b\x7c\xfe\x69\x2f\x3d\x06\x96\xeb\x97\xe8\xf2\x70\x71\x88\x2e\x9b\xe7\x3f\x6a\xc6\x36\x20\x81\x5b\xa4\x76\x70\xf9\xe2\xc4\xeb\x49\x03\xc6\xc1\xea\x7c\x36\x13\x4a\xd8\xb5\x63\xb8\x45\x55\x8f\x90\xd8\xae\x8b\x00\xbf\x28\x82\xe9\x7a\xb2\xf1\xe4\x51\x4d\xda\xe1\x58\x3d\xe7\x1c\x33\x65\x0f\x84\xec\x7f\x0d\x2c\x8e\x04\x7b\xe1\xaa\x37\xf2\xbb\x52\x76\x07\xfe\x81\xe6\xea\x9a\xc2\x61\x72\x26\x64\xbe\xc0\xf0\xec\xf4\x24\xfa\xf6\x45\xb9\x09\x20\x42\x32\xc5\xf3\x02\x98\xb4\x8b\xe2\x79\x8b\xec\xa8\xcc\x04\x43\x89\x9c\xc9\x48\xa8\x01\x4b\x12\x1a\x32\xd2\x2c\x12\xfa\x7d\xf1\x50\x4a\x8b\x22\x8d\x89\x89\x84\x32\xc0\x33\x82\x6a\x70\xc6\xa4\xb4\x0b\xc2\x6c\xbe\xf0\xf3\x17\x84\xcf\xc5\x7f\xdb\x2c\x19\x9d\xb9\x1c\x5a\x8c\xce\x90\x1e\x19\x25\xd1\x30\x3a\x06\xcb\x8f\x09\x0c\xca\xd5\x90\xa3\x9a\x15\xf3\x9c\xf1\x05\x44\x27\xa3\xe2\x2f\x89\xa8\x8b\x27\x02\x89\x2c\xa9\x46\x59\x32\x65\x92\x29\x0e\x5f\xd4\xf3\x17\xd5\xcd\x2b\x55\x9c\x5d\xa0\x9a\x89\xf9\x0d\xd3\x7f\x85\x58\x2d\xc4\x98\xd6\xe6\xd8\x07\xcb\x4b\xd0\x12\xd7\x29\xfc\xc0\x90\x7c\xad\x7d\xeb\x25\xa6\xed\xdb\xb6\x08\xe7\x04\xc6\x5c\x02\x4b\xa4\x50\x70\x0f\x1c\x55\xe2\xac\xf0\x7e\x34\xaa\xad\x41\xa0\xa5\xe0\xcc\x4d\xbc\x6d\x0c\xaf\x84\xf3\xce\x6f\xc2\x58\xa4\xf5\x27\x91\x0a\x67\x96\xf1\x68\x8f\x44\x9f\x32\xcb\x17\x9f\x7c\x46\x7f\x99\xd9\x77\x05\x6a\x7d\x23\x6a\xec\x23\x96\x98\x85\xf9\xba\xad\x1f\xa1\x94\x42\xcd\x3f\xeb\x84\x59\xe8\x6a\x98\xb2\xa7\xfb\x8c\xe6\xb9\xd1\xdf\x9e\xbe\x69\xab\x92\xb2\xa7\xcf\x8a\xad\x98\x90\x6c\x9a\xa7\xbd\x71\x68\x77\xde\xec\x52\x77\x8d\x05\xbd\xba\x5a\x48\xb5\xec\xaa\xe3\x0f\xf6\xa8\xbf\x6c\xec\xb1\x73\x66\x61\x50\x69\x05\xfc\x6d\xdc\xe0\x7a\x6e\xbd\x29\x27\xc8\xe5\x3f\x88\x14\x8c\x65\xa9\x33\xbf\xca\xa4\x6c\x91\x79\xe1\xd5\xa3\xc3\x0e\x5f\xef\xf6\x76\xdd\xdf\x6d\x93\x77\x80\x50\xd8\x6a\x5b\x4a\x74\x94\x54\x98\xc0\x79\x78\x3e\xc7\xc2\xbf\x33\x41\x90\x5c\x66\x24\xd4\xfc\x9e\x2f\x20\xc9\x9c\x3f\xaf\xe7\x0a\x37\xc3\x57\x4f\xc0\x33\x5b\xe4\xb3\xae\x8c\x72\x9d\xfb\x12\x31\x0f\x40\x69\xbb\xa6\xdc\xfe\x7c\xec\xd1\x06\x58\x57\x4f\x9a\x8a\x02\x29\x2c\xa1\x4f\x4a\x2e\x69\x09\x79\x59\x35\x05\xcb\x86\xcd\x9c\x85\x5d\x7f\x34\x38\x51\x03\xb1\x02\xf4\xf1\xb5\xea\xa7\x5d\x31\x99\x41\xbf\x96\x39\x9d\x14\x2a\x7b\x8a\x7b\x68\xfe\x08\xce\x3d\x87\x15\x78\xa1\x01\x18\xf1\xc5\xff\xde\x04\x2c\x4d\xde\xbf\xeb\x15\xe5\x88\x28\x7d\xff\xee\x85\x76\x0a\xcc\xf8\x39\x7c\xd4\x5d\xca\x36\x55\xc7\x17\xb1\xc6\xe4\x5c\x59\xd1\x0f\x2f\x4d\x30\x03\x3a\x04\x5f\x3e\x5b\xfa\xbd\x9d\x6b\x50\xae\xee\x40\x17\x00\x67\xb4\xc9\x63\xf7\xfe\x3d\xad\x45\x7a\x10\x10\xfb\x23\x71\x1b\x8b\x55\xd6\xdb\x11\x04\x07\x44\xdf\xfe\xf1\x17\x85\x32\x6d\xfb\x17\x8e\xb0\x70\x8c\x85\xb9\x82\xe8\x8d\x2d\x6a\x94\x38\x5f\xff\xbd\xb4\x4d\x03\xa2\x0b\x34\x36\x2f\x9b\xfc\xc1\xeb\x17\x1a\x3f\x82\x98\x2f\x8a\x22\x66\xe4\xa1\xe8\x6a\xdf\xd6\xfa\xb9\x7f\xb7\x44\x65\x99\x50\x40\x3e\x6b\x7b\xc2\x9e\xd1\x3c\xe4\x97\x78\xe0\xda\x0f\xaf\x6b\xe3\xbc\x49\x29\x77\xce\xe3\x4d\xf3\xd5\xd5\xbd\xcb\x1c\x8b\x94\x15\x55\xcd\x1b\x33\x4c\x96\x34\x04\x4e\xc3\x37\x66\xf8\xc6\x1c\xc3\xd2\x54\x32\xcf\x56\xe3\xe1\xcf\xc3\xd1\x00\x96\x66\x9a\x09\x99\x0c\xc7\x1e\x3d\x0a\x51\x93\x4c\xca\x09\x4a\xc1\x73\x17\x5d\xcf\x6e\xd1\x4e\x08\x4c\xbd\x58\xaf\xb1\x48\xb1\x02\x05\xc6\x4c\x08\xa7\xdd\xaa\xab\x24\x9a\x31\x21\x33\x82\x87\x05\x81\x59\xa0\x74\x3d\xc0\xa9\xd7\x0c\x0b\x6b\xf5\x47\xb0\x41\x98\xc6\x9a\xd9\x85\x53\xeb\xb8\x68\x3e\x03\x38\xa9\xce\x44\x3e\x8c\x3e\x8c\x02\x14\x86\x2f\xa0\xa8\xd0\x7f\x7b\x78\x98\xf8\x42\xce\x1b\x70\xb1\xcb\x39\x82\xc9\x4b\x90\x6c\x5d\x2f\xbe\xbd\xc4\x1a\x48\x60\xb2\x25\x1b\xfb\xc9\x4c\xc6\x39\x18\x53\x37\xcf\xd8\x4b\x68\x45\x0a\x98\xd9\xad\xc0\xd3\x6e\xf6\xf6\xf8\x28\xdc\x8b\x6c\x35\xf5\x1c\x87\x55\xbf\x80\x2b\x36\xc8\x98\xf8\x0f\xa0\x3a\xcb\xfb\x97\x8e\x7c\xe7\x66\xfb\xba\xe3\x15\x55\xf3\x1c\xad\x79\xd5\x7b\xb8\x78\x75\xf5\x7e\x19\xef\x54\x30\x05\x4b\x82\xef\x65\xbf\x90\x82\x7b\x25\x13\x02\x96\x88\x97\xe0\xd9\xfb\x02\xff\x07\x78\xfe\xee\x10\x1d\xef\x05\x51\x02\x83\x19\x71\xf0\x35\x5c\x51\x91\x67\x53\x61\x43\xb3\x79\x47\x99\x22\xe5\x19\x7b\xfc\xf3\xe8\x46\xec\x6f\x00\xd7\x06\x81\xe9\x13\xcd\x75\x96\xcb\x1d\x8d\xd2\x90\x7f\xb6\xab\x07\x17\xdf\xcb\x0c\xf9\x39\xa0\xb0\xeb\x0b\x54\x16\x9e\x42\x71\x13\x33\x29\xf1\x71\x42\x62\x25\x24\xcc\xe1\xca\x70\x26\x59\x59\x44\xce\x98\x34\xe0\x7d\x51\xce\x34\x9b\x0a\x29\xac\x08\x5a\xd9\x89\x4e\x92\x9e\xb2\x2a\xbe\xbd\x7a\xf8\xf3\xd7\xeb\xdb\xcb\x3f\xef\xaf\xee\x7e\xbf\xbe\xb8\xf2\xd7\x2a\x1e\x64\xe5\xdc\x09\xa1\xee\x93\xce\xa4\x0c\x08\x3c\xc0\x9d\x2c\xf9\x87\x92\xeb\x3b\x44\xfb\x37\x21\xa1\x3c\x5a\x3a\x8b\x2c\x65\xb0\x97\x0f\x2c\x50\x2a\x54\x6e\xcf\x1b\x30\xc6\x55\x04\x15\x48\x13\x58\x1d\xd7\xa6\x07\x12\xe7\xbe\xcd\xc4\x23\x61\x53\x4f\x38\x9d\x7c\x3c\x2b\x94\x59\x0a\x37\x98\xa9\x43\xf7\xa1\xd4\xf1\x6c\x54\xac\xd5\x51\xa1\x60\xdd\x6e\x87\x6a\x26\xe6\x83\x62\xe5\x10\x71\x65\xcf\x90\x05\x0f\xcb\xfc\x4d\x5d\x6d\x1a\xdc\x71\x2a\x1d\x1d\xc9\x2b\x54\xb5\xad\x80\x74\xfb\xdd\xd6\x25\x97\x30\x63\x99\x6c\x57\x77\xb1\x26\x81\x39\x16\x25\x33\xe6\xb6\xd4\xa7\x08\xa7\x41\x75\xdb\xc7\x49\x58\xc1\x99\x6c\xf3\x12\x18\xcb\xc8\x6e\xd7\x38\x97\x8f\x6c\xdd\x39\xff\x33\x45\x53\x08\x54\x89\x4f\x0a\x55\x06\x9b\x89\x0e\x47\x37\x41\xb4\x2b\x76\xd3\xbc\xf3\x09\x9f\x3e\x36\x09\x6f\x7b\x8b\xa4\x7a\x4c\x7f\x24\xc6\x61\xd2\xda\x37\x4e\x46\x6d\x06\x94\xae\xa3\x0b\xf4\x91\x9e\xce\x01\x66\x33\xe0\xb6\xb8\x16\x2b\xbb\x65\x2f\x52\xca\xbe\x52\x61\x02\x03\x42\x09\xad\x83\x8e\x94\x39\xcf\xb4\x83\xa6\x13\xa4\x1e\x05\x4a\xc1\x17\xa5\x4f\xcf\x93\x04\x95\xc9\x63\xdf\xa3\x45\xbd\x5f\xbd\x7a\x12\x6e\x03\x39\x28\x02\x0b\xd4\xed\x6b\x9a\x54\xdb\xf5\xa5\x20\x8f\xbb\xa3\x1d\x68\xd9\xe7\xc5\xf9\xe6\xf6\x26\xb0\xdf\x94\x61\x79\x83\x89\x5b\xe6\xdd\x5b\x7f\x8d\xd0\xfc\xa2\xa0\xfd\x0b\x1e\x50\x54\x66\xaf\x9a\xbe\x60\xf3\x5c\xd5\x4a\xe1\xf6\x30\x0a\x1d\xf2\x78\xf5\x6d\xb7\x05\x07\xf6\x12\xf5\xe4\xd9\xef\xfa\x23\xdf\x4c\xf5\xb4\xcf\x45\x12\x4d\x19\x1f\xb2\xcc\x2e\x90\xc4\xd7\x1c\x53\xc3\xe5\x87\x3c\xda\x7d\xb7\x4b\xe5\xed\xf1\x1d\xca\x43\x3f\xd2\xf8\x21\xae\x97\xa6\x88\xd6\x58\x62\x5a\x0b\x35\xaf\xde\x7e\x50\x86\xe0\x8e\x8b\xbc\x22\x3d\x9f\xb5\x3c\xba\xbd\x50\xa2\x4c\xb6\x30\xd7\x78\x3b\xa6\xc5\x47\xc2\x4c\x77\xa3\x38\xae\xbb\xb8\x11\x4e\x8d\xd2\xb5\xc5\x04\x2a\xd1\x28\xdc\x8e\xee\x4f\xbd\x9e\xef\x2a\x92\xce\xd8\xe6\xba\xcc\x84\x75\x58\x01\x4d\x3d\xeb\x4b\x61\x3a\xdb\xda\x23\xb3\x7c\xd1\x90\xe4\xb3\xe8\x77\x35\x8b\x4b\xdd\x87\xbf\xcc\x1c\x6c\x40\xed\xa3\xfa\xc8\x77\x42\xd2\xaf\x42\x25\x2e\x1e\x0f\x03\x54\xc3\x20\x9e\xa5\x9b\x47\xf4\x99\xc5\xac\xba\xbd\x7b\xed\x8f\x9c\x7e\x78\x64\xa2\x84\x3b\x98\xb5\xac\x59\x06\x5e\xaf\xe7\xea\x57\xcb\x7d\x29\xf0\x00\x65\x4c\x36\xfd\x17\x70\xdb\x93\x29\x76\x7c\x60\x13\xed\x3a\x76\xda\x79\x09\xde\x09\xeb\xa3\x12\x26\x9b\xa5\x3f\x39\x70\x1f\x3d\x1f\xfd\x27\x00\x00\xff\xff\x09\xbb\x53\xfc\xe4\x27\x00\x00") - -func coredns118JsonBytes() ([]byte, error) { - return bindataRead( - _coredns118Json, - "coredns-1.18.json", - ) -} - -func coredns118Json() (*asset, error) { - bytes, err := coredns118JsonBytes() - if err != nil { - return nil, err - } - - info := bindataFileInfo{name: "coredns-1.18.json", size: 0, mode: os.FileMode(0), modTime: time.Unix(0, 0)} - a := &asset{bytes: bytes, info: info, digest: [32]uint8{0xcb, 0x9d, 0x4c, 0xd6, 0xfd, 0x7e, 0xcb, 0xe5, 0xc5, 0x9e, 0x2, 0x8, 0xd4, 0xd3, 0xe3, 0xba, 0x62, 0xf1, 0x1b, 0xea, 0x1, 0x31, 0x15, 0x6d, 0x18, 0x7e, 0x19, 0x41, 0x91, 0x51, 0xaa, 0xc7}} - return a, nil -} - -var _coredns119Json = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\xec\x5a\x5f\x73\x1b\xb9\x0d\x7f\xf7\xa7\xd8\xd9\x99\xbc\x9d\x64\x29\x8e\x53\x9f\xdf\x7c\xb6\x9b\xf3\x34\x76\x35\xb6\x73\x2f\xcd\xcd\x0d\xc5\x85\x24\x56\x5c\x82\x05\xb9\xb2\x75\x19\x7f\xf7\x0e\xf7\x8f\xb4\x7f\xc8\x95\xe4\x3a\x9d\x74\xa6\x7a\x48\xd6\x4b\x00\x04\x81\x1f\x40\x80\xdc\x6f\x47\x51\x14\x33\x2d\x7e\x03\x32\x02\x55\x7c\x1e\xc5\xab\x71\xfc\x93\x7b\x2b\x2c\xa4\x26\x3e\x8f\xfe\x71\x14\x45\x51\xf4\x2d\xff\x37\x44\x9c\x8f\x2c\x85\x4a\xdc\xbb\x07\xa0\x95\xe0\xb0\x1d\x48\xc1\xb2\x84\x59\x16\x9f\x6f\xc4\x38\x41\x4a\xa1\x65\x56\xa0\x32\x8d\x81\x28\x8a\x35\x61\x0a\x76\x01\x99\x19\x0a\x3c\xd6\x48\xd6\xc9\xfd\x79\x7c\x7a\xb2\x11\xea\xa1\x33\x9c\x98\x06\x47\x69\x29\x83\x78\x43\xf8\xb2\xe5\x89\x25\x9b\x82\xec\xcc\x07\x4b\x33\x64\x29\xfb\x13\x15\x7b\x32\x43\x8e\xe9\x31\xc7\x54\xa3\x02\x95\x4f\xbc\xcc\xa6\x30\x48\x94\x69\x4e\xbe\x3c\x33\x03\xa6\x75\x0f\x41\x36\x05\x52\x60\x21\xd7\x8e\xcb\xcc\x58\xa0\x81\x29\xad\x53\xa9\xd9\xc3\xa2\x58\x9a\xd3\x5d\x22\xc1\xd5\xdd\x83\x7f\x45\x15\x91\x47\x87\x7c\xcc\x68\xc6\xb7\x04\x66\x6d\x2c\xa4\x95\xa4\x8d\x9c\xd8\x68\xe0\x4d\xf7\x38\xab\x6f\xdd\x5f\xfc\xea\x46\xab\x4d\xdd\x5e\x79\xc9\x1d\x9f\x47\xa7\x27\xed\xf7\x84\x16\x39\x4a\xc7\xf6\xe5\x6a\xd2\x66\xb3\x8c\xe6\x60\x27\x15\x73\x6d\xf0\xe5\xa7\xbd\xf4\x18\x58\xae\x5f\xa3\xcb\xe3\xe5\x21\xba\x6c\x9e\x7f\xaf\x19\xdb\x80\x04\x6e\x91\xda\xe0\xf2\xe1\xc4\xeb\x49\x03\xc6\x85\xd5\xc5\x6c\x26\x94\xb0\x6b\xc7\x70\x87\xaa\x8e\x90\xd8\xae\x0b\x80\x5f\x16\x60\xba\x99\x6c\x3c\x79\x54\x93\x76\x78\xac\x5e\x70\x8e\x99\xb2\x07\x86\xec\x7f\x1c\x58\x1c\x09\xf6\x8a\xab\x5e\xe4\x77\xa5\xec\x06\xfe\x81\xe6\xea\x9a\xc2\xc5\xe4\x4c\xc8\x7c\x82\xe1\xf9\xe9\x49\xf4\xed\xab\x72\x03\x40\x84\x64\x8a\xe7\x05\x30\x69\x17\xc5\xf3\x36\xb2\xa3\x32\x13\x0c\x25\x72\x26\x23\xa1\x06\x2c\x49\x68\xc8\x48\xb3\x48\xe8\x8f\xc5\x43\x29\x2d\x8a\x34\x26\x26\x12\xca\x00\xcf\x08\xaa\x97\x33\x26\xa5\x5d\x10\x66\xf3\x85\x9f\xbf\x20\x7c\x29\xfe\xdb\x66\xc9\xe8\xdc\xe5\xd0\xe2\xed\x0c\xe9\x89\x51\x12\x0d\xa3\x63\xb0\xfc\x98\xc0\xa0\x5c\x0d\x39\xaa\x59\x31\xce\x19\x5f\x40\x74\x32\x2a\xfe\x92\x88\xba\x78\x22\x90\xc8\x92\xea\x2d\x4b\xa6\x4c\x32\xc5\xe1\xab\x7a\xf9\xaa\xba\x79\xa5\xc2\xd9\x25\xaa\x99\x98\xdf\x32\xfd\x7f\x88\xd5\x20\xc6\xb4\x36\xc7\xbe\xb0\xbc\x02\x2d\x71\x9d\xc2\x0f\x1c\x92\x6f\xb5\x6f\xbd\xc6\xb4\x7d\xdb\x16\xe1\x9c\xc0\x98\x2b\x60\x89\x14\x0a\x1e\x80\xa3\x4a\x9c\x15\x3e\x8e\x46\xb5\x39\x08\xb4\x14\x9c\xb9\x81\xf7\x8d\xd7\x2b\xe1\xbc\xf3\xab\x30\x16\x69\xfd\x59\xa4\xc2\x99\x65\x3c\xda\x23\xd1\xa7\xcc\xf2\xc5\x67\x9f\xd1\x5f\x67\xf6\x5d\x40\xad\x6f\x44\x8d\x7d\xc4\x12\xb3\x30\x5f\xb7\xf5\x23\x94\x52\xa8\xf9\x17\x9d\x30\x0b\x5d\x0d\x53\xf6\xfc\x90\xd1\x3c\x37\xfa\xfb\xd3\x77\x6d\x55\x52\xf6\xfc\x45\xb1\x15\x13\x92\x4d\xf3\xb4\x37\x0e\xed\xce\x9b\x5d\xea\xbe\x31\xa1\x57\x57\x0b\xa9\x96\x5d\x75\xfc\x60\x8f\xfa\xcb\xc6\x1e\x3b\x67\x16\x06\x95\x56\xc0\xdf\xc7\x0d\xae\x97\xd6\x4a\xbd\x71\xd3\x23\x7c\x87\x13\x77\xbb\xb1\xee\xc8\xb6\x2d\x3b\x08\x2f\x8c\xb0\xad\x11\x3a\x4a\x2a\x4c\xe0\x22\x3c\x9e\x83\xfc\x5f\x99\x20\x48\xae\x32\x12\x6a\xfe\xc0\x17\x90\x64\xce\x51\x37\x73\x85\x9b\xd7\xd7\xcf\xc0\x33\x5b\x24\xaa\xae\x8c\x72\x9e\x87\x32\x14\x1e\x81\xd2\x76\xb1\xb8\xfd\xf9\xd8\xa3\x4d\xc4\x5c\x3f\x6b\x2a\x2a\x9f\xb0\x84\x3e\x29\xb9\xa4\x25\xac\x2b\xeb\x6e\xf3\x10\x76\x5d\xd1\x60\x42\x0d\xc4\x8a\x40\x8e\x6f\x54\x3f\xed\x8a\xc9\x0c\xfa\x15\xcc\xe9\xa4\x50\xd9\x73\xdc\x43\xf3\x7b\x70\xec\x25\xac\xc0\xe1\x6b\x67\xc4\x17\xff\xfd\xd5\xb3\x34\xf9\xf8\xa1\x57\x94\x23\xa2\xf4\xe3\x87\x57\x9a\x28\x30\xe2\xe7\xf0\x51\x77\x29\xdb\x54\x1d\x37\xc4\x1a\x93\x0b\x65\x45\x7f\x50\x69\x82\x19\xd0\x21\x51\xe5\xb3\xa5\xdf\xd1\xb9\x06\xe5\xec\x2e\xd4\x02\x21\x19\x6d\xb2\xd7\x83\x7f\x8b\x6a\x91\x1e\x14\x7e\xfd\x20\xac\xc1\xb0\xcc\x75\x3b\x40\x70\x00\xfa\xf6\xc7\x5f\x14\xca\xaf\xed\x5f\x18\x61\x61\x8c\x85\xb9\x82\x81\x1b\x5b\xd4\x28\x71\xbe\xfe\x9b\x2f\x44\x17\x68\x6c\x5e\x05\xf9\xc1\xeb\x17\x1a\x3f\x81\x98\x2f\x8a\x9a\x64\xe4\xa1\xe8\x6a\xdf\xd6\xfa\xa5\x77\xf3\xe3\xa8\x2c\x13\x0a\xc8\x67\x6d\x0f\xec\x19\xcd\x43\x7e\x89\x07\xae\x9b\xf0\xba\x36\xce\x7b\x8e\x72\xbf\x3c\xde\xf4\x52\x5d\xdd\xbb\xcc\xb1\x48\x59\x51\xa4\xbc\x33\xc3\x64\x49\x43\xe0\x34\x7c\x67\x86\xef\xcc\x31\x2c\x4d\x25\xf3\x7c\x35\x1e\x9e\x0d\x47\x03\x58\x9a\x69\x26\x64\x32\x1c\x7b\xf4\x28\x44\x4d\x32\x29\x27\x28\x05\xcf\x5d\x74\x33\xbb\x43\x3b\x21\x30\xf5\xda\xbb\xc6\x22\xc5\x0a\x14\x18\x33\x21\x9c\x76\x8b\xa8\x92\x68\xc6\x84\xcc\x08\x1e\x17\x04\x66\x81\xd2\x95\xf4\xa7\x5e\x33\x2c\xac\xd5\x9f\xc0\x06\xc3\x34\xd6\xcc\x2e\x9c\x5a\xc7\x45\x2f\x19\x88\x93\xea\x88\xe3\x6c\x74\x36\x0a\x50\x18\xbe\x80\xa2\xe0\xfe\xf5\xf1\x71\xe2\x83\x9c\x17\x70\xb1\xcb\x39\x82\xc9\x2b\x90\x6c\x5d\xaf\xa5\xbd\xc4\x1a\x48\x60\xb2\x25\x1b\xfb\xc9\x4c\xc6\x39\x18\x53\x37\xcf\xd8\x4b\x68\x45\x0a\x98\xd9\xad\xc0\xd3\x6e\xf6\xf6\xf8\x28\xdc\x5a\x6c\x35\xf5\x9c\x6e\x55\xbf\x80\x2b\x36\x91\x31\xf1\x9f\x27\x75\xa6\xf7\x4f\x1d\xf9\x8e\xc1\xf6\x75\xc7\x1b\xaa\xe6\x39\x29\xf3\xaa\xf7\x78\xf9\xe6\xea\xfd\x3c\xde\xa9\x60\x0a\x96\x04\xdf\xcb\x7e\x21\x05\xf7\x4a\x26\x04\x2c\x11\xaf\x89\x67\xef\x02\xfe\x07\xe2\xf9\xbb\x87\xe8\x78\xaf\x10\x25\x30\x98\x11\x07\x5f\x9b\x15\x15\x79\x36\x15\x36\x34\x9a\x37\x88\x29\x52\x9e\xb1\xc7\x7f\x19\xdd\x8a\xfd\x0d\xe0\x9a\x1f\x30\x7d\xa2\xb9\xce\x72\xb9\xa3\x51\x1a\xf2\xcf\x76\xf6\xe0\xe4\x7b\x99\x21\x3f\xd6\x13\x76\x7d\x89\xca\xc2\x73\x08\x37\x31\x93\x12\x9f\x26\x24\x56\x42\xc2\x1c\xae\x0d\x67\x92\x95\x45\xe4\x8c\x49\x03\xde\x85\x72\xa6\xd9\x54\x48\x61\x45\xd0\xca\x4e\x74\x92\xf4\x94\x55\xf1\xdd\xf5\xe3\x1f\xbf\xdc\xdc\x5d\xfd\xf1\x70\x7d\xff\xdb\xcd\xe5\xb5\xbf\x56\xf1\x44\x56\xce\x9d\x10\xea\x3e\xe9\x4c\xca\x80\xc0\x03\xdc\xc9\x92\xbf\x2b\xb9\xbe\x47\xb4\x7f\x15\x12\xca\x93\xa2\xf3\xc8\x52\x06\x7b\xf9\xc0\x02\xa5\x42\xe5\xf6\xbc\x05\x63\x5c\x45\x50\x05\x69\x02\xab\xe3\xda\xf0\x40\xe2\xdc\xb7\x99\x78\x24\x6c\xea\x09\xa7\x93\x8f\x67\x85\x32\x4b\xe1\x16\x33\x75\xe8\x3e\x94\x3a\x9e\x8d\x8a\xb5\x3a\x2a\x04\xd6\xed\x76\xa8\x66\x62\x3e\x28\x66\x0e\x11\x57\xf6\x0c\x59\xf0\xb0\xcc\xdf\xd4\xd5\xa6\xc1\x1d\xa7\xd2\xd1\x91\xbc\x41\x55\xdb\x02\xa4\xdb\xef\xb6\x2e\xb9\x82\x19\xcb\x64\xbb\xba\x8b\x35\x09\xcc\x63\x51\x32\x63\xee\x4a\x7d\x0a\x38\x0d\xaa\xcb\x3b\x4e\xc2\x0a\xce\x64\x9b\x97\xc0\x58\x46\x76\x3b\xc7\x85\x7c\x62\xeb\xce\x71\x9e\x29\x9a\x42\xa0\x4a\x7c\x52\xa8\x32\xd8\x0c\x74\x38\xba\x09\xa2\x5d\xb1\x9b\xe6\x15\x4e\xf8\x30\xb1\x49\x78\xd7\x5b\x24\xd5\x31\xfd\x89\x18\x87\x49\x6b\xdf\x38\x19\xb5\x19\x50\xba\x8e\x2e\xd0\x47\x7a\x3a\x07\x98\xcd\x80\xdb\xe2\x96\xab\xec\x96\xbd\x91\x52\xf6\x95\x0a\x13\x18\x10\x4a\x18\x36\xbb\xa8\x94\x39\xcf\xb4\x41\xd3\x01\xa9\x47\x81\x52\xf0\x65\xe9\xd3\x8b\x24\x41\x65\x72\xec\x7b\xb4\xa8\xf7\xab\xd7\xcf\xc2\x6d\x20\x07\x21\xb0\x88\xba\x7d\x4d\x93\x6a\xbb\xbe\x12\xe4\x71\x77\xb4\x23\x5a\xf6\x59\x38\xdf\x5c\xc6\x04\xf6\x9b\x12\x96\xb7\x98\xb8\x69\x3e\xbc\xf7\xd7\x08\xcd\x0f\x04\xda\xbf\xe0\x01\x45\x65\xf6\xaa\xe9\x0b\x36\xcf\x55\xad\x14\x6e\x0f\xa3\xd0\x21\x8f\x57\xdf\x76\x5b\x70\x60\x2f\x51\x4f\x9e\xfd\xae\x3f\xf2\x8d\x54\x4f\xfb\xdc\x0b\xd1\x94\xf1\x21\xcb\xec\x02\x49\xfc\x99\xc7\xd4\x70\x79\x96\xa3\xdd\x77\x59\x54\x5e\x06\xdf\xa3\x3c\xf4\x9b\x8b\x1f\xe2\xb6\x68\x8a\x68\x8d\x25\xa6\xb5\x50\xf3\x6a\xf5\x83\x12\x82\x3b\xee\xe5\x8a\xf4\x7c\xde\xf2\xe8\xf6\x7e\x88\x32\xd9\x8a\xb9\xc6\xea\x98\x16\x9f\x08\x33\xdd\x45\x71\x5c\x77\x71\x03\x4e\x8d\xd2\xb5\xc5\x04\x2a\xd1\x28\xdc\x8e\xee\x4f\xbd\x9e\xcf\x24\x92\xce\xbb\xcd\xed\x97\x09\xeb\xb0\x02\x9a\x7a\xe6\x97\xc2\x74\xb6\xb5\x27\x66\xf9\xa2\x21\xc9\x67\xd1\xef\x6a\x16\x97\xba\x0f\x5f\xcc\x1c\x6c\x40\xed\xa3\xfa\x9b\xef\x14\x49\xbf\x08\x95\x38\x3c\x1e\x16\x50\x0d\x83\x78\xa6\x6e\x1e\xd1\x67\x16\xb3\xea\x32\xee\xad\xbf\x59\xfa\xe1\x23\x13\x25\xdc\xc3\xac\x65\xcd\x12\x78\xbd\x9e\xab\xdf\x14\xf7\xa5\xc0\x03\x94\x31\xd9\xf4\x9f\xc0\x6d\x4f\xa6\xd8\xf1\xbd\x4c\xb4\xeb\xd8\x69\xe7\x9d\x76\x07\xd6\x47\x65\x98\x6c\xa6\xfe\xec\x82\xfb\xe8\xe5\xe8\xdf\x01\x00\x00\xff\xff\x01\x81\x50\x2d\xb3\x27\x00\x00") - -func coredns119JsonBytes() ([]byte, error) { - return bindataRead( - _coredns119Json, - "coredns-1.19.json", - ) -} - -func coredns119Json() (*asset, error) { - bytes, err := coredns119JsonBytes() - if err != nil { - return nil, err - } - - info := bindataFileInfo{name: "coredns-1.19.json", size: 0, mode: os.FileMode(0), modTime: time.Unix(0, 0)} - a := &asset{bytes: bytes, info: info, digest: [32]uint8{0xf9, 0x8d, 0x3f, 0x60, 0xae, 0x0, 0x84, 0xaa, 0x11, 0xe6, 0x42, 0x56, 0xc5, 0xa9, 0x7d, 0xfb, 0xf, 0x61, 0x8, 0x58, 0x94, 0x36, 0xd4, 0x33, 0xff, 0x22, 0xac, 0x2a, 0x17, 0x78, 0x79, 0xfd}} - return a, nil -} - -var _coredns120Json = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\xec\x5a\x5f\x6f\x1b\x39\x0e\x7f\xcf\xa7\x18\x0c\xd0\xb7\xb5\x63\x37\x9b\x5e\x36\x6f\xd9\x24\xd7\x0d\xae\xc9\x19\x49\xba\x2f\xd7\xc5\x42\xd6\xd0\xb6\xce\x1a\x51\x47\x69\x9c\x78\x8b\x7c\xf7\x83\xe6\x8f\x3d\x7f\xa4\xb1\x9d\x4d\x17\x3d\xe0\xfc\xd0\x4e\x46\x24\x45\x91\x3f\x52\xa4\x34\x5f\x8f\xa2\x28\x66\x5a\xfc\x0a\x64\x04\xaa\xf8\x3c\x8a\x57\xe3\xf8\x07\xf7\x56\x58\x48\x4d\x7c\x1e\xfd\xeb\x28\x8a\xa2\xe8\x6b\xfe\x6f\x88\x38\x1f\x59\x0a\x95\xb8\x77\x0f\x40\x2b\xc1\x61\x3b\x90\x82\x65\x09\xb3\x2c\x3e\xdf\x88\x71\x82\x94\x42\xcb\xac\x40\x65\x1a\x03\x51\x14\x6b\xc2\x14\xec\x02\x32\x33\x14\x78\xac\x91\xac\x93\xfb\xd3\xf8\xf4\x64\x23\xd4\x43\x67\x38\x31\x0d\x8e\xd2\x52\x06\xf1\x86\xf0\x65\xcb\x13\x4b\x36\x05\xd9\x99\x0f\x96\x66\xc8\x52\xf6\x07\x2a\xf6\x64\x86\x1c\xd3\x63\x8e\xa9\x46\x05\x2a\x9f\x78\x99\x4d\x61\x90\x28\xd3\x9c\x7c\x79\x66\x06\x4c\xeb\x1e\x82\x6c\x0a\xa4\xc0\x42\xae\x1d\x97\x99\xb1\x40\x03\x53\x5a\xa7\x52\xb3\x87\x45\xb1\x34\xa7\xbb\x44\x82\xab\xbb\x07\xff\x8a\x2a\x22\x8f\x0e\xf9\x98\xd1\x8c\x6f\x09\xcc\xda\x58\x48\x2b\x49\x1b\x39\xb1\xd1\xc0\x9b\xee\x71\x56\xdf\xba\xbf\xf8\xd5\x8d\x56\x9b\xba\xbd\xf2\x92\x3b\x3e\x8f\x4e\x4f\xda\xef\x09\x2d\x72\x94\x8e\xed\xf3\xd5\xa4\xcd\x66\x19\xcd\xc1\x4e\x2a\xe6\xda\xe0\xcb\x0f\x7b\xe9\x31\xb0\x5c\xbf\x46\x97\xc7\xcb\x43\x74\xd9\x3c\xff\x56\x33\xb6\x01\x09\xdc\x22\xb5\xc1\xe5\xc3\x89\xd7\x93\x06\x8c\x0b\xab\x8b\xd9\x4c\x28\x61\xd7\x8e\xe1\x0e\x55\x1d\x21\xb1\x5d\x17\x00\xbf\x2c\xc0\x74\x33\xd9\x78\xf2\xa8\x26\xed\xf0\x58\xbd\xe0\x1c\x33\x65\x0f\x0c\xd9\x3f\x1d\x58\x1c\x09\xf6\x8a\xab\x5e\xe4\x77\xa5\xec\x06\xfe\x81\xe6\xea\x9a\xc2\xc5\xe4\x4c\xc8\x7c\x82\xe1\xf9\xe9\x49\xf4\xf5\x8b\x72\x03\x40\x84\x64\x8a\xe7\x05\x30\x69\x17\xc5\xf3\x36\xb2\xa3\x32\x13\x0c\x25\x72\x26\x23\xa1\x06\x2c\x49\x68\xc8\x48\xb3\x48\xe8\x0f\xc5\x43\x29\x2d\x8a\x34\x26\x26\x12\xca\x00\xcf\x08\xaa\x97\x33\x26\xa5\x5d\x10\x66\xf3\x85\x9f\xbf\x20\x7c\x29\xfe\xdb\x66\xc9\xe8\xdc\xe5\xd0\xe2\xed\x0c\xe9\x89\x51\x12\x0d\xa3\x63\xb0\xfc\x98\xc0\xa0\x5c\x0d\x39\xaa\x59\x31\xce\x19\x5f\x40\x74\x32\x2a\xfe\x92\x88\xba\x78\x22\x90\xc8\x92\xea\x2d\x4b\xa6\x4c\x32\xc5\xe1\x8b\x7a\xf9\xa2\xba\x79\xa5\xc2\xd9\x25\xaa\x99\x98\xdf\x32\xfd\x7f\x88\xd5\x20\xc6\xb4\x36\xc7\xbe\xb0\xbc\x02\x2d\x71\x9d\xc2\x77\x1c\x92\x6f\xb5\x6f\xbd\xc6\xb4\x7d\xdb\x16\xe1\x9c\xc0\x98\x2b\x60\x89\x14\x0a\x1e\x80\xa3\x4a\x9c\x15\x3e\x8c\x46\xb5\x39\x08\xb4\x14\x9c\xb9\x81\xf7\x8d\xd7\x2b\xe1\xbc\xf3\x8b\x30\x16\x69\xfd\x49\xa4\xc2\x99\x65\x3c\xda\x23\xd1\xa7\xcc\xf2\xc5\x27\x9f\xd1\x5f\x67\xf6\x5d\x40\xad\x6f\x44\x8d\x7d\xc4\x12\xb3\x30\x5f\xb7\xf5\x23\x94\x52\xa8\xf9\x67\x9d\x30\x0b\x5d\x0d\x53\xf6\xfc\x90\xd1\x3c\x37\xfa\xfb\xd3\x77\x6d\x55\x52\xf6\xfc\x59\xb1\x15\x13\x92\x4d\xf3\xb4\x37\x0e\xed\xce\x9b\x5d\xea\xbe\x31\xa1\x57\x57\x0b\xa9\x96\x5d\x75\xfc\x60\x8f\xfa\xcb\xc6\x1e\x3b\x67\x16\x06\x95\x56\xc0\xdf\xc7\x0d\xae\x97\xd6\x4a\xbd\x71\xd3\x23\x7c\x87\x13\x77\xbb\xb1\xee\xc8\xb6\x2d\x3b\x08\x2f\x8c\xb0\xad\x11\x3a\x4a\x2a\x4c\xe0\x22\x3c\x9e\x83\xfc\x3f\x99\x20\x48\xae\x32\x12\x6a\xfe\xc0\x17\x90\x64\xce\x51\x37\x73\x85\x9b\xd7\xd7\xcf\xc0\x33\x5b\x24\xaa\xae\x8c\x72\x9e\x87\x32\x14\x1e\x81\xd2\x76\xb1\xb8\xfd\xf9\xd8\xa3\x4d\xc4\x5c\x3f\x6b\x2a\x2a\x9f\xb0\x84\x3e\x29\xb9\xa4\x25\xac\x2b\xeb\x6e\xf3\x10\x76\x5d\xd1\x60\x42\x0d\xc4\x8a\x40\x8e\x6f\x54\x3f\xed\x8a\xc9\x0c\xfa\x15\xcc\xe9\xa4\x50\xd9\x73\xdc\x43\xf3\x5b\x70\xec\x25\xac\xc0\xe1\x6b\x67\xc4\x17\x7f\xfd\xea\x59\x9a\x7c\xf8\xb1\x57\x94\x23\xa2\xf4\xc3\x8f\xaf\x34\x51\x60\xc4\xcf\xe1\xa3\xee\x52\xb6\xa9\x3a\x6e\x88\x35\x26\x17\xca\x8a\xfe\xa0\xd2\x04\x33\xa0\x43\xa2\xca\x67\x4b\xbf\xa3\x73\x0d\xca\xd9\x5d\xa8\x05\x42\x32\xda\x64\xaf\x07\xff\x16\xd5\x22\x3d\x28\xfc\xfa\x41\x58\x83\x61\x99\xeb\x76\x80\xe0\x00\xf4\xed\x8f\xbf\x28\x94\x5f\xdb\xbf\x30\xc2\xc2\x18\x0b\x73\x05\x03\x37\xb6\xa8\x51\xe2\x7c\xfd\x0f\x5f\x88\x2e\xd0\xd8\xbc\x0a\xf2\x83\xd7\x2f\x34\x7e\x02\x31\x5f\x14\x35\xc9\xc8\x43\xd1\xd5\xbe\xad\xf5\x4b\xef\xe6\xc7\x51\x59\x26\x14\x90\xcf\xda\x1e\xd8\x33\x9a\x87\xfc\x12\x0f\x5c\x37\xe1\x75\x6d\x9c\xf7\x1c\xe5\x7e\x79\xbc\xe9\xa5\xba\xba\x77\x99\x63\x91\xb2\xa2\x48\x79\x67\x86\xc9\x92\x86\xc0\x69\xf8\xce\x0c\xdf\x99\x63\x58\x9a\x4a\xe6\xf9\x6a\x3c\x3c\x1b\x9e\x0c\x60\x69\xa6\x99\x90\xc9\x70\xec\xd1\xa3\x10\x35\xc9\xa4\x9c\xa0\x14\x3c\x77\xd1\xcd\xec\x0e\xed\x84\xc0\xd4\x6b\xef\x1a\x8b\x14\x2b\x50\x60\xcc\x84\x70\xda\x2d\xa2\x4a\xa2\x19\x13\x32\x23\x78\x5c\x10\x98\x05\x4a\x57\xd2\x9f\x7a\xcd\xb0\xb0\x56\x7f\x04\x1b\x0c\xd3\x58\x33\xbb\x70\x6a\x1d\x17\xbd\x64\x20\x4e\xaa\x23\x8e\xb3\xd1\xd9\x28\x40\x61\xf8\x02\x8a\x82\xfb\x97\xc7\xc7\x89\x0f\x72\x5e\xc0\xc5\x2e\xe7\x08\x26\xaf\x40\xb2\x75\xbd\x96\xf6\x12\x6b\x20\x81\xc9\x96\x6c\xec\x27\x33\x19\xe7\x60\x4c\xdd\x3c\x63\x2f\xa1\x15\x29\x60\x66\xb7\x02\x4f\xbb\xd9\xdb\xe3\xa3\x70\x6b\xb1\xd5\xd4\x73\xba\x55\xfd\x02\xae\xd8\x44\xc6\xc4\x7f\x9e\xd4\x99\xde\x3f\x75\xe4\x3b\x06\xdb\xd7\x1d\x6f\xa8\x9a\xe7\xa4\xcc\xab\xde\xe3\xe5\x9b\xab\xf7\xd3\x78\xa7\x82\x29\x58\x12\x7c\x2f\xfb\x85\x14\xdc\x2b\x99\x10\xb0\x44\xbc\x26\x9e\xbd\x0b\xf8\x1f\x88\xe7\x6f\x1e\xa2\xe3\xbd\x42\x94\xc0\x60\x46\x1c\x7c\x6d\x56\x54\xe4\xd9\x54\xd8\xd0\x68\xde\x20\xa6\x48\x79\xc6\x1e\xff\x6d\x74\x2b\xf6\x37\x80\x6b\x7e\xc0\xf4\x89\xe6\x3a\xcb\xe5\x8e\x46\x69\xc8\x3f\xdb\xd9\x83\x93\xef\x65\x86\xfc\x58\x4f\xd8\xf5\x25\x2a\x0b\xcf\x21\xdc\xc4\x4c\x4a\x7c\x9a\x90\x58\x09\x09\x73\xb8\x36\x9c\x49\x56\x16\x91\x33\x26\x0d\x78\x17\xca\x99\x66\x53\x21\x85\x15\x41\x2b\x3b\xd1\x49\xd2\x53\x56\xc5\x77\xd7\x8f\xbf\xff\x7c\x73\x77\xf5\xfb\xc3\xf5\xfd\xaf\x37\x97\xd7\xfe\x5a\xc5\x13\x59\x39\x77\x42\xa8\xfb\xa4\x33\x29\x03\x02\x0f\x70\x27\x4b\xfe\xa9\xe4\xfa\x1e\xd1\xfe\x5d\x48\x28\x4f\x8a\xce\x23\x4b\x19\xec\xe5\x03\x0b\x94\x0a\x95\xdb\xf3\x16\x8c\x71\x15\x41\x15\xa4\x09\xac\x8e\x6b\xc3\x03\x89\x73\xdf\x66\xe2\x91\xb0\xa9\x27\x9c\x4e\x3e\x9e\x15\xca\x2c\x85\x5b\xcc\xd4\xa1\xfb\x50\xea\x78\x36\x2a\xd6\xea\xa8\x10\x58\xb7\xdb\xa1\x9a\x89\xf9\xa0\x98\x39\x44\x5c\xd9\x33\x64\xc1\xc3\x32\x7f\x53\x57\x9b\x06\x77\x9c\x4a\x47\x47\xf2\x06\x55\x6d\x0b\x90\x6e\xbf\xdb\xba\xe4\x0a\x66\x2c\x93\xed\xea\x2e\xd6\x24\x30\x8f\x45\xc9\x8c\xb9\x2b\xf5\x29\xe0\x34\xa8\x2e\xef\x38\x09\x2b\x38\x93\x6d\x5e\x02\x63\x19\xd9\xed\x1c\x17\xf2\x89\xad\x3b\xc7\x79\xa6\x68\x0a\x81\x2a\xf1\x49\xa1\xca\x60\x33\xd0\xe1\xe8\x26\x88\x76\xc5\x6e\x9a\x57\x38\xe1\xc3\xc4\x26\xe1\x5d\x6f\x91\x54\xc7\xf4\x47\x62\x1c\x26\xad\x7d\xe3\x64\xd4\x66\x40\xe9\x3a\xba\x40\x1f\xe9\xe9\x1c\x60\x36\x03\x6e\x8b\x5b\xae\xb2\x5b\xf6\x46\x4a\xd9\x57\x2a\x4c\x60\x40\x28\x61\xd8\xec\xa2\x52\xe6\x3c\xd3\x06\x4d\x07\xa4\x1e\x05\x4a\xc1\x97\xa5\x4f\x2f\x92\x04\x95\xc9\xb1\xef\xd1\xa2\xde\xaf\x5e\x3f\x0b\xb7\x81\x1c\x84\xc0\x22\xea\xf6\x35\x4d\xaa\xed\xfa\x4a\x90\xc7\xdd\xd1\x8e\x68\xd9\x67\xe1\x7c\x73\x19\x13\xd8\x6f\x4a\x58\xde\x62\xe2\xa6\xf9\xf1\xbd\xbf\x46\x68\x7e\x20\xd0\xfe\x05\x0f\x28\x2a\xb3\x57\x4d\x5f\xb0\x79\xae\x6a\xa5\x70\x7b\x18\x85\x0e\x79\xbc\xfa\xb6\xdb\x82\x03\x7b\x89\x7a\xf2\xec\x77\xfd\x91\x6f\xa4\x7a\xda\xe7\x5e\x88\xa6\x8c\x0f\x59\x66\x17\x48\xe2\x8f\x3c\xa6\x86\xcb\xb3\x1c\xed\xbe\xcb\xa2\xf2\x32\xf8\x1e\xe5\xa1\xdf\x5c\x7c\x17\xb7\x45\x53\x44\x6b\x2c\x31\xad\x85\x9a\x57\xab\x1f\x94\x10\xdc\x71\x2f\x57\xa4\xe7\xf3\x96\x47\xb7\xf7\x43\x94\xc9\x56\xcc\x35\x56\xc7\xb4\xf8\x48\x98\xe9\x2e\x8a\xe3\xba\x8b\x1b\x70\x6a\x94\xae\x2d\x26\x50\x89\x46\xe1\x76\x74\x7f\xea\xf5\x7c\x26\x91\x74\xde\x6d\x6e\xbf\x4c\x58\x87\x15\xd0\xd4\x33\xbf\x14\xa6\xb3\xad\x3d\x31\xcb\x17\x0d\x49\x3e\x8b\x7e\x53\xb3\xb8\xd4\x7d\xf8\x62\xe6\x60\xdf\x4c\xed\x44\x18\x8e\x2b\xa0\x75\x19\x47\x7f\xce\xbb\x52\xfc\x15\xce\x39\xaa\xbf\xf9\x46\xf9\xe2\x67\xa1\x12\x17\x75\x87\xa5\x8d\x86\xbd\x3c\x53\x37\x2f\x22\x32\x8b\x59\x75\xe5\xf8\xd6\x5f\x66\x7d\xf7\xf9\x07\x25\xdc\xc3\xac\x65\xcd\x12\xa7\xbd\x9e\xab\xdf\x87\xf7\x25\xfa\x03\x94\x31\xd9\xf4\xdf\xc0\x6d\x4f\x3e\xdc\xf1\x55\x50\xb4\xeb\x70\x6d\xe7\xcd\x7d\x07\xd6\x47\x65\xf0\x6c\xa6\xfe\xe4\xa2\xe4\xe8\xe5\xe8\xbf\x01\x00\x00\xff\xff\xfb\xb7\x82\x44\x99\x28\x00\x00") - -func coredns120JsonBytes() ([]byte, error) { - return bindataRead( - _coredns120Json, - "coredns-1.20.json", - ) -} - -func coredns120Json() (*asset, error) { - bytes, err := coredns120JsonBytes() - if err != nil { - return nil, err - } - - info := bindataFileInfo{name: "coredns-1.20.json", size: 0, mode: os.FileMode(0), modTime: time.Unix(0, 0)} - a := &asset{bytes: bytes, info: info, digest: [32]uint8{0xae, 0x95, 0x2e, 0x4e, 0x5, 0x56, 0xf8, 0xe4, 0x8, 0xf6, 0xc3, 0xef, 0x2e, 0x9, 0x61, 0xda, 0x19, 0x9e, 0xb8, 0x55, 0xa9, 0xf2, 0x89, 0xb8, 0x37, 0x66, 0x78, 0x3, 0x9d, 0x4, 0xc4, 0xfc}} - return a, nil -} - -var _coredns121Json = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\xec\x5a\xdf\x6f\x1b\x39\xee\x7f\xcf\x5f\x31\x18\xa0\x6f\xb5\x63\x37\x49\xbf\xd9\xbc\x65\x93\x6c\x37\xf8\x36\x39\x23\x4e\xf7\xe5\xba\x58\xc8\x1a\xda\xd6\x59\x23\xea\x28\x8d\x13\x6f\x91\xff\xfd\x30\xbf\x3c\xbf\xa4\xb1\x9d\x4d\x17\x3d\xe0\xfc\xd0\x3a\x12\x49\x51\xe4\x87\x14\x29\xf9\xdb\x51\x10\x84\x4c\x8b\xdf\x80\x8c\x40\x15\x5e\x04\xe1\x7a\x1c\xbe\x4f\x47\x85\x85\xd8\x84\x17\xc1\x3f\x8f\x82\x20\x08\xbe\x65\xff\xfa\x88\xb3\x99\x95\x50\x51\x3a\x36\x05\x5a\x0b\x0e\xd5\x44\x0c\x96\x45\xcc\xb2\xf0\x62\x2b\x26\x15\xa4\x14\x5a\x66\x05\x2a\xd3\x98\x08\x82\x50\x13\xc6\x60\x97\x90\x98\xa1\xc0\x63\x8d\x64\x53\xb9\x3f\x8d\xcf\x4e\xb6\x42\x1d\x74\x86\x13\xd3\x90\x52\x5a\x4a\x20\xdc\x12\xbe\x54\x3c\xa1\x64\x33\x90\x9d\xf5\x60\x65\x86\x2c\x66\x7f\xa2\x62\x4f\x66\xc8\x31\x3e\xe6\x18\x6b\x54\xa0\xb2\x85\x57\xc9\x0c\x06\x91\x32\xcd\xc5\x57\xe7\x66\xc0\xb4\xee\x21\x48\x66\x40\x0a\x2c\x64\xda\x71\x99\x18\x0b\x34\x30\x85\x75\x4a\x35\x7b\x58\x14\x8b\x33\xba\x2b\x24\xb8\xbe\x9f\xba\x77\x54\x12\x39\x74\xc8\xe6\x8c\x66\xbc\x22\x30\x1b\x63\x21\x2e\x25\x6d\xe5\x84\x46\x03\x6f\xba\x47\xe8\x5f\x58\x2c\xa4\x80\x0a\x03\xc5\xcc\xed\x64\x7d\x5a\xe9\xf2\xfb\xfb\x0e\xcf\x66\x82\x52\xf0\x4d\x86\x05\xa1\x16\x12\xa6\x96\xf1\x55\x5d\xb1\xd4\xa5\x6d\xb9\x75\x8f\xd4\xf6\xd5\x36\x6b\xc1\x1d\x5e\x04\x67\x27\xed\x71\x42\x8b\x1c\x65\xca\xf6\xe5\x7a\xd2\x66\xb3\x8c\x16\x60\x27\x25\x73\x6d\xf2\xe5\xfd\x5e\x7a\x0c\x2c\xd7\xaf\xd1\xe5\xf1\xea\x10\x5d\x9c\x96\x35\x20\x81\x5b\xa4\x36\x72\x5d\x20\x74\xc2\xc4\x80\x49\x63\xf6\x72\x3e\x17\x4a\xd8\xcc\x37\xf7\xa8\xea\xf0\x0b\xed\x26\x8f\x9e\xab\x1c\xa9\xb7\x93\x2d\x4c\x8e\x6a\xd2\x0e\x4f\x04\x97\x9c\x63\xa2\xec\x81\xf9\xe0\x2f\x47\x2d\x47\x82\xbd\x82\xb6\x37\xac\xba\x52\x76\x47\xd5\x81\xe6\xea\x9a\x22\x0d\xf8\xb9\x90\xd9\x02\xc3\x8b\xb3\x93\xe0\xdb\x57\x95\x4e\x00\x11\x92\xc9\xbf\x2f\x81\x49\xbb\xcc\xbf\x57\x69\x23\x28\xd2\xcc\x50\x22\x67\x32\x10\x6a\xc0\xa2\x88\x86\x8c\x34\x0b\x84\xfe\x98\x7f\x29\xa4\x05\x81\xc6\xc8\x04\x42\x19\xe0\x09\x41\x39\x38\x67\x52\xda\x25\x61\xb2\x58\xba\xf9\x73\xc2\x97\xfc\xbf\x2a\x05\x07\x17\x69\x82\xce\x47\xe7\x48\x4f\x8c\xa2\x60\x18\x1c\x83\xe5\xc7\x04\x06\xe5\x7a\xc8\x51\xcd\xf3\x79\xce\xf8\x12\x82\x93\x51\xfe\x97\x44\xd4\xf9\x37\x02\x89\x2c\x2a\x47\x59\x34\x63\x92\x29\x0e\x5f\xd5\xcb\x57\xd5\x4d\x5a\x25\xce\xae\x50\xcd\xc5\xe2\x8e\xe9\xff\x41\xac\x06\x31\xa6\xb5\x39\x76\x85\xe5\x35\x68\x89\x9b\x18\x7e\xe0\x90\x7c\xab\x43\xf1\x35\xa6\xed\x39\x13\x35\xe1\x82\xc0\x98\x6b\x60\x91\x14\x0a\xa6\xc0\x51\x45\xa9\x15\x3e\x8e\x46\xb5\x35\x08\xb4\x14\x9c\xa5\x13\x1f\x1a\xc3\x6b\x91\x7a\xe7\x57\x61\x2c\xd2\xe6\xb3\x88\x45\x6a\x96\xf1\x68\x8f\x44\x1f\x33\xcb\x97\x9f\x5d\x46\x7f\x9d\xd9\x77\x01\xb5\x7e\x10\x35\xce\x11\x4b\xcc\xc2\x62\xd3\xd6\x8f\x50\x4a\xa1\x16\x5f\x74\xc4\x2c\x74\x35\x8c\xd9\xf3\x34\xa1\x45\x66\xf4\x0f\x67\xef\xda\xaa\xc4\xec\xf9\x8b\x62\x6b\x26\x24\x9b\x65\x69\x6f\xec\x3b\x9d\xb7\xa7\xd4\x43\x63\x41\xa7\xae\x16\x62\x2d\xbb\xea\xb8\xc1\x1e\xf4\xd7\xa4\x3d\x76\x4e\x2c\x0c\x4a\xad\x80\x7f\x08\x1b\x5c\x2f\xad\x9d\x3a\xe3\xa6\x47\xf8\x0e\x27\xee\x76\x63\xdd\x91\x6d\x5b\x76\x10\x9e\x1b\xa1\xaa\x11\x3a\x4a\x2a\x8c\xe0\xd2\x3f\x9f\x81\xfc\xdf\x89\x20\x88\xae\x13\x12\x6a\x31\xe5\x4b\x88\x92\xd4\x51\xb7\x0b\x85\xdb\xe1\x9b\x67\xe0\x89\xcd\x13\x55\x57\x46\xb1\xce\xb4\x08\x85\x47\xa0\xb8\x5d\x2c\x56\x1f\x17\x7b\xb0\x8d\x98\x9b\x67\x4d\x79\xe5\xe3\x97\xd0\x27\x25\x93\xb4\x82\x4d\x69\xdd\x2a\x0f\x61\xd7\x15\x0d\x26\xd4\x40\x2c\x0f\xe4\xf0\x56\xf5\xd3\xae\x99\x4c\x3a\x75\xb6\x83\x4e\x0a\x95\x3c\x87\x3d\x34\xbf\x7b\xe7\x5e\xfc\x0a\x1c\xbe\x77\x46\x7c\xf9\xf7\xef\x9e\xc5\xd1\xc7\xd3\x5e\x51\x29\x11\xc5\x1f\x4f\x5f\x69\x22\xcf\x8c\x9b\xc3\x45\xdd\xa5\x6c\x53\x75\xdc\x10\x6a\x8c\x2e\x95\x15\xfd\x41\xa5\x09\xe6\x40\x87\x44\x95\xcb\x96\x6e\x47\x67\x1a\x14\xab\xa7\xa1\xe6\x09\xc9\x60\x9b\xbd\xa6\xee\x23\xaa\x45\x7a\x50\xf8\xf5\x83\xb0\x06\xc3\x22\xd7\xed\x00\xc1\x01\xe8\xdb\x1f\x7f\x81\x2f\xbf\xb6\x3f\x7e\x84\xf9\x31\xe6\xe7\xf2\x06\x6e\x68\x51\xa3\xc4\xc5\xe6\xff\x5d\x21\xba\x44\x63\xb3\x2a\xc8\x0d\x5e\xb7\xd0\xf0\x09\xc4\x62\x99\xd7\x24\x23\x07\x45\x57\xfb\xb6\xd6\x2f\xbd\x87\x1f\x47\x65\x99\x50\x40\x2e\x6b\x3b\x60\xcf\x68\xe1\xf3\x4b\x38\x48\xbb\x09\xa7\x6b\xc3\xac\xe7\x28\xce\xcb\xe3\x6d\x2f\xd5\xd5\xbd\xcb\x1c\x8a\x98\xe5\x45\xca\x3b\x33\x8c\x56\x34\x04\x4e\xc3\x77\x66\xf8\xce\x1c\xc3\xca\x94\x32\x2f\xd6\xe3\xe1\xf9\xf0\x74\x00\x2b\x33\x4b\x84\x8c\x86\x63\x87\x1e\xb9\xa8\x49\x22\x65\x75\x1b\x72\x3b\xbf\x47\x3b\x21\x30\xf5\xda\xbb\xc6\x22\xc5\x1a\x14\x18\x33\x21\x9c\x75\x8b\xa8\x82\x68\xce\x84\x4c\x08\x1e\x97\x04\x66\x89\x32\x2d\xe9\xcf\x9c\x66\x58\x5a\xab\x3f\x81\xf5\x86\x69\xa8\x99\x5d\xa6\x6a\x1d\xe7\xbd\xa4\x27\x4e\xca\x2b\x8e\xf3\xd1\xf9\xc8\x43\x61\xf8\x12\xf2\x82\xfb\xd7\xc7\xc7\x89\x0b\x72\x4e\xc0\x85\x69\xce\x11\x4c\x5e\x83\x64\x9b\x7a\x2d\xed\x24\xd6\x40\x02\xa3\x8a\x6c\xec\x26\x33\x09\xe7\x60\x4c\xdd\x3c\x63\x27\xa1\x15\x31\x60\x62\x2b\x81\x67\xdd\xec\xed\xf0\x91\xbf\xb5\xa8\x34\x75\xdc\x6e\x95\x1f\x8f\x2b\xb6\x91\x31\x71\xdf\x27\x75\x96\x77\x2f\x1d\xb8\xae\xc1\xf6\x75\xc7\x1b\xaa\xe6\xb8\x29\x73\xaa\xf7\x78\xf5\xe6\xea\xfd\x34\xde\xa9\x60\x0c\x96\x04\xdf\xcb\x7e\x3e\x05\xf7\x4a\x26\x04\x2c\x12\xaf\x89\x67\xe7\x06\xfe\x0b\xe2\xf9\xbb\x87\xe8\x78\xaf\x10\x25\x30\x98\x10\x07\x57\x9b\x15\xe4\x79\x36\x16\xd6\x37\x9b\x35\x88\x31\x52\x96\xb1\xc7\xff\x37\xba\x13\xfb\x1b\x20\x6d\x7e\xc0\xf4\x89\xe6\x3a\xc9\xe4\x8e\x46\xb1\xcf\x3f\xd5\xea\xde\xc5\xf7\x32\x43\x76\xad\x27\xec\xe6\x0a\x95\x85\x67\x1f\x6e\x42\x26\x25\x3e\x4d\x48\xac\x85\x84\x05\xdc\x18\xce\x24\x2b\x8a\xc8\x39\x93\x06\x9c\x1b\xe5\x4c\xb3\x99\x90\xc2\x0a\xaf\x95\x53\xd1\x51\xd4\x53\x56\x85\xf7\x37\x8f\x7f\xfc\x7c\x7b\x7f\xfd\xc7\xf4\xe6\xe1\xb7\xdb\xab\x1b\x77\xad\xe2\x88\xac\x8c\x3b\x22\xd4\x7d\xd2\x99\x94\x1e\x81\x07\xb8\x93\x45\xff\x50\x72\xf3\x80\x68\x7f\x11\x12\x8a\x9b\xa2\x8b\xc0\x52\x02\x7b\xf9\xc0\x02\xc5\x42\x65\xf6\xbc\x03\x63\xd2\x8a\xa0\x0c\xd2\x08\xd6\xc7\xb5\xe9\x81\xc4\x85\xeb\x30\x71\x48\xd8\xd6\x13\xa9\x4e\x2e\x9e\x35\xca\x24\x86\x3b\x4c\xd4\xa1\xe7\x50\x9c\xf2\x6c\x55\xac\xd5\x51\x3e\xb0\x56\xc7\xa1\x9a\x8b\xc5\x20\x5f\xd9\x47\x5c\xda\xd3\x67\xc1\xc3\x32\x7f\x53\x57\x1b\x7b\x4f\x9c\x52\xc7\x94\xe4\x0d\xaa\xda\x16\x20\xd3\xf3\xae\x72\xc9\x35\xcc\x59\x22\xdb\xd5\x5d\xa8\x49\x60\x16\x8b\x92\x19\x73\x5f\xe8\x93\xc3\x69\x50\xbe\x0c\x72\x12\x56\x70\x26\xdb\xbc\x04\xc6\x32\xb2\xd5\x1a\x97\xf2\x89\x6d\x3a\xd7\x79\x26\x6f\x0a\x81\x4a\xf1\x51\xae\xca\x60\x3b\xd1\xe1\xe8\x26\x88\x76\xc5\x6e\x9a\x4f\x38\xfe\xcb\xc4\x26\xe1\x7d\x6f\x91\x54\xc7\xf4\x27\x62\x1c\x26\xad\x73\xe3\x64\xd4\x66\x40\x99\x76\x74\x9e\x3e\xd2\xd1\x39\xc0\x7c\x0e\xdc\xe6\xaf\x5c\x45\xb7\xec\x8c\x94\xa2\xaf\x54\x18\xc1\x80\x50\xc2\xb0\xd9\x45\xc5\x2c\xf5\x4c\x1b\x34\x1d\x90\x3a\x14\x28\x04\x5f\x15\x3e\xbd\x8c\x22\x54\x26\xc3\xbe\x43\x8b\x7a\xbf\x7a\xf3\x2c\xd2\x03\xe4\x20\x04\xe6\x51\xb7\xaf\x69\x62\x6d\x37\xd7\x82\x1c\xee\x0e\x76\x44\xcb\x3e\x1b\xe7\xdb\xc7\x18\xcf\x79\x53\xc0\xf2\x0e\xa3\x74\x99\xd3\x0f\xee\x1a\xa1\xf9\xeb\x83\xf6\xc7\x7b\x41\x51\x9a\xbd\x6c\xfa\xbc\xcd\x73\x59\x2b\xf9\xdb\xc3\xc0\x77\xc9\xe3\xd4\xb7\xdd\x16\x1c\xd8\x4b\xd4\x93\x67\xbf\xeb\x8f\x5c\x33\xe5\xb7\x7d\xde\x85\x68\xc6\xf8\x90\x25\x76\x89\x24\xfe\xcc\x62\x6a\xb8\x3a\xcf\xd0\xee\x7a\x2c\x2a\x1e\x83\x1f\x50\x1e\xfa\x83\x8e\x1f\xe2\xb5\x68\x86\x68\x8d\x25\xa6\xb5\x50\x8b\x72\xf7\x83\x02\x82\x3b\xde\xe5\xf2\xf4\x7c\xd1\xf2\x68\xf5\x3e\x44\x89\x6c\xc5\x5c\x63\x77\x4c\x8b\x4f\x84\x89\xee\xa2\x38\xac\xbb\xb8\x01\xa7\x46\xe9\xda\x62\x02\x15\x69\x14\xe9\x89\xee\x4e\xbd\x8e\x9f\x49\x44\x9d\xb1\xed\xeb\x97\xf1\xeb\xb0\x06\x9a\x39\xd6\x97\xc2\x74\x8e\xb5\x27\x66\xf9\xb2\x21\xc9\x65\xd1\xef\x6a\x96\x34\x75\x1f\xbe\x99\x05\xd8\x37\x53\x3b\x12\x86\xe3\x1a\x68\x53\xc4\xd1\x5f\xf3\xae\x14\x7f\x87\x73\x8e\xea\x23\xdf\x29\x5f\xfc\x2c\x54\x94\x46\xdd\x61\x69\xa3\x61\x2f\xc7\xd2\xcd\x87\x88\xc4\x62\x52\x3e\x39\xbe\xf5\xcf\xbe\x7e\xf8\xfc\x83\x12\x1e\x60\xde\xb2\x66\x81\xd3\x5e\xcf\xd5\xdf\xc3\xfb\x12\xfd\x01\xca\x98\x64\xf6\x2f\xe0\xb6\x27\x1f\xee\xf8\x55\x50\xb0\xeb\x72\x6d\xe7\xcb\x7d\x07\xd6\x47\x45\xf0\x6c\x97\xfe\x9c\x46\xc9\xd1\xcb\xd1\x7f\x02\x00\x00\xff\xff\xba\x18\xe8\xd1\xf6\x28\x00\x00") - -func coredns121JsonBytes() ([]byte, error) { - return bindataRead( - _coredns121Json, - "coredns-1.21.json", - ) -} - -func coredns121Json() (*asset, error) { - bytes, err := coredns121JsonBytes() - if err != nil { - return nil, err - } - - info := bindataFileInfo{name: "coredns-1.21.json", size: 0, mode: os.FileMode(0), modTime: time.Unix(0, 0)} - a := &asset{bytes: bytes, info: info, digest: [32]uint8{0x17, 0x85, 0x5c, 0xa4, 0xad, 0xa7, 0x1, 0xa9, 0xb8, 0x6b, 0x7c, 0xa2, 0x47, 0xd7, 0x3d, 0x4, 0x21, 0xb, 0x38, 0xff, 0xc1, 0x25, 0x43, 0x9d, 0x68, 0xa9, 0x44, 0x23, 0x8f, 0xcc, 0x66, 0xf0}} - return a, nil -} - -// Asset loads and returns the asset for the given name. -// It returns an error if the asset could not be found or -// could not be loaded. -func Asset(name string) ([]byte, error) { - canonicalName := strings.Replace(name, "\\", "/", -1) - if f, ok := _bindata[canonicalName]; ok { - a, err := f() - if err != nil { - return nil, fmt.Errorf("Asset %s can't read by error: %v", name, err) - } - return a.bytes, nil - } - return nil, fmt.Errorf("Asset %s not found", name) -} - -// AssetString returns the asset contents as a string (instead of a []byte). -func AssetString(name string) (string, error) { - data, err := Asset(name) - return string(data), err -} - -// MustAsset is like Asset but panics when Asset would return an error. -// It simplifies safe initialization of global variables. -func MustAsset(name string) []byte { - a, err := Asset(name) - if err != nil { - panic("asset: Asset(" + name + "): " + err.Error()) - } - - return a -} - -// MustAssetString is like AssetString but panics when Asset would return an -// error. It simplifies safe initialization of global variables. -func MustAssetString(name string) string { - return string(MustAsset(name)) -} - -// AssetInfo loads and returns the asset info for the given name. -// It returns an error if the asset could not be found or -// could not be loaded. -func AssetInfo(name string) (os.FileInfo, error) { - canonicalName := strings.Replace(name, "\\", "/", -1) - if f, ok := _bindata[canonicalName]; ok { - a, err := f() - if err != nil { - return nil, fmt.Errorf("AssetInfo %s can't read by error: %v", name, err) - } - return a.info, nil - } - return nil, fmt.Errorf("AssetInfo %s not found", name) -} - -// AssetDigest returns the digest of the file with the given name. It returns an -// error if the asset could not be found or the digest could not be loaded. -func AssetDigest(name string) ([sha256.Size]byte, error) { - canonicalName := strings.Replace(name, "\\", "/", -1) - if f, ok := _bindata[canonicalName]; ok { - a, err := f() - if err != nil { - return [sha256.Size]byte{}, fmt.Errorf("AssetDigest %s can't read by error: %v", name, err) - } - return a.digest, nil - } - return [sha256.Size]byte{}, fmt.Errorf("AssetDigest %s not found", name) -} - -// Digests returns a map of all known files and their checksums. -func Digests() (map[string][sha256.Size]byte, error) { - mp := make(map[string][sha256.Size]byte, len(_bindata)) - for name := range _bindata { - a, err := _bindata[name]() - if err != nil { - return nil, err - } - mp[name] = a.digest - } - return mp, nil -} - -// AssetNames returns the names of the assets. -func AssetNames() []string { - names := make([]string, 0, len(_bindata)) - for name := range _bindata { - names = append(names, name) - } - return names -} - -// _bindata is a table, holding each asset generator, mapped to its name. -var _bindata = map[string]func() (*asset, error){ - "aws-node.yaml": awsNodeYaml, - "coredns-1.17.json": coredns117Json, - "coredns-1.18.json": coredns118Json, - "coredns-1.19.json": coredns119Json, - "coredns-1.20.json": coredns120Json, - "coredns-1.21.json": coredns121Json, -} - -// AssetDebug is true if the assets were built with the debug flag enabled. -const AssetDebug = false - -// AssetDir returns the file names below a certain -// directory embedded in the file by go-bindata. -// For example if you run go-bindata on data/... and data contains the -// following hierarchy: -// data/ -// foo.txt -// img/ -// a.png -// b.png -// then AssetDir("data") would return []string{"foo.txt", "img"}, -// AssetDir("data/img") would return []string{"a.png", "b.png"}, -// AssetDir("foo.txt") and AssetDir("notexist") would return an error, and -// AssetDir("") will return []string{"data"}. -func AssetDir(name string) ([]string, error) { - node := _bintree - if len(name) != 0 { - canonicalName := strings.Replace(name, "\\", "/", -1) - pathList := strings.Split(canonicalName, "/") - for _, p := range pathList { - node = node.Children[p] - if node == nil { - return nil, fmt.Errorf("Asset %s not found", name) - } - } - } - if node.Func != nil { - return nil, fmt.Errorf("Asset %s not found", name) - } - rv := make([]string, 0, len(node.Children)) - for childName := range node.Children { - rv = append(rv, childName) - } - return rv, nil -} - -type bintree struct { - Func func() (*asset, error) - Children map[string]*bintree -} - -var _bintree = &bintree{nil, map[string]*bintree{ - "aws-node.yaml": {awsNodeYaml, map[string]*bintree{}}, - "coredns-1.17.json": {coredns117Json, map[string]*bintree{}}, - "coredns-1.18.json": {coredns118Json, map[string]*bintree{}}, - "coredns-1.19.json": {coredns119Json, map[string]*bintree{}}, - "coredns-1.20.json": {coredns120Json, map[string]*bintree{}}, - "coredns-1.21.json": {coredns121Json, map[string]*bintree{}}, -}} - -// RestoreAsset restores an asset under the given directory. -func RestoreAsset(dir, name string) error { - data, err := Asset(name) - if err != nil { - return err - } - info, err := AssetInfo(name) - if err != nil { - return err - } - err = os.MkdirAll(_filePath(dir, filepath.Dir(name)), os.FileMode(0755)) - if err != nil { - return err - } - err = ioutil.WriteFile(_filePath(dir, name), data, info.Mode()) - if err != nil { - return err - } - return os.Chtimes(_filePath(dir, name), info.ModTime(), info.ModTime()) -} - -// RestoreAssets restores an asset under the given directory recursively. -func RestoreAssets(dir, name string) error { - children, err := AssetDir(name) - // File - if err != nil { - return RestoreAsset(dir, name) - } - // Dir - for _, child := range children { - err = RestoreAssets(dir, filepath.Join(name, child)) - if err != nil { - return err - } - } - return nil -} - -func _filePath(dir, name string) string { - canonicalName := strings.Replace(name, "\\", "/", -1) - return filepath.Join(append([]string{dir}, strings.Split(canonicalName, "/")...)...) -} diff --git a/pkg/addons/default/assets_test.go b/pkg/addons/default/assets_test.go index 2f36dffafa..c3dcbb4cc9 100644 --- a/pkg/addons/default/assets_test.go +++ b/pkg/addons/default/assets_test.go @@ -1,8 +1,6 @@ package defaultaddons import ( - "bytes" - "compress/gzip" "strings" ) @@ -10,7 +8,7 @@ func init() { // we must patch the manifest until we can use fake // clientset that supports CRDs - awsNode := string(MustAsset("aws-node.yaml")) + awsNode := string(awsNodeYaml) awsNodeParts := strings.Split(awsNode, "---\n") nonCRDs := []string{} @@ -23,16 +21,5 @@ func init() { awsNode = strings.Join(nonCRDs, "---\n") - var buf bytes.Buffer - zw := gzip.NewWriter(&buf) - - if _, err := zw.Write([]byte(awsNode)); err != nil { - panic(err) - } - - if err := zw.Close(); err != nil { - panic(err) - } - - _awsNodeYaml = buf.Bytes() + awsNodeYaml = []byte(awsNode) } diff --git a/pkg/addons/default/aws_node.go b/pkg/addons/default/aws_node.go index 835034e026..87784f41ce 100644 --- a/pkg/addons/default/aws_node.go +++ b/pkg/addons/default/aws_node.go @@ -14,6 +14,9 @@ import ( "github.com/weaveworks/eksctl/pkg/addons" "github.com/weaveworks/eksctl/pkg/kubernetes" + + // For go:embed + _ "embed" ) const ( @@ -24,6 +27,9 @@ const ( awsNodeInitImageFormatPrefix = "%s.dkr.ecr.%s.%s/amazon-k8s-cni-init" ) +//go:embed assets/aws-node.yaml +var awsNodeYaml []byte + // DoesAWSNodeSupportMultiArch makes sure awsnode supports ARM nodes func DoesAWSNodeSupportMultiArch(rawClient kubernetes.RawClientInterface, region string) (bool, error) { clusterDaemonSet, err := rawClient.ClientSet().AppsV1().DaemonSets(metav1.NamespaceSystem).Get(context.TODO(), AWSNode, metav1.GetOptions{}) @@ -76,7 +82,7 @@ func UpdateAWSNode(rawClient kubernetes.RawClientInterface, region string, plan } // if DaemonSets is present, go through our list of assets - list, err := LoadAsset(AWSNode, "yaml") + list, err := newList(awsNodeYaml) if err != nil { return false, err } diff --git a/pkg/addons/default/coredns.go b/pkg/addons/default/coredns.go index eed642188b..204f65639b 100644 --- a/pkg/addons/default/coredns.go +++ b/pkg/addons/default/coredns.go @@ -2,6 +2,7 @@ package defaultaddons import ( "context" + "embed" "fmt" "strings" @@ -16,6 +17,9 @@ import ( api "github.com/weaveworks/eksctl/pkg/apis/eksctl.io/v1alpha5" "github.com/weaveworks/eksctl/pkg/fargate/coredns" "github.com/weaveworks/eksctl/pkg/kubernetes" + + // For go:embed + _ "embed" ) const ( @@ -25,6 +29,9 @@ const ( KubeDNS = "kube-dns" ) +//go:embed assets/coredns*.json +var coreDNSDir embed.FS + func IsCoreDNSUpToDate(rawClient kubernetes.RawClientInterface, region, controlPlaneVersion string) (bool, error) { kubeDNSDeployment, err := rawClient.ClientSet().AppsV1().Deployments(metav1.NamespaceSystem).Get(context.TODO(), CoreDNS, metav1.GetOptions{}) if err != nil { @@ -165,9 +172,12 @@ func loadAssetCoreDNS(controlPlaneVersion string) (*metav1.List, error) { for _, version := range api.SupportedVersions() { if strings.HasPrefix(controlPlaneVersion, version+".") { - return LoadAsset(fmt.Sprintf("%s-%s", CoreDNS, version), "json") + manifest, err := coreDNSDir.ReadFile(fmt.Sprintf("assets/%s-%s.json", CoreDNS, version)) + if err != nil { + return nil, err + } + return newList(manifest) } } - return nil, errors.New("unsupported Kubernetes version") } diff --git a/pkg/addons/default/generate.go b/pkg/addons/default/generate.go deleted file mode 100644 index f05cf36e4a..0000000000 --- a/pkg/addons/default/generate.go +++ /dev/null @@ -1,3 +0,0 @@ -package defaultaddons - -//go:generate ${GOBIN}/go-bindata -pkg ${GOPACKAGE} -prefix assets -nometadata -o assets.go assets diff --git a/pkg/addons/default/helpers.go b/pkg/addons/default/helpers.go index 017260baaf..3f1e1fefaa 100644 --- a/pkg/addons/default/helpers.go +++ b/pkg/addons/default/helpers.go @@ -7,14 +7,10 @@ import ( ) // LoadAsset return embedded manifest as a runtime.Object -func LoadAsset(name, ext string) (*metav1.List, error) { - data, err := Asset(name + "." + ext) - if err != nil { - return nil, errors.Wrapf(err, "decoding embedded manifest for %q", name) - } +func newList(data []byte) (*metav1.List, error) { list, err := kubernetes.NewList(data) if err != nil { - return nil, errors.Wrapf(err, "loading individual resources from manifest for %q", name) + return nil, errors.Wrapf(err, "loading individual resources from manifest") } return list, nil } diff --git a/pkg/addons/device_plugin.go b/pkg/addons/device_plugin.go index 694668ad8b..557a8fc69c 100644 --- a/pkg/addons/device_plugin.go +++ b/pkg/addons/device_plugin.go @@ -8,7 +8,6 @@ import ( "github.com/kris-nova/logger" "github.com/pkg/errors" api "github.com/weaveworks/eksctl/pkg/apis/eksctl.io/v1alpha5" - "github.com/weaveworks/eksctl/pkg/assetutil" "github.com/weaveworks/eksctl/pkg/kubernetes" appsv1 "k8s.io/api/apps/v1" @@ -16,8 +15,20 @@ import ( metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/watch" clientappsv1 "k8s.io/client-go/kubernetes/typed/apps/v1" + + // For go:embed + _ "embed" ) +//go:embed assets/efa-device-plugin.yaml +var efaDevicePluginYaml []byte + +//go:embed assets/neuron-device-plugin.yaml +var neuronDevicePluginYaml []byte + +//go:embed assets/nvidia-device-plugin.yaml +var nvidiaDevicePluginYaml []byte + func useRegionalImage(spec *v1.PodTemplateSpec, region string, account string) error { imageFormat := spec.Spec.Containers[0].Image dnsSuffix, err := awsDNSSuffixForRegion(region) @@ -137,7 +148,7 @@ func (n *NeuronDevicePlugin) PlanMode() bool { } func (n *NeuronDevicePlugin) Manifest() []byte { - return assetutil.MustLoad(neuronDevicePluginYamlBytes) + return neuronDevicePluginYaml } func (n *NeuronDevicePlugin) SetImage(t *v1.PodTemplateSpec) error { @@ -178,7 +189,7 @@ func (n *NvidiaDevicePlugin) SetImage(t *v1.PodTemplateSpec) error { } func (n *NvidiaDevicePlugin) Manifest() []byte { - return assetutil.MustLoad(nvidiaDevicePluginYamlBytes) + return nvidiaDevicePluginYaml } // Deploy deploys the Nvidia device plugin to the specified cluster @@ -202,7 +213,7 @@ func (n *EFADevicePlugin) PlanMode() bool { } func (n *EFADevicePlugin) Manifest() []byte { - return assetutil.MustLoad(efaDevicePluginYamlBytes) + return efaDevicePluginYaml } func (n *EFADevicePlugin) SetImage(t *v1.PodTemplateSpec) error { diff --git a/pkg/addons/generate.go b/pkg/addons/generate.go deleted file mode 100644 index 20e61b6872..0000000000 --- a/pkg/addons/generate.go +++ /dev/null @@ -1,3 +0,0 @@ -package addons - -//go:generate ${GOBIN}/go-bindata -pkg ${GOPACKAGE} -prefix assets -nometadata -o assets.go assets diff --git a/pkg/addons/vpc_controller.go b/pkg/addons/vpc_controller.go index 4af6c3ab57..e61306b020 100644 --- a/pkg/addons/vpc_controller.go +++ b/pkg/addons/vpc_controller.go @@ -21,8 +21,29 @@ import ( apierrors "k8s.io/apimachinery/pkg/api/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" + + // For go:embed + _ "embed" ) +//go:embed assets/vpc-admission-webhook-config.yaml +var vpcAdmissionWebhookConfigYaml []byte + +//go:embed assets/vpc-admission-webhook-csr.yaml +var vpcAdmissionWebhookCsrYaml []byte + +//go:embed assets/vpc-admission-webhook-dep.yaml +var vpcAdmissionWebhookDepYaml []byte + +//go:embed assets/vpc-admission-webhook.yaml +var vpcAdmissionWebhookYaml []byte + +//go:embed assets/vpc-resource-controller-dep.yaml +var vpcResourceControllerDepYaml []byte + +//go:embed assets/vpc-resource-controller.yaml +var vpcResourceControllerYaml []byte + const ( vpcControllerNamespace = metav1.NamespaceSystem vpcControllerName = "vpc-resource-controller" @@ -112,7 +133,7 @@ func (v *VPCController) generateCert() error { return errors.Wrap(err, "generating CSR") } - manifest := assetutil.MustLoad(vpcAdmissionWebhookCsrYamlBytes) + manifest := vpcAdmissionWebhookCsrYaml rawExtension, err := kubernetes.NewRawExtension(manifest) if err != nil { return err @@ -258,22 +279,22 @@ func (v *VPCController) deployVPCResourceController() error { return err } } - if err := v.applyResources(assetutil.MustLoad(vpcResourceControllerYamlBytes)); err != nil { + if err := v.applyResources(vpcResourceControllerYaml); err != nil { return err } - return v.applyDeployment(assetutil.MustLoad(vpcResourceControllerDepYamlBytes)) + return v.applyDeployment(vpcResourceControllerDepYaml) } func (v *VPCController) deployVPCWebhook() error { - if err := v.applyResources(assetutil.MustLoad(vpcAdmissionWebhookYamlBytes)); err != nil { + if err := v.applyResources(vpcAdmissionWebhookYaml); err != nil { return err } - if err := v.applyDeployment(assetutil.MustLoad(vpcAdmissionWebhookDepYamlBytes)); err != nil { + if err := v.applyDeployment(vpcAdmissionWebhookDepYaml); err != nil { return err } - manifest := assetutil.MustLoad(vpcAdmissionWebhookConfigYamlBytes) + manifest := vpcAdmissionWebhookConfigYaml rawExtension, err := kubernetes.NewRawExtension(manifest) if err != nil { return err diff --git a/pkg/apis/eksctl.io/v1alpha5/generate.go b/pkg/apis/eksctl.io/v1alpha5/generate.go index 3aa9d55505..2695d4193c 100644 --- a/pkg/apis/eksctl.io/v1alpha5/generate.go +++ b/pkg/apis/eksctl.io/v1alpha5/generate.go @@ -1,4 +1,12 @@ package v1alpha5 +import ( + // For go:embed + _ "embed" +) + //go:generate go run ../../../../cmd/schema assets/schema.json -//go:generate ${GOBIN}/go-bindata -pkg ${GOPACKAGE} -prefix assets -nometadata -o schema.go assets + +//SchemaJSON contains the schema +//go:embed assets/schema.json +var SchemaJSON string diff --git a/pkg/apis/eksctl.io/v1alpha5/schema.go b/pkg/apis/eksctl.io/v1alpha5/schema.go deleted file mode 100644 index cb537e8041..0000000000 --- a/pkg/apis/eksctl.io/v1alpha5/schema.go +++ /dev/null @@ -1,274 +0,0 @@ -// Code generated by go-bindata. DO NOT EDIT. -// sources: -// assets/schema.json (87.655kB) - -package v1alpha5 - -import ( - "bytes" - "compress/gzip" - "crypto/sha256" - "fmt" - "io" - "io/ioutil" - "os" - "path/filepath" - "strings" - "time" -) - -func bindataRead(data []byte, name string) ([]byte, error) { - gz, err := gzip.NewReader(bytes.NewBuffer(data)) - if err != nil { - return nil, fmt.Errorf("read %q: %w", name, err) - } - - var buf bytes.Buffer - _, err = io.Copy(&buf, gz) - clErr := gz.Close() - - if err != nil { - return nil, fmt.Errorf("read %q: %w", name, err) - } - if clErr != nil { - return nil, err - } - - return buf.Bytes(), nil -} - -type asset struct { - bytes []byte - info os.FileInfo - digest [sha256.Size]byte -} - -type bindataFileInfo struct { - name string - size int64 - mode os.FileMode - modTime time.Time -} - -func (fi bindataFileInfo) Name() string { - return fi.name -} -func (fi bindataFileInfo) Size() int64 { - return fi.size -} -func (fi bindataFileInfo) Mode() os.FileMode { - return fi.mode -} -func (fi bindataFileInfo) ModTime() time.Time { - return fi.modTime -} -func (fi bindataFileInfo) IsDir() bool { - return false -} -func (fi bindataFileInfo) Sys() interface{} { - return nil -} - -var _schemaJson = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\xec\x7d\x7b\x73\x1b\x37\xf2\xe0\xff\xfb\x29\x50\xcc\xd6\x6f\xed\x2d\x8e\x68\x39\xbb\xd9\x6c\x36\xa7\x3a\x5a\x52\x1c\x9e\x23\x89\x27\xca\xc9\x5d\x24\xd7\x1a\x9c\x01\x49\xac\x86\xc0\x2c\x80\x91\xc4\xfc\x9c\xfb\xec\x57\x78\xcd\x13\x33\x9c\x97\x6c\x6d\x95\xfe\xb2\x3c\x9c\x69\x34\x1a\x8d\x7e\xa1\xbb\xf1\xdf\x7f\x00\x60\xf4\x47\x86\x56\xa3\xef\xc0\xe8\xab\x49\x80\x56\x98\x60\x81\x29\xe1\x93\xe3\x30\xe6\x02\xb1\x63\x4a\x56\x78\x3d\x1a\xcb\x17\xc5\x2e\x42\xf2\x45\xba\xfc\x17\xf2\x85\x7e\xf6\x47\xee\x6f\xd0\x16\xca\xc7\x1b\x21\xa2\xef\x26\x93\x7f\x71\x4a\x3c\xfd\xf4\x80\xb2\xf5\x24\x60\x70\x25\xbc\x57\x7f\x9b\xe8\x67\x5f\xe9\xef\x32\x43\x8d\xbe\x03\x12\x0f\x00\x46\xd3\x5f\x17\xf1\x92\x20\x71\x06\xa3\x08\x93\x75\xf2\x03\x00\x23\x18\x04\xea\x6d\x18\xce\x19\x8d\x10\x13\x18\xf1\xcc\xef\x95\xd3\xb0\x20\x17\x11\xf2\x47\xe6\xe5\xdf\xc7\x16\xaa\x63\x46\xea\x79\x80\xb8\xcf\x70\x24\x41\xa8\x99\xd1\x30\xe0\x80\x2b\x40\x40\x50\x30\xfd\x15\x6c\x35\x8a\xfc\x00\xcc\x56\x40\x6c\x10\xb8\x45\x3b\x80\x39\x80\x04\x4c\x7f\x1d\x03\xb1\x81\x02\xc0\x90\x53\xb0\x44\x3e\xdd\x22\xae\xde\x21\x70\x8b\x00\xd5\xef\x1b\x68\x54\x6c\x10\xbb\xc7\x1c\x81\x98\xa3\x04\x90\xa0\x80\xa1\x15\x62\xf2\x0f\xb1\xc1\x76\xec\x83\x14\xc3\x07\x0f\x13\x81\xc2\x10\xff\xcb\xdb\x88\x6d\xe8\x3d\x7d\x8c\x03\xb4\x82\x71\x28\x24\x76\xff\xfd\xbb\x5e\x0a\xb3\x10\xa3\xdc\x22\x65\x16\x3d\xaa\x58\x6a\xf8\x5b\xee\xff\x99\x85\xe4\x82\x49\xc6\x19\x67\x7f\x2b\x90\xc6\x87\x04\x2c\x11\xa0\x5b\x2c\x04\x0a\x00\x2e\x13\x23\xff\xf9\x1e\x4a\x37\x00\x97\x40\xfb\x3d\x05\x3c\xf2\x71\xc0\x8a\xb3\x70\xb3\xf0\x1a\x8b\x4d\xbc\x3c\xf0\xe9\xf6\xd3\x3d\x82\x77\xe8\x9e\xb2\x5b\xfe\x09\xdd\x72\x5f\x84\x9f\xa2\xdb\xf5\xa7\x58\xe0\x90\x7f\xc2\x91\xa4\xf7\x6c\x7e\x8e\x84\x7b\x44\x1c\xec\xa1\x5a\xfa\x55\x69\xa3\x44\x6a\x71\x19\x0a\x2e\x58\x80\x24\xde\xd7\x39\xb8\xe3\xdc\xda\x14\x67\x69\xfe\xfb\x61\xbc\x67\x33\xaf\x60\xc8\x51\x9e\x31\x82\x40\x51\x39\xe1\x08\x86\xfe\x1d\x63\x86\x82\x3c\x06\x92\x4b\xcb\xa3\x54\x72\x8f\x10\xd0\xdf\xcc\x69\x88\xfd\x5d\xb3\x15\x98\x91\x10\x13\x74\x42\xfd\x78\x8b\x88\xa8\xe5\x2e\xbd\xf1\x20\x88\x14\x78\x10\x98\x6f\xe4\xb6\xd0\xe3\xb6\x62\xae\xfd\xd0\x9c\x2b\x9d\x9d\xe1\xf4\xf2\x9c\x17\x67\x89\x05\xda\x16\x1f\xd6\xb0\x43\x0e\x78\xe6\x3d\xc8\x18\xdc\xd5\x52\x23\xc4\x5c\x48\xf1\x21\x91\xb0\x62\x64\x36\x3d\xd3\xf3\xc1\x52\xc6\x74\x22\x4b\x0b\xb0\x4e\xfa\x28\x7e\x69\xba\x17\x32\xdf\x45\x88\x6d\x31\xe7\x92\x27\xde\xd0\x98\x04\x90\x95\x18\xa8\x85\x20\x9a\x5e\x9e\x5b\xe4\x33\x80\xc1\xd2\x40\x56\x93\xe0\x9c\xfa\x18\x0a\xd4\x8a\x3c\xad\x00\x3b\x27\xca\x11\xbb\xc3\x3e\x9a\xfa\x3e\x8d\x89\xb8\xa4\x21\x9a\x5e\x9e\x77\xa1\x98\x80\xeb\x12\xf7\xed\x55\xe5\x9d\x98\xb1\xa0\xc2\x5d\x04\xbf\xda\x20\xb0\x45\x02\x06\x50\x40\x45\x84\x28\x0a\x77\x5a\x61\x21\xe0\x6b\x7b\xc7\x10\x47\x32\xd8\x3d\x16\x1b\xe0\x43\x81\xd6\x94\xe1\xdf\xa0\x84\x02\x20\x09\x00\x65\x6b\x48\xcc\x83\x03\x70\x0a\xfd\x0d\x10\x70\x0d\x7c\x4a\xe4\x67\x8a\x21\xa1\x52\x00\xf2\x65\x48\x00\x8d\xf4\x6c\xc1\x1d\x0c\x63\x34\x06\x4b\x2a\x36\xf2\xa5\xfb\x0d\xf6\x37\x60\x47\x63\xa0\x64\x0d\x3a\x68\xb5\xc8\xff\x59\x93\x71\x28\xff\x22\xab\xdc\x21\xc6\x71\x4e\xda\x37\xe6\xb2\x7b\x14\x86\xef\x08\xbd\x27\x73\x23\x00\x9a\x89\xf5\x5f\x4a\x9f\xd5\x71\xcf\x8a\x32\x23\x54\x30\x91\x04\xda\x6e\x29\xc9\x49\x9d\x56\xcb\xb7\x1f\x5a\x47\x6d\xac\x64\x9b\x83\xac\x7b\x77\x77\x9d\xfe\xa8\xf8\x6d\xb4\x47\x36\xd6\x2e\x51\x51\x4a\xb4\xb2\x12\xea\x2d\x75\xb9\x05\x4e\xdf\x2d\x00\x94\xe6\x83\xe4\xe5\x15\x5e\xc7\x4c\xf1\x78\x4b\x0b\xba\x0e\x52\xce\x52\xb1\xee\x52\x48\xe3\xe0\x17\x28\xfc\x4d\x13\x3b\xd6\x6c\xd3\x9f\xe8\x7a\x9d\x77\x77\x6a\x98\xb6\x34\x90\xfd\xba\x23\xbf\x14\x70\x18\x64\x15\x7c\x4a\x04\xc4\x84\x1b\x82\x81\x08\x32\xb8\x45\x02\x31\x0e\x18\x0a\xa1\xb4\x93\x05\x05\x19\x5a\x35\x5d\x94\xd6\x80\xeb\xd7\xa8\x4c\xf8\xca\xa5\x42\x04\x2e\x43\x74\xb5\x8b\xca\xc2\xa5\x99\x35\x35\xce\xff\x8a\x48\xbc\xcd\x2d\x84\x25\x77\x84\x0b\xaf\xca\x87\x71\x80\x85\xeb\xb1\xd8\x20\x22\xb0\x0f\x05\x65\xe5\x9f\x25\xb1\x18\x0d\x43\xc4\xce\x20\x81\x6b\xe4\x78\x45\xba\xe4\x41\x1c\xba\x7e\x82\x61\x58\x7e\xf8\xe7\x51\xee\xc9\x87\x01\x4c\x44\x45\x52\xa9\x41\x42\xbd\x18\x72\x01\x35\xb1\xc1\x0b\x8e\x10\xb8\x4e\x97\x4b\xda\xbf\xfc\xc3\x8b\x49\xcc\xe1\x1a\x4d\x7c\xf9\xfc\x5e\x3e\xf7\x0c\x0f\x7b\x06\xc4\xe4\x2b\xf3\x40\x73\x89\x87\x1e\xe0\x36\x0a\x11\x7f\xf9\xf2\x00\xfc\x0c\x43\x1c\x00\x44\x04\x93\x76\x22\x64\xe8\x3b\xf0\xf1\x46\x52\xfd\x66\xf4\x71\xac\xfe\x94\xb4\x4e\xff\x93\xa1\xb0\x7d\x58\xa2\xab\xfd\x21\xa1\x66\xf2\x79\x18\xda\x3f\xff\x7c\x33\xfa\xd8\x52\xc1\xef\x21\xcc\xf7\x10\x6c\x18\x5a\xfd\x8f\x9b\x51\x67\x82\xdc\x8c\x8e\x0a\xd4\xfd\x7e\x02\x8f\xdc\x54\xfa\xde\xa7\x01\x3a\xfa\xaf\x7f\xc7\x54\xfc\x03\x46\x58\xff\xf1\xfd\x44\x3d\x1d\xe7\x7f\x95\x14\xac\xfd\x3d\x43\xd4\x9a\xf7\x4a\x74\xae\x79\x37\x21\x7d\xdd\xb8\x61\x58\xf3\xeb\x9f\x73\xbf\x1d\x74\x15\xa7\x59\x39\x31\xa4\x2c\x45\xac\x5e\xe6\x59\x8b\xcf\xac\x78\x5b\x89\xda\x16\xbc\x53\xae\xea\x50\xe1\x5e\x6f\xdd\x5a\xad\x59\x0b\xe0\x16\x93\x7c\x14\x21\xc2\x3f\x1b\xc3\xa5\xb9\x5f\x2f\x75\x74\x53\xe9\x5c\x11\x2d\x54\xf1\x86\x86\x52\xcd\xed\x7a\xa7\x88\xb7\xf0\x0c\x9d\xda\x60\xa4\x43\x3c\x07\x98\x4e\xee\x0e\x61\x18\x6d\xe0\x5f\xb3\xa8\x7d\x70\x8f\x7f\x07\x71\x08\x97\x38\xc4\x62\xf7\x2b\x25\x5d\xb5\x55\x1f\x12\xf8\x2e\x1b\xa8\x86\xe8\x65\xd3\xa9\x4e\x5f\x2c\x0a\x3a\x81\xc7\x51\x44\x99\x68\xa2\x16\x5e\xb6\x92\xbf\x8b\x96\x32\x36\x2f\x4c\x0d\x5a\x52\x9e\xba\xa9\xb4\x82\x6c\x0d\x05\x9a\x33\xba\xc2\x61\xe3\x65\x72\x53\xf0\x87\x1c\xac\x5e\x8b\xb7\xc6\xa2\xd9\xaa\xbd\xc5\xf5\xce\xf6\x0f\x3f\xbd\xff\x3f\xe0\xe7\x43\x70\x72\x3a\xbf\x3c\x3d\x9e\x5e\xcd\x2e\xce\xc1\xf9\xc5\xd5\xec\xf8\xf4\x00\x6c\x84\x88\xf8\x77\x93\x4c\x64\x73\x92\x46\x36\x27\x9a\xed\x27\x98\xf3\x18\xf1\xc9\xeb\xbf\x7f\xf3\x35\x78\x8b\x05\x40\x0f\x11\xe5\x88\xe7\x8d\x70\x20\xfd\xa8\x1f\xc2\xf8\x01\xdc\x1d\x5a\x17\x15\x41\x16\x62\xc4\x00\x16\xc8\xbc\x44\x57\x60\x8d\x05\x8d\xda\xb9\x68\x4f\x73\x06\x55\xab\x26\x7f\x6b\xba\x70\x17\x45\x4a\x14\x66\xbe\x0f\xd1\xd7\x0a\xd1\x7b\x1c\x86\xf2\x15\x81\x49\x8c\xa4\x92\x58\xaa\x23\x81\x00\x60\x02\x56\xb1\x88\x19\x32\x38\x83\x28\x84\x84\x8f\x01\x43\x51\x08\x7d\x65\xca\x6c\x90\xa2\x48\x7e\x00\xb8\xa4\x77\xed\x22\x5d\x5f\x14\x51\xe7\x4a\x60\xb8\x6d\x25\xf5\x66\xd3\xb3\xaa\x68\xbd\xb4\x91\xc4\x6e\xce\xe8\x1d\x0e\x10\xeb\x27\x21\x66\x05\x68\xbd\x64\x84\x52\xd6\xbd\xb5\x5b\xde\x6a\xd8\xab\xd8\x6e\xe3\x25\x62\x04\x09\xc4\xcf\x91\x90\xdb\xac\x64\x6e\xd4\x4c\xff\x5d\xc5\xc7\xce\x91\xb6\xca\xda\x0c\xce\x69\x80\xde\x32\x1a\x97\xf7\x55\x2b\xca\x9f\x15\xa0\x0d\x11\x56\x57\x3a\x50\x42\x5c\x2b\xfc\x80\xd2\x4d\x89\x06\x54\xf8\x63\xb2\xf6\x48\xf2\xc6\x4b\xb5\x0f\xae\xcd\xcc\x40\xfa\x43\xf2\x11\xba\xe5\x9e\xf9\x59\x7d\xc7\x87\xd0\x96\x0e\x4c\x6e\x46\x47\x45\xc4\xa5\x8e\x54\xf8\x95\xbe\x2f\x23\x75\x33\x3a\x2a\x4f\xa2\x5a\xc9\x26\xa6\x66\x9b\x2d\x79\x86\x04\xac\x38\x37\x18\x86\x25\x06\xe5\x85\x1f\x28\x03\x98\xac\x28\xdb\xa6\x41\x5d\xeb\xdf\x01\xe5\x40\x3b\x56\xdb\xc5\x22\xed\x74\xe3\xbe\x51\x1b\xf2\x42\x93\x45\x8c\x18\xbe\x83\x02\x99\xd5\x69\xb6\x94\xf3\xfc\x37\x75\x04\x84\x61\x48\xef\x53\x15\x22\xa5\x3e\x04\xab\x38\x0c\x77\x9e\x19\x39\xf1\x7e\x30\x31\x71\x6e\x42\x15\xfb\x81\x0d\xe4\x80\xc6\x42\x9d\xac\x00\x49\x30\x29\x64\x00\xf4\x7d\xc4\xf9\x58\x11\xc5\x82\xd0\xcf\xd4\x51\xfc\x2f\x0b\x60\x22\xb0\x1c\x60\x6e\x7c\xfa\x00\xdc\x61\x08\x7e\x9e\x1f\x03\x44\x82\x88\x62\x22\xda\x19\x2b\x4f\x77\x16\xce\x35\xe5\xc8\x67\x48\xf0\x53\xe2\xb3\x9d\x9d\x43\x83\x65\x5d\x94\x3e\x73\x42\xbf\x8b\xfc\x56\x3b\xfe\xe7\xf9\x71\x57\x7f\xbf\xc6\x71\x75\xc9\xa1\x06\x0a\xad\x60\x4c\xd4\x9a\x04\x85\x39\x8f\x4b\xce\x70\xf5\x36\x72\x8b\xb5\x5a\x35\x58\xe3\xbd\xd4\x7a\xa0\x6e\xdf\xb0\x96\x1b\x0a\x1e\x49\xd9\xd4\x1d\x24\xb6\x02\x01\xc7\x52\x64\x99\x6d\x33\x36\xb6\xa1\x36\xff\x50\xa0\x0f\xcd\x0c\xc1\xc0\x74\x3e\x6b\x1c\x55\xe9\x03\x38\xe5\x0b\x4f\x49\x46\xcf\x9c\xe0\x78\xc6\xec\x4a\x99\x2f\xc7\xe0\xea\x5d\x65\x13\xdb\xa8\x41\x5e\x7e\xa4\xc7\x6b\xa3\x24\x9a\x90\x7b\xc1\x80\xaf\xb2\xcb\xec\xb6\xf8\xe0\x0a\xfd\x9c\x26\xbb\xbd\x41\x28\xdd\x30\xe2\x54\xc9\x92\x2a\x3b\x72\x49\x69\x88\x60\xc5\xfe\x8e\xe2\x65\x88\xfd\xb6\x00\x5a\xed\xeb\x3c\x92\x55\x63\x0f\xc2\x85\xfa\xa4\xc9\x4a\x67\x18\x61\x25\x58\x11\x4b\x64\xa8\x15\xbb\x19\x85\xdb\xf2\x18\xab\x25\x70\xd7\x12\x4b\x47\xa5\xc1\xe2\x5a\xc1\x40\x83\xd3\x07\xe4\xc7\x12\x5c\xb3\xf4\x81\x3a\x15\xcd\x68\x68\x3c\xb6\xe5\x0e\x44\x34\xd0\x09\x1e\x1a\x6f\xa9\x88\xa6\xf3\x19\x3f\x00\x57\x1b\xcc\x81\x7a\x15\x73\x00\x83\x40\x47\x2e\xa5\x07\x97\x9a\xff\xe0\xf2\xcd\xf4\x58\x39\x88\x30\x16\x9b\xe4\x28\xfc\x00\x28\x93\x7a\x4e\x03\x90\xa0\x0d\x24\xde\x1f\x5e\x58\x4f\x3f\xa0\x3e\x3f\x80\xf7\xfc\x00\x6e\xe1\x6f\x94\x28\x97\x1f\xdd\xf2\x49\x08\x05\xe2\x62\x12\x73\xc4\xd6\x31\x0e\xd0\x24\xa2\x81\x87\x2c\x10\x4f\xe2\x73\x20\x17\xa6\x9d\x7d\xf5\x99\x66\x9c\x5a\x69\x43\x4d\xf3\x66\x74\x54\xa6\xe2\xfe\x28\x58\x81\x5d\xe6\x83\x26\xda\x38\x93\x60\x24\x45\x24\xa5\x0c\x06\x92\xc8\x20\x99\x8f\x22\xea\x47\xc3\x15\xa7\xef\x16\xc0\x44\xd8\xc0\xa2\x10\x6d\x34\x5f\x7b\x26\xdc\xd7\xd2\x69\xea\x87\x58\xc9\xc4\x2e\x22\x73\x33\x3a\x72\xe0\x5e\xbd\x18\xf9\xbc\x80\x7e\x3e\x4e\x2a\x35\x16\x39\xa8\x43\xb8\x3c\x06\x4f\xb9\x1f\x14\xa2\xea\x80\x82\x21\x39\x47\x4c\xb2\xf9\x2f\x66\x01\x67\xd3\x33\x60\xb0\x00\x76\x72\x1f\x5e\x4c\x30\xdc\x1a\x48\x16\xd0\xe4\x2b\x45\x48\x4f\xaa\x67\xcf\x9c\x95\x29\xfb\xa6\xdd\xb2\xb6\xc4\x2f\xb3\x8e\x2d\x50\xba\x19\x1d\xb9\xe6\xb5\x77\x75\x7b\x24\x73\x65\x20\x7c\xa6\x0d\x0a\xc3\x10\x58\xab\xd7\x5b\x42\x29\x0f\xd5\x7f\x30\xe2\x86\xa2\x4a\x40\x1a\x93\x47\xaf\xb6\x14\x8f\x29\x7a\xc0\xa2\x57\x2f\xc9\x67\xd3\x33\x2b\xe2\xde\x73\xc4\xde\x2a\x11\xa7\xe5\xed\x3f\x6d\x46\xce\x3f\x0d\x6a\x18\xf1\x0e\x12\x7d\xc8\x39\x36\x13\xdb\x5d\xe6\x74\x33\x3a\xaa\xa0\x5f\x35\x63\xdd\x45\xfe\x25\xe2\x34\x66\x3e\x3a\x4e\x8e\x6c\xdd\xe9\xb5\x45\xe3\xac\xd6\x2f\x57\x89\x46\x26\x0f\x3d\xc9\x8c\xda\x01\x82\xe4\x0c\x4c\x1e\x23\x8b\xf5\x86\x92\x2e\x67\x7a\x5e\x9c\x6c\x33\xfd\x44\x85\x75\xdb\x05\x96\x1f\x77\xf0\x34\x1b\x4e\xb0\x18\x39\x89\x2a\xf7\xfb\xc5\xec\xe4\xb8\x0f\x05\xb5\x4f\x9e\xce\x41\xc2\x03\x91\x71\x1e\x01\xe4\xe0\x1e\x85\xa1\xfc\x77\x76\xb9\x98\x26\x7a\x67\xaa\x38\x08\x1c\x9f\xcf\x40\x14\xc6\x6b\x4c\xda\x45\xe4\x07\x1a\xb3\xa3\xd9\x5e\x10\x72\xcd\x85\xd7\x7e\x9b\xa4\x00\xaf\x85\xe5\xe2\x5a\xd6\x1a\xb5\xdb\x70\x6b\x0d\xe8\x7b\x48\x11\x24\x17\x0b\x0a\xc1\xf0\x32\x16\xc8\xe4\x7d\xfa\x85\x58\x41\xc3\x74\xf5\x3d\xd0\x2a\xbc\x0b\x15\x76\x6d\x52\xfc\x41\x08\x15\x30\x5f\x39\x54\x4f\x81\x47\xc9\x2c\xde\x9b\xcf\x1a\xc2\x25\x0a\x9f\x36\x8a\x5d\xf3\xe0\xe5\x77\x3c\x82\x7e\xf3\x8f\x5b\x6d\xe2\x62\x0a\x6b\x3a\x5c\x99\xbc\x63\x37\x63\x0c\xb8\x39\xb2\x61\xee\x7b\x04\x7c\x48\x74\xe1\x53\x62\xd3\x5d\x28\xe2\x4b\xf6\x55\xf2\xac\x68\xfd\xb5\xdc\x3d\xbd\x87\xab\xd8\x5e\x05\x33\xbc\xc9\x46\xfb\xa2\x75\x32\x69\x21\x59\x7e\x82\xc3\xd6\xcf\x54\x8e\xe2\xe4\xfb\xe7\xba\x9a\x26\x75\x47\xfd\xe3\x3d\x99\x02\x16\x15\xdd\x28\x2c\x17\xea\xc5\x13\xad\x81\x3b\xa7\xda\xe9\x64\xd1\x6a\x39\x77\x50\xf3\x8b\x15\x17\xe9\x70\xf4\x80\x74\xed\x31\xa2\x93\x34\x72\x9d\xce\xf7\xeb\xaa\xda\x23\xf3\x08\xf9\x78\x85\x7d\xbd\xe6\xaa\xac\x15\x13\x2e\x10\x0c\x2c\xd2\x2a\x79\x2b\x91\xbd\xde\x1a\x11\xc4\x94\xf3\x95\x7c\xd1\xee\x40\x7c\x88\x01\x2b\xa9\x71\x41\xc2\x5e\xce\x95\xc6\x6e\x07\xf0\x0a\x50\x12\xee\x92\x9d\x5e\x08\x27\x68\x54\xf8\x86\xc6\x61\x00\x96\x28\xf1\x47\xe5\xf2\xd1\x58\xe8\xff\x63\xb2\x9e\x58\xdd\x6b\x52\x66\xfa\xf0\xd1\x67\x46\xcd\x1d\xe9\x10\x50\xc4\x0d\xf3\xa9\xaa\x54\xec\x42\xc3\x70\xc2\x7f\x52\x65\x71\xd2\xe1\x97\x08\x25\xde\x58\x2f\x29\xd0\x0a\x58\x03\x1b\x75\xb0\xda\xae\x8e\xc6\xa8\xeb\xe8\xb6\xae\x3e\xaa\xb6\xd0\xa9\xaa\x78\x2a\xaf\x38\xf7\x28\x85\x32\x9f\xba\x44\xa5\x4b\x60\x14\x39\x70\x48\x17\x52\x57\xaf\x15\x56\x3b\xad\x50\x84\x24\xe8\x55\x88\xd5\x1e\x7e\x23\x3b\x78\x51\xdc\xe8\x95\xd6\x30\x6b\x19\x37\x6d\xc5\x64\x16\xf8\x80\x0b\xa2\x59\x23\x6b\xc5\x55\xed\xc4\x86\xbd\x24\xf6\xc2\x73\x11\xbc\xe8\xd4\xd7\xd4\xef\x67\x19\x16\xad\xdb\x65\xfe\x3f\x8d\x90\x40\x3e\x82\xc8\x96\x58\x30\x69\xf8\x24\x3c\x8a\xd7\x84\x32\x1d\xcd\xfd\xa8\xc3\xb9\x2d\x4b\x82\xea\x61\xea\x6a\x16\x0d\x38\x29\x63\x79\x84\x90\x40\xdd\xac\x0d\x7b\x14\x03\x47\x4d\x26\x57\xf8\xd4\x6d\xfa\x68\xc6\xe8\x8e\x9f\x0a\x36\xfe\xb2\x00\x1a\x10\xd8\x50\x6e\x0c\x03\xcc\x3b\x21\xdd\x04\xde\xd3\xb7\x00\xd4\x41\xb3\xf4\x7e\xe0\xda\xcc\x46\xc7\x1c\x1d\x07\x10\xad\xa8\xd3\x19\xee\x60\xe5\xe2\x75\xb3\xd6\x45\x6e\x77\x90\x61\x48\x44\x5a\x0b\x78\x78\x70\xf8\x37\x5b\xb5\x77\x78\x70\xf8\x6d\xe6\xef\xbf\xa7\x7f\xbf\x7e\x75\x33\xfa\x08\x5e\x18\x44\x5f\xda\xa7\x87\xad\xcb\xfc\x5c\x58\x64\xeb\xd2\x24\x3a\x35\x65\x6b\x12\xc3\xfa\x9f\xff\x5e\xfb\xf3\xeb\x57\xb9\x9f\xb3\x33\x2a\xbc\x78\x58\x28\x90\xab\x5a\x30\x09\xb3\x49\xfe\xb7\x9c\x58\xb1\x2a\x56\xce\xc6\xf1\xec\xef\xe5\x67\x85\x31\xf4\xb3\xc3\x8a\x34\xf2\x56\xba\xb8\x42\x19\x39\x58\xaf\xb8\x9d\x1f\x33\x16\x99\x54\x3e\x6b\x37\x31\xcc\x64\x73\xb6\x4f\x0a\x6a\x04\xcc\xa5\xce\xcf\xa7\x57\x4d\x6c\xa5\x35\x14\xe8\x1e\xf6\x09\x5f\x54\xec\xcd\x1f\xf1\x7a\x13\xee\xa6\x3a\xc3\x30\x44\x72\x0b\x5a\xa3\x0f\x71\x00\xc1\x46\xfd\x0e\xa0\x7d\x01\x9c\x4f\xaf\x80\xc1\x46\x6d\xd1\x05\x26\x6b\xc7\x77\x5c\x3d\xce\xbe\x5d\xd8\xda\x27\x98\xdb\x01\x03\xfd\x27\x97\x6f\x0f\xbb\xd5\x0b\xb3\xcb\x6f\xcc\x16\xf3\xcc\xc2\xd4\x13\xae\x01\x55\x3f\xf5\x2c\x28\x43\x83\x3c\xac\x1a\x6a\x64\x64\x82\xc6\xa2\x89\x54\x28\xd0\xa0\xb8\xc9\x1d\x80\x00\xb0\xab\x33\xc4\xee\xb7\xac\x3b\xc8\xa6\x95\x44\xf5\xf3\x59\xbd\xfb\x78\x24\xf3\x89\x6b\x03\xea\x3e\x69\x6d\xd2\x2c\x9b\xb9\xcb\xc5\xce\x7b\x4e\x95\xab\x53\x1f\xfb\x02\x6c\xb5\x1c\x76\x12\x65\x2c\x06\x74\x95\x92\xec\x76\x12\x00\x0d\xdd\x74\xaf\x6b\x7b\x76\x53\x03\xc8\xb5\x98\x3f\xcf\x8f\x1b\x9d\xc3\xc4\x82\x4e\xc3\x90\xfa\x50\xa0\xd9\xfc\xee\x9b\x3e\x71\xbf\x69\x0e\xd6\xcf\xdf\x00\xe9\x90\x21\x2e\xb4\x83\x3d\xbf\xfb\x06\x1c\xcf\x4e\x2e\xc1\x32\xa4\xfe\xad\x0e\xd2\x4e\xfe\xfa\x0d\x90\x2b\x84\x1f\x92\x90\x8e\xc4\xbb\x55\x4c\x68\xa8\x41\x9d\x5c\xf9\xf9\x1b\xe9\xf9\xd5\x49\xcf\x35\xa3\x97\x52\xa5\x6b\xe3\xb3\x08\x99\x72\x2d\x55\xc9\x91\x96\x5d\xcc\x67\x49\xee\xe1\x5d\xe4\x7b\x44\x97\x0e\xa8\x1e\x0f\x49\x85\x8d\x7e\xdd\x13\xd4\x13\x1b\x94\xcd\x27\x87\x11\xf6\x74\xfa\xaf\x97\xd4\x67\x0c\x50\xe6\x35\x0c\x22\xb6\xb4\xab\x34\xe1\xea\xcc\x23\xf4\x20\x18\x94\xbc\xf3\xe5\x4e\xe2\x54\x06\x57\x22\x79\x34\x23\xdb\x63\x0e\xb9\xec\x63\x80\x0e\xd6\x07\x00\xea\x5f\xe4\xdb\x56\x48\x18\xc9\x00\x24\x00\xb2\x03\x30\xf0\x36\xb4\x2c\x78\x9a\x2c\xca\x63\xe1\xe0\xa4\x79\x8b\x2e\x92\xd9\xe3\x32\x55\x4c\xb2\xd8\x40\xa6\x2b\x4a\x16\xc8\x8f\x19\x16\x3b\x55\x59\x72\x19\x3b\x0a\xe0\xdb\x4a\x35\x69\xb5\xfa\x30\x94\x56\x51\x10\x00\x6e\xe0\x03\x55\x16\x01\x58\x1c\x9a\xd3\x4b\x12\x80\x15\xa3\x5b\x25\x52\x8c\x81\x92\x58\xbf\x85\x8f\xe4\xbb\x2a\x82\xad\xb0\xd6\xa5\x52\xf9\x57\x4c\x06\xb6\xa9\xbd\x8a\x49\xb6\x34\x51\x67\x7d\xd2\xed\x36\x26\xd8\xcf\x1d\x79\xe5\x12\xc3\xd4\x28\xb9\xef\x0c\x50\xdd\x68\x0d\xf8\xca\x93\x00\x4b\x64\x2d\xad\x00\xdc\x6f\x10\x01\xb1\xb4\xdb\x8c\xef\x9c\x78\xd3\x79\xec\x78\x3b\xeb\xf4\x99\x88\x4d\x88\xd8\x20\x75\x8f\xc0\x86\x2d\x14\x32\x4e\x55\x8d\xbd\xa5\x4b\x4d\xbe\xac\x94\xd3\xf5\x82\xa9\x96\xd6\x6c\x20\x57\x2c\x23\xaa\x8d\xc5\x73\xfb\x2d\x97\x52\x3b\x29\x30\x69\xc5\x84\xbd\x06\x72\x12\x91\x67\x25\x4d\x0f\x8f\xf4\x05\xbc\x85\xfa\xd8\x56\x73\xde\x5c\x32\x5e\x4e\x8c\xbd\x54\xa2\x35\xe5\x56\xc9\x79\x4b\x24\xee\x11\x22\x0e\x76\x55\x6c\xda\x8a\x36\x8f\x83\x81\x9b\x68\x6e\x41\xdd\x83\x7c\x5a\xeb\x20\x4f\x77\x87\x0c\x72\xf2\x60\xf1\xb6\xb5\xba\xab\x01\xe5\x9e\x50\xc9\x6f\x02\x7b\xf7\xe5\xc2\xa5\x8a\x0b\xb8\xdc\xa2\x9d\x8e\x62\x4e\x7f\x35\xb4\x27\x77\x88\x60\x44\x7c\x64\xd2\xd1\x55\x28\xd8\x94\x46\x7f\x78\x31\xb1\x45\xd2\x13\x86\x94\xf4\xf1\x30\xdc\x7a\x90\x04\xde\x5d\xe4\x4f\x5e\x66\x13\x64\xaf\x8d\x74\x7a\xc0\x3a\xa6\xfc\xf3\xfc\x98\x57\xda\x7e\x31\x47\x9e\x7d\x53\x82\xf2\x54\x97\x6e\xcf\x8f\xb9\xa0\x5b\x2f\x77\x30\xf6\xb2\x9d\x5a\xd8\x3b\xc3\x8c\x39\x58\x3b\xb9\x9b\xd1\x51\x96\x16\xba\xea\x3f\x9d\xee\x5e\xab\xb2\xc5\x14\x6f\x46\x47\x0e\xe2\xc9\x11\x3b\xf7\xf5\xca\x37\xb9\x56\x3e\x47\xa5\x90\x71\xf0\x9d\xdb\x68\x6d\xb0\xe3\xda\xd9\x50\xe3\x1a\xaf\xb1\xa0\xa1\xea\xfc\x99\x5a\x1d\x34\xa0\xe3\xbd\x0e\xe9\x12\x86\xb6\xb1\xbc\x6a\x7e\x13\x86\xc0\xdf\xe0\x30\xe8\xe8\x81\x37\x81\x98\x73\xc5\x0b\xad\x93\x06\x6e\x35\x3e\xcc\x69\x9a\x2d\xe0\x8a\x34\x92\xed\xf6\x6f\x15\x0c\xb7\xc5\x31\x68\xd9\xe6\x6c\x7a\xa6\xb2\x74\xfe\xc4\xc1\xf4\xf2\x5c\x6a\x6e\x93\xc9\xca\x62\xa2\x8b\x1a\x29\x11\xd4\xa2\xd6\x6e\x5a\x6d\x61\x57\xd8\x06\x21\xf2\x05\xed\xd9\x5b\x27\xcf\x42\x0b\x03\x73\x08\xb3\x4b\x6b\x38\x9d\xaa\x68\x8d\x6f\x8d\x33\x90\x62\x31\xa4\x50\x1d\xaf\xd9\xe6\x87\x3d\xc8\xd9\x6f\x24\x37\x71\x9d\x39\x54\x2d\xd8\xe7\x4a\x9a\xf9\x31\x63\x88\x88\x42\xf6\x41\xaf\x0d\xd1\x02\x6c\x1b\x53\xe2\x33\xdb\xe2\x16\x57\x93\x00\x67\x98\x3f\xa0\xc0\xa8\x4c\xa0\x3a\x0d\xa8\x64\x67\x7b\x7d\x87\x5a\x4e\xe9\xfa\x98\x05\x55\x17\x81\x10\x4a\x90\xad\xcf\x09\xc6\x4a\x5a\xda\xa0\x80\x8d\xbc\x59\xcf\x4e\xb5\xd1\x32\xad\xb3\xda\x91\xfc\x89\xa0\xec\x5c\xce\x27\x75\x10\xff\x3e\x73\x60\x9e\xa6\x16\x98\x43\xf3\x56\x24\x6f\x01\xa9\xea\xb0\xbd\x95\x7d\x54\x3c\x35\x75\x69\x12\xa7\xe4\xad\x37\x96\x8a\xe7\xaa\x3c\x97\x54\xd9\xcf\x06\xd1\x32\x8f\x1b\x4e\x13\xd2\x4e\xe4\xc0\xa6\x2c\x24\x92\x2e\x11\x7f\x6e\xe1\xda\x4c\xb0\x76\x1c\xa4\xc6\x52\x49\xd4\x4c\x23\x8b\x45\x57\xcf\x34\x36\x5b\xbe\x7c\xe9\x52\x8e\x86\x99\x66\x06\x0a\x33\x90\x70\x4f\x46\xef\x17\xb4\x55\x3b\x01\x35\xc0\x08\x0d\x73\xab\x9a\x94\x4d\x35\xa4\x45\x02\x4e\x07\xe3\xb4\x90\x1d\x90\x12\x8d\xe1\xf7\x10\x19\x55\x65\x5d\x83\x6e\xf0\x1e\xb6\x53\xd3\xed\xdd\xd5\x68\x4a\x36\x77\x18\x3f\x34\x6a\xaf\x12\x3a\xd4\x55\x85\x59\x1a\xc6\x0f\x3f\x84\x79\xf9\xe9\x48\x53\x24\x20\x93\x55\x08\x23\xa9\x7a\x35\x1b\x2a\xd4\x93\xbf\x22\xc8\xb9\x3a\x23\x50\x18\xc8\x27\xaa\xc3\xe6\x92\x52\xc1\x05\x83\x91\x6a\xfc\x65\x22\xa9\x1c\xa1\xa4\x41\xea\x2a\x8c\x1f\xfc\xe0\x00\x53\x55\xa2\x3e\x51\x1a\x3a\x5b\xe2\x46\x89\x52\xe0\xab\x32\xa2\xfb\x72\x21\x9f\x12\xe2\xce\xed\xbe\xc6\x22\x69\xb7\xd9\xcf\x0a\x66\x28\xa2\x1c\x0b\xca\x76\x49\x86\xa1\x49\xbe\x3d\x00\xc7\xfa\xfe\x31\x84\xc5\x06\x31\xf0\x56\x1d\x71\x02\xaa\xfe\x0a\xe1\xb2\xbd\x69\xdc\x67\xac\x8e\x82\x20\x4b\xa8\x71\x91\xd7\x07\x91\x04\xa6\xdd\x24\xd4\x7d\x60\x33\x9d\x5c\xf5\x01\x41\xae\xd5\x39\x54\x0d\x5f\x33\x64\x50\xda\x7a\xa5\xa7\x79\x11\x71\x70\x45\x69\x78\x8b\x05\x78\x61\x7a\xcc\xbe\x6c\x2e\x2e\x1e\x1b\x8f\x92\x4c\xf9\xa1\x20\x2f\x1a\xdc\xa3\xe8\x56\xe0\xad\xef\x4c\x84\x85\x4d\xa9\xa2\xb6\x90\xab\xb0\x5c\xba\x71\x2b\x36\x65\x63\x82\x0e\x34\x4a\xcd\xdd\x84\x6f\x71\xa3\x62\xd9\x04\x68\x39\x92\x54\x23\xa3\xed\xcb\x75\x02\x40\x07\xb6\x2c\x83\x08\xaa\xca\xc8\x24\x07\x41\xf0\xa6\x30\xa8\x14\x4a\xb9\xf6\x32\xb6\x75\xf5\xe9\x49\x3b\x41\x30\xd4\x98\x4e\xb9\x28\x09\x08\xf3\xa6\x6b\x0d\x89\x2e\xec\xdb\xad\x68\x94\xa4\xb8\x29\xdc\x7e\x44\xe1\x16\x58\x40\x00\xab\xc3\x90\x7f\xc5\xc4\x57\x5b\x4f\x1d\x29\xc2\xa4\x05\xb7\x99\xa9\x69\x92\x35\x18\x01\x1f\x03\x21\x27\x75\xa5\xc0\x68\x46\xd9\x4b\xf9\x66\x2b\xaa\x9a\xeb\x47\x2c\x66\x94\x80\x1d\x8d\xd9\x23\xb0\x5b\x9b\x81\x3a\x2a\x1d\x96\x9f\x7d\xca\x95\xe3\x9a\x4d\xfd\xd9\x95\x91\x22\x84\x14\x66\x46\xe6\x4b\xab\x23\xed\xe6\x47\x02\x10\x62\x72\x2b\x7f\xc7\xc2\xa5\x33\x0e\xc0\xf5\x5b\xdd\xd9\x5c\x75\xff\xf9\xf0\x62\xa2\xdb\x67\x7a\xff\x8e\xb1\x7f\xcb\x05\xcc\xb5\x2c\x1b\x52\x7b\xf5\x46\x3c\x73\x1e\x54\xc6\xf9\x66\x74\x94\x9d\x57\x9a\x21\x94\x91\xda\x17\x51\xa3\x34\xc9\x55\xde\xf2\xae\xd9\x2f\xca\x46\xef\xbe\x5f\x5e\x17\xd9\x78\xc0\x2d\x52\x86\xdd\x71\x57\x28\x6a\x7c\x71\x2e\xb7\x96\x4d\x6b\xa6\x39\xa7\x02\x7d\xa7\xab\x6f\x54\xe8\xcf\x34\x5c\x55\x32\x97\x86\x81\x36\x5a\x81\x50\xb7\xf3\x7c\x0e\xae\xff\x2c\x13\xc9\x31\x7e\xa9\xd1\xff\xde\xf8\x90\xb2\xe7\x1a\x87\x86\x8c\xf5\x37\x70\x5e\x3f\xc5\x81\x7f\x33\xfa\xf8\x9d\x6e\x17\x65\xbb\xa1\x25\x7d\xa3\x06\xcd\xb2\x97\x63\xe5\x72\xd8\x9b\x8d\xea\x4e\x57\x97\xc0\x86\x48\x3b\x77\x2f\x02\x25\xe8\x62\x55\xdd\xf2\xb7\xc2\x60\x9a\x9d\x1c\x57\x5f\xf7\xf0\x7b\x69\x90\xaa\x72\xdb\x12\x3d\xf2\xec\x9f\xa4\x37\x20\x7b\xa2\x9f\x24\x52\xa9\xd7\xd2\x7e\x7b\xb5\x77\xa4\x2c\x43\xba\x9c\x6c\x21\x26\x69\xf2\xc0\xeb\xbf\x79\x92\xac\x9e\x1d\xf7\x60\x07\xb7\x61\x0b\x27\xab\xdd\x0c\xca\xbd\xf4\x06\xc1\x57\x65\x3b\x54\x90\x26\x93\x88\x90\x6c\xdb\x7c\xe7\x9c\x06\x0e\x5b\x6b\x87\xcc\x92\x65\x97\x71\x8c\xfe\xd7\xe2\xe2\x7c\xf2\x7f\xa7\x67\x3f\x25\xad\x71\xf8\x18\xf0\xd8\xdf\x00\xc8\x81\x4a\x54\x70\x5c\x0b\x46\x99\xfb\xda\xd3\xa6\xeb\xf2\x78\x08\xd4\xb8\x71\x33\x69\x45\x13\xdf\x19\x37\xaf\xbc\x9e\x33\x8a\xa7\xcc\xdf\x60\x81\x7c\x11\xb3\x3e\x62\xef\x78\xfe\x1e\x64\x41\xd9\x03\xae\xd3\xe3\xd7\xda\xbe\x27\x52\xb6\xef\x22\x64\xaf\xde\x2b\x49\xc8\x87\x6f\xbf\xf9\xe7\x37\x7f\xb9\x19\x7d\x54\xf7\x0a\x6e\x83\xf4\x6f\xb6\x55\x7f\xb7\x92\x91\x3d\xf1\xc9\x8a\x53\x8d\x58\xbe\x28\x28\x77\xeb\x9e\xc4\xb5\xe6\x67\x89\x7e\xee\xe7\x26\x62\x57\x0f\x5a\x2c\x03\x52\x43\x95\x1e\xca\x01\xf6\x5f\x2f\xb3\x8e\xaa\xcf\xaa\x25\x29\x8b\xd7\x67\x96\x7a\xd2\xea\x76\x2f\xe6\xa4\x87\xc4\xdb\x25\x62\x92\xaa\x6f\xe7\xef\xf9\x01\x98\x09\xd5\xc8\x6b\xa9\xce\x80\xa4\xc6\x7f\x95\x89\x15\x13\x4a\xbc\xb7\xf3\xf7\x79\xc2\xb7\x4c\xde\x7d\x84\xe1\x9d\x64\xda\xa2\x2d\xed\xd5\x97\x28\x8f\xa8\x06\x07\xae\x36\x08\xc4\x04\x0b\x9b\x4c\xac\x0c\xdc\xb7\xf8\x4d\x0f\x12\xec\x83\xec\x9c\xdd\xdd\xf1\xfc\xfd\xa3\x70\x81\x06\x3c\xc4\x82\x6a\x48\x1d\xad\x8c\x22\x1a\x76\x39\x8b\xfb\x60\x5c\x2d\x03\x07\xf1\x0d\xb4\x26\xc8\x09\x1b\x7b\xe0\x66\xad\xea\x96\x5a\xa5\x1e\x56\x4e\x13\x54\xdd\x05\xd5\x40\x21\x98\x40\xf8\x6c\x7e\xf7\x97\xe3\xd9\xc9\x65\x1f\x85\x30\x3b\xb9\x04\x0c\x92\x75\x72\xb8\x86\x18\x02\x1f\x6d\x9b\x92\xf9\x47\x25\x69\xd5\xe5\xed\x6b\x82\x82\x76\xc2\xdd\x09\x5b\x0b\xdd\x64\x00\x23\x6c\x0b\xc3\x74\xe4\xab\x22\x5d\x06\x61\x92\xf4\xae\x67\xe3\x37\xa5\xc9\xa0\xad\x99\xa4\x09\xac\x1c\x93\xfc\x04\x63\xe2\x6f\xae\xd0\x36\x0a\xf3\x35\x94\x15\x4e\x14\x0e\x9a\xbb\x50\x7b\x2b\x68\xea\x18\x47\x23\x06\x84\xc1\x0c\xcc\x4e\x5a\xf1\x86\xe3\x73\xb7\x24\xec\xdd\x5d\xa1\x38\x92\x81\x08\x4e\x32\x82\x38\x5b\x3f\x12\x56\xbc\x7f\x75\x71\x72\x61\x6f\xd3\x04\x7f\x34\x5f\x8f\xc1\x1f\x7f\x52\x9d\xad\x7b\x4d\xfe\x91\x50\xea\xb8\x89\xf2\x19\xc6\x77\x55\xb7\xdf\xd6\x6d\xa5\x1c\x0b\x97\x2e\x9e\x1b\x38\xb7\x15\x6e\x71\xef\x7e\x7c\x3b\x70\xad\xf3\xb7\xc1\xf4\x6c\x96\xb9\xda\x5b\xe7\x74\xc3\x2d\x4e\x2f\x56\x18\x83\x8f\x30\x16\xd4\xe3\x7c\xfb\xd1\xfc\xfd\x71\x2c\x5d\x81\x8f\x5c\x40\x81\xfd\x76\x06\xb0\x1d\xbe\x7c\xc1\x6b\x79\xe8\x9b\xd1\x51\x06\x49\xe9\xbc\xd9\xba\x78\x8b\x50\xa1\xb7\x86\x7c\x9c\x3c\xa2\xcc\x3c\xd5\x68\x5a\x23\xd7\xb9\xeb\xe0\x16\xff\x00\xb7\xb8\xba\xb5\x5f\xf7\x08\x8b\xee\xb0\xfd\x13\x26\xf1\xc3\xeb\x72\xe7\x92\xf7\xcb\x98\x88\xf8\xf5\xab\x57\x7f\xb1\x1d\x4e\xf4\x93\xc3\x6f\xd3\x27\x6f\xa8\x10\x21\x62\xd4\xbf\x45\xc9\xfd\xe8\xbf\x60\x12\xd0\x7b\xbe\x50\xa5\x9c\xaf\x5f\x1d\xfe\xfd\x98\x32\xd5\xa9\x5a\x5d\x29\x5d\xf9\xd6\x0f\x71\x18\xee\x7b\xeb\xd5\x5f\x8a\xb0\x86\x6d\xb6\x90\x25\x48\xa3\x16\x28\x29\x8d\x6a\x1a\xaa\xa4\x64\xab\x79\x29\x4b\xc9\x9a\xd7\xea\x89\xdb\xe6\xc3\x1c\xbd\x9b\x7f\x58\x58\x82\x86\xfd\x5f\xb2\x84\x6d\xe2\xcb\x55\xbe\x0f\x40\x86\x2f\xdd\xbf\x48\x42\x17\x7f\xc9\x52\xb7\xf8\x5b\x3d\x49\xf7\xbe\x9d\xa3\xe3\x9e\xb7\x0b\xc4\xdb\xef\x81\x42\xbe\x5e\xc4\x3c\x42\x24\x98\x33\xea\x23\xce\x1f\xf9\xee\xee\x5a\xe9\x8c\x10\xb8\x66\x28\x44\x77\x90\x08\x95\x3b\x1a\x50\x9f\xd7\x5f\xa1\x31\xfd\x65\xa1\x3a\x9a\xfe\x60\x53\x64\x1c\x97\x4f\xdc\x73\x2f\xe9\x0a\xef\xc5\x51\x00\x05\xd2\xad\x99\xd5\xe5\x13\x5f\xf9\x2b\x92\xfe\xce\x73\x2f\x78\x8c\x86\x21\x26\x6b\xfd\xcc\xe3\x9a\x52\x91\xa5\x54\x9f\x2a\xf6\x27\x3b\xa9\x9b\xd1\x51\x69\x0d\xaa\x8b\xe1\x3f\xef\xcd\xef\xb5\xa6\x1f\xde\x62\xa1\xef\x1d\xd5\x39\x71\xb6\x15\xee\xf4\xd7\x54\xc7\x4b\x25\xc9\x7d\x18\xaa\xda\xae\xdf\x28\x41\x1e\xbc\x87\x0c\x79\x5a\xa7\xea\x1f\xda\xad\xaa\x1e\xb6\xa4\xd1\x9b\x0c\x64\x6e\x22\x2d\x61\x5b\x4d\xed\x65\x56\xca\x34\x3a\x3e\x4c\x0c\xb1\x4a\x01\x55\x1d\x4d\x48\x32\x87\x57\x94\x81\xec\xf7\x1d\xca\x48\x9b\x43\x75\x4e\x3c\x40\x5c\x5a\x8e\xc7\x30\x82\x3e\x16\x95\x96\x8a\x8d\x96\xb8\x61\xe8\x2a\xec\xd9\xd9\xc9\xe2\xee\xb0\x4f\xe1\xbf\xb1\x63\x79\xda\x51\xc4\x98\xf0\x49\x7f\x44\xdb\xa4\xd2\xa4\xf1\xaa\x21\x5f\x03\x41\x6f\x11\x69\x47\xb6\x21\x87\x4a\xb5\x65\x6a\xb6\x57\xd0\x68\x4e\x03\x09\xa8\x0f\x91\x4c\x21\xb5\xba\x96\xe3\xec\x64\x91\x4e\x40\x45\x07\x88\x69\x5b\x98\x75\x89\x23\x1a\xb4\x23\xce\x10\x43\x34\x21\x0a\x5a\xf2\x8b\x48\xe0\x2d\xfe\x0d\x55\x3a\xd1\x6d\x6e\xc6\xb9\x3e\x7d\xb3\x50\x01\x80\xad\xb9\x16\x6f\xaf\x8a\x3b\x3d\x7e\x5d\x56\x01\x68\xc9\x3d\x6a\xf1\xea\x70\x37\x94\x45\xa7\xb1\x4e\x6a\x88\xc5\xcd\xe8\xa8\x38\xc1\x9a\x66\x2a\x2b\x78\xaa\x2f\xf1\xed\x43\x59\xdd\x45\xc1\xc4\x60\xe1\x03\xde\xc6\x5b\x5d\xbf\x8f\x82\x4c\x14\xf3\xf4\x87\xa9\x67\x6f\x0c\xb6\xd5\x3f\x3e\x64\xaa\x6a\xcf\x34\x7e\x50\xb7\x28\x61\x6e\x7a\x44\xb4\x22\xe7\x63\xe1\xe0\x26\x9b\x02\x71\x82\x04\xc4\x21\x0a\xce\x28\xc1\x82\x2a\x45\xda\x83\x88\x7a\x1d\x54\x50\x33\x30\x80\xc1\x36\x85\xdc\x86\x16\x7b\x40\x39\xa7\x84\xe1\xb6\xa5\x4a\x9b\x4d\xcf\x2a\x40\x99\x98\x6c\x83\xee\xfd\xb5\xdf\xcf\x55\x33\xa8\x3e\x10\x1c\x07\x7f\x35\x33\x2b\x1d\x17\x36\xd3\xd3\x36\x25\x44\x2a\x54\x67\x48\xba\xa3\xa6\xde\x0f\xb7\x76\xee\x57\xfb\x93\x36\xf6\x7e\xff\xe5\xcc\xc9\x94\x0c\x10\xd8\x1b\x4a\xf2\x87\x55\x1d\xa9\x5a\x09\xce\x49\x8c\x2f\x5f\x14\xd5\xe0\xca\xa9\x8a\xa8\x35\xa8\xe6\xf4\x42\xa4\xbb\xe1\x42\x90\xb4\xb5\x42\x31\x4a\x6a\xcc\x1f\x5b\x8a\x99\xdc\xf0\xdf\x75\x91\xba\x0c\xe5\xa4\xce\x16\x3e\xcc\x69\xc0\xe7\x88\x49\xb9\xd5\xc9\x70\xdd\xc2\x87\x05\xfe\xad\xe3\xb7\x98\x74\xfe\xb6\xeb\x45\x5d\xf4\x0e\x31\x86\x03\x94\x24\x6d\x1f\xd3\xed\x16\x92\x3e\x07\x10\x17\x06\x64\xd2\xc2\xfc\x4f\x3c\xcd\xa8\x8f\x54\xb9\x88\x7a\xbd\xd5\x72\x27\x40\x1d\x3d\xcc\xab\xe0\x3b\x27\x9c\x94\x10\x37\xcc\xbf\x4f\x5e\x6f\x7e\xaa\x9b\x56\x29\xeb\x0e\x57\x98\x98\xd2\x38\x6d\x33\xa4\x37\x92\xf0\x08\xde\xb7\x3d\xbb\xeb\x39\x94\x9b\x26\xac\xb4\xfe\x5f\x4e\x98\xeb\x9b\x8c\x91\xc4\x7a\x45\x19\x2a\x2c\xad\x95\xc3\x89\x73\xd5\x25\x55\xb6\xe3\x10\x15\xb4\x53\x8d\xf2\xce\x13\xc7\x65\x00\xb3\xee\xda\x76\xdf\x4b\xdd\xa1\xda\xbe\x3e\xe6\x75\xcf\x94\x47\x7b\x2b\xca\x3c\xc5\xc1\x30\xf4\x12\x91\xa7\x5b\x3f\x75\x13\xb6\x06\xaf\x46\x1d\x78\x1a\x21\x73\x33\x3a\x2a\xcf\x51\x35\xfc\xa9\x41\x32\xa3\xdf\x94\x03\x58\x55\xde\x10\x22\xc8\xd1\xcf\xbd\xcf\x27\x55\x51\xfc\xd9\x2c\x39\xd4\xb3\x19\x50\xef\x12\x7f\x09\x05\xea\x05\xad\x64\x5a\x11\xb4\x2d\x6c\xe7\x4c\x73\x3d\x85\x1a\xd6\x7c\x26\x06\xf9\xe2\x6d\x55\x67\xaf\x88\x96\x64\x63\x17\xff\x0e\x02\x09\xa9\x23\xc3\x35\x03\xd2\x8c\x21\x38\xdf\xb4\xa5\xcd\xe2\xc7\xfa\x29\xa6\xed\xb1\x39\xdf\xd8\xbe\x73\xda\xc8\xc0\xbc\xeb\x94\x9b\x02\x75\x4f\xf2\x0b\xf7\x1c\xd1\xa1\xd5\x72\x88\xb4\x4b\xb7\xd2\x7d\xb0\x9c\x04\x78\x52\x5d\x3a\xa6\x51\x14\x62\xd3\x5e\x43\xee\xf4\x34\xc0\x0c\xde\xa6\x4d\x2f\x69\x29\xa3\x92\x83\x17\x49\x7b\xcb\x97\x63\x50\x00\x23\xa5\xc3\xb9\x65\x83\xa4\x57\x47\x0d\x2c\x0b\xa9\x15\xf5\x9f\x34\xee\x0d\x5c\x1c\x01\x5d\x1d\x97\x5b\xf5\x6b\x4a\x04\xc1\x15\xcc\x75\x8d\xec\xbe\x3d\x34\x52\xaa\x92\x23\x8a\xc2\x9d\x9d\x73\x37\x49\xb1\x17\x98\x93\x2e\xfa\x08\xa9\x94\xca\xd6\x84\x0c\xef\xb3\x9f\x36\x14\x8c\x1b\x7a\xaf\x94\x97\xfa\x14\x24\xa0\x5a\x66\xad\x36\x02\xe8\x9c\xee\x1d\x0d\xe3\x2d\x3a\x25\x3e\xdb\x45\x62\x7f\xc4\xb2\x06\xc6\xec\x62\x5e\x19\x5d\xaf\xf5\xc9\xf4\xe7\xef\xb6\xfc\x1d\xda\xcd\x4e\xba\x78\x67\x1a\x42\xd7\xd0\x98\xfe\xba\x89\x4b\x59\xb7\xa6\x6b\xbc\x86\xcb\x9d\x68\x19\x43\xa9\xf8\x2a\xdd\xbf\xdf\xbe\xaa\xc1\xf9\x6a\xc3\x68\xbc\xde\x44\x71\xa5\x25\xd2\x80\xf0\x0d\x62\x5a\x1d\xd2\x64\xd6\x91\xca\x8e\xc1\x1c\xbc\x35\x57\xa3\xcc\x63\x16\x51\x8e\xc0\x62\x71\x32\xd6\x6f\x7c\x5d\xfd\x86\x71\xcf\x4c\xb2\xb5\xb6\xf5\x6c\xd5\xfe\x06\xaf\x37\x40\x24\x53\x2f\x64\xe0\x60\x7a\x68\xc0\xaa\x9a\x1d\x69\x36\xa2\x00\x48\xe6\x4c\x46\xe6\xbe\x7d\xe5\x98\x86\x01\xf8\xf1\xc4\x3c\x16\xf6\x71\x4a\x57\x90\x9c\x92\xc8\xd7\x86\x4d\x9c\x59\x47\x85\x7c\x99\x2a\x62\xe5\x3f\xfa\xba\xc9\x47\x1d\xe9\x97\x1d\x09\xd3\xc3\xd2\x48\x6e\x92\x66\xbf\xe2\x7e\xf9\xab\x94\xca\xb9\x37\x45\xf9\xcd\x86\x84\xcf\xa8\xb7\x75\xf4\x75\x93\xdc\x98\x75\x54\x4a\x89\x29\x7e\x29\xb5\x1f\x3d\x2c\x3e\xe2\x7e\xf9\x91\x78\x94\xeb\x91\xd2\x9c\xb5\xaa\xc0\x73\x6d\x8e\x82\xc3\xc8\xad\x0e\xff\x57\x1d\x2c\xd4\x1c\x4f\x3b\x02\x70\x8e\x78\x9e\x5b\xac\x16\xbc\x8c\x72\x2c\xb8\x36\x50\x50\xb4\x5e\x0b\x07\x2c\x79\x12\x8e\xaa\x1d\xbf\xea\x08\xe6\x9e\xe4\xa1\xaa\x73\x53\xb7\x28\x75\xeb\xa5\x1a\x95\x5b\xad\x0a\xdd\x3a\xb6\x4e\x0d\xec\x8b\x56\x35\x09\x69\x56\xe6\x17\x54\x1f\xaa\x3b\x03\x87\xee\x23\xd1\xba\x13\xa5\xcc\x6f\x4b\x77\x6e\x47\xf5\x29\x61\xe5\x69\x4b\xd1\x67\x2f\xdb\xc0\x55\xd6\x5f\xf5\x81\x40\x75\x1c\xc5\xfc\xd0\x2f\x63\x9f\xa1\x88\x21\x8e\x88\xbe\xd8\xe5\xf4\xdd\xc2\xcb\xf6\xe4\xd7\xbe\x81\xca\x9d\x56\x2a\x46\xda\x79\x52\xae\x4b\xb7\x22\x8a\xa4\x90\xc7\x48\x17\x08\x06\x4a\xcc\xdf\xab\xd0\x3f\x63\x19\x02\xef\xcf\xd1\x78\x24\x04\xd4\xf8\x49\x62\x35\x12\x0c\xfb\xfc\x98\x86\x72\xfd\xf3\x51\xa8\x8a\xcc\xea\x35\x83\x24\x0e\xa1\xdc\xd5\xcd\x13\xac\xb3\x1f\x75\xb9\x72\x43\xa3\xf9\xa8\x31\x83\x8e\x3a\x24\x3b\x33\x07\xc6\x83\x30\xa3\xea\x96\xb4\xd4\xd7\x87\x5b\x0f\x57\xfb\x1b\x63\xd5\xe7\xeb\xda\xcf\x5d\xbf\x3e\x5c\x82\x63\xba\x9c\x1e\xe4\x9e\x99\x93\x9f\x30\x4b\x21\x3d\xa4\xd1\x15\x9a\x35\xd3\x18\x34\x8d\xb1\x09\xea\x37\xa3\x23\x07\xe5\xca\x1d\x38\x9e\xeb\x0e\x9e\xeb\x0e\x9e\xeb\x0e\x9e\xeb\x0e\x9e\xeb\x0e\x9e\x7e\xdd\x41\x9d\x45\x03\x5a\xc7\x57\xcb\xd0\x5a\x5b\x13\x7b\x3c\x9b\xe7\xb2\x88\xe7\xb2\x88\xe7\xb2\x88\x86\xab\xfa\x5c\x16\xd1\x88\x4c\x3d\xcb\x22\xfc\x10\x72\x8e\xfd\x9f\x28\x0c\xde\xc0\x50\xba\xf1\xec\x1c\x6e\xbf\x20\xb7\x4d\xcd\x05\x90\x08\xa8\x3e\xd4\x4b\x83\x14\x37\xed\x25\x63\xd5\x98\x5a\xfb\x13\xed\xcf\xa8\x5a\x03\xaf\xa0\x99\xca\xbc\x39\x39\xaf\x3c\x80\x69\x60\x77\x5e\x1f\x6b\x1b\x19\x06\x01\x43\xbc\xfa\x86\x2c\x7b\x4f\x94\x1e\xd3\x0b\x08\xf7\xcc\x27\x2f\xd3\xce\xba\x27\xe7\x0b\x10\x52\x7a\x9b\x8f\xbb\xed\xa7\xc7\xde\xd4\x99\xea\xd1\x6f\x46\x47\xf9\x19\xa8\x3c\x19\x27\x46\x6e\x22\x5a\x4d\x7f\x19\x13\x81\x7b\x5d\x37\x94\xbd\xab\x80\x69\x68\xe0\xc5\xf1\xe5\xec\x65\x36\xd1\x32\x19\x8f\xdb\xce\xaf\x24\x1f\x8b\x6c\x77\x27\x42\xdb\x71\xdc\x34\x88\xe2\x63\x86\x02\x5c\x3e\x18\x6e\x31\xfb\xcc\x61\xe4\xf5\xd5\xd7\xe0\x3d\x09\xa5\xe0\x44\x41\xb7\x92\x90\x65\xcc\xb8\x80\xcb\x10\x79\x11\x62\xca\x57\x26\x3e\xf2\x92\x13\x70\x2f\xb6\xe0\xbd\x2d\x0d\x90\x0e\x0a\x8c\xc1\x9d\x72\x1e\x28\x09\x77\x8a\x06\x57\x9e\xc4\x3f\x3d\x37\xef\x7a\xb8\xda\xaf\xae\xa4\xc3\x54\x6e\x46\x47\x59\x12\x6a\xdf\x75\xdf\xe4\x9c\x4b\xfb\x5c\x6e\xf6\x5c\x6e\xf6\x5c\x6e\xf6\x5c\x6e\x56\x41\xd9\xe7\x72\xb3\xe7\x72\xb3\xaa\x53\xe1\xe7\x72\xb3\xff\xd0\x72\x33\x7e\x82\xb9\x0e\x0c\x38\x42\x51\xfb\x58\xc3\x09\xc3\x39\xdc\x6d\xbc\x44\x21\x12\xa7\xea\x3e\xd6\x16\x89\x73\x85\x5e\xad\x0d\x9c\x13\xfc\x1b\x02\x1f\xcd\x70\x1f\x93\xfe\xb8\xb9\xc8\x3f\xfe\x0d\x93\xb5\x27\x36\xc8\x33\xef\x4d\xda\xc9\xf4\x8a\x03\x85\x32\xd8\xc4\xdf\x90\x48\xe9\x20\xac\xf9\xc9\xc6\xa1\xd3\x26\xb5\xff\xb1\x85\x70\xcf\xa5\x5e\xcf\xa5\x5e\xcf\xa5\x5e\xcf\xa5\x5e\xcf\xa5\x5e\xff\xc1\xa5\x5e\x8f\x54\x00\xf5\x5c\x2f\xf4\x5c\x2f\xf4\x5c\x2f\xd4\x94\xfa\x4f\x1a\xf7\xce\xf5\x42\xee\x1d\xaf\xdf\xfd\x45\xaa\x8f\x3d\x55\x13\x4f\xa0\xe0\x47\x40\xb6\x46\x42\xad\xc1\xf4\xf2\xfc\x29\x9c\x33\x69\x8c\x8c\xfd\x32\xec\x29\x53\x23\xd0\x4e\x32\x3d\xd7\x45\xd5\x99\x30\x35\x30\x9e\xeb\xa2\x9e\xeb\xa2\x9e\xeb\xa2\x9e\xeb\xa2\x9e\xeb\xa2\x9e\xeb\xa2\xc0\x73\x5d\x14\x78\xae\x8b\xca\x90\xed\x8b\xd4\x45\xe5\x43\xfa\xf9\x45\x2e\xe7\x9c\x66\x7e\xcf\xa4\x87\x64\x9f\x56\x65\x6c\xd5\x18\xd9\x65\xc7\xa2\xca\xd4\xcc\x0d\x94\xa4\x39\xd5\x9f\x3e\x64\xbf\x29\x66\xf5\x98\x9f\x86\xb8\x77\x27\x7f\x8b\x65\x9a\x83\x09\xc4\x06\x0a\x75\x1f\x4c\xe2\x63\xab\xbb\x29\xcb\x5e\x4d\xb3\x3b\x79\xba\x8f\xa3\x86\x29\x15\x92\xbc\x71\xe7\x16\x56\x16\x8a\x68\xde\x9a\x06\x5b\x4c\xd2\x74\xe8\x2e\x06\xb1\x4d\x08\x1c\xfc\x78\x28\xb9\x96\x06\x92\x1d\xb8\xce\xee\x91\x24\x09\xd1\x79\x8d\x62\xf6\x4d\x8f\xf2\xdc\xff\x27\x5f\x65\x06\xf1\xe8\xca\xb3\x90\xda\xf9\xfd\x39\xd4\x6a\xef\x48\xec\x84\xcc\xcd\xe8\xc8\x39\xdd\xc2\xa9\x53\x2b\x0d\xec\x5c\x6f\xd7\x32\x0e\xb8\x97\x54\x54\x39\xc7\xe7\xa5\xa4\xd1\x25\x94\x96\x9a\xcb\x15\x6c\xb6\x8d\x3a\x0d\xe1\xde\x41\xb3\xe9\x59\x93\x8d\x03\x85\x80\xfe\x66\xae\x72\xb1\x1f\x3d\xb6\xe0\xdc\x71\xa9\x7d\xa3\xee\xdd\x9e\x5e\x9e\xf7\x39\x4f\xbe\xa4\x83\x80\xe8\x9b\x54\x20\x61\xcc\x11\xdb\x62\x2e\x4d\x6e\xfe\x86\xc6\x24\x80\x7b\x2f\xd3\x73\x82\xbc\xc7\x62\x33\x0d\x02\x4a\xe6\xf6\x0e\xcc\xd6\x09\x14\xf9\xcf\x3b\x6e\xb9\x12\xa7\xd4\xaf\x61\xcd\xda\xd4\xd1\xbc\x05\x2d\x6b\x69\x34\xe0\xbe\x57\xa9\x67\xd3\xb3\xac\x56\xa3\x2b\x00\xd3\x3d\xd8\x72\x93\xef\x87\x57\xb9\xa3\xab\xf8\xa0\x7a\x7b\x87\xcb\x19\x59\x33\xc4\x2b\xb3\x65\x6b\xb5\x21\x8c\xa2\x33\x54\x3e\x44\xe9\x92\x0f\xb7\x8a\xc3\xd0\x1e\x6d\x08\x0a\xa6\x06\x72\xab\x13\xc0\x7a\x50\x75\x33\x98\x33\x74\x87\xd1\xfd\xe3\x4d\x04\xd8\x11\x86\x9b\x50\x02\xd2\x3d\xb1\x58\xd0\x85\x0f\xc3\xfd\x76\x4e\x93\x49\x25\x77\xec\xea\x7c\x5d\x9b\xbb\x6e\x0b\x47\xda\x1e\xd5\x36\x86\xea\x9c\x9a\x8f\x98\xd0\x37\x9a\x0d\x32\x37\xa9\x54\x8d\xbf\xad\x8c\xcf\x20\x00\x0c\xf9\x94\x05\x8a\xd8\x97\x34\x16\x08\xfc\xf5\x6b\x80\x09\xa0\x52\xea\xa9\x83\x27\x1a\xde\xe9\x0b\xd8\x4f\xce\x17\xaf\x0e\x81\xbf\x81\x61\x88\xc8\x1a\x1d\x80\x33\xca\x10\xc0\x24\x2d\x89\x36\x81\x9a\x95\x14\x4b\xe0\x7a\x83\x18\x4a\xed\x38\x39\x13\xd3\x97\x80\x1d\x60\xaa\x72\x2e\x27\x39\x05\x3f\x81\xfe\x16\x4d\x02\xc2\x5f\x1d\x4e\x98\x44\xe5\xaf\x5f\x4f\xbe\xe2\x48\x78\x71\xe4\x41\x0f\xc3\xad\xc7\x68\x88\xba\xe5\x7c\x7e\xce\x89\x97\xcd\xc6\xa1\xe6\x7e\x33\x3a\x92\x44\xad\xce\x51\x52\x25\xea\xbf\x40\xe1\xef\x95\x53\xce\xcf\xd1\x72\xaf\x6c\x6c\xca\x65\x04\xdd\x83\xd3\x37\x0b\x70\xbc\x98\x81\x17\xa7\x21\xe4\x02\xfb\xe0\x4d\x48\xfd\x5b\xb0\x10\x92\x7c\x89\xad\xaa\xfe\x0f\xd7\x08\xcc\x88\x40\x6c\x05\x7d\xf4\x12\x04\x0c\xdf\x75\xdc\x68\x83\x0d\xee\xa6\xd0\xaa\x9b\xf6\x40\x0f\x02\x31\x02\xc3\x9a\xa2\x9f\x26\x14\x86\x81\xb1\x8c\x2d\x3c\x2f\x20\x1c\x44\x8c\xfe\x0b\xf9\x22\xb9\x19\x5c\x49\x18\x5d\xe7\x9b\xb0\x76\x2b\x5a\xf6\x18\xc6\x39\xfb\x15\xaf\x4c\x2a\xad\xa5\x1a\xde\xc2\x35\x7a\x13\xe3\x30\xe8\x27\xfe\x54\x5a\xb2\xc6\x57\xe9\x97\xd3\xe3\xcb\x94\x2f\x52\x5e\xb8\x44\x6b\xcc\x05\xdb\xbd\x34\x0a\xe8\x00\x5c\x6d\x30\x07\x98\x83\x98\xa3\x55\x1c\x2a\x00\x4b\x89\x0e\x26\xeb\xb1\xfa\x9f\xb9\xe8\x7e\x0c\x20\x38\x9e\xa9\xda\x04\x29\x3c\xa4\xa3\x4f\x10\xd2\xc2\x25\x8a\xf9\x06\xa8\x99\xa8\xff\x9e\x1e\x5f\xb6\x5b\x8b\x27\x86\xbb\x73\xa1\x1e\x2e\x61\xa5\x41\x5f\x5e\xe1\x56\xb6\x76\x8e\x07\xdc\x4a\xbf\x62\x9f\x55\xa8\x51\x87\x4d\x57\x6d\x24\x15\x84\x63\x81\xa7\x0b\x82\x61\xec\x34\x36\x8b\x64\x72\x8b\xeb\xc7\x30\xd2\xa5\x85\x9c\xec\xd6\xae\x96\x79\x1e\x48\x85\x39\xbe\x27\x83\xb9\xea\xf6\xe0\x5c\xe7\xa7\x12\x05\xaa\x0c\x79\xdf\x04\xf3\x2f\x91\x29\xc0\x1c\x22\x63\xcd\x02\x05\xcc\x40\x55\x39\x6b\x75\x05\x22\xd9\x4a\x62\xe4\xbf\x9e\xc4\x1c\xb1\xb5\x2a\x11\xb1\xb0\x3c\x0b\xcb\x14\xba\xa9\x5d\xa7\x5a\x3f\x77\x2b\x6d\x2b\x65\xb1\x0d\x8a\xde\xcd\xe8\xc8\x45\x84\x24\xa9\xad\x0e\xf1\x66\x99\x6d\x9f\xef\x5e\x15\xe7\xf0\x5b\xf8\x30\x67\xb8\x9a\x5d\x74\xd1\x4a\xe5\xc4\x28\x01\x01\xda\x42\x12\x80\x48\x41\x71\x8e\x41\xc9\x89\x7a\xe7\x0d\xe4\xa8\x69\xf1\x5e\xc5\x80\xee\x23\x73\x3b\xc0\x1c\x31\x1f\x11\x01\xd7\x68\xba\xa4\x77\xa8\xc7\x78\x39\x16\xbb\x54\xf7\xa7\x5f\xbf\xf2\x0e\x5f\xbd\xfa\xd0\x8a\x39\x6b\xbe\x4c\xe7\x74\xf8\xca\x3d\x2b\xc9\x5b\xd3\x30\xa4\xbe\x32\x86\x17\x82\x41\x81\xd6\x9d\x42\x44\x12\x92\x15\x47\x73\x4a\xcb\x09\xfb\x1d\xa8\x71\xe8\xbd\xee\x46\x0c\xc7\x87\x29\x2d\x5e\x77\x55\x88\x55\xfd\xf2\x12\xfe\xde\xc7\x8f\x2d\xd9\xa9\x96\xba\xfb\x17\x71\x5c\x27\xb9\x07\x54\x7b\xee\x80\xf1\x75\x5e\x6c\x25\x69\xc8\xf2\x71\x5a\xcc\x3b\x69\xde\x99\xac\x6e\xb0\x52\x7e\x71\x61\x94\x9b\xd1\x51\x1e\x9d\x9a\xfe\x61\x8b\xb7\xcd\xa2\x5a\x2a\x14\x39\x3b\xf9\x72\x99\x70\x1a\x03\xc4\x41\xba\x74\xc0\x9e\x59\xeb\x14\x35\xde\x2f\x51\xb0\xd3\x00\x4e\xe1\x70\x8f\xc5\xe6\x27\xea\xc3\xb0\x97\x33\xa1\xd0\x01\xb0\x80\x03\x90\x8c\x1f\x6a\x44\xb2\x99\xca\xe0\x9c\x0a\x7b\x6b\xbe\x49\x5d\x29\x75\x67\x6c\x67\x06\x3c\x3e\x02\xa9\x90\x12\x2c\x76\xd7\x08\x4b\x52\x2e\x36\x90\xf5\xab\x63\x35\x53\x51\x5d\xfe\xf2\x93\xe1\x0a\x36\x80\x5b\x4a\xd6\xca\x18\x4d\x71\xd5\x05\xa3\xdd\x2a\x27\x86\x1f\xb0\x8a\x56\xad\x64\x7a\xba\x8b\xdd\x24\x76\xf2\xf0\x20\xb2\xd3\xa7\x44\x30\x1a\xf2\xd2\x8e\xaa\x49\xe4\x6f\x72\x88\xda\x14\x66\x85\xf0\x5b\xfc\xd8\x2c\xa4\x1f\xd2\x5e\x81\xec\xd9\x0a\x48\x8d\x75\x2f\xfd\x64\xb9\x7c\x6a\x99\x17\x8b\x1f\x0b\xb2\x3d\x62\xf4\x0e\x07\x28\x30\xee\x74\x30\x06\x54\x6c\x10\xbb\xc7\x1c\x01\x2c\xe4\x53\xbc\x26\x94\xa1\xe0\x00\x5c\x90\x70\x07\x28\x41\x80\xae\xc0\x3c\x5e\x86\xd8\x7f\x87\x76\x73\x28\x36\xe3\xf4\xbf\x2a\xe1\x3b\xf9\xdf\x39\xdc\x22\x1b\x40\x4c\x32\x60\xdb\xd5\x54\x3d\xe1\x69\xb8\xa3\x61\xca\x91\x59\xf0\x52\x01\x74\x7b\xcf\xad\x14\xda\xbd\x96\xf3\xa6\x44\x50\x53\x3b\x11\x73\x4c\xd6\x60\xb1\x38\xfb\xf0\x62\x82\x25\x5f\x06\xb1\xca\x94\xf9\x8a\xf3\x8d\xa7\x63\x25\xed\x42\xca\x15\xe3\x66\x74\x7f\xc5\x30\x37\xa3\xa3\x2a\xdc\xaa\x23\xba\x91\xa5\x6f\x8f\xe4\x56\xbd\x46\xe0\x16\x29\x44\x97\x48\x2a\xd2\xb4\x28\x41\xa3\x22\x31\xbb\x45\x3b\x7f\x03\x31\x39\x00\x59\x86\x52\xe2\x43\x6f\xdb\x3b\x18\xc6\x28\xcb\x27\xad\x08\xf7\x88\x68\xd4\x93\xae\xc1\x09\x76\x43\xf2\x11\xc9\xe4\x98\xa8\x32\x8d\x27\x42\xca\xc7\x44\xa9\x9e\xac\x52\x1c\xf4\x20\xeb\xd5\x06\x81\x08\x8a\x8d\xc5\x54\xe2\x18\xf5\x62\x11\x23\xfa\x92\xa9\x18\xd5\xac\xac\xc3\x9b\xd1\xff\x9b\x1c\x70\xbe\x99\xe0\xe0\x9f\x8c\xc3\x83\x28\x5e\xde\x8c\xb2\x02\x50\x0e\xd0\x6f\x51\x3e\xef\x84\x74\xd6\x71\x69\x52\xfa\xf1\xfe\x89\xb9\x9d\x67\x55\x8f\xb4\xc8\x26\x9c\xce\x1e\xb9\x92\xb6\xab\xc1\xa4\x34\x7f\x25\x57\x3a\x05\x68\xa5\x68\xd8\x4f\x01\xa7\xee\x1a\xd0\x77\x95\xf6\xa6\xb2\x49\xd3\x9a\xc7\xbc\xea\x56\x99\x82\x7d\xb2\x2c\xda\x40\x77\xdb\x64\xfa\xda\xa8\x26\x09\x88\xab\x15\xf2\x1b\x96\xa7\xdf\x7e\xcb\x0f\x30\xfd\x04\x23\xfc\xc9\xa7\x0c\x7d\xba\x3b\x3c\x50\xe3\x9c\x6a\x18\x4e\x2e\xbd\xdd\xab\x0c\x9d\x9f\xa9\x3d\xd0\xf8\xc3\x56\xdc\x78\x9b\xe7\x2e\x3d\xd2\xb8\x44\x91\x41\x18\x26\xdb\xec\x1f\xbc\x8b\x97\x88\x11\xa4\xb2\x4b\xd5\xf2\x34\x65\x8c\x7a\x28\x6e\x06\x78\xef\xae\x29\xab\xe4\x83\x2d\x7c\x78\x4f\x4c\x8a\x7f\xd8\xab\x2a\x89\x23\x91\xf4\x19\xca\xf4\x16\x32\xc5\xb1\x1b\x28\x8c\xe1\xe9\xd3\x2d\x02\x71\x3a\x26\xb8\xdf\x20\xa2\x8b\xc8\xa4\xa1\x95\xc9\xb5\x05\x2f\x6c\x1f\x82\x00\x40\x6e\x60\xb6\xb3\x03\x3f\x1b\x52\x4e\x6e\xce\x13\x37\x0d\xdf\x3d\x69\x32\x47\x09\x9a\x4f\x8c\xd4\x59\xc4\x3a\xca\x80\x02\xb7\x37\x59\xaa\xc1\x1c\x78\x95\xb1\xec\x0e\x49\x26\x93\xef\x92\x89\xdb\x05\x76\x4e\x76\x5c\xcc\x4e\x8e\x67\x01\x22\x02\x8b\xdd\x5c\x7b\x9f\xac\xe1\xc5\x08\xd9\x73\x23\xce\x63\xc4\xde\x5f\xfe\x94\x3f\x3b\xc5\x88\x88\xd9\x49\x8b\x73\x43\xfb\x45\x07\xe5\xa1\x03\x18\xc7\x21\xc4\x95\x3e\xeb\xfe\xcf\x7b\xb4\xd7\x4a\x28\xd0\xe1\xe3\xae\xad\x75\xec\xe2\xa8\x59\x3f\xed\xc6\x47\x5f\xba\xef\xc1\x5e\x04\x63\x8e\x98\x5c\x87\xce\x1c\x64\x01\xb4\xe4\xa1\x56\x22\xac\xdd\xbe\xab\x9c\x5d\x35\xd6\x15\x1b\xaa\x6a\xa3\x54\xf3\x62\x71\xe9\x07\x34\xc5\x95\xa1\x1c\x21\x5f\x25\x22\x13\x20\x25\x98\x0d\x9c\xb1\x6c\xa3\xde\xd3\x77\x0b\x00\x63\xb1\xf9\x8d\x74\x38\x3a\x6a\x39\x40\x5e\xa6\x46\x88\xc1\x7c\x8b\xbd\xea\x00\x69\x42\x86\x1f\xc2\xf8\x61\xca\xca\xbb\xe4\xf3\x35\x4c\x48\x0f\x6f\x7c\x5d\xa2\x07\x42\x4c\x10\x80\x6c\xad\x2a\x86\x6c\x74\x18\x01\x89\x2a\x08\x20\xda\x52\x02\x4e\x4e\xe7\x97\xa7\xc7\xd3\xab\xd3\x93\x56\x06\x43\xef\xc1\x9c\x7b\x30\xa5\xe6\x8f\x28\xdc\xda\x75\xf8\x0f\xa1\xaa\x44\x19\x58\x9c\x1f\x9f\xae\x95\xc3\x39\x29\x2b\x81\x61\x61\x5f\x3f\x83\x04\xaf\x10\xaf\x6e\x6b\xdd\x24\x3c\x7c\xac\x40\xaa\x18\xb5\xca\x62\x53\x0b\xbd\xb5\x90\x6d\x04\xe6\x2d\x16\xe0\x12\x45\x14\x50\xa2\x4f\x65\xc3\xb0\x2b\x6d\x06\x19\xd0\x49\x1d\x55\x5e\xdc\x23\xd2\x26\xc7\x54\x30\x24\x12\xb7\x08\x45\x40\x30\xe8\xdf\x4a\x01\x24\x91\xfc\x13\x07\x7c\x47\x7c\x29\x84\x54\xc6\xda\x3f\x74\xc8\x09\x73\x20\x85\xee\x1d\x0c\x11\x11\xf2\x4b\x53\x6a\x2b\x0d\x3e\xcf\x5b\x63\xe1\xc9\xaf\x3c\x01\xd7\x6a\xce\xfa\x11\xa1\x02\x71\x8f\xa1\x15\xc0\x44\x53\xa0\x23\x35\x9f\x0a\xce\x95\x16\x15\x8f\x60\x75\x2a\x51\x83\x45\x39\xd6\x87\x89\x20\x81\x25\x9d\x15\xa6\xfa\x5a\x5b\xbe\x50\xb8\xe8\x6b\xf9\x8a\x1b\x0a\x1d\xac\x0f\xc0\xaa\x07\x7d\x1f\x61\xf8\x0a\x23\x12\x06\x17\xa4\xfa\x8a\xad\x46\xa7\x74\x84\x0b\x16\xfb\x42\x63\x24\x28\x90\x40\x3d\xd5\x51\x7d\x4b\x03\xdd\x3f\x49\x77\x23\x56\xa8\x06\x28\x0a\xe9\x4e\xc5\x5c\x21\xcf\xbc\xdb\x91\x52\x8f\x3c\x7a\xb3\xd4\xb9\x7b\x2c\x36\x72\x09\xfa\x92\xd1\x86\x02\x07\xd1\x06\x8d\x00\x76\xb4\x45\xab\x34\x42\x49\x2c\x3a\xb7\xa5\x8b\x72\x2e\xa6\x74\x2a\xf7\xc4\x54\x6a\xa6\xfa\x07\xb1\x3d\xcd\x01\xb9\xa4\x66\xde\xcf\xb6\x3d\x89\x19\x0a\xa1\x48\x4f\x0e\xa8\xa5\xb4\xba\x31\x23\x11\x91\x69\x92\x42\xb2\x71\xa5\x20\x65\x28\xa2\x1c\x0b\xca\x76\x52\xc4\x49\x11\xd8\x3c\x06\xf0\xf9\x31\xcb\x59\xbb\x73\x47\xbb\xd3\x9a\xab\x43\x69\x1c\xb5\xaa\x57\x6d\xc5\x93\x29\xf8\x41\xd6\x3c\xed\x84\x5a\xee\x82\x9a\x94\x16\x35\x5e\xa7\x66\xd0\xf2\xb4\xd5\x4d\x4a\x8c\x2a\x68\xe7\x4f\x9c\x92\x20\xa2\x98\x88\x85\xbe\x8e\xa1\xa3\x05\x3c\xce\xff\xea\xec\x7a\x63\xf3\xe4\xcb\x24\x49\xd1\x4a\x73\x9d\xcb\x3f\x86\x74\xcd\x47\xb9\x87\x1f\x06\x30\xbc\x53\x72\x67\xb2\xd2\x90\x21\x8a\xbd\xa4\xc2\x04\x27\xb7\x31\x17\x60\x89\x80\xed\x83\x2f\x6d\x64\xdb\x3d\xd4\x56\x6b\xe8\x36\x4b\x88\x08\xa6\x60\x9a\xfe\x53\xf9\x89\xdb\xab\x1b\x33\xd3\xb5\x8f\xe4\x24\x5b\xdf\xd9\xf8\x19\xe6\x90\x6d\x95\x94\x9f\x4c\xcd\xbd\x88\x99\xf9\xd5\xbc\x25\xa7\x5c\xb8\x23\xd1\xa9\x3a\x51\xff\xeb\x16\x6c\x6d\x99\x52\xf3\x4a\xf6\xad\x00\x54\xe5\x38\x3b\xdb\x2e\xb6\x5b\x1f\xdf\xae\x70\x6b\x8c\x86\x56\x12\x0d\x95\xdb\xd9\xd4\x6c\xf1\x41\xa4\x5e\xf6\x16\xa4\x72\x48\x79\xdf\xec\xdb\xdc\xb1\xd4\x1c\x7a\x41\x2a\xaa\xc2\xfd\x26\xe2\x90\xc6\x22\x8a\x45\xcf\x3c\x88\x0b\x05\x04\x04\x98\xa9\xf6\x41\xbb\xc4\x85\xb6\x37\xff\x05\xf2\x2f\x89\x12\x10\xe6\x46\x73\x0e\x5e\xac\x55\xb7\x34\x81\x92\xdf\x8c\x3f\xde\xee\x60\xe5\x51\xc7\xce\x30\xe9\xc1\xe4\xfb\x7f\xc7\xd8\xbf\xe5\x02\x32\xe1\x49\xa5\xef\x49\x63\xad\x22\xe7\x89\x21\xdd\x9e\xad\x07\x51\xe9\x4a\x4d\xe3\x7f\xcb\x41\xc1\x42\x8e\x6a\x91\x3d\x00\xc7\x3a\x49\x0d\x82\x25\x83\xc4\xdf\x8c\x81\x74\x07\xd5\xd5\x5b\xca\x81\xdf\x40\xbe\xc9\x18\xb0\xed\x44\xea\x90\xe3\x3a\x69\xa3\x13\x14\x7a\x50\x46\xe5\xe9\x51\x06\xde\x5f\xfe\x04\xaa\xb1\x6d\x35\xe9\x2e\x20\x4d\xf1\x21\x2f\x37\xb9\x83\x51\xe4\x05\xe8\x6e\x88\xe6\x74\x86\x58\x2e\xd6\x1a\x3b\x77\xf1\xd0\xb6\xbc\xbe\x0c\x46\xdd\x75\x03\x41\xba\x03\xd2\x4d\x45\x8d\x42\xb5\x97\xbd\x65\x6d\x64\x18\x04\xd9\xa8\x51\x6a\x2a\x77\x32\xde\x1f\x0b\x95\x9c\xec\xbc\x44\x11\x6d\x22\x38\xf5\x0e\xe8\x99\x3c\xb6\xc6\xc2\x6c\x25\x10\x93\x00\x31\xdb\x2d\xd2\xe0\x5d\x10\xff\x58\x2a\xda\x7b\x1c\x86\x3a\x41\x55\x6e\x39\xe9\xb5\xfc\x97\x0a\xd6\xa1\x60\xac\x63\x1a\x5b\xa8\xbe\xed\xe8\x10\x0f\x87\x15\xdc\x46\xff\xd8\x87\x99\xdb\xda\xd9\x42\xdc\x37\x56\xa8\x60\x18\xbc\x2d\x6e\xd6\x9b\x33\xc2\xca\xdf\x40\xb2\x46\xbc\x4f\x74\xaf\xdb\x28\xce\x49\xaf\xc2\xf8\x61\x80\x6c\xc4\x54\x0d\x66\x57\x4e\x85\x7d\xea\x96\xed\x9e\xc9\x45\x23\xe3\x34\x2a\x36\xe9\xc3\x40\x8f\x83\x85\x93\x6e\x11\x14\x9b\x2f\x77\x76\x71\x89\x42\x28\xf0\x9d\x4e\x9a\xd4\x77\xa8\x9a\x42\x8b\x42\x64\x40\x53\xc0\xfc\x70\x11\xf1\x34\xc6\xa0\x26\x6f\x2e\xda\x92\x7c\xb3\xc2\x24\xc8\xa6\x33\xe5\xc2\xef\xaa\xcd\xb8\xa1\xcf\xf5\x8d\xea\x44\xe8\xf1\x1d\x17\x68\x7b\x33\x1a\x83\x9b\xd1\x12\x72\x74\x33\xfa\xd0\x75\xed\xbe\xe8\x74\xb4\x23\x94\x99\x92\xcd\x03\xd5\xff\xca\xa9\xe9\xbf\x3e\xec\x67\x0a\x6d\x1c\x2f\x16\x3f\xf6\xcf\xf1\x9d\x67\xd2\x61\xad\xd1\x6d\xd2\x5d\xed\x51\xa7\x9c\x49\x2c\x36\x88\x08\xec\xcb\x9f\x3b\x52\xbf\xdf\x48\x4e\x42\xc4\xac\x8f\x20\xbd\x32\x0b\x2f\x91\x90\x86\x91\xc1\xad\xc4\x07\x6a\xcd\x4d\xa2\x4d\x4e\xef\xe6\x36\x7b\x6b\x29\xf2\x58\x43\x57\xdb\x6d\x6b\x2c\xfe\x67\xda\x1f\xf1\x3b\xca\xd6\x13\x39\x62\x85\x1d\x57\x48\x12\xe8\xa9\xb1\x24\x88\x47\x57\x58\x9d\x06\xe9\x68\xb9\x4a\xde\x1b\x97\xec\xa5\x92\xe8\x76\xe9\xc0\x22\x65\x4b\xc6\x41\xed\x5e\x1f\xda\x02\xde\x1b\x33\x86\x45\xf1\x98\xdc\x01\xad\xa5\xe3\xe3\x44\xaa\xf7\x8f\x9a\xb3\x6b\x17\xc8\x67\x48\x70\xd3\xed\xb8\x51\x73\x8b\x5b\xb4\x9b\x5e\x9e\x37\xcf\x4e\x33\xef\x3f\x56\x7e\xb2\x13\x97\xe1\xe3\x37\xef\xce\x16\x00\x25\x54\x4a\xf2\x5a\x06\x8a\xdf\x54\x41\xcf\xad\xd5\x2f\x28\x0c\xdf\x11\x7a\xdf\xae\x39\xe0\x20\x2d\xe4\x54\xdf\xa4\x5c\x7b\xa4\x72\x9f\xb7\x03\xb0\x40\x08\x5c\xa7\x0f\xc0\xf4\x97\x05\x08\xa8\xcf\xeb\xdb\x8d\xa0\x5b\x6e\x2f\xa3\xcd\xb4\xf2\x28\x83\x57\x9d\x46\xda\x05\x2d\x9a\xa3\xdd\xac\xf5\x48\x1b\x54\x6f\x46\x47\x0e\x52\x7c\x3f\x81\x47\xd5\xdd\xf2\x6b\xce\x49\xe1\x3d\xcf\x76\xb6\x3e\xd6\x95\xa8\x83\x2f\xab\x2e\xdc\x53\x15\x80\xf7\xdc\x0b\x29\x0c\x3c\xd3\xd1\x80\x79\x7e\x32\xa6\x59\x6a\x89\x10\xb0\x18\x75\x5d\xe9\xda\x71\x06\x59\xf3\x36\x73\xea\xc1\x07\x7b\x27\x72\x33\x3a\x2a\x53\xac\x33\x43\x0c\xd4\x40\x51\x91\x2b\xdb\xc6\x2f\xa1\x9d\x59\xe4\xdc\x6f\xf9\x35\xee\xd4\xfd\xaf\xcb\x72\xd6\xe0\x37\x50\x4f\xc2\x9b\xd1\x51\x69\xa2\x9d\x97\x06\x2d\xf9\xf1\x62\xf6\xf8\x5b\x14\x2d\xb9\xe7\x73\x5c\xde\x98\x92\x15\xed\x8f\xba\xe9\x5f\x61\xe5\x32\xed\xbe\x6f\x13\x2f\xcc\xe3\x78\xcd\x27\xe5\x6f\x6d\xbb\x46\xfd\x3f\x2f\x4a\xda\xf4\x0e\xb8\x33\xab\xa6\x52\xdb\xa9\xbc\x07\xea\x52\x3a\xbb\x89\xd4\x7d\xd5\x57\x9f\x69\xd5\x57\x75\xab\xbe\xaa\x59\xf5\x82\x14\x5b\x86\x74\xad\x76\x86\xee\xb4\xc7\x93\xf2\x6e\x4c\xd6\x29\xa0\x1d\x81\x5b\xec\x7b\x91\xbd\x5a\x06\x93\xf5\x90\xeb\x5e\x31\x99\xf2\xba\x0f\x85\xbc\x5d\xf9\x32\xa1\xba\xaf\xfc\x80\x3d\x30\xf3\x8d\x29\x6b\x1a\x52\x9a\x45\xcf\xbd\xdf\x78\x93\x67\xbf\x92\xa4\x5c\x4e\x74\x14\x56\x0b\x4b\x11\x0b\xca\x30\x0c\xd5\x8e\x3a\xd8\x06\x5d\xd6\xbb\xe5\x3c\x5a\xed\xf3\x76\xd8\xdf\x8c\x8e\x4a\x44\xea\xbc\xd4\x5f\xba\x71\x67\xbb\x85\x18\x64\x90\xa1\x8e\xe4\xdb\xf5\xbb\xac\xb6\x77\x2b\x36\x5e\x85\x69\x54\xa7\x96\xeb\x84\xf7\x20\x2e\xa5\x3a\x9a\x57\x1d\x70\xa4\xbc\xf3\xe9\x76\x4b\x49\xda\x30\xbb\x4d\xef\xca\xfd\x90\x72\xae\x62\xba\x79\x3e\xdd\x23\x78\x87\xee\x29\xbb\xe5\x9f\xf4\xdd\xdc\x9f\xa2\xdb\xf5\xa7\x58\xe0\x90\x7f\xc2\x11\x41\xe2\x60\x36\x3f\xcf\x5f\xc0\x52\x11\xa3\x2a\xf1\x30\x01\xb3\x39\x80\x41\xc0\x10\x57\xad\x84\x8e\x67\x27\x97\x80\x50\xd1\x2e\xbf\x6b\x0f\x98\xdc\xbc\xf6\x54\x55\x57\xcf\x21\x07\x25\x7f\x2f\x68\xe6\xa3\xf2\x09\xc1\xbe\x8b\x17\xae\xd2\xb2\xe2\xec\x3e\x70\x9f\x15\x94\xea\x72\x20\x09\x42\xc4\x41\x4c\xb6\x90\xf1\x0d\x0c\xd5\xe5\x97\x4b\x2a\x36\x60\x0b\xa3\x6b\x8d\xfa\x07\xfd\x8f\x3a\xad\xbc\xfe\x50\x18\xb8\x29\x8d\xfb\x8f\xf4\x07\xbb\xe1\x7f\xff\xc3\xef\x7f\xf8\xff\x01\x00\x00\xff\xff\x0a\xa2\xe4\x70\x67\x56\x01\x00") - -func schemaJsonBytes() ([]byte, error) { - return bindataRead( - _schemaJson, - "schema.json", - ) -} - -func schemaJson() (*asset, error) { - bytes, err := schemaJsonBytes() - if err != nil { - return nil, err - } - - info := bindataFileInfo{name: "schema.json", size: 0, mode: os.FileMode(0), modTime: time.Unix(0, 0)} - a := &asset{bytes: bytes, info: info, digest: [32]uint8{0x16, 0x3a, 0x6d, 0x45, 0x58, 0xc1, 0x87, 0x23, 0xf2, 0x10, 0x81, 0x88, 0x2, 0x85, 0xa5, 0xc2, 0xec, 0x8, 0xe7, 0x19, 0x53, 0x3b, 0x82, 0xc7, 0x4b, 0xa0, 0x4a, 0x44, 0x81, 0xa, 0xde, 0xa6}} - return a, nil -} - -// Asset loads and returns the asset for the given name. -// It returns an error if the asset could not be found or -// could not be loaded. -func Asset(name string) ([]byte, error) { - canonicalName := strings.Replace(name, "\\", "/", -1) - if f, ok := _bindata[canonicalName]; ok { - a, err := f() - if err != nil { - return nil, fmt.Errorf("Asset %s can't read by error: %v", name, err) - } - return a.bytes, nil - } - return nil, fmt.Errorf("Asset %s not found", name) -} - -// AssetString returns the asset contents as a string (instead of a []byte). -func AssetString(name string) (string, error) { - data, err := Asset(name) - return string(data), err -} - -// MustAsset is like Asset but panics when Asset would return an error. -// It simplifies safe initialization of global variables. -func MustAsset(name string) []byte { - a, err := Asset(name) - if err != nil { - panic("asset: Asset(" + name + "): " + err.Error()) - } - - return a -} - -// MustAssetString is like AssetString but panics when Asset would return an -// error. It simplifies safe initialization of global variables. -func MustAssetString(name string) string { - return string(MustAsset(name)) -} - -// AssetInfo loads and returns the asset info for the given name. -// It returns an error if the asset could not be found or -// could not be loaded. -func AssetInfo(name string) (os.FileInfo, error) { - canonicalName := strings.Replace(name, "\\", "/", -1) - if f, ok := _bindata[canonicalName]; ok { - a, err := f() - if err != nil { - return nil, fmt.Errorf("AssetInfo %s can't read by error: %v", name, err) - } - return a.info, nil - } - return nil, fmt.Errorf("AssetInfo %s not found", name) -} - -// AssetDigest returns the digest of the file with the given name. It returns an -// error if the asset could not be found or the digest could not be loaded. -func AssetDigest(name string) ([sha256.Size]byte, error) { - canonicalName := strings.Replace(name, "\\", "/", -1) - if f, ok := _bindata[canonicalName]; ok { - a, err := f() - if err != nil { - return [sha256.Size]byte{}, fmt.Errorf("AssetDigest %s can't read by error: %v", name, err) - } - return a.digest, nil - } - return [sha256.Size]byte{}, fmt.Errorf("AssetDigest %s not found", name) -} - -// Digests returns a map of all known files and their checksums. -func Digests() (map[string][sha256.Size]byte, error) { - mp := make(map[string][sha256.Size]byte, len(_bindata)) - for name := range _bindata { - a, err := _bindata[name]() - if err != nil { - return nil, err - } - mp[name] = a.digest - } - return mp, nil -} - -// AssetNames returns the names of the assets. -func AssetNames() []string { - names := make([]string, 0, len(_bindata)) - for name := range _bindata { - names = append(names, name) - } - return names -} - -// _bindata is a table, holding each asset generator, mapped to its name. -var _bindata = map[string]func() (*asset, error){ - "schema.json": schemaJson, -} - -// AssetDebug is true if the assets were built with the debug flag enabled. -const AssetDebug = false - -// AssetDir returns the file names below a certain -// directory embedded in the file by go-bindata. -// For example if you run go-bindata on data/... and data contains the -// following hierarchy: -// data/ -// foo.txt -// img/ -// a.png -// b.png -// then AssetDir("data") would return []string{"foo.txt", "img"}, -// AssetDir("data/img") would return []string{"a.png", "b.png"}, -// AssetDir("foo.txt") and AssetDir("notexist") would return an error, and -// AssetDir("") will return []string{"data"}. -func AssetDir(name string) ([]string, error) { - node := _bintree - if len(name) != 0 { - canonicalName := strings.Replace(name, "\\", "/", -1) - pathList := strings.Split(canonicalName, "/") - for _, p := range pathList { - node = node.Children[p] - if node == nil { - return nil, fmt.Errorf("Asset %s not found", name) - } - } - } - if node.Func != nil { - return nil, fmt.Errorf("Asset %s not found", name) - } - rv := make([]string, 0, len(node.Children)) - for childName := range node.Children { - rv = append(rv, childName) - } - return rv, nil -} - -type bintree struct { - Func func() (*asset, error) - Children map[string]*bintree -} - -var _bintree = &bintree{nil, map[string]*bintree{ - "schema.json": {schemaJson, map[string]*bintree{}}, -}} - -// RestoreAsset restores an asset under the given directory. -func RestoreAsset(dir, name string) error { - data, err := Asset(name) - if err != nil { - return err - } - info, err := AssetInfo(name) - if err != nil { - return err - } - err = os.MkdirAll(_filePath(dir, filepath.Dir(name)), os.FileMode(0755)) - if err != nil { - return err - } - err = ioutil.WriteFile(_filePath(dir, name), data, info.Mode()) - if err != nil { - return err - } - return os.Chtimes(_filePath(dir, name), info.ModTime(), info.ModTime()) -} - -// RestoreAssets restores an asset under the given directory recursively. -func RestoreAssets(dir, name string) error { - children, err := AssetDir(name) - // File - if err != nil { - return RestoreAsset(dir, name) - } - // Dir - for _, child := range children { - err = RestoreAssets(dir, filepath.Join(name, child)) - if err != nil { - return err - } - } - return nil -} - -func _filePath(dir, name string) string { - canonicalName := strings.Replace(name, "\\", "/", -1) - return filepath.Join(append([]string{dir}, strings.Split(canonicalName, "/")...)...) -} diff --git a/pkg/authconfigmap/assets.go b/pkg/authconfigmap/assets.go deleted file mode 100644 index fed4761932..0000000000 --- a/pkg/authconfigmap/assets.go +++ /dev/null @@ -1,274 +0,0 @@ -// Code generated by go-bindata. DO NOT EDIT. -// sources: -// assets/emr-containers-rbac.yaml (1.468kB) - -package authconfigmap - -import ( - "bytes" - "compress/gzip" - "crypto/sha256" - "fmt" - "io" - "io/ioutil" - "os" - "path/filepath" - "strings" - "time" -) - -func bindataRead(data []byte, name string) ([]byte, error) { - gz, err := gzip.NewReader(bytes.NewBuffer(data)) - if err != nil { - return nil, fmt.Errorf("read %q: %w", name, err) - } - - var buf bytes.Buffer - _, err = io.Copy(&buf, gz) - clErr := gz.Close() - - if err != nil { - return nil, fmt.Errorf("read %q: %w", name, err) - } - if clErr != nil { - return nil, err - } - - return buf.Bytes(), nil -} - -type asset struct { - bytes []byte - info os.FileInfo - digest [sha256.Size]byte -} - -type bindataFileInfo struct { - name string - size int64 - mode os.FileMode - modTime time.Time -} - -func (fi bindataFileInfo) Name() string { - return fi.name -} -func (fi bindataFileInfo) Size() int64 { - return fi.size -} -func (fi bindataFileInfo) Mode() os.FileMode { - return fi.mode -} -func (fi bindataFileInfo) ModTime() time.Time { - return fi.modTime -} -func (fi bindataFileInfo) IsDir() bool { - return false -} -func (fi bindataFileInfo) Sys() interface{} { - return nil -} - -var _emrContainersRbacYaml = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\xc4\x94\x3f\x8f\xdb\x30\x0c\xc5\x77\x7d\x0a\x21\xf3\x39\x87\x6e\x85\xc7\x2e\xdd\x0f\x68\x97\xa2\x03\x25\xbf\xf8\x74\x27\x8b\x02\x29\xa7\x7f\x3e\x7d\x21\x39\xbe\x2b\x5a\xa7\x48\x8a\xa0\x9d\x44\x93\xf6\xd3\x8f\x0f\x26\x29\x87\x8f\x10\x0d\x9c\x7a\x2b\x8e\xfc\x9e\xe6\xf2\xc8\x12\xbe\x53\x09\x9c\xf6\xcf\x6f\x75\x1f\xf8\xfe\xf8\xc6\x3c\x87\x34\xf4\xf6\x81\x23\xcc\x84\x42\x03\x15\xea\x8d\xb5\x89\x26\xf4\x16\x93\x74\x9e\x53\xa1\x90\x20\x6a\x64\x8e\xd0\x5a\xed\x2c\xe5\xf0\x5e\x78\xce\xda\xdb\x4f\xbb\xdd\x67\x63\xad\xb5\x02\xe5\x59\x3c\x5a\xae\x0a\x68\x26\x0f\x3d\x55\x8f\x10\xd7\x2a\x23\x4a\x4b\x5d\x20\xa2\x90\x63\xf0\x20\xef\x79\x4e\x45\x77\x77\x76\x4d\xb5\xd8\x73\x3a\x84\x71\xa2\xdc\x9e\x70\xc4\xe9\x9d\xcc\xc3\xcb\x79\x1f\x79\xdc\x22\xb8\xb3\xbb\x18\xb4\x9d\x5f\xa8\xf8\xc7\x1a\x0c\x50\x2f\xc1\xa1\x69\x0b\xa8\xb4\x08\x43\x28\x4b\x35\x62\xc9\x2c\x91\xe7\x18\xe1\xab\x9d\x35\x47\x29\x71\x39\x7d\x91\x57\xc1\x48\x0e\xf1\xf2\x66\xbd\xa0\xfc\x66\xd7\x2b\x48\x7e\xe5\x5c\x49\x16\xf4\x8d\x0b\x28\x67\xdd\xbc\xa4\x32\x1e\xe6\xa8\x58\xac\x1a\x90\x23\x7f\x9b\x9a\x73\x37\x76\xe9\x3a\x47\xdc\x4b\x27\xbf\x10\x3f\xb1\xfb\xcf\x68\xf8\x5a\x90\xea\x28\x6d\x3a\x1a\xd2\x28\x50\xdd\xfe\xcf\xff\x1d\xe4\xd9\x21\xdf\x62\x16\x8e\xcb\x04\xd5\xc0\x85\x34\x84\x34\xde\x9c\xff\xea\x29\x31\x5d\xd7\x99\xbf\x58\x5c\xef\x96\x06\x2e\xd8\x5f\x1c\xf1\x80\x43\xad\xaf\xde\xfd\xe1\x12\x63\xed\x4f\xcb\xf1\x8c\xa4\xce\xee\x09\xbe\x68\x6f\xba\xab\x34\x3f\x28\xe4\x9c\xe6\x8f\x00\x00\x00\xff\xff\x8b\x95\x6b\x36\xbc\x05\x00\x00") - -func emrContainersRbacYamlBytes() ([]byte, error) { - return bindataRead( - _emrContainersRbacYaml, - "emr-containers-rbac.yaml", - ) -} - -func emrContainersRbacYaml() (*asset, error) { - bytes, err := emrContainersRbacYamlBytes() - if err != nil { - return nil, err - } - - info := bindataFileInfo{name: "emr-containers-rbac.yaml", size: 0, mode: os.FileMode(0), modTime: time.Unix(0, 0)} - a := &asset{bytes: bytes, info: info, digest: [32]uint8{0xba, 0xbc, 0x51, 0xe8, 0x47, 0x23, 0x61, 0x8, 0xb1, 0x55, 0x1d, 0xce, 0x13, 0x1e, 0xda, 0x59, 0x4e, 0x6d, 0xda, 0x2b, 0xc5, 0x4, 0x3d, 0x7a, 0x8, 0xce, 0x29, 0xdf, 0x28, 0xab, 0x7d, 0x60}} - return a, nil -} - -// Asset loads and returns the asset for the given name. -// It returns an error if the asset could not be found or -// could not be loaded. -func Asset(name string) ([]byte, error) { - canonicalName := strings.Replace(name, "\\", "/", -1) - if f, ok := _bindata[canonicalName]; ok { - a, err := f() - if err != nil { - return nil, fmt.Errorf("Asset %s can't read by error: %v", name, err) - } - return a.bytes, nil - } - return nil, fmt.Errorf("Asset %s not found", name) -} - -// AssetString returns the asset contents as a string (instead of a []byte). -func AssetString(name string) (string, error) { - data, err := Asset(name) - return string(data), err -} - -// MustAsset is like Asset but panics when Asset would return an error. -// It simplifies safe initialization of global variables. -func MustAsset(name string) []byte { - a, err := Asset(name) - if err != nil { - panic("asset: Asset(" + name + "): " + err.Error()) - } - - return a -} - -// MustAssetString is like AssetString but panics when Asset would return an -// error. It simplifies safe initialization of global variables. -func MustAssetString(name string) string { - return string(MustAsset(name)) -} - -// AssetInfo loads and returns the asset info for the given name. -// It returns an error if the asset could not be found or -// could not be loaded. -func AssetInfo(name string) (os.FileInfo, error) { - canonicalName := strings.Replace(name, "\\", "/", -1) - if f, ok := _bindata[canonicalName]; ok { - a, err := f() - if err != nil { - return nil, fmt.Errorf("AssetInfo %s can't read by error: %v", name, err) - } - return a.info, nil - } - return nil, fmt.Errorf("AssetInfo %s not found", name) -} - -// AssetDigest returns the digest of the file with the given name. It returns an -// error if the asset could not be found or the digest could not be loaded. -func AssetDigest(name string) ([sha256.Size]byte, error) { - canonicalName := strings.Replace(name, "\\", "/", -1) - if f, ok := _bindata[canonicalName]; ok { - a, err := f() - if err != nil { - return [sha256.Size]byte{}, fmt.Errorf("AssetDigest %s can't read by error: %v", name, err) - } - return a.digest, nil - } - return [sha256.Size]byte{}, fmt.Errorf("AssetDigest %s not found", name) -} - -// Digests returns a map of all known files and their checksums. -func Digests() (map[string][sha256.Size]byte, error) { - mp := make(map[string][sha256.Size]byte, len(_bindata)) - for name := range _bindata { - a, err := _bindata[name]() - if err != nil { - return nil, err - } - mp[name] = a.digest - } - return mp, nil -} - -// AssetNames returns the names of the assets. -func AssetNames() []string { - names := make([]string, 0, len(_bindata)) - for name := range _bindata { - names = append(names, name) - } - return names -} - -// _bindata is a table, holding each asset generator, mapped to its name. -var _bindata = map[string]func() (*asset, error){ - "emr-containers-rbac.yaml": emrContainersRbacYaml, -} - -// AssetDebug is true if the assets were built with the debug flag enabled. -const AssetDebug = false - -// AssetDir returns the file names below a certain -// directory embedded in the file by go-bindata. -// For example if you run go-bindata on data/... and data contains the -// following hierarchy: -// data/ -// foo.txt -// img/ -// a.png -// b.png -// then AssetDir("data") would return []string{"foo.txt", "img"}, -// AssetDir("data/img") would return []string{"a.png", "b.png"}, -// AssetDir("foo.txt") and AssetDir("notexist") would return an error, and -// AssetDir("") will return []string{"data"}. -func AssetDir(name string) ([]string, error) { - node := _bintree - if len(name) != 0 { - canonicalName := strings.Replace(name, "\\", "/", -1) - pathList := strings.Split(canonicalName, "/") - for _, p := range pathList { - node = node.Children[p] - if node == nil { - return nil, fmt.Errorf("Asset %s not found", name) - } - } - } - if node.Func != nil { - return nil, fmt.Errorf("Asset %s not found", name) - } - rv := make([]string, 0, len(node.Children)) - for childName := range node.Children { - rv = append(rv, childName) - } - return rv, nil -} - -type bintree struct { - Func func() (*asset, error) - Children map[string]*bintree -} - -var _bintree = &bintree{nil, map[string]*bintree{ - "emr-containers-rbac.yaml": {emrContainersRbacYaml, map[string]*bintree{}}, -}} - -// RestoreAsset restores an asset under the given directory. -func RestoreAsset(dir, name string) error { - data, err := Asset(name) - if err != nil { - return err - } - info, err := AssetInfo(name) - if err != nil { - return err - } - err = os.MkdirAll(_filePath(dir, filepath.Dir(name)), os.FileMode(0755)) - if err != nil { - return err - } - err = ioutil.WriteFile(_filePath(dir, name), data, info.Mode()) - if err != nil { - return err - } - return os.Chtimes(_filePath(dir, name), info.ModTime(), info.ModTime()) -} - -// RestoreAssets restores an asset under the given directory recursively. -func RestoreAssets(dir, name string) error { - children, err := AssetDir(name) - // File - if err != nil { - return RestoreAsset(dir, name) - } - // Dir - for _, child := range children { - err = RestoreAssets(dir, filepath.Join(name, child)) - if err != nil { - return err - } - } - return nil -} - -func _filePath(dir, name string) string { - canonicalName := strings.Replace(name, "\\", "/", -1) - return filepath.Join(append([]string{dir}, strings.Split(canonicalName, "/")...)...) -} diff --git a/pkg/authconfigmap/service_access.go b/pkg/authconfigmap/service_access.go index c6f18622bc..a00a0ff06b 100644 --- a/pkg/authconfigmap/service_access.go +++ b/pkg/authconfigmap/service_access.go @@ -3,6 +3,9 @@ package authconfigmap import ( "fmt" + // go go:embed to work + _ "embed" + "github.com/kris-nova/logger" "github.com/pkg/errors" "github.com/weaveworks/eksctl/pkg/assetutil" @@ -12,7 +15,8 @@ import ( "k8s.io/apimachinery/pkg/runtime" ) -//go:generate ${GOBIN}/go-bindata -pkg ${GOPACKAGE} -prefix assets -nometadata -o assets.go assets +//go:embed assets/emr-containers-rbac.yaml +var emrContainersRbacYamlBytes []byte type ServiceName string @@ -126,7 +130,7 @@ func lookupService(serviceName string) (resources []byte, sd serviceDetails, err switch ServiceName(serviceName) { case emrContainers: - return assetutil.MustLoad(emrContainersRbacYamlBytes), emrContainersService, nil + return emrContainersRbacYamlBytes, emrContainersService, nil default: return nil, sd, errors.Errorf("invalid service name %q", serviceName) } diff --git a/pkg/ctl/utils/schema.go b/pkg/ctl/utils/schema.go index ef5e41afb6..9e0aa2fa94 100644 --- a/pkg/ctl/utils/schema.go +++ b/pkg/ctl/utils/schema.go @@ -2,7 +2,6 @@ package utils import ( "fmt" - "log" "github.com/spf13/cobra" @@ -19,9 +18,5 @@ func schemaCmd(cmd *cmdutils.Cmd) { } func doSchemaCmd(cmd *cmdutils.Cmd) { - schema, err := api.Asset("schema.json") - if err != nil { - log.Fatal(err.Error()) - } - fmt.Printf("%s", schema) + fmt.Printf("%s", api.SchemaJSON) } diff --git a/pkg/nodebootstrap/al2.go b/pkg/nodebootstrap/al2.go index b5c587fa80..241d15019f 100644 --- a/pkg/nodebootstrap/al2.go +++ b/pkg/nodebootstrap/al2.go @@ -4,6 +4,7 @@ import ( "github.com/kris-nova/logger" "github.com/pkg/errors" api "github.com/weaveworks/eksctl/pkg/apis/eksctl.io/v1alpha5" + "github.com/weaveworks/eksctl/pkg/nodebootstrap/assets" ) const ( @@ -23,13 +24,13 @@ func NewAL2Bootstrapper(clusterConfig *api.ClusterConfig, ng *api.NodeGroup) *Am } func (b *AmazonLinux2) UserData() (string, error) { - var scripts []string + var scripts []script if api.IsEnabled(b.ng.EFAEnabled) { - scripts = append(scripts, "efa.al2.sh") + scripts = append(scripts, script{name: "efa.al2.sh", contents: assets.EfaAl2Sh}) } - body, err := linuxConfig(b.clusterConfig, al2BootScript, b.ng, scripts...) + body, err := linuxConfig(b.clusterConfig, al2BootScript, assets.BootstrapAl2Sh, b.ng, scripts...) if err != nil { return "", errors.Wrap(err, "encoding user data") } diff --git a/pkg/nodebootstrap/assets/assets.go b/pkg/nodebootstrap/assets/assets.go new file mode 100644 index 0000000000..d622110cac --- /dev/null +++ b/pkg/nodebootstrap/assets/assets.go @@ -0,0 +1,38 @@ +package assets + +import ( + // Import go:embed + _ "embed" +) + +//EksctlAl2Conf holds the eksctl.al2.conf contents +//go:embed scripts/10-eksctl.al2.conf +var EksctlAl2Conf string + +//BootstrapAl2Sh holds the bootstrap.al2.sh contents +//go:embed scripts/bootstrap.al2.sh +var BootstrapAl2Sh string + +//BootstrapHelperSh holds the bootstrap.helper.sh contents +//go:embed scripts/bootstrap.helper.sh +var BootstrapHelperSh string + +//BootstrapUbuntuSh holds the bootstrap.ubuntu.sh contents +//go:embed scripts/bootstrap.ubuntu.sh +var BootstrapUbuntuSh string + +//EfaAl2Sh holds the efa.al2.sh contents +//go:embed scripts/efa.al2.sh +var EfaAl2Sh string + +//EfaManagedBoothook holds the efa.managed.boothook contents +//go:embed scripts/efa.managed.boothook +var EfaManagedBoothook string + +//InstallSsmAl2Sh holds the install-ssm.al2.sh contents +//go:embed scripts/install-ssm.al2.sh +var InstallSsmAl2Sh string + +//KubeletYaml holds the kubelet.yaml contents +//go:embed scripts/kubelet.yaml +var KubeletYaml string diff --git a/pkg/nodebootstrap/bindata/assets/10-eksctl.al2.conf b/pkg/nodebootstrap/assets/scripts/10-eksctl.al2.conf similarity index 100% rename from pkg/nodebootstrap/bindata/assets/10-eksctl.al2.conf rename to pkg/nodebootstrap/assets/scripts/10-eksctl.al2.conf diff --git a/pkg/nodebootstrap/bindata/assets/bootstrap.al2.sh b/pkg/nodebootstrap/assets/scripts/bootstrap.al2.sh similarity index 100% rename from pkg/nodebootstrap/bindata/assets/bootstrap.al2.sh rename to pkg/nodebootstrap/assets/scripts/bootstrap.al2.sh diff --git a/pkg/nodebootstrap/bindata/assets/bootstrap.helper.sh b/pkg/nodebootstrap/assets/scripts/bootstrap.helper.sh similarity index 100% rename from pkg/nodebootstrap/bindata/assets/bootstrap.helper.sh rename to pkg/nodebootstrap/assets/scripts/bootstrap.helper.sh diff --git a/pkg/nodebootstrap/bindata/assets/bootstrap.ubuntu.sh b/pkg/nodebootstrap/assets/scripts/bootstrap.ubuntu.sh similarity index 100% rename from pkg/nodebootstrap/bindata/assets/bootstrap.ubuntu.sh rename to pkg/nodebootstrap/assets/scripts/bootstrap.ubuntu.sh diff --git a/pkg/nodebootstrap/bindata/assets/efa.al2.sh b/pkg/nodebootstrap/assets/scripts/efa.al2.sh similarity index 100% rename from pkg/nodebootstrap/bindata/assets/efa.al2.sh rename to pkg/nodebootstrap/assets/scripts/efa.al2.sh diff --git a/pkg/nodebootstrap/bindata/assets/efa.managed.boothook b/pkg/nodebootstrap/assets/scripts/efa.managed.boothook similarity index 100% rename from pkg/nodebootstrap/bindata/assets/efa.managed.boothook rename to pkg/nodebootstrap/assets/scripts/efa.managed.boothook diff --git a/pkg/nodebootstrap/bindata/assets/install-ssm.al2.sh b/pkg/nodebootstrap/assets/scripts/install-ssm.al2.sh similarity index 100% rename from pkg/nodebootstrap/bindata/assets/install-ssm.al2.sh rename to pkg/nodebootstrap/assets/scripts/install-ssm.al2.sh diff --git a/pkg/nodebootstrap/bindata/assets/kubelet.yaml b/pkg/nodebootstrap/assets/scripts/kubelet.yaml similarity index 100% rename from pkg/nodebootstrap/bindata/assets/kubelet.yaml rename to pkg/nodebootstrap/assets/scripts/kubelet.yaml diff --git a/pkg/nodebootstrap/bindata/assets.go b/pkg/nodebootstrap/bindata/assets.go deleted file mode 100644 index f72a7775d9..0000000000 --- a/pkg/nodebootstrap/bindata/assets.go +++ /dev/null @@ -1,485 +0,0 @@ -// Code generated by go-bindata. DO NOT EDIT. -// sources: -// bindata/assets/10-eksctl.al2.conf (1.025kB) -// bindata/assets/bootstrap.al2.sh (755B) -// bindata/assets/bootstrap.helper.sh (1.403kB) -// bindata/assets/bootstrap.legacy.al2.sh (1.286kB) -// bindata/assets/bootstrap.legacy.ubuntu.sh (2.275kB) -// bindata/assets/bootstrap.ubuntu.sh (597B) -// bindata/assets/efa.al2.sh (351B) -// bindata/assets/efa.managed.boothook (484B) -// bindata/assets/install-ssm.al2.sh (159B) -// bindata/assets/kubelet.yaml (480B) - -package bindata - -import ( - "bytes" - "compress/gzip" - "crypto/sha256" - "fmt" - "io" - "io/ioutil" - "os" - "path/filepath" - "strings" - "time" -) - -func bindataRead(data []byte, name string) ([]byte, error) { - gz, err := gzip.NewReader(bytes.NewBuffer(data)) - if err != nil { - return nil, fmt.Errorf("read %q: %w", name, err) - } - - var buf bytes.Buffer - _, err = io.Copy(&buf, gz) - clErr := gz.Close() - - if err != nil { - return nil, fmt.Errorf("read %q: %w", name, err) - } - if clErr != nil { - return nil, err - } - - return buf.Bytes(), nil -} - -type asset struct { - bytes []byte - info os.FileInfo - digest [sha256.Size]byte -} - -type bindataFileInfo struct { - name string - size int64 - mode os.FileMode - modTime time.Time -} - -func (fi bindataFileInfo) Name() string { - return fi.name -} -func (fi bindataFileInfo) Size() int64 { - return fi.size -} -func (fi bindataFileInfo) Mode() os.FileMode { - return fi.mode -} -func (fi bindataFileInfo) ModTime() time.Time { - return fi.modTime -} -func (fi bindataFileInfo) IsDir() bool { - return false -} -func (fi bindataFileInfo) Sys() interface{} { - return nil -} - -var _bindataAssets10EksctlAl2Conf = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\x8c\x52\xdf\x6b\xdb\x30\x10\x7e\xf7\x5f\x71\x90\x3e\x6c\x10\xd9\xac\x7d\x2b\xf8\xc1\x8b\xdd\x12\x96\x3a\x25\x76\xb7\xc1\x36\x8c\x2c\x5d\xd2\x23\xb2\x64\x24\x39\x69\x57\xf2\xbf\x0f\xc7\xf1\x96\xb2\x32\xf6\x26\xdd\x77\xf7\x7d\xdf\xfd\x98\x00\x6e\x9d\xf0\x8a\xb9\x16\x05\xad\x49\x80\x7b\x76\x1e\x1b\x09\xd2\x9a\x96\x91\x86\x4e\x93\x87\xb5\xb1\xb0\xed\x6a\x54\xe8\xa7\xc7\x4f\xd2\xf0\x9f\x46\xc3\x82\x74\xf7\x04\x97\xf0\x2e\x59\x5c\xbe\x0f\x26\x50\x2e\xd3\x25\xa4\xd8\x5a\x14\xdc\xa3\x9c\xc2\x9e\x94\x82\x1a\xc1\x62\x63\x76\x28\xc1\x19\xa3\x83\xe0\x5b\x81\x76\x47\x02\x7f\x04\x13\x58\x18\xc1\x15\x34\xe8\xb9\xe4\x9e\x43\xcb\x2d\x6f\xd0\xa3\x75\xd7\xb0\xca\x6e\xe7\xcb\x7c\x0a\xc9\x97\xa2\x4a\xb3\x9b\xe4\x61\x51\x56\x43\x2c\xc8\xf4\x8e\xac\xd1\x0d\x6a\x7f\x43\x0a\xe3\x08\xbd\x88\x86\x56\xa2\x91\x2b\x44\xbd\x0b\x26\x70\xab\x4c\xcd\x15\x70\x2d\xc1\x79\xee\x49\xbc\xd2\x98\x2d\x1e\x8a\x32\x5b\x55\x69\x5e\x4c\x21\x5f\xa6\x59\xb5\x48\x3e\x66\x8b\xf1\x53\x26\xf3\xbc\x2c\xfe\x29\x77\x9a\xcb\x49\x6d\x68\x47\x1b\xcd\xde\x10\x3b\x52\xce\xef\xa7\x30\xcf\x8b\x32\xc9\x67\x59\x35\x4f\xff\x8b\x5b\xf5\xac\x47\x85\x20\x7b\x42\x51\x78\x6e\x7d\x7c\xf6\x8c\x3a\x67\xa3\x9a\xf4\x58\x00\xdf\x03\x00\xc6\xb4\x91\xc8\xa8\x8d\x2f\x5e\x4e\xca\x87\x73\x40\xf1\x1a\x95\x1b\xc1\xa1\xed\xc3\x94\xab\xf6\x91\x87\x83\x7e\x48\x26\x22\xed\x3c\xd7\x02\x19\xc9\xf8\xe2\xe5\xcc\xf8\xc8\xd5\xf0\x27\xd6\x1a\xd9\x13\xdd\x25\x5f\xab\xfb\x65\x5a\x8c\x90\xc5\x0d\x39\x8f\xf6\xa8\x17\x7b\xdb\xe1\x79\x70\x4f\xfe\x91\x79\x4e\xda\xff\x36\x31\x8c\x7b\x2c\x17\xca\x74\x92\xb5\xd6\xec\x48\xa2\x8d\xf9\xde\x8d\x80\xd1\x7d\x1d\x5a\x66\x3b\xed\xa9\xc1\x58\x1a\xb1\x45\x3b\x76\x87\x7e\x6f\xec\x96\xb5\xaa\xdb\x90\x8e\x85\xa6\xb1\x4e\x13\xab\x49\x33\x49\x36\x8e\x4c\xeb\x23\xa1\xa9\x1f\xdb\x19\x2c\x8c\x5e\x0f\x78\xbf\x86\x1e\xd7\xe8\x43\x79\xca\x68\x8d\x64\xa4\xd7\x96\x9f\x59\xa0\x86\x6f\x30\xbe\x78\xe9\xaf\x34\xfb\x54\x54\xd9\x6c\x55\x25\xb3\xd9\xf2\x21\x2f\x0f\xa1\xdc\xda\x10\x85\x0d\x07\xf8\xf5\x11\x1f\x4e\xd1\x22\x5b\x7d\x9e\xcf\xb2\xa2\x4a\x97\x77\xc9\x3c\x3f\xf4\xcb\x8f\x5a\xde\x39\xbc\xbe\x0a\xaf\x18\x6e\x5d\xdd\x91\x92\xe1\x87\x93\x89\x7e\xc7\xbd\x4d\xda\xfc\x75\x2b\x43\x38\x7c\xe6\x8d\xfa\x33\xaa\xb7\x12\xfb\xa3\xea\xb3\x82\x5f\x01\x00\x00\xff\xff\x04\xfc\xe9\x45\x01\x04\x00\x00") - -func bindataAssets10EksctlAl2ConfBytes() ([]byte, error) { - return bindataRead( - _bindataAssets10EksctlAl2Conf, - "bindata/assets/10-eksctl.al2.conf", - ) -} - -func bindataAssets10EksctlAl2Conf() (*asset, error) { - bytes, err := bindataAssets10EksctlAl2ConfBytes() - if err != nil { - return nil, err - } - - info := bindataFileInfo{name: "bindata/assets/10-eksctl.al2.conf", size: 0, mode: os.FileMode(0), modTime: time.Unix(0, 0)} - a := &asset{bytes: bytes, info: info, digest: [32]uint8{0xb0, 0x2b, 0x5f, 0x5a, 0xc4, 0x94, 0x74, 0x90, 0x34, 0x26, 0x3b, 0xc9, 0x7, 0x3f, 0x89, 0x8f, 0xe9, 0x6f, 0xe5, 0x33, 0x58, 0x2b, 0x82, 0x48, 0xd, 0xca, 0x2b, 0x91, 0x5f, 0x6f, 0x4a, 0xab}} - return a, nil -} - -var _bindataAssetsBootstrapAl2Sh = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\x6c\x92\xd1\x6a\xdb\x4c\x10\x85\xef\xf7\x29\xe6\xd7\x1f\x30\x14\x56\x6a\x21\xe4\xa2\x17\x05\xc5\x55\x83\xa9\xa3\x04\x59\x2e\x81\x34\x88\xd5\x6a\x6c\x6f\x2c\xed\xaa\x3b\x23\x93\x12\xfc\xee\x65\xdb\x5a\x71\x9d\x5c\xee\xcc\x77\xce\xcc\x1c\xf6\xff\xff\x92\xda\xd8\xa4\x56\xb4\x11\x82\x90\x41\x3a\x40\xef\xf1\xc9\xf0\xe1\xd9\x9b\x1e\x57\xca\xb4\x87\xb7\x75\x83\x25\x64\x21\xc8\x0d\x5e\x23\x24\x3b\xe5\x93\xd6\xd4\x89\x6e\xdd\xd0\x24\xa4\xbd\xe9\x99\x12\xdc\x92\xe6\x36\xa9\x9d\x63\x62\xaf\xfa\x78\x83\x6d\x8f\x3e\x0e\x83\x50\x6f\x1c\x44\x7f\x88\x8f\xe0\x07\x6b\x8d\x5d\x43\x82\xac\x83\xec\x45\x13\x89\xd7\xb5\x98\x36\x10\x9d\x3d\x4f\xe7\xcb\x45\x99\x15\x55\x9e\x5e\x67\xfb\x08\xbe\x0b\x00\x29\x55\x6f\x08\xfd\x0e\xbd\x44\xdb\xf4\xce\x58\x0e\x68\x7a\x3b\xab\x16\x59\xf1\x2d\x2b\xaa\x65\x31\x1f\xe1\xfa\xe2\x5c\xea\x76\x20\x46\x2f\xb5\x0a\xe0\xe5\xc5\x79\x75\xf0\x9d\xa6\x23\xd8\x58\x1a\x41\xd3\x1f\x0f\xff\x9c\x2f\x46\x6a\x3b\xd4\xd8\x22\x4b\x7c\x62\xaf\xa4\xf2\x6b\x0a\xe4\xd7\xe5\x65\x36\xcf\xca\x2a\xbb\x2b\x8b\xb4\x4a\x8b\xab\x17\x81\x76\x96\x95\xb1\xe8\xa5\x1f\x2c\x9b\x0e\x7f\x3b\xdf\xe4\x65\x3a\xcb\xb3\xa2\x2a\x96\x79\x39\x0b\xb7\x9d\xc6\xd5\xa1\x5f\x87\xb8\x06\x42\x0f\xae\x67\xe3\x2c\x81\xb1\xec\xe0\xb0\x82\x76\x76\x65\xd6\xf1\x23\x39\x1b\x89\x90\x19\x4c\x7c\x07\x72\x05\x67\xcf\xe5\xf5\x6d\x15\x76\xaa\xa6\x37\xf9\x97\xfd\x04\xb2\xbb\x59\x29\x1e\x7f\x80\x24\x98\xc4\xf7\xef\x1f\xe0\x1d\xc4\xf7\x1f\x1e\x26\xc7\xbb\x07\x74\x76\xb5\x8f\x5e\xdf\x33\x76\x3e\x85\xde\xbf\xde\x91\xe8\x76\x6f\x54\xdf\x32\x16\x82\x7e\x12\x63\xa7\xb9\x85\x46\x61\xe7\xac\xf4\xd8\x3a\xd5\x9c\x7e\x14\x24\x56\x9e\xc3\xf1\x63\xda\x5b\x8a\x8e\xd4\x7f\x89\x43\xfb\x44\xdf\x38\x8b\x91\xf8\x15\x00\x00\xff\xff\xb9\x79\x57\x7c\xf3\x02\x00\x00") - -func bindataAssetsBootstrapAl2ShBytes() ([]byte, error) { - return bindataRead( - _bindataAssetsBootstrapAl2Sh, - "bindata/assets/bootstrap.al2.sh", - ) -} - -func bindataAssetsBootstrapAl2Sh() (*asset, error) { - bytes, err := bindataAssetsBootstrapAl2ShBytes() - if err != nil { - return nil, err - } - - info := bindataFileInfo{name: "bindata/assets/bootstrap.al2.sh", size: 0, mode: os.FileMode(0), modTime: time.Unix(0, 0)} - a := &asset{bytes: bytes, info: info, digest: [32]uint8{0x3d, 0x1a, 0x18, 0x7b, 0x3b, 0xc, 0x5a, 0xfe, 0xcd, 0xaf, 0x4a, 0x56, 0xd7, 0xbb, 0x38, 0x7e, 0x27, 0xdf, 0x36, 0xa8, 0x4d, 0x27, 0x12, 0xce, 0x6d, 0x48, 0x6f, 0x84, 0xab, 0x31, 0x57, 0xc9}} - return a, nil -} - -var _bindataAssetsBootstrapHelperSh = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\x7c\x54\x7f\x6f\xda\x48\x10\xfd\x7f\x3f\xc5\xdc\x82\x9a\xa0\xcb\xe2\x36\xea\x45\x3a\x24\xa4\x23\xe0\xf6\xac\x12\x83\xc0\x9c\x72\x8a\x22\x6b\xb1\x87\xb0\xc5\xec\x5a\xbb\xe3\x92\x2a\xf2\x77\x3f\xd9\xc4\x89\xc9\xa9\xf9\x6b\x3d\x3f\xde\x9b\x37\xe3\xd1\x74\x7e\xf3\xd6\x4a\x7b\x6b\xe9\xb6\x8c\x39\x24\x10\x06\xd0\x5a\x7c\x54\xd4\x98\xb9\xca\x71\x23\x55\xd6\xd8\xda\x14\xda\x21\x31\xe6\x4c\x61\x13\x04\x0f\x29\xf1\x70\xe7\x12\xca\xbc\x5d\xb1\xc6\x0c\xa9\x8f\xfa\x07\x74\x60\xa3\x32\x84\x83\x55\x44\xa8\x61\xfd\x13\xd6\xc6\x90\x23\x2b\xf3\x1c\x2d\x63\x1d\x58\x39\x84\xe0\x66\xb2\xfc\x71\x09\x64\xe0\x01\x09\xf6\x48\x32\x95\x24\x59\x34\xfb\xe6\x87\x43\xde\x3d\x4f\x0a\x9b\x81\x10\x4e\x65\xa8\x09\xc4\x2d\xcc\x57\x11\x88\xbf\x81\xdf\x0a\x79\x70\x02\x93\x4b\xd1\x80\x04\x99\x1d\x6a\x41\x94\x09\x87\x89\xd1\xa9\x1b\xc0\xd5\xc7\x8f\x1c\xb6\x44\xf9\xc0\xf3\x3e\x5d\xfd\xd9\xbf\xfc\xe3\x73\xff\xf9\xf5\x32\x49\xe8\xc8\x93\xb9\xf2\x6a\x64\x8f\xb3\x4d\xa1\x13\x52\x46\x57\x62\xe2\x86\xf7\xbc\x07\x4f\x0c\xe0\x8d\x92\x77\x24\x0c\xa0\x5b\xeb\xe7\xc0\xdf\x2f\x5d\xc1\x44\x85\xf3\xba\x9f\x38\x2b\x19\x1b\xcd\x83\x78\xe9\x2f\xfe\xf1\x17\xf1\x6a\x31\x1d\xf2\xee\xd3\xa9\xa7\xe4\xec\xfa\xea\x73\x3c\x9e\xae\x96\x91\xbf\x88\xc7\xa3\x2a\xe5\xd4\x53\x72\x16\x84\xcb\x68\x14\x8e\xfd\x38\x98\x54\x23\x6c\xf7\x02\x4a\x3b\x92\x3a\x41\xa1\xd2\x5e\x2b\x73\x1a\x7c\xf1\xc7\xff\x8e\xa7\xfe\xaf\x01\x99\xda\xa0\x48\x7e\x26\x19\xf6\x38\x6b\xea\x4d\xc2\x65\x25\xa1\x65\x0e\x44\xc9\x59\x38\x9b\xf8\x71\x34\x0a\xc2\xa8\x0e\xb7\xcc\x3a\x7c\x33\xba\x8d\xe7\xb3\x49\x1d\x6b\xbe\x5f\x71\xd3\xd1\xb5\x3f\x7d\xc5\x1d\xcd\xf2\x42\x9b\xf4\x28\xa2\xd6\x30\xec\x3e\xfd\x5f\x7c\x79\x21\xb3\x7c\x2b\xfb\xc7\x6d\xec\x2b\xe3\xb5\xda\x6d\x23\x82\x49\xc9\x19\xfb\xb6\xba\xf6\xa7\x7e\x14\x8f\x16\x5f\x97\xc3\x73\x2e\xc4\xb1\x84\x5c\x63\xe6\x86\xa7\xd5\x79\x8f\xdd\xdd\x81\xd0\x70\xda\x4d\xc9\xe1\xfe\x1e\x3e\x7c\x80\x36\xd5\xef\x35\x97\xc5\x07\xe5\x08\xad\x38\x28\xda\x0a\x92\x4a\xd3\x0b\x69\x03\xee\xb1\x0e\x08\xb1\x97\x8f\x22\x37\xa9\x03\xe9\x40\xc2\x78\x1a\x80\xb4\x0f\xc5\xbe\xda\x32\xe5\x20\xc5\xdc\x62\x22\x09\xd3\x0b\xa0\xad\x72\x95\x4f\xc2\xc1\xd8\x9d\xb4\xa6\xd0\x29\x14\x9a\x54\x06\x07\x7c\xcd\x04\x57\xe4\xb9\xb1\x04\x1b\x63\x61\x2f\x1f\xe7\x26\x75\x73\xb4\xa1\x49\xf1\xb5\x8b\x66\xee\xef\xb4\xd0\x08\x1b\xb6\xb3\x7b\x2f\x63\xf3\x6f\xa3\xc5\xe8\x38\x3c\xde\x7d\x6a\xc3\xef\xfe\xba\xaf\xe6\xdb\x6c\x45\x38\xba\xf1\xdb\x5b\x52\xd9\x25\x7f\xe1\x19\xcf\xc2\x2f\xc1\xd7\xe1\x59\x7d\x48\xaa\x0b\x62\x35\x12\xba\xe6\x98\x34\xaf\x48\x8c\xde\xa8\x87\xfe\x77\x67\xf4\xd9\x1b\x11\x27\x14\xa7\xb7\x48\xe0\x23\x59\xf9\x8c\x8a\x6e\xe6\x71\x85\xac\x01\xc3\x33\x8f\xf6\xf9\x09\xfd\x73\xda\x78\x16\x56\xbf\xc8\x5f\xc4\x8b\x55\x18\x05\xcf\xea\xdf\x3a\x07\x22\x35\xc9\x0e\x6d\x5a\x72\xe8\x40\x8a\x1b\x59\x64\xc7\x99\xcb\xec\x12\xbe\x17\x8e\x40\x69\x48\xa4\xc3\x0b\xd0\x86\xa0\x70\x98\x56\x9e\x62\x5d\x68\x2a\xd8\x7f\x01\x00\x00\xff\xff\xf7\xbf\x51\x00\x7b\x05\x00\x00") - -func bindataAssetsBootstrapHelperShBytes() ([]byte, error) { - return bindataRead( - _bindataAssetsBootstrapHelperSh, - "bindata/assets/bootstrap.helper.sh", - ) -} - -func bindataAssetsBootstrapHelperSh() (*asset, error) { - bytes, err := bindataAssetsBootstrapHelperShBytes() - if err != nil { - return nil, err - } - - info := bindataFileInfo{name: "bindata/assets/bootstrap.helper.sh", size: 0, mode: os.FileMode(0), modTime: time.Unix(0, 0)} - a := &asset{bytes: bytes, info: info, digest: [32]uint8{0x45, 0x8c, 0xa1, 0xd0, 0x1e, 0x75, 0xe, 0x4b, 0x2f, 0x73, 0xb3, 0x29, 0x78, 0xe7, 0x17, 0x48, 0xff, 0x1e, 0x0, 0xa7, 0xca, 0xe1, 0x49, 0x7b, 0x15, 0x9c, 0xb8, 0xf8, 0x11, 0x53, 0x96, 0x8a}} - return a, nil -} - -var _bindataAssetsBootstrapLegacyAl2Sh = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\x7c\x93\x61\x4f\x02\x47\x10\x86\xbf\xef\xaf\x98\x1e\x17\x23\xa9\xcb\xa9\xb1\x26\xa2\x34\xa1\xdc\x99\x5e\x8a\x40\x0a\xb6\x1a\x63\x2f\xcb\xde\x50\x36\x2e\xbb\x97\xdb\x01\x35\xe4\xfa\xdb\x9b\xc5\xc3\x82\x5a\x3f\xc1\xcc\xbc\xb3\xf3\xee\x33\xb7\x8d\x1f\xa2\xa9\x32\xd1\x54\xb8\x39\x6b\xc0\x64\x18\x0f\x21\xc6\xa2\x44\x29\x08\xf3\x23\x78\x56\x5a\xc3\x14\xa1\xc4\x85\x5d\x61\x0e\xce\x5a\xc3\x98\x43\x02\x6e\x01\xcb\x12\x5f\x14\x6d\xc3\x42\x15\x38\x13\x4a\x6f\x63\x63\x97\xc6\x21\x31\x36\x5b\x1a\x49\xca\x1a\xf8\x1b\x29\x5b\x88\x97\xac\xb0\xb9\x3b\x6c\xc2\x9a\x01\x3c\xcf\x95\xf6\xc7\x8b\x1c\x94\x71\x24\x8c\xc4\x8c\x5e\x0b\x04\xaf\xb9\x84\xdc\x32\x00\x00\x35\x03\x78\x78\x80\x20\x5c\xef\x89\xaa\x00\x3a\x1d\x9f\x3d\xa9\x02\x78\x7c\x84\x83\x83\x5a\xe5\x9b\x7d\xf1\x1f\xf8\xeb\xe1\x98\x5f\x3c\xfe\x18\xfa\xf2\x25\xd0\x1c\xcd\xe6\x40\x00\x94\x73\x0b\xb5\xb2\x4e\x95\x48\xcb\xf2\xad\x3e\x53\x0c\x20\xb7\x06\xe1\x0a\x22\x24\x19\xe1\x93\x93\xa4\xa3\xad\xfb\xd6\x42\x14\xac\x62\xac\x01\xb7\x0e\x21\xbd\x89\xc7\xab\x53\x20\xeb\x6f\x08\x0b\x24\x91\x0b\x12\x6c\x32\xfc\x2d\x19\x74\x82\xf0\x50\x2e\x4b\x0d\x9c\x3b\xa5\xd1\x10\xf0\x3b\x18\xdd\x4e\x80\xff\x0a\xc1\x1d\x17\xcf\x8e\xa3\x3c\xe5\xdb\x26\x4e\xf6\x09\x0d\x27\xd2\xdc\xa1\xb4\x26\x77\x6d\x38\x3f\x3e\x0e\x60\x4e\x54\xb4\xa3\xe8\xe4\xfc\xa2\x75\xfa\xd3\x59\xab\xfe\x8d\xb4\x20\x74\x14\x89\x42\x45\x9b\xce\x66\xf0\x01\x77\x7d\x6e\x8d\xfb\x83\x93\x6f\x2c\xb4\x21\xdc\xf8\x0f\x20\xf8\x7e\xb4\x6f\xe3\xbe\x2f\x0a\x4f\x02\xcf\x64\x30\x8c\x93\x2c\x1d\xf9\x8b\xef\x3a\x00\x6d\xa5\xd0\x5c\x15\xab\xb3\x66\xc0\xd2\xc1\x78\xd2\x1d\xf4\x92\x2c\x8d\x3f\x09\xb7\x3b\xe6\x2a\xdf\x55\x4e\xee\x47\xc9\xff\x6b\xfd\xf7\xd0\x0c\x58\xf7\xcf\x71\x36\x4e\x7e\xff\x23\xed\x25\xe3\x2c\x1e\xde\x74\xd3\xc1\xa7\x1e\x87\xe5\x4a\x49\x74\x51\x6e\x17\x42\x79\x64\x8c\x39\xbb\x2c\x25\xee\xed\xfa\x69\x39\x45\x8d\xd4\x42\xb3\x82\x06\xd0\x5c\x39\x90\xc2\x80\x5d\x61\x59\xaa\x1c\xe1\xa6\x7b\x97\x8d\x86\xf1\x98\xfd\x67\xb1\x9f\x5e\x27\xbd\xfb\x5e\xff\x1b\x9f\x5a\xcd\x90\xcb\x57\xa9\xbd\xdb\x0d\xaa\x7e\xf7\x97\xa4\x3f\xee\x04\xe1\x7a\x27\xac\x8e\x8c\xcd\xdf\xd4\x1b\x71\x27\x5c\x7f\x9e\x52\x79\xe7\x52\x10\xfc\xfc\xa5\xf1\x0d\xf0\x8d\xfd\xab\xab\x64\x78\xfd\xbe\x98\x7a\x50\x3a\xaa\xf6\xd6\xb0\x33\x21\x8d\xab\x0f\xdc\x77\x8a\x3e\xae\xbe\x04\x1d\xae\xbf\xc8\x56\x6c\x0b\xaa\x13\xae\xb7\x7f\xdb\xbc\xe6\x53\xbf\x27\xff\x68\xf7\x07\x04\xcd\x6a\x0f\xcf\x3e\x1d\xe6\xef\xc3\xdc\xab\x23\x5c\x48\xd2\x90\x0b\x5c\x58\xc3\x4b\xd4\x56\xe4\x3b\x79\x34\x62\xaa\x11\x6a\x22\x3b\x05\x47\xa2\xa4\xf7\xfc\xbf\x01\x00\x00\xff\xff\x46\x01\xeb\xc2\x06\x05\x00\x00") - -func bindataAssetsBootstrapLegacyAl2ShBytes() ([]byte, error) { - return bindataRead( - _bindataAssetsBootstrapLegacyAl2Sh, - "bindata/assets/bootstrap.legacy.al2.sh", - ) -} - -func bindataAssetsBootstrapLegacyAl2Sh() (*asset, error) { - bytes, err := bindataAssetsBootstrapLegacyAl2ShBytes() - if err != nil { - return nil, err - } - - info := bindataFileInfo{name: "bindata/assets/bootstrap.legacy.al2.sh", size: 0, mode: os.FileMode(0), modTime: time.Unix(0, 0)} - a := &asset{bytes: bytes, info: info, digest: [32]uint8{0x35, 0xb1, 0x58, 0xf5, 0xe6, 0x40, 0x92, 0xbe, 0xa6, 0x27, 0xc2, 0xfc, 0xbd, 0xc2, 0xe8, 0x54, 0x5e, 0x40, 0x37, 0x77, 0x73, 0x87, 0x9, 0xf, 0x97, 0xc4, 0xbc, 0x10, 0x5, 0x1b, 0x44, 0xf8}} - return a, nil -} - -var _bindataAssetsBootstrapLegacyUbuntuSh = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\x7c\x55\xf1\x6f\x1a\xb9\x12\xfe\xdd\x7f\xc5\xbc\x0d\xea\x0b\x7a\x31\xdb\xa4\x7d\x95\x9a\x96\xd3\x71\x81\xde\xa1\xa6\x10\x15\x72\xd7\x2a\xca\x21\x63\x0f\x59\x0b\xaf\xbd\xb2\x67\xa1\x51\xc4\xfd\xed\x27\x2f\xbb\x84\xd0\x36\x3f\xb1\xf6\xf7\xcd\xf8\xf3\xf8\x9b\xe1\xe8\x3f\xe9\x5c\xdb\x74\x2e\x42\xc6\x8e\x60\x3a\xee\x8f\xa1\x8f\x85\x47\x29\x08\xd5\x09\xac\xb5\x31\x30\x47\xf0\x98\xbb\x15\x2a\x08\xce\x59\xc6\x02\x12\x70\x07\xe8\x3d\x7e\xd3\xd4\x2c\x0b\x5d\xe0\x42\x68\xd3\xac\xad\x2b\x6d\x40\x62\x6c\x51\x5a\x49\xda\x59\xb8\x43\x9a\xe5\xe2\xdb\xac\x70\x2a\x1c\xb7\xe1\x81\x01\xac\x33\x6d\x62\x7a\xa1\x40\xdb\x40\xc2\x4a\x9c\xd1\x7d\x81\x10\x39\xef\x40\x39\x06\x00\xa0\x17\x00\x37\x37\x90\xb4\x1e\x9e\x90\x36\x09\x74\xbb\x71\xf7\x74\x93\xc0\xed\x2d\xbc\x78\x51\xb3\x62\x70\x04\xff\x81\xbf\x6f\x5e\xf2\xb7\xb7\xff\x6b\x45\xf8\x1d\x50\x86\xb6\x4a\x08\x80\x32\x73\x50\x33\xdf\xd5\x7b\x1e\xa9\xf4\x5b\xc2\x42\x33\x00\xe5\x2c\xc2\x7b\x48\x91\x64\x8a\xcb\x20\xc9\xa4\x8d\xfc\x4e\x2e\x0a\xb6\x61\xec\x08\xae\x03\xc2\xf0\x53\x7f\xb2\x3a\x03\x72\xf1\x8a\x90\x23\x09\x25\x48\xb0\xe9\xf8\xe3\x60\xd4\x4d\x5a\xc7\xb2\xf4\x06\x38\x0f\xda\xa0\x25\xe0\x5f\xe0\xea\x7a\x0a\xfc\x0f\x48\xbe\x70\xb1\x0e\x1c\xe5\x19\x6f\x82\x38\xb9\x25\x5a\x4e\x64\x78\x40\xe9\xac\x0a\xe7\xf0\xe6\xe5\xcb\x04\x32\xa2\xe2\x3c\x4d\x4f\xdf\xbc\xed\x9c\xfd\xff\x75\xa7\xfe\x4d\x8d\x20\x0c\x94\x8a\x42\xa7\x55\x64\x3b\x39\xa8\x77\x9d\xb7\xae\xf7\x81\x92\x67\x24\x9c\x43\xab\xd2\x9f\x40\xf2\xfc\xd1\x31\x8c\xc7\xb8\xb4\x75\x9a\xc4\x9a\x8c\xc6\xfd\xc1\x6c\x78\x15\x2f\xbe\xaf\x00\x8c\x93\xc2\x70\x5d\xac\x5e\xb7\x13\x36\x1c\x4d\xa6\xbd\xd1\xc5\x60\x36\xec\x7f\x47\x6c\x1e\x99\x6b\xb5\xcf\x9c\x7e\xbd\x1a\xfc\x9c\x1b\x0d\xd1\x4e\x58\xef\xaf\xc9\x6c\x32\xf8\xfc\xe7\xf0\x62\x30\x99\xf5\xc7\x9f\x7a\xc3\xd1\x77\x31\x01\xfd\x4a\x4b\x0c\xa9\x72\xb9\xd0\xb1\x64\x2c\xb8\xd2\x4b\x7c\xf2\xd4\xcb\x72\x8e\x06\xa9\x83\x76\x05\x47\x40\x99\x0e\x20\x85\x05\xb7\x42\xef\xb5\x42\xf8\xd4\xfb\x32\xbb\x1a\xf7\x27\x8c\x3d\x4a\xbc\x1c\x7e\x18\x5c\x7c\xbd\xb8\x7c\x46\xa7\xd1\x0b\xe4\xf2\x5e\x9a\xa8\x96\x49\x41\xf0\xcb\x0f\x8f\xad\xaa\x55\x1d\xfe\xfe\xfd\x60\xfc\x61\x57\xd5\xd6\x43\xfd\xb5\x79\x52\xc3\xd6\xc3\xde\x6a\x73\x50\xb4\x3d\x30\xae\x37\xac\xd1\xde\x6d\x3d\x34\x9f\xe7\xbc\x56\x5c\x3b\x3c\xf6\xd1\xd3\xa8\xa4\xbd\x61\x51\x09\x0b\x56\x14\x20\x8c\x16\x01\x6a\xb5\x1c\x97\xa1\x53\x7f\x37\x7b\x87\x34\x49\x66\x47\x93\x64\x9a\xbd\x2d\x2d\x90\x2b\xf6\x93\xb1\x70\x1f\x08\xf3\xc8\xf3\x18\x90\x78\x9c\x2c\xa8\x18\x3b\x66\x00\xdb\x41\x75\x1e\xdb\x39\x20\x84\xcc\x95\x46\xc5\x29\x65\x9c\x5b\xa2\x02\x41\x80\x2b\xf4\xf7\x40\x3a\xc7\x26\x29\x04\x12\x9e\x02\x94\xc5\x49\x95\x61\x9d\x69\x99\x81\x0e\xb0\xce\x04\xc1\x1a\x41\x39\xd0\x16\x7a\x97\x67\x70\xbc\xc3\xe6\x22\xa0\x02\x67\xa1\x30\x42\x5b\xd8\x6a\x52\xdb\x04\xc2\x2a\xc8\x51\x58\x8a\x6d\x3f\x8f\x03\xcb\x93\x98\x1b\x8c\xcb\xdc\x05\x6a\xd8\xa0\x74\x20\xef\x42\xfb\x04\xe6\x25\x81\xa6\xff\x86\x2a\xde\x3a\x02\x69\x50\x78\xc8\xdc\x3a\x06\x19\x27\x54\x7d\xa5\x85\x77\xf9\xa3\xf0\x58\x9f\xb5\xa6\xcc\x95\x04\x99\x58\x69\x7b\x57\x25\x20\x07\xb2\x0c\xe4\x72\x1d\x30\xc6\x6d\x89\x9a\x02\x9a\x05\x03\x78\xc6\xd1\x3b\x6b\x3d\x4f\xfb\x29\xa1\x31\x75\xc5\x60\x00\x0b\x23\xee\x42\xf7\xb8\x1a\x9c\x89\x75\x0a\xb9\x2e\xf6\x7c\x9a\x6c\x81\x5c\x7c\xe3\xd1\x58\x7b\x9e\x6b\xa0\x2a\xc6\x88\x39\x9a\xd0\xc4\x5d\xf6\x7e\x1b\x5c\x4e\x36\x27\xc2\x14\x99\xe8\x6c\x0f\xee\x68\x97\xee\xcd\x86\x03\xcf\x9f\x6c\xb3\xe8\x05\x56\xdd\xb5\x8f\xee\xda\xb2\x39\xb0\x70\x8a\x6b\xbb\xf0\x82\x4b\x67\x49\x68\x8b\x9e\xeb\x5c\xdc\xc5\xa8\x38\x41\x06\x1f\x27\xb3\xc1\xc5\xe7\x59\xef\xe2\x62\x7c\x3d\x9a\x6e\x3a\x6a\xe9\x3b\x28\x7d\x67\x0b\xf7\x07\x1f\x7a\xd7\x97\xd3\xd9\xe7\xc1\xef\xc3\xf1\x68\x53\xef\x1e\x8c\x9d\x4d\x2c\x57\x5a\x88\x32\xe0\xf9\xab\xce\xab\xe8\xea\x79\xa9\x8d\xea\x9c\xd6\x22\xa4\x71\xa5\xe2\x85\x77\x2b\xad\xd0\x77\xc5\x3a\x34\x80\xd5\x7c\xae\x2d\x57\xda\x77\x53\x57\x50\x2a\xad\x8e\x7f\xd3\x7b\xb0\x74\x76\xb1\xc5\xe3\xbb\x44\xdc\x22\x75\x54\xc3\xd8\x5d\xca\x97\x36\x76\x41\x57\x39\xb9\x44\xdf\x94\x1b\x69\xed\xfc\x92\x17\xa6\xbc\xd3\xb6\x2b\xad\xae\x01\x8f\x77\x3a\x10\x7a\x1e\x4b\xd9\x25\x5f\xe2\x21\x10\x7d\xc8\x63\x6e\xda\xbd\xd4\xb4\x37\x1c\x4d\x77\x4f\x59\x75\xb5\xb3\x0b\x7d\xd7\x3d\xf4\xd4\x76\xbb\x73\x2f\x72\xf3\xa8\xf3\x47\xc4\x68\xbe\x86\xd5\x8e\x06\xdb\x8e\x88\xc7\xd1\x12\x6b\x19\xe7\x53\x65\xbc\x9b\x5f\x6f\x37\x09\x6b\xb3\x66\x90\x08\xff\x84\xc7\xfe\x0d\x00\x00\xff\xff\x76\x63\xcb\x48\xe3\x08\x00\x00") - -func bindataAssetsBootstrapLegacyUbuntuShBytes() ([]byte, error) { - return bindataRead( - _bindataAssetsBootstrapLegacyUbuntuSh, - "bindata/assets/bootstrap.legacy.ubuntu.sh", - ) -} - -func bindataAssetsBootstrapLegacyUbuntuSh() (*asset, error) { - bytes, err := bindataAssetsBootstrapLegacyUbuntuShBytes() - if err != nil { - return nil, err - } - - info := bindataFileInfo{name: "bindata/assets/bootstrap.legacy.ubuntu.sh", size: 0, mode: os.FileMode(0), modTime: time.Unix(0, 0)} - a := &asset{bytes: bytes, info: info, digest: [32]uint8{0x38, 0xdc, 0xce, 0x7f, 0x6d, 0x30, 0x36, 0x5b, 0x8b, 0xc2, 0x38, 0x8d, 0x9e, 0xe4, 0xf8, 0x27, 0xd5, 0x77, 0x77, 0x8b, 0xaf, 0x59, 0xb3, 0x1a, 0xcd, 0x96, 0xe1, 0xcd, 0xc6, 0x2b, 0x19, 0x6b}} - return a, nil -} - -var _bindataAssetsBootstrapUbuntuSh = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\x6c\x91\xdf\x6b\xdb\x30\x10\xc7\xdf\xf5\x57\xdc\xb4\x82\x61\x20\x6b\x7b\xdd\xc3\x20\xeb\xbc\x52\xd6\x66\x23\x71\xa1\x90\x05\x23\x2b\x17\x5b\x89\x23\x69\x3a\x39\x04\x82\xff\xf7\x21\x86\xb3\x34\xc9\xe3\xdd\xf7\xc7\x7d\x6c\xbd\x7f\x27\x6b\x63\x65\xad\xa8\x65\x8c\x30\x82\x70\x80\x21\xe0\xc1\xc4\x71\xf4\xc6\xe3\x5a\x99\x6e\x9c\xad\xeb\x2d\x61\x64\x8c\x5c\x1f\x34\x82\xdc\xab\x20\x3b\x53\x4b\xdd\xb9\x7e\x25\x49\x07\xe3\x23\x49\xdc\x92\x8e\x9d\xac\x9d\x8b\x14\x83\xf2\x79\x8b\x9d\xc7\x90\xa7\x43\xa8\x5b\x07\xfc\x9f\xe3\x33\x84\xde\x5a\x63\x1b\x90\x18\x75\x8a\xfd\xcf\x70\x76\xbd\xcb\xa9\x05\x7e\x77\xbc\x7f\x7a\x99\x97\xc5\xac\x9a\x4e\x9e\x8b\x81\xc3\x6f\x06\x20\xc4\xca\x92\xd0\x5d\x4f\x11\x83\x30\xfe\xdc\xf6\x6d\x3a\x3f\xb9\xb6\x7d\x8d\x1d\x46\x81\x87\x18\x94\x50\xa1\xa1\xe4\xfc\xf1\xf2\xb5\x78\x2a\xca\xaa\x78\x2d\x67\x93\x6a\x32\x7b\x98\x0f\xfc\x92\x74\x87\xa1\x49\xa4\x3d\x61\x00\xe7\xa3\x71\x96\xc0\xd8\xe8\x60\xec\xd4\xce\xae\x4d\x93\x6f\xc8\x59\xce\x12\x2e\x64\x61\x07\x62\x0d\x77\xc7\xf2\xf9\x57\x95\x8e\x54\xf7\x3f\xa7\xdf\x87\x0c\x8a\xd7\xc7\x92\x6d\xfe\x80\x20\xc8\xf2\xc5\xc7\x25\x7c\x80\x7c\xf1\x69\x99\x9d\xc3\x24\xeb\xe3\xc3\xc0\xaf\x01\x4f\xca\x97\xa4\xbd\xed\xe6\x6c\xb7\xbf\xb1\xbd\x55\x7c\xf5\x16\x48\x51\x85\x98\x3e\xf2\xf4\x9b\xb6\xc4\x19\x59\xe5\x47\xf1\x5c\xb9\x88\xaf\x9c\x45\xce\xfe\x06\x00\x00\xff\xff\xad\x08\x49\xa5\x55\x02\x00\x00") - -func bindataAssetsBootstrapUbuntuShBytes() ([]byte, error) { - return bindataRead( - _bindataAssetsBootstrapUbuntuSh, - "bindata/assets/bootstrap.ubuntu.sh", - ) -} - -func bindataAssetsBootstrapUbuntuSh() (*asset, error) { - bytes, err := bindataAssetsBootstrapUbuntuShBytes() - if err != nil { - return nil, err - } - - info := bindataFileInfo{name: "bindata/assets/bootstrap.ubuntu.sh", size: 0, mode: os.FileMode(0), modTime: time.Unix(0, 0)} - a := &asset{bytes: bytes, info: info, digest: [32]uint8{0x6d, 0x94, 0xc2, 0xe1, 0x4f, 0x4c, 0xb5, 0x4d, 0x57, 0x4a, 0xa2, 0x51, 0x56, 0xf7, 0x8a, 0x83, 0xfe, 0xe7, 0x9c, 0xf3, 0x3f, 0x7b, 0xb6, 0x17, 0xc1, 0x29, 0x5b, 0x9c, 0x33, 0x76, 0xed, 0x28}} - return a, nil -} - -var _bindataAssetsEfaAl2Sh = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\x7c\xd0\x4d\x6a\xc3\x40\x0c\x05\xe0\xbd\x4e\xa1\xd2\xb5\x46\x25\xdd\x15\xba\xea\x01\x7a\x84\xa0\xa4\x1a\x7b\xc0\xf3\xd3\x91\x8c\x93\x9c\xbe\x38\x4d\xe8\xc2\x34\x9b\x81\x37\x7c\x12\x3c\x3d\x3f\xf1\x21\x15\x3e\x88\x8d\x00\xa6\x8e\x54\x51\x7b\xd7\x53\xf2\x7b\x6c\xa9\x69\x94\x34\xdd\x73\xa9\x73\x31\x75\x80\xf3\x9c\x31\x15\x73\x99\x26\xa4\x33\x2e\x83\x3a\xac\x0f\xd2\x37\x12\x79\xca\x5a\x67\x7f\xdf\xbd\xe0\xe8\xde\xec\x8d\xd9\x5e\x69\x36\x5a\xd4\x9c\x76\x41\xb2\x5c\x6a\x91\xc5\xc2\xb1\x66\x96\xc5\x48\xa3\xd0\x6d\x9f\xf6\xed\x0f\x4d\xe2\x6a\x1e\x5c\x7a\x18\x2e\x48\x9f\xc8\x9e\xdb\xd6\xdd\x00\xb8\x74\xa4\x53\x7c\xac\x90\x3e\xae\x00\x8e\x5f\xff\x40\x08\xac\x51\xf6\x7f\x83\x36\xae\x6d\x69\x00\xae\xcd\xf9\xb7\xc6\x4a\xae\x87\x8c\x69\x9f\x4a\xac\x48\x0d\x35\x0a\xfc\x04\x00\x00\xff\xff\x8f\x52\xee\x9a\x5f\x01\x00\x00") - -func bindataAssetsEfaAl2ShBytes() ([]byte, error) { - return bindataRead( - _bindataAssetsEfaAl2Sh, - "bindata/assets/efa.al2.sh", - ) -} - -func bindataAssetsEfaAl2Sh() (*asset, error) { - bytes, err := bindataAssetsEfaAl2ShBytes() - if err != nil { - return nil, err - } - - info := bindataFileInfo{name: "bindata/assets/efa.al2.sh", size: 0, mode: os.FileMode(0), modTime: time.Unix(0, 0)} - a := &asset{bytes: bytes, info: info, digest: [32]uint8{0x8f, 0xd9, 0x1d, 0x49, 0x21, 0x82, 0x43, 0xb0, 0xeb, 0x4d, 0xa2, 0x59, 0x42, 0xc6, 0xba, 0xc9, 0xb5, 0x60, 0xcd, 0x1d, 0x96, 0x18, 0x48, 0x80, 0x1b, 0x66, 0xda, 0x3e, 0x7, 0x93, 0xdb, 0x9e}} - return a, nil -} - -var _bindataAssetsEfaManagedBoothook = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\x8c\x90\x4d\x4e\xc4\x30\x0c\x85\xf7\x39\x85\x2f\xe0\x04\x0d\x3b\x24\x56\x1c\x80\x23\x54\xa6\xe3\xb4\x91\x9a\x1f\x62\x47\x65\xe6\xf4\x28\xed\x88\x0d\xad\x60\x67\xf9\x3d\x7f\xcf\x7a\xe3\x92\xdb\x15\x43\x0a\x8a\x85\x2b\xe4\x34\x32\xdc\x5a\x1c\xd6\x89\xb5\x0f\x10\x92\x28\x2d\x0b\xe0\x0d\xfa\xce\x1c\x1d\x74\x61\x60\x4f\xdb\x00\xf8\x09\x88\x1a\x22\xe7\xa6\xaf\x97\x27\x98\x55\x8b\xbc\x38\x27\xcf\xd8\x04\x57\x16\xc5\x8b\xa5\x48\xf7\x9c\x68\x15\x3b\xe6\xe8\x68\x15\x64\x4f\xf8\x08\xe3\xfa\x7b\x83\x0b\x29\x8b\x5a\xa5\x6a\xa7\x3b\xe0\x3b\x38\x8d\xe5\x2f\x9f\x39\xfc\x57\xa9\x6e\xef\x2a\x55\xc0\x2f\xff\x2f\x12\xe0\xdb\xe6\x33\xa5\xc9\x7c\x3d\x39\x39\x4c\x7b\xa8\x5b\xa2\x75\xec\x69\xf8\xf1\x5b\x99\x7b\xb1\x38\x99\x92\xcb\x19\xf3\x10\xba\x63\x7c\x06\x97\x8b\xba\xbd\xcd\xce\x76\x1f\x21\x39\x1f\x76\x0d\x4b\xf7\x99\xef\x00\x00\x00\xff\xff\xd7\xd4\x31\xc2\xe4\x01\x00\x00") - -func bindataAssetsEfaManagedBoothookBytes() ([]byte, error) { - return bindataRead( - _bindataAssetsEfaManagedBoothook, - "bindata/assets/efa.managed.boothook", - ) -} - -func bindataAssetsEfaManagedBoothook() (*asset, error) { - bytes, err := bindataAssetsEfaManagedBoothookBytes() - if err != nil { - return nil, err - } - - info := bindataFileInfo{name: "bindata/assets/efa.managed.boothook", size: 0, mode: os.FileMode(0), modTime: time.Unix(0, 0)} - a := &asset{bytes: bytes, info: info, digest: [32]uint8{0xa6, 0x40, 0xf1, 0xae, 0x67, 0xa7, 0xe, 0xc, 0x31, 0x61, 0x86, 0x41, 0x8b, 0xd1, 0x55, 0x3f, 0x84, 0xbd, 0x4c, 0xdd, 0x84, 0xc9, 0xee, 0x9d, 0x36, 0xda, 0x8f, 0x6c, 0xbc, 0x6a, 0xaf, 0xed}} - return a, nil -} - -var _bindataAssetsInstallSsmAl2Sh = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\x7c\xca\x41\x0a\x02\x31\x0c\x05\xd0\x7d\x4f\x11\x71\x5d\xe6\x4c\xa9\x44\x0d\xa4\xe9\xd0\xff\x07\xac\xa7\x77\x35\x2b\x61\x96\x0f\xde\xfd\xb6\x35\xcf\xad\x29\xde\xa5\xc0\x28\x75\x88\xcd\x69\x1f\xe7\xc9\xdd\x77\x7b\xaa\xc7\xe9\x1c\x47\xc2\x58\xca\x3a\xba\x78\x82\x1a\x21\x75\x89\x76\xfd\x8e\xac\x40\xaf\xfa\xb2\x64\xc1\x02\xad\x3f\x18\x62\xa9\x2d\xec\x6a\x80\x3a\xf9\x1f\x7e\x01\x00\x00\xff\xff\x93\x2c\xf6\x43\x9f\x00\x00\x00") - -func bindataAssetsInstallSsmAl2ShBytes() ([]byte, error) { - return bindataRead( - _bindataAssetsInstallSsmAl2Sh, - "bindata/assets/install-ssm.al2.sh", - ) -} - -func bindataAssetsInstallSsmAl2Sh() (*asset, error) { - bytes, err := bindataAssetsInstallSsmAl2ShBytes() - if err != nil { - return nil, err - } - - info := bindataFileInfo{name: "bindata/assets/install-ssm.al2.sh", size: 0, mode: os.FileMode(0), modTime: time.Unix(0, 0)} - a := &asset{bytes: bytes, info: info, digest: [32]uint8{0x18, 0xf9, 0xf8, 0x5e, 0xb9, 0xcf, 0xfb, 0x94, 0xb4, 0x85, 0xa3, 0x62, 0xf0, 0x3b, 0x88, 0x44, 0xe3, 0x84, 0xfa, 0x85, 0x39, 0xdb, 0xed, 0xa2, 0x6a, 0x1, 0x7b, 0xe5, 0x49, 0x21, 0xef, 0x3d}} - return a, nil -} - -var _bindataAssetsKubeletYaml = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\x6c\x91\xc1\xca\xdb\x30\x10\x84\xef\x7a\x8a\x85\x5e\x8b\xed\xb4\x04\x5a\xdd\xd2\x84\xf6\xd0\x40\xa0\x71\xdb\xf3\x5a\x1a\x37\xc2\xb2\x36\x48\xeb\xa4\xed\xd3\x97\xd8\xee\x0f\x81\x1f\x9d\x86\x99\x61\x3e\x49\x6f\xa8\x3d\x1d\x4e\x74\xc0\x35\xc3\xb1\xc2\xbf\xa5\x7b\x88\x91\x3a\x50\xc6\x28\x37\x78\x2a\x22\xc9\x0c\x21\x79\x4b\x5f\xa7\x0e\x11\xba\x97\xd4\x87\x5f\x53\x66\x0d\x92\x0c\x5f\xc3\x0f\xe4\x12\x24\x59\x1a\x96\x40\xe5\xe6\x44\x35\x7c\x28\x55\x90\xfa\xb6\xe9\xa0\xbc\x31\x86\xbd\xcf\x28\xc5\x52\x53\xcd\xc7\xb8\x38\x15\x45\x3e\xc8\xc8\x21\x59\x5a\x65\x15\xc5\x71\x34\x86\x27\xbd\x20\x69\x70\xf3\x90\x35\x44\x9c\x24\xfd\x19\x65\x2a\x0f\x41\x84\xc4\x5d\x84\xb7\xd4\x73\x2c\x30\x44\x77\x74\x17\x91\x61\x71\x1d\xbb\x0b\xda\xf6\x68\xe9\xdd\xd8\x94\xe7\x82\xe6\xe9\x91\xff\xbd\x6d\x3e\xae\xe1\x18\x90\x74\xbf\xfb\x1c\x22\x2c\xd5\x50\x57\x63\x28\x4e\x63\xed\xb8\x72\x59\x17\x1a\xc9\xe1\xef\x0b\xcc\x28\x1e\x96\x7e\x2e\x93\xaf\x8e\xef\xd6\x0a\xfc\x8c\xb1\xfd\x8f\x31\x9b\xdf\x13\x3f\xdb\xef\x9b\x62\x4c\x41\xbe\x21\xb7\xc7\xf3\x27\x11\x2d\x9a\xf9\xba\xc2\x9a\x1e\xac\x53\xc6\x17\x56\xcc\xd7\xff\x26\xca\x8a\xf5\x4b\xce\x73\x6d\x8f\xac\xa1\x7f\xbc\x17\xd6\xd6\xbf\x00\x00\x00\xff\xff\x46\x42\xbb\xf2\xe0\x01\x00\x00") - -func bindataAssetsKubeletYamlBytes() ([]byte, error) { - return bindataRead( - _bindataAssetsKubeletYaml, - "bindata/assets/kubelet.yaml", - ) -} - -func bindataAssetsKubeletYaml() (*asset, error) { - bytes, err := bindataAssetsKubeletYamlBytes() - if err != nil { - return nil, err - } - - info := bindataFileInfo{name: "bindata/assets/kubelet.yaml", size: 0, mode: os.FileMode(0), modTime: time.Unix(0, 0)} - a := &asset{bytes: bytes, info: info, digest: [32]uint8{0x90, 0x31, 0x7a, 0x5b, 0xa3, 0xbf, 0x93, 0x44, 0x7, 0x84, 0xfb, 0x4e, 0x10, 0x44, 0x47, 0xaa, 0xd1, 0x9, 0x71, 0x33, 0xdc, 0x75, 0x6b, 0x7c, 0x1c, 0x25, 0x25, 0xfa, 0x82, 0x6d, 0xc4, 0xf}} - return a, nil -} - -// Asset loads and returns the asset for the given name. -// It returns an error if the asset could not be found or -// could not be loaded. -func Asset(name string) ([]byte, error) { - canonicalName := strings.Replace(name, "\\", "/", -1) - if f, ok := _bindata[canonicalName]; ok { - a, err := f() - if err != nil { - return nil, fmt.Errorf("Asset %s can't read by error: %v", name, err) - } - return a.bytes, nil - } - return nil, fmt.Errorf("Asset %s not found", name) -} - -// AssetString returns the asset contents as a string (instead of a []byte). -func AssetString(name string) (string, error) { - data, err := Asset(name) - return string(data), err -} - -// MustAsset is like Asset but panics when Asset would return an error. -// It simplifies safe initialization of global variables. -func MustAsset(name string) []byte { - a, err := Asset(name) - if err != nil { - panic("asset: Asset(" + name + "): " + err.Error()) - } - - return a -} - -// MustAssetString is like AssetString but panics when Asset would return an -// error. It simplifies safe initialization of global variables. -func MustAssetString(name string) string { - return string(MustAsset(name)) -} - -// AssetInfo loads and returns the asset info for the given name. -// It returns an error if the asset could not be found or -// could not be loaded. -func AssetInfo(name string) (os.FileInfo, error) { - canonicalName := strings.Replace(name, "\\", "/", -1) - if f, ok := _bindata[canonicalName]; ok { - a, err := f() - if err != nil { - return nil, fmt.Errorf("AssetInfo %s can't read by error: %v", name, err) - } - return a.info, nil - } - return nil, fmt.Errorf("AssetInfo %s not found", name) -} - -// AssetDigest returns the digest of the file with the given name. It returns an -// error if the asset could not be found or the digest could not be loaded. -func AssetDigest(name string) ([sha256.Size]byte, error) { - canonicalName := strings.Replace(name, "\\", "/", -1) - if f, ok := _bindata[canonicalName]; ok { - a, err := f() - if err != nil { - return [sha256.Size]byte{}, fmt.Errorf("AssetDigest %s can't read by error: %v", name, err) - } - return a.digest, nil - } - return [sha256.Size]byte{}, fmt.Errorf("AssetDigest %s not found", name) -} - -// Digests returns a map of all known files and their checksums. -func Digests() (map[string][sha256.Size]byte, error) { - mp := make(map[string][sha256.Size]byte, len(_bindata)) - for name := range _bindata { - a, err := _bindata[name]() - if err != nil { - return nil, err - } - mp[name] = a.digest - } - return mp, nil -} - -// AssetNames returns the names of the assets. -func AssetNames() []string { - names := make([]string, 0, len(_bindata)) - for name := range _bindata { - names = append(names, name) - } - return names -} - -// _bindata is a table, holding each asset generator, mapped to its name. -var _bindata = map[string]func() (*asset, error){ - "bindata/assets/10-eksctl.al2.conf": bindataAssets10EksctlAl2Conf, - "bindata/assets/bootstrap.al2.sh": bindataAssetsBootstrapAl2Sh, - "bindata/assets/bootstrap.helper.sh": bindataAssetsBootstrapHelperSh, - "bindata/assets/bootstrap.legacy.al2.sh": bindataAssetsBootstrapLegacyAl2Sh, - "bindata/assets/bootstrap.legacy.ubuntu.sh": bindataAssetsBootstrapLegacyUbuntuSh, - "bindata/assets/bootstrap.ubuntu.sh": bindataAssetsBootstrapUbuntuSh, - "bindata/assets/efa.al2.sh": bindataAssetsEfaAl2Sh, - "bindata/assets/efa.managed.boothook": bindataAssetsEfaManagedBoothook, - "bindata/assets/install-ssm.al2.sh": bindataAssetsInstallSsmAl2Sh, - "bindata/assets/kubelet.yaml": bindataAssetsKubeletYaml, -} - -// AssetDebug is true if the assets were built with the debug flag enabled. -const AssetDebug = false - -// AssetDir returns the file names below a certain -// directory embedded in the file by go-bindata. -// For example if you run go-bindata on data/... and data contains the -// following hierarchy: -// data/ -// foo.txt -// img/ -// a.png -// b.png -// then AssetDir("data") would return []string{"foo.txt", "img"}, -// AssetDir("data/img") would return []string{"a.png", "b.png"}, -// AssetDir("foo.txt") and AssetDir("notexist") would return an error, and -// AssetDir("") will return []string{"data"}. -func AssetDir(name string) ([]string, error) { - node := _bintree - if len(name) != 0 { - canonicalName := strings.Replace(name, "\\", "/", -1) - pathList := strings.Split(canonicalName, "/") - for _, p := range pathList { - node = node.Children[p] - if node == nil { - return nil, fmt.Errorf("Asset %s not found", name) - } - } - } - if node.Func != nil { - return nil, fmt.Errorf("Asset %s not found", name) - } - rv := make([]string, 0, len(node.Children)) - for childName := range node.Children { - rv = append(rv, childName) - } - return rv, nil -} - -type bintree struct { - Func func() (*asset, error) - Children map[string]*bintree -} - -var _bintree = &bintree{nil, map[string]*bintree{ - "bindata": {nil, map[string]*bintree{ - "assets": {nil, map[string]*bintree{ - "10-eksctl.al2.conf": {bindataAssets10EksctlAl2Conf, map[string]*bintree{}}, - "bootstrap.al2.sh": {bindataAssetsBootstrapAl2Sh, map[string]*bintree{}}, - "bootstrap.helper.sh": {bindataAssetsBootstrapHelperSh, map[string]*bintree{}}, - "bootstrap.legacy.al2.sh": {bindataAssetsBootstrapLegacyAl2Sh, map[string]*bintree{}}, - "bootstrap.legacy.ubuntu.sh": {bindataAssetsBootstrapLegacyUbuntuSh, map[string]*bintree{}}, - "bootstrap.ubuntu.sh": {bindataAssetsBootstrapUbuntuSh, map[string]*bintree{}}, - "efa.al2.sh": {bindataAssetsEfaAl2Sh, map[string]*bintree{}}, - "efa.managed.boothook": {bindataAssetsEfaManagedBoothook, map[string]*bintree{}}, - "install-ssm.al2.sh": {bindataAssetsInstallSsmAl2Sh, map[string]*bintree{}}, - "kubelet.yaml": {bindataAssetsKubeletYaml, map[string]*bintree{}}, - }}, - }}, -}} - -// RestoreAsset restores an asset under the given directory. -func RestoreAsset(dir, name string) error { - data, err := Asset(name) - if err != nil { - return err - } - info, err := AssetInfo(name) - if err != nil { - return err - } - err = os.MkdirAll(_filePath(dir, filepath.Dir(name)), os.FileMode(0755)) - if err != nil { - return err - } - err = ioutil.WriteFile(_filePath(dir, name), data, info.Mode()) - if err != nil { - return err - } - return os.Chtimes(_filePath(dir, name), info.ModTime(), info.ModTime()) -} - -// RestoreAssets restores an asset under the given directory recursively. -func RestoreAssets(dir, name string) error { - children, err := AssetDir(name) - // File - if err != nil { - return RestoreAsset(dir, name) - } - // Dir - for _, child := range children { - err = RestoreAssets(dir, filepath.Join(name, child)) - if err != nil { - return err - } - } - return nil -} - -func _filePath(dir, name string) string { - canonicalName := strings.Replace(name, "\\", "/", -1) - return filepath.Join(append([]string{dir}, strings.Split(canonicalName, "/")...)...) -} diff --git a/pkg/nodebootstrap/legacy/al2.go b/pkg/nodebootstrap/legacy/al2.go index 00dd292a48..48aca9ff98 100644 --- a/pkg/nodebootstrap/legacy/al2.go +++ b/pkg/nodebootstrap/legacy/al2.go @@ -7,9 +7,16 @@ import ( "github.com/pkg/errors" api "github.com/weaveworks/eksctl/pkg/apis/eksctl.io/v1alpha5" "github.com/weaveworks/eksctl/pkg/cloudconfig" + "github.com/weaveworks/eksctl/pkg/nodebootstrap/assets" "github.com/weaveworks/eksctl/pkg/utils/kubeconfig" + + //For go:embed + _ "embed" ) +//go:embed scripts/bootstrap.legacy.al2.sh +var bootstrapLegacyAl2Sh string + type AL2Bootstrapper struct { clusterSpec *api.ClusterConfig ng *api.NodeGroup @@ -30,7 +37,7 @@ func (b AL2Bootstrapper) UserData() (string, error) { return "", err } - var scripts []string + var scripts []script for _, command := range b.ng.PreBootstrapCommands { config.AddShellCommand(command) @@ -40,9 +47,9 @@ func (b AL2Bootstrapper) UserData() (string, error) { config.AddShellCommand(*b.ng.OverrideBootstrapCommand) } else { if api.IsEnabled(b.ng.EFAEnabled) { - scripts = append(scripts, "efa.al2.sh") + scripts = append(scripts, script{name: "efa.al2.sh", contents: assets.EfaAl2Sh}) } - scripts = append(scripts, "bootstrap.legacy.al2.sh") + scripts = append(scripts, script{name: "bootstrap.legacy.al2.sh", contents: bootstrapLegacyAl2Sh}) } if err = addFilesAndScripts(config, files, scripts); err != nil { @@ -74,9 +81,9 @@ func makeAmazonLinux2Config(spec *api.ClusterConfig, ng *api.NodeGroup) ([]confi } files := []configFile{{ - dir: kubeletDropInUnitDir, - name: "10-eksctl.al2.conf", - isAsset: true, + dir: kubeletDropInUnitDir, + name: "10-eksctl.al2.conf", + contents: assets.EksctlAl2Conf, }, { dir: configDir, name: "metadata.env", diff --git a/pkg/nodebootstrap/bindata/assets/bootstrap.legacy.al2.sh b/pkg/nodebootstrap/legacy/scripts/bootstrap.legacy.al2.sh similarity index 100% rename from pkg/nodebootstrap/bindata/assets/bootstrap.legacy.al2.sh rename to pkg/nodebootstrap/legacy/scripts/bootstrap.legacy.al2.sh diff --git a/pkg/nodebootstrap/bindata/assets/bootstrap.legacy.ubuntu.sh b/pkg/nodebootstrap/legacy/scripts/bootstrap.legacy.ubuntu.sh similarity index 100% rename from pkg/nodebootstrap/bindata/assets/bootstrap.legacy.ubuntu.sh rename to pkg/nodebootstrap/legacy/scripts/bootstrap.legacy.ubuntu.sh diff --git a/pkg/nodebootstrap/legacy/ubuntu.go b/pkg/nodebootstrap/legacy/ubuntu.go index c2a3da0223..8eef15d043 100644 --- a/pkg/nodebootstrap/legacy/ubuntu.go +++ b/pkg/nodebootstrap/legacy/ubuntu.go @@ -9,8 +9,14 @@ import ( api "github.com/weaveworks/eksctl/pkg/apis/eksctl.io/v1alpha5" "github.com/weaveworks/eksctl/pkg/cloudconfig" "github.com/weaveworks/eksctl/pkg/utils/kubeconfig" + + // Import go:embed + _ "embed" ) +//go:embed scripts/bootstrap.legacy.ubuntu.sh +var bootstrapLegacyUbuntuShBytes []byte + const ubuntu2004ResolveConfPath = "/run/systemd/resolve/resolv.conf" type UbuntuBootstrapper struct { @@ -33,7 +39,7 @@ func (b UbuntuBootstrapper) UserData() (string, error) { return "", err } - scripts := []string{} + var scripts []script for _, command := range b.ng.PreBootstrapCommands { config.AddShellCommand(command) @@ -42,7 +48,7 @@ func (b UbuntuBootstrapper) UserData() (string, error) { if b.ng.OverrideBootstrapCommand != nil { config.AddShellCommand(*b.ng.OverrideBootstrapCommand) } else { - scripts = append(scripts, "bootstrap.legacy.ubuntu.sh") + scripts = append(scripts, script{name: "bootstrap.legacy.ubuntu.sh", contents: string(bootstrapLegacyUbuntuShBytes)}) } if err = addFilesAndScripts(config, files, scripts); err != nil { diff --git a/pkg/nodebootstrap/legacy/userdata.go b/pkg/nodebootstrap/legacy/userdata.go index 96a8807e75..f77979f20b 100644 --- a/pkg/nodebootstrap/legacy/userdata.go +++ b/pkg/nodebootstrap/legacy/userdata.go @@ -2,7 +2,6 @@ package legacy import ( "fmt" - "path/filepath" "strings" "github.com/pkg/errors" @@ -14,12 +13,11 @@ import ( api "github.com/weaveworks/eksctl/pkg/apis/eksctl.io/v1alpha5" "github.com/weaveworks/eksctl/pkg/cloudconfig" - "github.com/weaveworks/eksctl/pkg/nodebootstrap/bindata" + "github.com/weaveworks/eksctl/pkg/nodebootstrap/assets" "github.com/weaveworks/eksctl/pkg/utils/kubeconfig" ) const ( - dataDir = "bindata/assets" configDir = "/etc/eksctl/" kubeletDropInUnitDir = "/etc/systemd/system/kubelet.service.d/" ) @@ -28,42 +26,27 @@ type configFile struct { dir string name string contents string - isAsset bool } -func getAsset(name string) (string, error) { - data, err := bindata.Asset(filepath.Join(dataDir, name)) - if err != nil { - return "", errors.Wrapf(err, "decoding embedded file %q", name) - } - return string(data), nil +type script struct { + name string + contents string } -func addFilesAndScripts(config *cloudconfig.CloudConfig, files []configFile, scripts []string) error { +func addFilesAndScripts(config *cloudconfig.CloudConfig, files []configFile, scripts []script) error { for _, file := range files { f := cloudconfig.File{ - Path: file.dir + file.name, + Path: file.dir + file.name, + Content: file.contents, } - if file.isAsset { - data, err := getAsset(file.name) - if err != nil { - return err - } - f.Content = data - } else { - f.Content = file.contents - } + f.Content = file.contents config.AddFile(f) } - for _, scriptName := range scripts { - data, err := getAsset(scriptName) - if err != nil { - return err - } - config.RunScript(scriptName, data) + for _, s := range scripts { + config.RunScript(s.name, s.contents) } return nil } @@ -90,11 +73,7 @@ func getKubeReserved(info InstanceTypeInfo) api.InlineDocument { } func makeKubeletConfigYAML(spec *api.ClusterConfig, ng *api.NodeGroup) ([]byte, error) { - data, err := bindata.Asset(filepath.Join(dataDir, "kubelet.yaml")) - if err != nil { - return nil, err - } - + data := []byte(assets.KubeletYaml) // use a map here, as using struct will require us to add defaulting etc, // and we only need to add a few top-level fields obj := api.InlineDocument{} @@ -145,7 +124,7 @@ func makeKubeletConfigYAML(spec *api.ClusterConfig, ng *api.NodeGroup) ([]byte, } } - data, err = yaml.Marshal(obj) + data, err := yaml.Marshal(obj) if err != nil { return nil, err } diff --git a/pkg/nodebootstrap/managed_al2.go b/pkg/nodebootstrap/managed_al2.go index 0876f32969..92437add7f 100644 --- a/pkg/nodebootstrap/managed_al2.go +++ b/pkg/nodebootstrap/managed_al2.go @@ -11,6 +11,7 @@ import ( "github.com/pkg/errors" api "github.com/weaveworks/eksctl/pkg/apis/eksctl.io/v1alpha5" + "github.com/weaveworks/eksctl/pkg/nodebootstrap/assets" ) // ManagedAL2 is a bootstrapper for managed Amazon Linux 2 nodegroups @@ -52,11 +53,7 @@ func (m *ManagedAL2) UserData() (string, error) { } if api.IsEnabled(ng.EFAEnabled) { - data, err := getAsset("efa.managed.boothook") - if err != nil { - return "", err - } - cloudboot = append(cloudboot, data) + cloudboot = append(cloudboot, assets.EfaManagedBoothook) } if len(scripts) == 0 && len(cloudboot) == 0 { diff --git a/pkg/nodebootstrap/ubuntu.go b/pkg/nodebootstrap/ubuntu.go index f8523e7e10..a84ce95e92 100644 --- a/pkg/nodebootstrap/ubuntu.go +++ b/pkg/nodebootstrap/ubuntu.go @@ -4,6 +4,7 @@ import ( "github.com/kris-nova/logger" "github.com/pkg/errors" api "github.com/weaveworks/eksctl/pkg/apis/eksctl.io/v1alpha5" + "github.com/weaveworks/eksctl/pkg/nodebootstrap/assets" ) const ( @@ -23,7 +24,7 @@ func NewUbuntuBootstrapper(clusterConfig *api.ClusterConfig, np api.NodePool) *U } func (b *Ubuntu) UserData() (string, error) { - body, err := linuxConfig(b.clusterConfig, ubuntuBootScript, b.np) + body, err := linuxConfig(b.clusterConfig, ubuntuBootScript, assets.BootstrapUbuntuSh, b.np) if err != nil { return "", errors.Wrap(err, "encoding user data") } diff --git a/pkg/nodebootstrap/userdata.go b/pkg/nodebootstrap/userdata.go index 007a60755e..42c46426d2 100644 --- a/pkg/nodebootstrap/userdata.go +++ b/pkg/nodebootstrap/userdata.go @@ -5,27 +5,23 @@ import ( "encoding/json" "fmt" "net" - "path/filepath" "strconv" "strings" "github.com/kris-nova/logger" "github.com/pkg/errors" + "github.com/weaveworks/eksctl/pkg/nodebootstrap/assets" "github.com/weaveworks/eksctl/pkg/nodebootstrap/utils" kubeletapi "k8s.io/kubelet/config/v1beta1" api "github.com/weaveworks/eksctl/pkg/apis/eksctl.io/v1alpha5" "github.com/weaveworks/eksctl/pkg/cloudconfig" - "github.com/weaveworks/eksctl/pkg/nodebootstrap/bindata" "github.com/weaveworks/eksctl/pkg/nodebootstrap/legacy" ) -//go:generate ${GOBIN}/go-bindata -pkg bindata -prefix assets -nometadata -o bindata/assets.go bindata/assets - const ( - dataDir = "bindata/assets" configDir = "/etc/eksctl/" envFile = "kubelet.env" extraKubeConfFile = "kubelet-extra.json" @@ -104,7 +100,7 @@ func GetClusterDNS(clusterConfig *api.ClusterConfig) (string, error) { return ip.String(), nil } -func linuxConfig(clusterConfig *api.ClusterConfig, bootScript string, np api.NodePool, scripts ...string) (string, error) { +func linuxConfig(clusterConfig *api.ClusterConfig, bootScriptName, bootScriptContent string, np api.NodePool, scripts ...script) (string, error) { config := cloudconfig.New() ng := np.BaseNodeGroup() @@ -114,13 +110,13 @@ func linuxConfig(clusterConfig *api.ClusterConfig, bootScript string, np api.Nod var files []cloudconfig.File if len(scripts) == 0 { - scripts = []string{} + scripts = []script{} } if ng.OverrideBootstrapCommand != nil { config.AddShellCommand(*ng.OverrideBootstrapCommand) } else { - scripts = append(scripts, commonLinuxBootScript, bootScript) + scripts = append(scripts, script{name: commonLinuxBootScript, contents: assets.BootstrapHelperSh}, script{name: bootScriptName, contents: bootScriptContent}) var kubeletExtraConf *api.InlineDocument if unmanaged, ok := np.(*api.NodeGroup); ok { kubeletExtraConf = unmanaged.KubeletExtraConfig @@ -207,27 +203,19 @@ func formatLabels(labels map[string]string) string { return makeKeyValues(labels, ",") } -func addFilesAndScripts(config *cloudconfig.CloudConfig, files []cloudconfig.File, scripts []string) error { +type script struct { + name string + contents string +} + +func addFilesAndScripts(config *cloudconfig.CloudConfig, files []cloudconfig.File, scripts []script) error { for _, file := range files { config.AddFile(file) } - for _, scriptName := range scripts { - data, err := getAsset(scriptName) - if err != nil { - return err - } - config.RunScript(scriptName, data) + for _, s := range scripts { + config.RunScript(s.name, s.contents) } return nil } - -func getAsset(name string) (string, error) { - data, err := bindata.Asset(filepath.Join(dataDir, name)) - if err != nil { - return "", errors.Wrapf(err, "decoding embedded file %q", name) - } - - return string(data), nil -} diff --git a/tools.go b/tools.go index b67d1d5df6..cecb7fea8c 100644 --- a/tools.go +++ b/tools.go @@ -1,4 +1,4 @@ -// +build tools +//go:build tools package eksctl @@ -9,7 +9,6 @@ import ( _ "github.com/github-release/github-release" _ "github.com/golangci/golangci-lint/cmd/golangci-lint" _ "github.com/goreleaser/goreleaser" - _ "github.com/kevinburke/go-bindata/go-bindata" _ "github.com/maxbrunsfeld/counterfeiter/v6" _ "github.com/vektra/mockery/cmd/mockery" _ "golang.org/x/tools/cmd/stringer" From 4858dbb56c4708d448d93f417974f1323aa797fe Mon Sep 17 00:00:00 2001 From: Chetan Patwal Date: Thu, 28 Oct 2021 19:53:08 +0530 Subject: [PATCH 028/124] Add ARM support and fix AMI resolution for Ubuntu (#4367) --- integration/tests/managed/managed_nodegroup_test.go | 2 +- pkg/ami/auto_resolver.go | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/integration/tests/managed/managed_nodegroup_test.go b/integration/tests/managed/managed_nodegroup_test.go index b147ad5861..77a2d22115 100644 --- a/integration/tests/managed/managed_nodegroup_test.go +++ b/integration/tests/managed/managed_nodegroup_test.go @@ -118,7 +118,7 @@ var _ = Describe("(Integration) Create Managed Nodegroups", func() { }, }), - PEntry("Ubuntu", &api.ManagedNodeGroup{ + Entry("Ubuntu", &api.ManagedNodeGroup{ NodeGroupBase: &api.NodeGroupBase{ Name: "ubuntu", VolumeSize: aws.Int(25), diff --git a/pkg/ami/auto_resolver.go b/pkg/ami/auto_resolver.go index 3acfeccf3d..8b3a362bc9 100644 --- a/pkg/ami/auto_resolver.go +++ b/pkg/ami/auto_resolver.go @@ -26,7 +26,8 @@ func MakeImageSearchPatterns(version string) map[string]map[int]string { ImageClassARM: fmt.Sprintf("amazon-eks-arm64-node-%s-*", version), }, api.NodeImageFamilyUbuntu2004: { - ImageClassGeneral: fmt.Sprintf("ubuntu-eks/k8s_%s/images/*20.04*", version), + ImageClassGeneral: fmt.Sprintf("ubuntu-eks/k8s_%s/images/*20.04-amd64*", version), + ImageClassARM: fmt.Sprintf("ubuntu-eks/k8s_%s/images/*20.04-arm64*", version), }, api.NodeImageFamilyUbuntu1804: { ImageClassGeneral: fmt.Sprintf("ubuntu-eks/k8s_%s/images/*18.04*", version), From d5733509ab45accf240ac416ac26966913e49ed7 Mon Sep 17 00:00:00 2001 From: cpu1 Date: Tue, 28 Sep 2021 16:46:07 +0530 Subject: [PATCH 029/124] Add bootstrapper for native Bottlerocket --- pkg/apis/eksctl.io/v1alpha5/defaults.go | 7 +- pkg/eks/nodegroup_service.go | 2 +- pkg/nodebootstrap/bottlerocket.go | 46 ++++++------ pkg/nodebootstrap/managed_bottlerocket.go | 89 +++++++++++++++++++++++ pkg/nodebootstrap/userdata.go | 2 +- 5 files changed, 121 insertions(+), 25 deletions(-) create mode 100644 pkg/nodebootstrap/managed_bottlerocket.go diff --git a/pkg/apis/eksctl.io/v1alpha5/defaults.go b/pkg/apis/eksctl.io/v1alpha5/defaults.go index 92d0600509..1bd25fd46b 100644 --- a/pkg/apis/eksctl.io/v1alpha5/defaults.go +++ b/pkg/apis/eksctl.io/v1alpha5/defaults.go @@ -259,12 +259,15 @@ func setBottlerocketNodeGroupDefaults(ng *NodeGroupBase) { if ng.Bottlerocket == nil { ng.Bottlerocket = &NodeGroupBottlerocket{} } + if ng.Bottlerocket.Settings == nil { + ng.Bottlerocket.Settings = &InlineDocument{} + } // Use the SSH settings if the user hasn't explicitly configured the Admin // Container. If SSH was enabled, the user will be able to ssh into the // Bottlerocket node via the admin container. - if ng.Bottlerocket.EnableAdminContainer == nil && ng.SSH != nil { - ng.Bottlerocket.EnableAdminContainer = ng.SSH.Allow + if ng.Bottlerocket.EnableAdminContainer == nil && ng.SSH != nil && IsEnabled(ng.SSH.Allow) { + ng.Bottlerocket.EnableAdminContainer = Enabled() } } diff --git a/pkg/eks/nodegroup_service.go b/pkg/eks/nodegroup_service.go index 6eaf1812aa..239037b658 100644 --- a/pkg/eks/nodegroup_service.go +++ b/pkg/eks/nodegroup_service.go @@ -70,7 +70,7 @@ func (m *NodeGroupService) Normalize(nodePools []api.NodePool, clusterMeta *api. for _, np := range nodePools { switch ng := np.(type) { case *api.ManagedNodeGroup: - hasNativeAMIFamilySupport := ng.AMIFamily == api.NodeImageFamilyAmazonLinux2 + hasNativeAMIFamilySupport := ng.AMIFamily == api.NodeImageFamilyAmazonLinux2 || ng.AMIFamily == api.NodeImageFamilyBottlerocket if !hasNativeAMIFamilySupport && !api.IsAMI(ng.AMI) { if err := ResolveAMI(m.Provider, clusterMeta.Version, np); err != nil { return err diff --git a/pkg/nodebootstrap/bottlerocket.go b/pkg/nodebootstrap/bottlerocket.go index 3adc3edbd7..05926712af 100644 --- a/pkg/nodebootstrap/bottlerocket.go +++ b/pkg/nodebootstrap/bottlerocket.go @@ -5,7 +5,7 @@ import ( "fmt" "strings" - "github.com/pelletier/go-toml" + toml "github.com/pelletier/go-toml" "github.com/pkg/errors" api "github.com/weaveworks/eksctl/pkg/apis/eksctl.io/v1alpha5" ) @@ -25,9 +25,6 @@ func NewBottlerocketBootstrapper(clusterConfig *api.ClusterConfig, np api.NodePo // NewUserDataForBottlerocket generates TOML userdata for bootstrapping a Bottlerocket node. func (b *Bottlerocket) UserData() (string, error) { ng := b.np.BaseNodeGroup() - if ng.Bottlerocket.Settings == nil { - ng.Bottlerocket.Settings = &api.InlineDocument{} - } // Update settings based on NodeGroup configuration. Values set here are not // allowed to be set by the user - the values are owned by the NodeGroup and @@ -57,30 +54,21 @@ func (b *Bottlerocket) UserData() (string, error) { } func setDerivedBottlerocketSettings(np api.NodePool) error { - ng := np.BaseNodeGroup() - settings := *ng.Bottlerocket.Settings - - var kubernetesSettings map[string]interface{} - - if val, ok := settings["kubernetes"]; ok { - kubernetesSettings, ok = val.(map[string]interface{}) - if !ok { - return errors.Errorf("expected settings.kubernetes to be of type %T; got %T", kubernetesSettings, val) - } - } else { - kubernetesSettings = make(map[string]interface{}) - settings["kubernetes"] = kubernetesSettings + kubernetesSettings, err := extractKubernetesSettings(np) + if err != nil { + return err } + ng := np.BaseNodeGroup() if len(ng.Labels) != 0 { kubernetesSettings["node-labels"] = ng.Labels } - if ng.MaxPodsPerNode != 0 { - kubernetesSettings["max-pods"] = ng.MaxPodsPerNode - } if taints := np.NGTaints(); len(taints) != 0 { kubernetesSettings["node-taints"] = taintsToMap(taints) } + if ng.MaxPodsPerNode != 0 { + kubernetesSettings["max-pods"] = ng.MaxPodsPerNode + } if ng, ok := np.(*api.NodeGroup); ok { if ng.ClusterDNS != "" { @@ -90,6 +78,22 @@ func setDerivedBottlerocketSettings(np api.NodePool) error { return nil } +func extractKubernetesSettings(np api.NodePool) (map[string]interface{}, error) { + settings := *np.BaseNodeGroup().Bottlerocket.Settings + + var kubernetesSettings map[string]interface{} + if val, ok := settings["kubernetes"]; ok { + kubernetesSettings, ok = val.(map[string]interface{}) + if !ok { + return nil, errors.Errorf("expected settings.kubernetes to be of type %T; got %T", kubernetesSettings, val) + } + } else { + kubernetesSettings = make(map[string]interface{}) + settings["kubernetes"] = kubernetesSettings + } + return kubernetesSettings, nil +} + func taintsToMap(taints []api.NodeGroupTaint) map[string]string { ret := map[string]string{} for _, t := range taints { @@ -150,7 +154,7 @@ func bottlerocketSettingsTOML(spec *api.ClusterConfig, ng *api.NodeGroupBase, tr // Provide value only if given, with `enabled` // commented out otherwise. enabled := false - isUnset := ng.Bottlerocket == nil || ng.Bottlerocket.EnableAdminContainer == nil + isUnset := ng.Bottlerocket.EnableAdminContainer == nil if !isUnset { enabled = *ng.Bottlerocket.EnableAdminContainer } diff --git a/pkg/nodebootstrap/managed_bottlerocket.go b/pkg/nodebootstrap/managed_bottlerocket.go new file mode 100644 index 0000000000..9e3f483cb6 --- /dev/null +++ b/pkg/nodebootstrap/managed_bottlerocket.go @@ -0,0 +1,89 @@ +package nodebootstrap + +import ( + "encoding/base64" + + toml "github.com/pelletier/go-toml" + "github.com/pkg/errors" + + api "github.com/weaveworks/eksctl/pkg/apis/eksctl.io/v1alpha5" +) + +type ManagedBottlerocket struct { + clusterConfig *api.ClusterConfig + ng *api.ManagedNodeGroup +} + +// NewManagedBottlerocketBootstrapper returns a new bootstrapper for managed Bottlerocket. +func NewManagedBottlerocketBootstrapper(clusterConfig *api.ClusterConfig, ng *api.ManagedNodeGroup) *ManagedBottlerocket { + return &ManagedBottlerocket{ + clusterConfig: clusterConfig, + ng: ng, + } +} + +// UserData generates TOML userdata for bootstrapping a Bottlerocket node. +func (b *ManagedBottlerocket) UserData() (string, error) { + if err := b.setDerivedSettings(); err != nil { + return "", err + } + + settings, err := toml.TreeFromMap(map[string]interface{}{ + "settings": *b.ng.Bottlerocket.Settings, + }) + if err != nil { + return "", errors.Wrap(err, "error loading user-provided Bottlerocket settings") + } + + // Check and protect all input key names against TOML's dotted key semantics. + ProtectTOMLKeys([]string{"settings"}, settings) + + if enableAdminContainer := b.ng.Bottlerocket.EnableAdminContainer; enableAdminContainer != nil { + const adminContainerEnabledKey = "settings.host-containers.admin.enabled" + if settings.Has(adminContainerEnabledKey) { + return "", errors.Errorf("cannot set both bottlerocket.enableAdminContainer and %s", adminContainerEnabledKey) + } + settings.Set(adminContainerEnabledKey, *enableAdminContainer) + } + + userData := settings.String() + if userData == "" { + return "", errors.New("generated unexpected empty TOML user-data from input") + } + + return base64.StdEncoding.EncodeToString([]byte(userData)), nil +} + +func (b *ManagedBottlerocket) setDerivedSettings() error { + kubernetesSettings, err := extractKubernetesSettings(b.ng) + if err != nil { + return err + } + if err := validateBottlerocketSettings(kubernetesSettings); err != nil { + return err + } + + if b.ng.MaxPodsPerNode != 0 { + kubernetesSettings["max-pods"] = b.ng.MaxPodsPerNode + } + + return nil +} + +func validateBottlerocketSettings(kubernetesSettings map[string]interface{}) error { + clusterBootstrapKeys := []string{"cluster-certificate", "api-server", "cluster-name", "cluster-dns-ip"} + for _, k := range clusterBootstrapKeys { + if _, ok := kubernetesSettings[k]; ok { + return errors.Errorf("cannot set settings.kubernetes.%s; EKS automatically injects cluster bootstrapping fields into user-data", k) + } + } + + apiFields := []string{"node-labels", "node-taints"} + for _, k := range apiFields { + if _, ok := kubernetesSettings[k]; ok { + return errors.Errorf("cannot set settings.kubernetes.%s; labels and taints should be set on the managedNodeGroup object", k) + } + } + + return nil +} diff --git a/pkg/nodebootstrap/userdata.go b/pkg/nodebootstrap/userdata.go index 42c46426d2..0df5bdf36f 100644 --- a/pkg/nodebootstrap/userdata.go +++ b/pkg/nodebootstrap/userdata.go @@ -77,7 +77,7 @@ func NewManagedBootstrapper(clusterConfig *api.ClusterConfig, ng *api.ManagedNod case api.NodeImageFamilyAmazonLinux2: return NewManagedAL2Bootstrapper(ng) case api.NodeImageFamilyBottlerocket: - return NewBottlerocketBootstrapper(clusterConfig, ng) + return NewManagedBottlerocketBootstrapper(clusterConfig, ng) case api.NodeImageFamilyUbuntu1804, api.NodeImageFamilyUbuntu2004: return NewUbuntuBootstrapper(clusterConfig, ng) } From 33fd8b77f5721d29acd6850612eef2193d431790 Mon Sep 17 00:00:00 2001 From: cpu1 Date: Tue, 28 Sep 2021 16:47:06 +0530 Subject: [PATCH 030/124] Pass new AMI type to MNG API --- pkg/cfn/builder/managed_nodegroup.go | 39 ++++++++++++++++++++++------ 1 file changed, 31 insertions(+), 8 deletions(-) diff --git a/pkg/cfn/builder/managed_nodegroup.go b/pkg/cfn/builder/managed_nodegroup.go index 98c86da9f2..5fc8a8744d 100644 --- a/pkg/cfn/builder/managed_nodegroup.go +++ b/pkg/cfn/builder/managed_nodegroup.go @@ -127,7 +127,7 @@ func (m *ManagedNodeGroupResourceSet) AddAllResources() error { instanceTypes := m.nodeGroup.InstanceTypeList() makeAMIType := func() *gfnt.Value { - return gfnt.NewString(getAMIType(selectManagedInstanceType(m.nodeGroup))) + return gfnt.NewString(getAMIType(m.nodeGroup, selectManagedInstanceType(m.nodeGroup))) } var launchTemplate *gfneks.Nodegroup_LaunchTemplateSpecification @@ -152,9 +152,10 @@ func (m *ManagedNodeGroupResourceSet) AddAllResources() error { if launchTemplateData.InstanceType == nil { managedResource.AmiType = makeAMIType() } else { - managedResource.AmiType = gfnt.NewString(getAMIType(*launchTemplateData.InstanceType)) + managedResource.AmiType = gfnt.NewString(getAMIType(m.nodeGroup, *launchTemplateData.InstanceType)) } } + if launchTemplateData.InstanceType == nil { managedResource.InstanceTypes = gfnt.NewStringSlice(instanceTypes...) } @@ -259,14 +260,36 @@ func validateLaunchTemplate(launchTemplateData *ec2.ResponseLaunchTemplateData, return nil } -func getAMIType(instanceType string) string { - if instanceutils.IsGPUInstanceType(instanceType) { - return eks.AMITypesAl2X8664Gpu +func getAMIType(ng *api.ManagedNodeGroup, instanceType string) string { + amiTypeMapping := map[string]struct { + X86_64 string + GPU string + ARM string + }{ + api.NodeImageFamilyAmazonLinux2: { + X86_64: eks.AMITypesAl2X8664, + GPU: eks.AMITypesAl2X8664Gpu, + ARM: eks.AMITypesAl2Arm64, + }, + api.NodeImageFamilyBottlerocket: { + X86_64: eks.AMITypesBottlerocketX8664, + ARM: eks.AMITypesBottlerocketArm64, + }, + } + + amiType, ok := amiTypeMapping[ng.AMIFamily] + if !ok { + return eks.AMITypesCustom } - if instanceutils.IsARMInstanceType(instanceType) { - return eks.AMITypesAl2Arm64 + + switch { + case instanceutils.IsGPUInstanceType(instanceType): + return amiType.GPU + case instanceutils.IsARMInstanceType(instanceType): + return amiType.ARM + default: + return amiType.X86_64 } - return eks.AMITypesAl2X8664 } // RenderJSON implements the ResourceSet interface From 6587e1b50735182684bebdcef7173559239e60ec Mon Sep 17 00:00:00 2001 From: cpu1 Date: Tue, 28 Sep 2021 16:47:20 +0530 Subject: [PATCH 031/124] Add test for native Bottlerocket support --- pkg/nodebootstrap/bottlerocket_test.go | 5 +- .../managed_bottlerocket_test.go | 214 ++++++++++++++++++ 2 files changed, 216 insertions(+), 3 deletions(-) create mode 100644 pkg/nodebootstrap/managed_bottlerocket_test.go diff --git a/pkg/nodebootstrap/bottlerocket_test.go b/pkg/nodebootstrap/bottlerocket_test.go index e6b50633f0..0828a1e65f 100644 --- a/pkg/nodebootstrap/bottlerocket_test.go +++ b/pkg/nodebootstrap/bottlerocket_test.go @@ -7,10 +7,10 @@ import ( . "github.com/onsi/ginkgo" . "github.com/onsi/gomega" + toml "github.com/pelletier/go-toml" "github.com/stretchr/testify/require" "github.com/tj/assert" - "github.com/pelletier/go-toml" api "github.com/weaveworks/eksctl/pkg/apis/eksctl.io/v1alpha5" "github.com/weaveworks/eksctl/pkg/nodebootstrap" ) @@ -33,8 +33,7 @@ var _ = Describe("Bottlerocket", func() { ng = api.NewNodeGroup() ng.AMIFamily = "Bottlerocket" - // SetNodeGroupDefaults ensures this is non-nil for Bottlerocket nodegroups - ng.Bottlerocket = &api.NodeGroupBottlerocket{} + api.SetNodeGroupDefaults(ng, clusterConfig.Metadata) }) Describe("with no user settings", func() { diff --git a/pkg/nodebootstrap/managed_bottlerocket_test.go b/pkg/nodebootstrap/managed_bottlerocket_test.go new file mode 100644 index 0000000000..38baca28a9 --- /dev/null +++ b/pkg/nodebootstrap/managed_bottlerocket_test.go @@ -0,0 +1,214 @@ +package nodebootstrap_test + +import ( + "encoding/base64" + + . "github.com/onsi/ginkgo/extensions/table" + + . "github.com/onsi/ginkgo" + . "github.com/onsi/gomega" + + api "github.com/weaveworks/eksctl/pkg/apis/eksctl.io/v1alpha5" + "github.com/weaveworks/eksctl/pkg/nodebootstrap" +) + +var _ = Describe("Managed Bottlerocket", func() { + + type bottlerocketEntry struct { + setFields func(group *api.ManagedNodeGroup) + + expectedErr string + expectedUserData string + } + + DescribeTable("User data", func(e bottlerocketEntry) { + clusterConfig := api.NewClusterConfig() + clusterConfig.Metadata.Name = "managed-bottlerocket" + clusterConfig.Status = &api.ClusterStatus{ + Endpoint: "bottlerocket.cluster.com", + CertificateAuthorityData: []byte("CertificateAuthorityData"), + } + + ng := api.NewManagedNodeGroup() + ng.AMIFamily = api.NodeImageFamilyBottlerocket + api.SetManagedNodeGroupDefaults(ng, clusterConfig.Metadata) + if e.setFields != nil { + e.setFields(ng) + } + + bootstrapper := nodebootstrap.NewManagedBootstrapper(clusterConfig, ng) + userData, err := bootstrapper.UserData() + if e.expectedErr != "" { + Expect(err).To(HaveOccurred()) + Expect(err).To(MatchError(ContainSubstring(e.expectedErr))) + return + } + + Expect(err).ToNot(HaveOccurred()) + actual, err := base64.StdEncoding.DecodeString(userData) + Expect(err).ToNot(HaveOccurred()) + Expect(string(actual)).To(Equal(e.expectedUserData)) + }, + Entry("no settings", bottlerocketEntry{ + expectedUserData: ` +[settings] + + [settings.kubernetes] +`, + }), + Entry("maxPods set", bottlerocketEntry{ + setFields: func(ng *api.ManagedNodeGroup) { + ng.MaxPodsPerNode = 44 + }, + expectedUserData: ` +[settings] + + [settings.kubernetes] + max-pods = 44 +`, + }), + + Entry("enableAdminContainer set", bottlerocketEntry{ + setFields: func(ng *api.ManagedNodeGroup) { + ng.Bottlerocket.EnableAdminContainer = api.Enabled() + }, + expectedUserData: ` +[settings] + + [settings.host-containers] + + [settings.host-containers.admin] + enabled = true + + [settings.kubernetes] +`, + }), + + Entry("host containers enabled", bottlerocketEntry{ + setFields: func(ng *api.ManagedNodeGroup) { + ng.Bottlerocket.Settings = &api.InlineDocument{ + "host-containers": api.InlineDocument{ + "example": map[string]bool{ + "enabled": true, + }, + }, + } + }, + expectedUserData: ` +[settings] + + [settings.host-containers] + + [settings.host-containers.example] + enabled = true + + [settings.kubernetes] +`, + }), + + Entry("retain user-specified admin container setting", bottlerocketEntry{ + setFields: func(ng *api.ManagedNodeGroup) { + ng.Bottlerocket.Settings = &api.InlineDocument{ + "host-containers": map[string]interface{}{ + "admin": map[string]interface{}{ + "enabled": true, + }, + }, + } + }, + expectedUserData: ` +[settings] + + [settings.host-containers] + + [settings.host-containers.admin] + enabled = true + + [settings.kubernetes] +`, + }), + + Entry("labels and taints set", bottlerocketEntry{ + setFields: func(ng *api.ManagedNodeGroup) { + ng.Labels = map[string]string{ + "key": "value", + } + ng.Taints = []api.NodeGroupTaint{ + { + Key: "foo", + Value: "bar", + Effect: "NoExecute", + }, + } + }, + + expectedUserData: ` +[settings] + + [settings.kubernetes] +`, + }), + + Entry("preserve dotted keys", bottlerocketEntry{ + setFields: func(ng *api.ManagedNodeGroup) { + ng.Bottlerocket.Settings = &api.InlineDocument{ + "a.b.c": "value", + } + }, + + expectedUserData: ` +[settings] + "a.b.c" = "value" + + [settings.kubernetes] +`, + }), + + Entry("cluster bootstrap settings set", bottlerocketEntry{ + setFields: func(ng *api.ManagedNodeGroup) { + ng.Bottlerocket.Settings = &api.InlineDocument{ + "kubernetes": map[string]interface{}{ + "cluster-certificate": "test", + "api-server": "https://test.com", + "cluster-name": "test", + "cluster-dns-ip": "192.2.0.53", + }, + } + }, + + expectedErr: "EKS automatically injects cluster bootstrapping fields into user-data", + }), + + Entry("labels and taints in Bottlerocket settings", bottlerocketEntry{ + setFields: func(ng *api.ManagedNodeGroup) { + ng.Bottlerocket.Settings = &api.InlineDocument{ + "kubernetes": map[string]interface{}{ + "node-labels": map[string]string{ + "key": "value", + }, + "node-taints": map[string]string{ + "foo": "bar:NoExecute", + }, + }, + } + }, + + expectedErr: "cannot set settings.kubernetes.node-labels; labels and taints should be set on the managedNodeGroup object", + }), + + Entry("conflicting settings", bottlerocketEntry{ + setFields: func(ng *api.ManagedNodeGroup) { + ng.Bottlerocket.EnableAdminContainer = api.Enabled() + ng.Bottlerocket.Settings = &api.InlineDocument{ + "host-containers": map[string]interface{}{ + "admin": map[string]interface{}{ + "enabled": false, + }, + }, + } + }, + + expectedErr: "cannot set both bottlerocket.enableAdminContainer and settings.host-containers.admin.enabled", + }), + ) +}) From 8901fbcd1d804cffc38a810021f68815b4a73f74 Mon Sep 17 00:00:00 2001 From: cpu1 Date: Tue, 28 Sep 2021 17:52:38 +0530 Subject: [PATCH 032/124] Add integration tests for native Bottlerocket support --- .../tests/managed/managed_nodegroup_test.go | 84 ++++++++++++------- 1 file changed, 56 insertions(+), 28 deletions(-) diff --git a/integration/tests/managed/managed_nodegroup_test.go b/integration/tests/managed/managed_nodegroup_test.go index 77a2d22115..39cb21877d 100644 --- a/integration/tests/managed/managed_nodegroup_test.go +++ b/integration/tests/managed/managed_nodegroup_test.go @@ -191,37 +191,65 @@ var _ = Describe("(Integration) Create Managed Nodegroups", func() { }), ) - Context("Bottlerocket nodegroups", func() { - It("should work as a node AMI family", func() { - clusterConfig := makeClusterConfig() - clusterConfig.ManagedNodeGroups = []*api.ManagedNodeGroup{ + DescribeTable("Bottlerocket nodegroup", func(ng *api.ManagedNodeGroup) { + clusterConfig := makeClusterConfig() + clusterConfig.ManagedNodeGroups = []*api.ManagedNodeGroup{ng} + cmd := params.EksctlCreateCmd. + WithArgs( + "nodegroup", + "--config-file", "-", + "--verbose", "4", + ). + WithoutArg("--region", params.Region). + WithStdin(testutils.ClusterConfigReader(clusterConfig)) + + Expect(cmd).To(RunSuccessfully()) + }, + Entry("standard config", &api.ManagedNodeGroup{ + NodeGroupBase: &api.NodeGroupBase{ + Name: "bottlerocket", + VolumeSize: aws.Int(35), + AMIFamily: "Bottlerocket", + Labels: map[string]string{ + "ami-family": "bottlerocket", + }, + Bottlerocket: &api.NodeGroupBottlerocket{ + EnableAdminContainer: api.Enabled(), + }, + }, + Taints: []api.NodeGroupTaint{ { - NodeGroupBase: &api.NodeGroupBase{ - Name: "bottlerocket", - VolumeSize: aws.Int(35), - AMIFamily: "Bottlerocket", - }, - Taints: []api.NodeGroupTaint{ - { - Key: "key1", - Value: "value1", - Effect: "PreferNoSchedule", - }, - }, + Key: "key1", + Value: "value1", + Effect: "PreferNoSchedule", }, - } - cmd := params.EksctlCreateCmd. - WithArgs( - "nodegroup", - "--config-file", "-", - "--verbose", "4", - ). - WithoutArg("--region", params.Region). - WithStdin(testutils.ClusterConfigReader(clusterConfig)) + }, + }), - Expect(cmd).To(RunSuccessfully()) - }) - }) + Entry("with Bottlerocket settings", &api.ManagedNodeGroup{ + NodeGroupBase: &api.NodeGroupBase{ + Name: "bottlerocket", + VolumeSize: aws.Int(20), + AMIFamily: "Bottlerocket", + Labels: map[string]string{ + "ami-family": "bottlerocket", + }, + Bottlerocket: &api.NodeGroupBottlerocket{ + EnableAdminContainer: api.Enabled(), + Settings: &api.InlineDocument{ + "motd": "Bottlerocket is the future", + }, + }, + }, + Taints: []api.NodeGroupTaint{ + { + Key: "key1", + Value: "value1", + Effect: "PreferNoSchedule", + }, + }, + }), + ) Context("cluster with 1 managed nodegroup", func() { It("should have created an EKS cluster and two CloudFormation stacks", func() { From 849e326cd3b834bf48993756ab6a1d73e4367f93 Mon Sep 17 00:00:00 2001 From: cpu1 Date: Mon, 18 Oct 2021 16:16:49 +0530 Subject: [PATCH 033/124] Add test for AMI types --- pkg/apis/eksctl.io/v1alpha5/defaults_test.go | 16 +- .../managed_nodegroup_ami_type_test.go | 144 ++++++++++++++++++ 2 files changed, 159 insertions(+), 1 deletion(-) create mode 100644 pkg/cfn/builder/managed_nodegroup_ami_type_test.go diff --git a/pkg/apis/eksctl.io/v1alpha5/defaults_test.go b/pkg/apis/eksctl.io/v1alpha5/defaults_test.go index fd777f2b2c..41a7bfe6c8 100644 --- a/pkg/apis/eksctl.io/v1alpha5/defaults_test.go +++ b/pkg/apis/eksctl.io/v1alpha5/defaults_test.go @@ -144,6 +144,20 @@ var _ = Describe("ClusterConfig validation", func() { Expect(*testNodeGroup.Bottlerocket.EnableAdminContainer).To(BeTrue()) }) + It("leaves EnableAdminContainer unset if SSH is disabled", func() { + testNodeGroup := NodeGroup{ + NodeGroupBase: &NodeGroupBase{ + AMIFamily: NodeImageFamilyBottlerocket, + SSH: &NodeGroupSSH{ + Allow: Disabled(), + }, + }, + } + + SetNodeGroupDefaults(&testNodeGroup, &ClusterMeta{}) + Expect(testNodeGroup.Bottlerocket.EnableAdminContainer).To(BeNil()) + }) + It("has default NodeGroup configuration", func() { testNodeGroup := NodeGroup{ NodeGroupBase: &NodeGroupBase{ @@ -154,7 +168,7 @@ var _ = Describe("ClusterConfig validation", func() { SetNodeGroupDefaults(&testNodeGroup, &ClusterMeta{}) Expect(testNodeGroup.Bottlerocket).ToNot(BeNil()) - Expect(*testNodeGroup.Bottlerocket.EnableAdminContainer).To(BeFalse()) + Expect(testNodeGroup.Bottlerocket.EnableAdminContainer).To(BeNil()) }) }) diff --git a/pkg/cfn/builder/managed_nodegroup_ami_type_test.go b/pkg/cfn/builder/managed_nodegroup_ami_type_test.go new file mode 100644 index 0000000000..937fe65f0c --- /dev/null +++ b/pkg/cfn/builder/managed_nodegroup_ami_type_test.go @@ -0,0 +1,144 @@ +package builder + +import ( + . "github.com/onsi/ginkgo/extensions/table" + . "github.com/onsi/gomega" + api "github.com/weaveworks/eksctl/pkg/apis/eksctl.io/v1alpha5" + "github.com/weaveworks/eksctl/pkg/nodebootstrap" + "github.com/weaveworks/eksctl/pkg/testutils/mockprovider" + vpcfakes "github.com/weaveworks/eksctl/pkg/vpc/fakes" + "github.com/weaveworks/goformation/v4" + gfneks "github.com/weaveworks/goformation/v4/cloudformation/eks" +) + +type amiTypeEntry struct { + nodeGroup *api.ManagedNodeGroup + + expectedAMIType string +} + +var _ = DescribeTable("Managed Nodegroup AMI type", func(e amiTypeEntry) { + clusterConfig := api.NewClusterConfig() + clusterConfig.Status = &api.ClusterStatus{ + Endpoint: "https://test.com", + } + api.SetManagedNodeGroupDefaults(e.nodeGroup, clusterConfig.Metadata) + p := mockprovider.NewMockProvider() + fakeVPCImporter := new(vpcfakes.FakeImporter) + bootstrapper := nodebootstrap.NewManagedBootstrapper(clusterConfig, e.nodeGroup) + stack := NewManagedNodeGroup(p.EC2(), clusterConfig, e.nodeGroup, nil, bootstrapper, false, fakeVPCImporter) + + Expect(stack.AddAllResources()).To(Succeed()) + bytes, err := stack.RenderJSON() + Expect(err).ToNot(HaveOccurred()) + + template, err := goformation.ParseJSON(bytes) + Expect(err).ToNot(HaveOccurred()) + ngResource, ok := template.Resources["ManagedNodeGroup"] + Expect(ok).To(BeTrue()) + ng, ok := ngResource.(*gfneks.Nodegroup) + Expect(ok).To(BeTrue()) + Expect(ng.AmiType.String()).To(Equal(e.expectedAMIType)) +}, + Entry("default AMI type", amiTypeEntry{ + nodeGroup: &api.ManagedNodeGroup{ + NodeGroupBase: &api.NodeGroupBase{ + Name: "test", + }, + }, + expectedAMIType: "AL2_x86_64", + }), + + Entry("AL2 AMI type", amiTypeEntry{ + nodeGroup: &api.ManagedNodeGroup{ + NodeGroupBase: &api.NodeGroupBase{ + Name: "test", + AMIFamily: api.NodeImageFamilyAmazonLinux2, + }, + }, + expectedAMIType: "AL2_x86_64", + }), + + Entry("AMI type", amiTypeEntry{ + nodeGroup: &api.ManagedNodeGroup{ + NodeGroupBase: &api.NodeGroupBase{ + Name: "test", + }, + }, + expectedAMIType: "AL2_x86_64", + }), + + Entry("default GPU instance type", amiTypeEntry{ + nodeGroup: &api.ManagedNodeGroup{ + NodeGroupBase: &api.NodeGroupBase{ + Name: "test", + InstanceType: "p2.xlarge", + }, + }, + expectedAMIType: "AL2_x86_64_GPU", + }), + + Entry("AL2 GPU instance type", amiTypeEntry{ + nodeGroup: &api.ManagedNodeGroup{ + NodeGroupBase: &api.NodeGroupBase{ + Name: "test", + AMIFamily: api.NodeImageFamilyAmazonLinux2, + InstanceType: "p2.xlarge", + }, + }, + expectedAMIType: "AL2_x86_64_GPU", + }), + + Entry("AL2 ARM instance type", amiTypeEntry{ + nodeGroup: &api.ManagedNodeGroup{ + NodeGroupBase: &api.NodeGroupBase{ + Name: "test", + AMIFamily: api.NodeImageFamilyAmazonLinux2, + InstanceType: "a1.2xlarge", + }, + }, + expectedAMIType: "AL2_ARM_64", + }), + + Entry("Bottlerocket AMI type", amiTypeEntry{ + nodeGroup: &api.ManagedNodeGroup{ + NodeGroupBase: &api.NodeGroupBase{ + Name: "test", + AMIFamily: api.NodeImageFamilyBottlerocket, + }, + }, + expectedAMIType: "BOTTLEROCKET_x86_64", + }), + + Entry("Bottlerocket on ARM", amiTypeEntry{ + nodeGroup: &api.ManagedNodeGroup{ + NodeGroupBase: &api.NodeGroupBase{ + Name: "test", + AMIFamily: api.NodeImageFamilyBottlerocket, + InstanceType: "a1.2xlarge", + }, + }, + expectedAMIType: "BOTTLEROCKET_ARM_64", + }), + + Entry("Bottlerocket on ARM", amiTypeEntry{ + nodeGroup: &api.ManagedNodeGroup{ + NodeGroupBase: &api.NodeGroupBase{ + Name: "test", + AMIFamily: api.NodeImageFamilyBottlerocket, + InstanceType: "a1.2xlarge", + }, + }, + expectedAMIType: "BOTTLEROCKET_ARM_64", + }), + + Entry("non-native Ubuntu", amiTypeEntry{ + nodeGroup: &api.ManagedNodeGroup{ + NodeGroupBase: &api.NodeGroupBase{ + Name: "test", + AMIFamily: api.NodeImageFamilyUbuntu2004, + }, + }, + expectedAMIType: "CUSTOM", + }), +) From 0e84577c176893cb0f4de448fa2eb65568aadd20 Mon Sep 17 00:00:00 2001 From: cpu1 Date: Mon, 25 Oct 2021 18:57:23 +0530 Subject: [PATCH 034/124] Improve integration tests for Bottlerocket --- .../tests/managed/managed_nodegroup_test.go | 145 +++++++++++------- pkg/nodebootstrap/managed_bottlerocket.go | 4 + 2 files changed, 97 insertions(+), 52 deletions(-) diff --git a/integration/tests/managed/managed_nodegroup_test.go b/integration/tests/managed/managed_nodegroup_test.go index 39cb21877d..45747054ea 100644 --- a/integration/tests/managed/managed_nodegroup_test.go +++ b/integration/tests/managed/managed_nodegroup_test.go @@ -25,6 +25,7 @@ import ( "github.com/weaveworks/eksctl/integration/utilities/kube" api "github.com/weaveworks/eksctl/pkg/apis/eksctl.io/v1alpha5" "github.com/weaveworks/eksctl/pkg/testutils" + "github.com/weaveworks/eksctl/pkg/utils/names" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/client-go/kubernetes" @@ -191,65 +192,105 @@ var _ = Describe("(Integration) Create Managed Nodegroups", func() { }), ) - DescribeTable("Bottlerocket nodegroup", func(ng *api.ManagedNodeGroup) { - clusterConfig := makeClusterConfig() - clusterConfig.ManagedNodeGroups = []*api.ManagedNodeGroup{ng} - cmd := params.EksctlCreateCmd. - WithArgs( - "nodegroup", - "--config-file", "-", - "--verbose", "4", - ). - WithoutArg("--region", params.Region). - WithStdin(testutils.ClusterConfigReader(clusterConfig)) + Describe("Bottlerocket nodegroup", func() { + var kubeTest *harness.Test - Expect(cmd).To(RunSuccessfully()) - }, - Entry("standard config", &api.ManagedNodeGroup{ - NodeGroupBase: &api.NodeGroupBase{ - Name: "bottlerocket", - VolumeSize: aws.Int(35), - AMIFamily: "Bottlerocket", - Labels: map[string]string{ - "ami-family": "bottlerocket", - }, - Bottlerocket: &api.NodeGroupBottlerocket{ - EnableAdminContainer: api.Enabled(), + BeforeEach(func() { + var err error + kubeTest, err = kube.NewTest(params.KubeconfigPath) + Expect(err).ToNot(HaveOccurred()) + }) + + AfterEach(func() { + kubeTest.Close() + }) + + assertCreateBottlerocket := func(ng *api.ManagedNodeGroup) *corev1.NodeList { + clusterConfig := makeClusterConfig() + ng.Name = names.ForNodeGroup("", "") + + clusterConfig.ManagedNodeGroups = []*api.ManagedNodeGroup{ng} + cmd := params.EksctlCreateCmd. + WithArgs( + "nodegroup", + "--config-file", "-", + "--verbose", "4", + ). + WithoutArg("--region", params.Region). + WithStdin(testutils.ClusterConfigReader(clusterConfig)) + + Expect(cmd).To(RunSuccessfully()) + + nodeList := kubeTest.ListNodes(metav1.ListOptions{ + LabelSelector: fmt.Sprintf("%s=%s", "eks.amazonaws.com/nodegroup", ng.Name), + }) + Expect(nodeList.Items).ToNot(BeEmpty()) + for _, node := range nodeList.Items { + Expect(node.Status.NodeInfo.OSImage).To(ContainSubstring("Bottlerocket")) + } + return nodeList + } + + It("should create a standard nodegroup", func() { + ng := &api.ManagedNodeGroup{ + NodeGroupBase: &api.NodeGroupBase{ + VolumeSize: aws.Int(35), + AMIFamily: "Bottlerocket", + Labels: map[string]string{ + "ami-family": "bottlerocket", + }, + Bottlerocket: &api.NodeGroupBottlerocket{ + EnableAdminContainer: api.Enabled(), + }, + ScalingConfig: &api.ScalingConfig{ + DesiredCapacity: aws.Int(1), + }, }, - }, - Taints: []api.NodeGroupTaint{ - { - Key: "key1", - Value: "value1", - Effect: "PreferNoSchedule", + Taints: []api.NodeGroupTaint{ + { + Key: "key1", + Value: "value1", + Effect: "PreferNoSchedule", + }, }, - }, - }), + } - Entry("with Bottlerocket settings", &api.ManagedNodeGroup{ - NodeGroupBase: &api.NodeGroupBase{ - Name: "bottlerocket", - VolumeSize: aws.Int(20), - AMIFamily: "Bottlerocket", - Labels: map[string]string{ - "ami-family": "bottlerocket", - }, - Bottlerocket: &api.NodeGroupBottlerocket{ - EnableAdminContainer: api.Enabled(), - Settings: &api.InlineDocument{ - "motd": "Bottlerocket is the future", + assertCreateBottlerocket(ng) + }) + + It("should create a nodegroup with custom Bottlerocket settings", func() { + ng := &api.ManagedNodeGroup{ + NodeGroupBase: &api.NodeGroupBase{ + VolumeSize: aws.Int(20), + AMIFamily: "Bottlerocket", + Labels: map[string]string{ + "ami-family": "bottlerocket", + }, + Bottlerocket: &api.NodeGroupBottlerocket{ + EnableAdminContainer: api.Enabled(), + Settings: &api.InlineDocument{ + "motd": "Bottlerocket is the future", + "network": map[string]string{ + "hostname": "custom-bottlerocket-host", + }, + }, }, }, - }, - Taints: []api.NodeGroupTaint{ - { - Key: "key1", - Value: "value1", - Effect: "PreferNoSchedule", + Taints: []api.NodeGroupTaint{ + { + Key: "key1", + Value: "value1", + Effect: "PreferNoSchedule", + }, }, - }, - }), - ) + } + + nodeList := assertCreateBottlerocket(ng) + for _, node := range nodeList.Items { + Expect(node.Labels["kubernetes.io/hostname"]).To(Equal("custom-bottlerocket-host")) + } + }) + }) Context("cluster with 1 managed nodegroup", func() { It("should have created an EKS cluster and two CloudFormation stacks", func() { diff --git a/pkg/nodebootstrap/managed_bottlerocket.go b/pkg/nodebootstrap/managed_bottlerocket.go index 9e3f483cb6..ddac0c69c2 100644 --- a/pkg/nodebootstrap/managed_bottlerocket.go +++ b/pkg/nodebootstrap/managed_bottlerocket.go @@ -54,6 +54,8 @@ func (b *ManagedBottlerocket) UserData() (string, error) { return base64.StdEncoding.EncodeToString([]byte(userData)), nil } +// setDerivedSettings configures settings that are derived from top-level nodegroup config +// as opposed to settings configured in `bottlerocket.settings`. func (b *ManagedBottlerocket) setDerivedSettings() error { kubernetesSettings, err := extractKubernetesSettings(b.ng) if err != nil { @@ -70,6 +72,8 @@ func (b *ManagedBottlerocket) setDerivedSettings() error { return nil } +// validateBottlerocketSettings validates the supplied Kubernetes settings to ensure fields related to bootstrapping +// and fields available on the ManagedNodeGroup object are not set by the user. func validateBottlerocketSettings(kubernetesSettings map[string]interface{}) error { clusterBootstrapKeys := []string{"cluster-certificate", "api-server", "cluster-name", "cluster-dns-ip"} for _, k := range clusterBootstrapKeys { From a974707a7af8258a1f69d360794d050c63270d0c Mon Sep 17 00:00:00 2001 From: cpu1 Date: Fri, 29 Oct 2021 13:02:53 +0530 Subject: [PATCH 035/124] Update AWS SDK, generate mocks --- go.mod | 2 +- go.sum | 2 + pkg/eks/mocks/EC2API.go | 800 +++++++++++++++++++++++++++++++++++++++- 3 files changed, 785 insertions(+), 19 deletions(-) diff --git a/go.mod b/go.mod index 66e8f8b882..94655d5e75 100644 --- a/go.mod +++ b/go.mod @@ -41,7 +41,7 @@ require ( github.com/ashanbrown/forbidigo v1.2.0 // indirect github.com/ashanbrown/makezero v0.0.0-20210520155254-b6261585ddde // indirect github.com/aws/amazon-ec2-instance-selector/v2 v2.0.3-0.20210303155736-3e43512d88f8 - github.com/aws/aws-sdk-go v1.40.38 + github.com/aws/aws-sdk-go v1.41.13 github.com/awslabs/goformation/v4 v4.15.5 // indirect github.com/bazelbuild/bazel-gazelle v0.19.1 // indirect github.com/bazelbuild/buildtools v0.0.0-20190917191645-69366ca98f89 // indirect diff --git a/go.sum b/go.sum index 2bccb422f5..1349a3c0aa 100644 --- a/go.sum +++ b/go.sum @@ -301,6 +301,8 @@ github.com/aws/aws-sdk-go v1.37.0/go.mod h1:hcU610XS61/+aQV88ixoOzUoG7v3b31pl2zK github.com/aws/aws-sdk-go v1.40.34/go.mod h1:585smgzpB/KqRA+K3y/NL/oYRqQvpNJYvLm+LY1U59Q= github.com/aws/aws-sdk-go v1.40.38 h1:kl3iIW0h/JEBFjSBcAxDsiRbKMPz4aI5FJIHMCAQ+J0= github.com/aws/aws-sdk-go v1.40.38/go.mod h1:585smgzpB/KqRA+K3y/NL/oYRqQvpNJYvLm+LY1U59Q= +github.com/aws/aws-sdk-go v1.41.13 h1:wGgr6jkHdGExF33phfOqijFq7ZF+h7a6FXvJc77GpTc= +github.com/aws/aws-sdk-go v1.41.13/go.mod h1:585smgzpB/KqRA+K3y/NL/oYRqQvpNJYvLm+LY1U59Q= github.com/aws/aws-sdk-go-v2 v0.18.0/go.mod h1:JWVYvqSMppoMJC0x5wdwiImzgXTI9FuZwxzkQq9wy+g= github.com/aws/aws-sdk-go-v2 v1.9.0 h1:+S+dSqQCN3MSU5vJRu1HqHrq00cJn6heIMU7X9hcsoo= github.com/aws/aws-sdk-go-v2 v1.9.0/go.mod h1:cK/D0BBs0b/oWPIcX/Z/obahJK1TT7IPVjy53i/mX/4= diff --git a/pkg/eks/mocks/EC2API.go b/pkg/eks/mocks/EC2API.go index 7251f620e5..bf61ba8ab0 100644 --- a/pkg/eks/mocks/EC2API.go +++ b/pkg/eks/mocks/EC2API.go @@ -2692,6 +2692,84 @@ func (_m *EC2API) CancelCapacityReservation(_a0 *ec2.CancelCapacityReservationIn return r0, r1 } +// CancelCapacityReservationFleets provides a mock function with given fields: _a0 +func (_m *EC2API) CancelCapacityReservationFleets(_a0 *ec2.CancelCapacityReservationFleetsInput) (*ec2.CancelCapacityReservationFleetsOutput, error) { + ret := _m.Called(_a0) + + var r0 *ec2.CancelCapacityReservationFleetsOutput + if rf, ok := ret.Get(0).(func(*ec2.CancelCapacityReservationFleetsInput) *ec2.CancelCapacityReservationFleetsOutput); ok { + r0 = rf(_a0) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*ec2.CancelCapacityReservationFleetsOutput) + } + } + + var r1 error + if rf, ok := ret.Get(1).(func(*ec2.CancelCapacityReservationFleetsInput) error); ok { + r1 = rf(_a0) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// CancelCapacityReservationFleetsRequest provides a mock function with given fields: _a0 +func (_m *EC2API) CancelCapacityReservationFleetsRequest(_a0 *ec2.CancelCapacityReservationFleetsInput) (*request.Request, *ec2.CancelCapacityReservationFleetsOutput) { + ret := _m.Called(_a0) + + var r0 *request.Request + if rf, ok := ret.Get(0).(func(*ec2.CancelCapacityReservationFleetsInput) *request.Request); ok { + r0 = rf(_a0) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*request.Request) + } + } + + var r1 *ec2.CancelCapacityReservationFleetsOutput + if rf, ok := ret.Get(1).(func(*ec2.CancelCapacityReservationFleetsInput) *ec2.CancelCapacityReservationFleetsOutput); ok { + r1 = rf(_a0) + } else { + if ret.Get(1) != nil { + r1 = ret.Get(1).(*ec2.CancelCapacityReservationFleetsOutput) + } + } + + return r0, r1 +} + +// CancelCapacityReservationFleetsWithContext provides a mock function with given fields: _a0, _a1, _a2 +func (_m *EC2API) CancelCapacityReservationFleetsWithContext(_a0 context.Context, _a1 *ec2.CancelCapacityReservationFleetsInput, _a2 ...request.Option) (*ec2.CancelCapacityReservationFleetsOutput, error) { + _va := make([]interface{}, len(_a2)) + for _i := range _a2 { + _va[_i] = _a2[_i] + } + var _ca []interface{} + _ca = append(_ca, _a0, _a1) + _ca = append(_ca, _va...) + ret := _m.Called(_ca...) + + var r0 *ec2.CancelCapacityReservationFleetsOutput + if rf, ok := ret.Get(0).(func(context.Context, *ec2.CancelCapacityReservationFleetsInput, ...request.Option) *ec2.CancelCapacityReservationFleetsOutput); ok { + r0 = rf(_a0, _a1, _a2...) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*ec2.CancelCapacityReservationFleetsOutput) + } + } + + var r1 error + if rf, ok := ret.Get(1).(func(context.Context, *ec2.CancelCapacityReservationFleetsInput, ...request.Option) error); ok { + r1 = rf(_a0, _a1, _a2...) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + // CancelCapacityReservationRequest provides a mock function with given fields: _a0 func (_m *EC2API) CancelCapacityReservationRequest(_a0 *ec2.CancelCapacityReservationInput) (*request.Request, *ec2.CancelCapacityReservationOutput) { ret := _m.Called(_a0) @@ -3550,6 +3628,84 @@ func (_m *EC2API) CreateCapacityReservation(_a0 *ec2.CreateCapacityReservationIn return r0, r1 } +// CreateCapacityReservationFleet provides a mock function with given fields: _a0 +func (_m *EC2API) CreateCapacityReservationFleet(_a0 *ec2.CreateCapacityReservationFleetInput) (*ec2.CreateCapacityReservationFleetOutput, error) { + ret := _m.Called(_a0) + + var r0 *ec2.CreateCapacityReservationFleetOutput + if rf, ok := ret.Get(0).(func(*ec2.CreateCapacityReservationFleetInput) *ec2.CreateCapacityReservationFleetOutput); ok { + r0 = rf(_a0) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*ec2.CreateCapacityReservationFleetOutput) + } + } + + var r1 error + if rf, ok := ret.Get(1).(func(*ec2.CreateCapacityReservationFleetInput) error); ok { + r1 = rf(_a0) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// CreateCapacityReservationFleetRequest provides a mock function with given fields: _a0 +func (_m *EC2API) CreateCapacityReservationFleetRequest(_a0 *ec2.CreateCapacityReservationFleetInput) (*request.Request, *ec2.CreateCapacityReservationFleetOutput) { + ret := _m.Called(_a0) + + var r0 *request.Request + if rf, ok := ret.Get(0).(func(*ec2.CreateCapacityReservationFleetInput) *request.Request); ok { + r0 = rf(_a0) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*request.Request) + } + } + + var r1 *ec2.CreateCapacityReservationFleetOutput + if rf, ok := ret.Get(1).(func(*ec2.CreateCapacityReservationFleetInput) *ec2.CreateCapacityReservationFleetOutput); ok { + r1 = rf(_a0) + } else { + if ret.Get(1) != nil { + r1 = ret.Get(1).(*ec2.CreateCapacityReservationFleetOutput) + } + } + + return r0, r1 +} + +// CreateCapacityReservationFleetWithContext provides a mock function with given fields: _a0, _a1, _a2 +func (_m *EC2API) CreateCapacityReservationFleetWithContext(_a0 context.Context, _a1 *ec2.CreateCapacityReservationFleetInput, _a2 ...request.Option) (*ec2.CreateCapacityReservationFleetOutput, error) { + _va := make([]interface{}, len(_a2)) + for _i := range _a2 { + _va[_i] = _a2[_i] + } + var _ca []interface{} + _ca = append(_ca, _a0, _a1) + _ca = append(_ca, _va...) + ret := _m.Called(_ca...) + + var r0 *ec2.CreateCapacityReservationFleetOutput + if rf, ok := ret.Get(0).(func(context.Context, *ec2.CreateCapacityReservationFleetInput, ...request.Option) *ec2.CreateCapacityReservationFleetOutput); ok { + r0 = rf(_a0, _a1, _a2...) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*ec2.CreateCapacityReservationFleetOutput) + } + } + + var r1 error + if rf, ok := ret.Get(1).(func(context.Context, *ec2.CreateCapacityReservationFleetInput, ...request.Option) error); ok { + r1 = rf(_a0, _a1, _a2...) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + // CreateCapacityReservationRequest provides a mock function with given fields: _a0 func (_m *EC2API) CreateCapacityReservationRequest(_a0 *ec2.CreateCapacityReservationInput) (*request.Request, *ec2.CreateCapacityReservationOutput) { ret := _m.Called(_a0) @@ -13893,6 +14049,119 @@ func (_m *EC2API) DescribeByoipCidrsWithContext(_a0 context.Context, _a1 *ec2.De return r0, r1 } +// DescribeCapacityReservationFleets provides a mock function with given fields: _a0 +func (_m *EC2API) DescribeCapacityReservationFleets(_a0 *ec2.DescribeCapacityReservationFleetsInput) (*ec2.DescribeCapacityReservationFleetsOutput, error) { + ret := _m.Called(_a0) + + var r0 *ec2.DescribeCapacityReservationFleetsOutput + if rf, ok := ret.Get(0).(func(*ec2.DescribeCapacityReservationFleetsInput) *ec2.DescribeCapacityReservationFleetsOutput); ok { + r0 = rf(_a0) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*ec2.DescribeCapacityReservationFleetsOutput) + } + } + + var r1 error + if rf, ok := ret.Get(1).(func(*ec2.DescribeCapacityReservationFleetsInput) error); ok { + r1 = rf(_a0) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// DescribeCapacityReservationFleetsPages provides a mock function with given fields: _a0, _a1 +func (_m *EC2API) DescribeCapacityReservationFleetsPages(_a0 *ec2.DescribeCapacityReservationFleetsInput, _a1 func(*ec2.DescribeCapacityReservationFleetsOutput, bool) bool) error { + ret := _m.Called(_a0, _a1) + + var r0 error + if rf, ok := ret.Get(0).(func(*ec2.DescribeCapacityReservationFleetsInput, func(*ec2.DescribeCapacityReservationFleetsOutput, bool) bool) error); ok { + r0 = rf(_a0, _a1) + } else { + r0 = ret.Error(0) + } + + return r0 +} + +// DescribeCapacityReservationFleetsPagesWithContext provides a mock function with given fields: _a0, _a1, _a2, _a3 +func (_m *EC2API) DescribeCapacityReservationFleetsPagesWithContext(_a0 context.Context, _a1 *ec2.DescribeCapacityReservationFleetsInput, _a2 func(*ec2.DescribeCapacityReservationFleetsOutput, bool) bool, _a3 ...request.Option) error { + _va := make([]interface{}, len(_a3)) + for _i := range _a3 { + _va[_i] = _a3[_i] + } + var _ca []interface{} + _ca = append(_ca, _a0, _a1, _a2) + _ca = append(_ca, _va...) + ret := _m.Called(_ca...) + + var r0 error + if rf, ok := ret.Get(0).(func(context.Context, *ec2.DescribeCapacityReservationFleetsInput, func(*ec2.DescribeCapacityReservationFleetsOutput, bool) bool, ...request.Option) error); ok { + r0 = rf(_a0, _a1, _a2, _a3...) + } else { + r0 = ret.Error(0) + } + + return r0 +} + +// DescribeCapacityReservationFleetsRequest provides a mock function with given fields: _a0 +func (_m *EC2API) DescribeCapacityReservationFleetsRequest(_a0 *ec2.DescribeCapacityReservationFleetsInput) (*request.Request, *ec2.DescribeCapacityReservationFleetsOutput) { + ret := _m.Called(_a0) + + var r0 *request.Request + if rf, ok := ret.Get(0).(func(*ec2.DescribeCapacityReservationFleetsInput) *request.Request); ok { + r0 = rf(_a0) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*request.Request) + } + } + + var r1 *ec2.DescribeCapacityReservationFleetsOutput + if rf, ok := ret.Get(1).(func(*ec2.DescribeCapacityReservationFleetsInput) *ec2.DescribeCapacityReservationFleetsOutput); ok { + r1 = rf(_a0) + } else { + if ret.Get(1) != nil { + r1 = ret.Get(1).(*ec2.DescribeCapacityReservationFleetsOutput) + } + } + + return r0, r1 +} + +// DescribeCapacityReservationFleetsWithContext provides a mock function with given fields: _a0, _a1, _a2 +func (_m *EC2API) DescribeCapacityReservationFleetsWithContext(_a0 context.Context, _a1 *ec2.DescribeCapacityReservationFleetsInput, _a2 ...request.Option) (*ec2.DescribeCapacityReservationFleetsOutput, error) { + _va := make([]interface{}, len(_a2)) + for _i := range _a2 { + _va[_i] = _a2[_i] + } + var _ca []interface{} + _ca = append(_ca, _a0, _a1) + _ca = append(_ca, _va...) + ret := _m.Called(_ca...) + + var r0 *ec2.DescribeCapacityReservationFleetsOutput + if rf, ok := ret.Get(0).(func(context.Context, *ec2.DescribeCapacityReservationFleetsInput, ...request.Option) *ec2.DescribeCapacityReservationFleetsOutput); ok { + r0 = rf(_a0, _a1, _a2...) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*ec2.DescribeCapacityReservationFleetsOutput) + } + } + + var r1 error + if rf, ok := ret.Get(1).(func(context.Context, *ec2.DescribeCapacityReservationFleetsInput, ...request.Option) error); ok { + r1 = rf(_a0, _a1, _a2...) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + // DescribeCapacityReservations provides a mock function with given fields: _a0 func (_m *EC2API) DescribeCapacityReservations(_a0 *ec2.DescribeCapacityReservationsInput) (*ec2.DescribeCapacityReservationsOutput, error) { ret := _m.Called(_a0) @@ -30069,21 +30338,21 @@ func (_m *EC2API) GetHostReservationPurchasePreviewWithContext(_a0 context.Conte return r0, r1 } -// GetLaunchTemplateData provides a mock function with given fields: _a0 -func (_m *EC2API) GetLaunchTemplateData(_a0 *ec2.GetLaunchTemplateDataInput) (*ec2.GetLaunchTemplateDataOutput, error) { +// GetInstanceTypesFromInstanceRequirements provides a mock function with given fields: _a0 +func (_m *EC2API) GetInstanceTypesFromInstanceRequirements(_a0 *ec2.GetInstanceTypesFromInstanceRequirementsInput) (*ec2.GetInstanceTypesFromInstanceRequirementsOutput, error) { ret := _m.Called(_a0) - var r0 *ec2.GetLaunchTemplateDataOutput - if rf, ok := ret.Get(0).(func(*ec2.GetLaunchTemplateDataInput) *ec2.GetLaunchTemplateDataOutput); ok { + var r0 *ec2.GetInstanceTypesFromInstanceRequirementsOutput + if rf, ok := ret.Get(0).(func(*ec2.GetInstanceTypesFromInstanceRequirementsInput) *ec2.GetInstanceTypesFromInstanceRequirementsOutput); ok { r0 = rf(_a0) } else { if ret.Get(0) != nil { - r0 = ret.Get(0).(*ec2.GetLaunchTemplateDataOutput) + r0 = ret.Get(0).(*ec2.GetInstanceTypesFromInstanceRequirementsOutput) } } var r1 error - if rf, ok := ret.Get(1).(func(*ec2.GetLaunchTemplateDataInput) error); ok { + if rf, ok := ret.Get(1).(func(*ec2.GetInstanceTypesFromInstanceRequirementsInput) error); ok { r1 = rf(_a0) } else { r1 = ret.Error(1) @@ -30092,12 +30361,47 @@ func (_m *EC2API) GetLaunchTemplateData(_a0 *ec2.GetLaunchTemplateDataInput) (*e return r0, r1 } -// GetLaunchTemplateDataRequest provides a mock function with given fields: _a0 -func (_m *EC2API) GetLaunchTemplateDataRequest(_a0 *ec2.GetLaunchTemplateDataInput) (*request.Request, *ec2.GetLaunchTemplateDataOutput) { +// GetInstanceTypesFromInstanceRequirementsPages provides a mock function with given fields: _a0, _a1 +func (_m *EC2API) GetInstanceTypesFromInstanceRequirementsPages(_a0 *ec2.GetInstanceTypesFromInstanceRequirementsInput, _a1 func(*ec2.GetInstanceTypesFromInstanceRequirementsOutput, bool) bool) error { + ret := _m.Called(_a0, _a1) + + var r0 error + if rf, ok := ret.Get(0).(func(*ec2.GetInstanceTypesFromInstanceRequirementsInput, func(*ec2.GetInstanceTypesFromInstanceRequirementsOutput, bool) bool) error); ok { + r0 = rf(_a0, _a1) + } else { + r0 = ret.Error(0) + } + + return r0 +} + +// GetInstanceTypesFromInstanceRequirementsPagesWithContext provides a mock function with given fields: _a0, _a1, _a2, _a3 +func (_m *EC2API) GetInstanceTypesFromInstanceRequirementsPagesWithContext(_a0 context.Context, _a1 *ec2.GetInstanceTypesFromInstanceRequirementsInput, _a2 func(*ec2.GetInstanceTypesFromInstanceRequirementsOutput, bool) bool, _a3 ...request.Option) error { + _va := make([]interface{}, len(_a3)) + for _i := range _a3 { + _va[_i] = _a3[_i] + } + var _ca []interface{} + _ca = append(_ca, _a0, _a1, _a2) + _ca = append(_ca, _va...) + ret := _m.Called(_ca...) + + var r0 error + if rf, ok := ret.Get(0).(func(context.Context, *ec2.GetInstanceTypesFromInstanceRequirementsInput, func(*ec2.GetInstanceTypesFromInstanceRequirementsOutput, bool) bool, ...request.Option) error); ok { + r0 = rf(_a0, _a1, _a2, _a3...) + } else { + r0 = ret.Error(0) + } + + return r0 +} + +// GetInstanceTypesFromInstanceRequirementsRequest provides a mock function with given fields: _a0 +func (_m *EC2API) GetInstanceTypesFromInstanceRequirementsRequest(_a0 *ec2.GetInstanceTypesFromInstanceRequirementsInput) (*request.Request, *ec2.GetInstanceTypesFromInstanceRequirementsOutput) { ret := _m.Called(_a0) var r0 *request.Request - if rf, ok := ret.Get(0).(func(*ec2.GetLaunchTemplateDataInput) *request.Request); ok { + if rf, ok := ret.Get(0).(func(*ec2.GetInstanceTypesFromInstanceRequirementsInput) *request.Request); ok { r0 = rf(_a0) } else { if ret.Get(0) != nil { @@ -30105,20 +30409,20 @@ func (_m *EC2API) GetLaunchTemplateDataRequest(_a0 *ec2.GetLaunchTemplateDataInp } } - var r1 *ec2.GetLaunchTemplateDataOutput - if rf, ok := ret.Get(1).(func(*ec2.GetLaunchTemplateDataInput) *ec2.GetLaunchTemplateDataOutput); ok { + var r1 *ec2.GetInstanceTypesFromInstanceRequirementsOutput + if rf, ok := ret.Get(1).(func(*ec2.GetInstanceTypesFromInstanceRequirementsInput) *ec2.GetInstanceTypesFromInstanceRequirementsOutput); ok { r1 = rf(_a0) } else { if ret.Get(1) != nil { - r1 = ret.Get(1).(*ec2.GetLaunchTemplateDataOutput) + r1 = ret.Get(1).(*ec2.GetInstanceTypesFromInstanceRequirementsOutput) } } return r0, r1 } -// GetLaunchTemplateDataWithContext provides a mock function with given fields: _a0, _a1, _a2 -func (_m *EC2API) GetLaunchTemplateDataWithContext(_a0 context.Context, _a1 *ec2.GetLaunchTemplateDataInput, _a2 ...request.Option) (*ec2.GetLaunchTemplateDataOutput, error) { +// GetInstanceTypesFromInstanceRequirementsWithContext provides a mock function with given fields: _a0, _a1, _a2 +func (_m *EC2API) GetInstanceTypesFromInstanceRequirementsWithContext(_a0 context.Context, _a1 *ec2.GetInstanceTypesFromInstanceRequirementsInput, _a2 ...request.Option) (*ec2.GetInstanceTypesFromInstanceRequirementsOutput, error) { _va := make([]interface{}, len(_a2)) for _i := range _a2 { _va[_i] = _a2[_i] @@ -30128,17 +30432,95 @@ func (_m *EC2API) GetLaunchTemplateDataWithContext(_a0 context.Context, _a1 *ec2 _ca = append(_ca, _va...) ret := _m.Called(_ca...) - var r0 *ec2.GetLaunchTemplateDataOutput - if rf, ok := ret.Get(0).(func(context.Context, *ec2.GetLaunchTemplateDataInput, ...request.Option) *ec2.GetLaunchTemplateDataOutput); ok { + var r0 *ec2.GetInstanceTypesFromInstanceRequirementsOutput + if rf, ok := ret.Get(0).(func(context.Context, *ec2.GetInstanceTypesFromInstanceRequirementsInput, ...request.Option) *ec2.GetInstanceTypesFromInstanceRequirementsOutput); ok { r0 = rf(_a0, _a1, _a2...) } else { if ret.Get(0) != nil { - r0 = ret.Get(0).(*ec2.GetLaunchTemplateDataOutput) + r0 = ret.Get(0).(*ec2.GetInstanceTypesFromInstanceRequirementsOutput) } } var r1 error - if rf, ok := ret.Get(1).(func(context.Context, *ec2.GetLaunchTemplateDataInput, ...request.Option) error); ok { + if rf, ok := ret.Get(1).(func(context.Context, *ec2.GetInstanceTypesFromInstanceRequirementsInput, ...request.Option) error); ok { + r1 = rf(_a0, _a1, _a2...) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// GetLaunchTemplateData provides a mock function with given fields: _a0 +func (_m *EC2API) GetLaunchTemplateData(_a0 *ec2.GetLaunchTemplateDataInput) (*ec2.GetLaunchTemplateDataOutput, error) { + ret := _m.Called(_a0) + + var r0 *ec2.GetLaunchTemplateDataOutput + if rf, ok := ret.Get(0).(func(*ec2.GetLaunchTemplateDataInput) *ec2.GetLaunchTemplateDataOutput); ok { + r0 = rf(_a0) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*ec2.GetLaunchTemplateDataOutput) + } + } + + var r1 error + if rf, ok := ret.Get(1).(func(*ec2.GetLaunchTemplateDataInput) error); ok { + r1 = rf(_a0) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// GetLaunchTemplateDataRequest provides a mock function with given fields: _a0 +func (_m *EC2API) GetLaunchTemplateDataRequest(_a0 *ec2.GetLaunchTemplateDataInput) (*request.Request, *ec2.GetLaunchTemplateDataOutput) { + ret := _m.Called(_a0) + + var r0 *request.Request + if rf, ok := ret.Get(0).(func(*ec2.GetLaunchTemplateDataInput) *request.Request); ok { + r0 = rf(_a0) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*request.Request) + } + } + + var r1 *ec2.GetLaunchTemplateDataOutput + if rf, ok := ret.Get(1).(func(*ec2.GetLaunchTemplateDataInput) *ec2.GetLaunchTemplateDataOutput); ok { + r1 = rf(_a0) + } else { + if ret.Get(1) != nil { + r1 = ret.Get(1).(*ec2.GetLaunchTemplateDataOutput) + } + } + + return r0, r1 +} + +// GetLaunchTemplateDataWithContext provides a mock function with given fields: _a0, _a1, _a2 +func (_m *EC2API) GetLaunchTemplateDataWithContext(_a0 context.Context, _a1 *ec2.GetLaunchTemplateDataInput, _a2 ...request.Option) (*ec2.GetLaunchTemplateDataOutput, error) { + _va := make([]interface{}, len(_a2)) + for _i := range _a2 { + _va[_i] = _a2[_i] + } + var _ca []interface{} + _ca = append(_ca, _a0, _a1) + _ca = append(_ca, _va...) + ret := _m.Called(_ca...) + + var r0 *ec2.GetLaunchTemplateDataOutput + if rf, ok := ret.Get(0).(func(context.Context, *ec2.GetLaunchTemplateDataInput, ...request.Option) *ec2.GetLaunchTemplateDataOutput); ok { + r0 = rf(_a0, _a1, _a2...) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*ec2.GetLaunchTemplateDataOutput) + } + } + + var r1 error + if rf, ok := ret.Get(1).(func(context.Context, *ec2.GetLaunchTemplateDataInput, ...request.Option) error); ok { r1 = rf(_a0, _a1, _a2...) } else { r1 = ret.Error(1) @@ -30607,6 +30989,119 @@ func (_m *EC2API) GetSerialConsoleAccessStatusWithContext(_a0 context.Context, _ return r0, r1 } +// GetSpotPlacementScores provides a mock function with given fields: _a0 +func (_m *EC2API) GetSpotPlacementScores(_a0 *ec2.GetSpotPlacementScoresInput) (*ec2.GetSpotPlacementScoresOutput, error) { + ret := _m.Called(_a0) + + var r0 *ec2.GetSpotPlacementScoresOutput + if rf, ok := ret.Get(0).(func(*ec2.GetSpotPlacementScoresInput) *ec2.GetSpotPlacementScoresOutput); ok { + r0 = rf(_a0) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*ec2.GetSpotPlacementScoresOutput) + } + } + + var r1 error + if rf, ok := ret.Get(1).(func(*ec2.GetSpotPlacementScoresInput) error); ok { + r1 = rf(_a0) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// GetSpotPlacementScoresPages provides a mock function with given fields: _a0, _a1 +func (_m *EC2API) GetSpotPlacementScoresPages(_a0 *ec2.GetSpotPlacementScoresInput, _a1 func(*ec2.GetSpotPlacementScoresOutput, bool) bool) error { + ret := _m.Called(_a0, _a1) + + var r0 error + if rf, ok := ret.Get(0).(func(*ec2.GetSpotPlacementScoresInput, func(*ec2.GetSpotPlacementScoresOutput, bool) bool) error); ok { + r0 = rf(_a0, _a1) + } else { + r0 = ret.Error(0) + } + + return r0 +} + +// GetSpotPlacementScoresPagesWithContext provides a mock function with given fields: _a0, _a1, _a2, _a3 +func (_m *EC2API) GetSpotPlacementScoresPagesWithContext(_a0 context.Context, _a1 *ec2.GetSpotPlacementScoresInput, _a2 func(*ec2.GetSpotPlacementScoresOutput, bool) bool, _a3 ...request.Option) error { + _va := make([]interface{}, len(_a3)) + for _i := range _a3 { + _va[_i] = _a3[_i] + } + var _ca []interface{} + _ca = append(_ca, _a0, _a1, _a2) + _ca = append(_ca, _va...) + ret := _m.Called(_ca...) + + var r0 error + if rf, ok := ret.Get(0).(func(context.Context, *ec2.GetSpotPlacementScoresInput, func(*ec2.GetSpotPlacementScoresOutput, bool) bool, ...request.Option) error); ok { + r0 = rf(_a0, _a1, _a2, _a3...) + } else { + r0 = ret.Error(0) + } + + return r0 +} + +// GetSpotPlacementScoresRequest provides a mock function with given fields: _a0 +func (_m *EC2API) GetSpotPlacementScoresRequest(_a0 *ec2.GetSpotPlacementScoresInput) (*request.Request, *ec2.GetSpotPlacementScoresOutput) { + ret := _m.Called(_a0) + + var r0 *request.Request + if rf, ok := ret.Get(0).(func(*ec2.GetSpotPlacementScoresInput) *request.Request); ok { + r0 = rf(_a0) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*request.Request) + } + } + + var r1 *ec2.GetSpotPlacementScoresOutput + if rf, ok := ret.Get(1).(func(*ec2.GetSpotPlacementScoresInput) *ec2.GetSpotPlacementScoresOutput); ok { + r1 = rf(_a0) + } else { + if ret.Get(1) != nil { + r1 = ret.Get(1).(*ec2.GetSpotPlacementScoresOutput) + } + } + + return r0, r1 +} + +// GetSpotPlacementScoresWithContext provides a mock function with given fields: _a0, _a1, _a2 +func (_m *EC2API) GetSpotPlacementScoresWithContext(_a0 context.Context, _a1 *ec2.GetSpotPlacementScoresInput, _a2 ...request.Option) (*ec2.GetSpotPlacementScoresOutput, error) { + _va := make([]interface{}, len(_a2)) + for _i := range _a2 { + _va[_i] = _a2[_i] + } + var _ca []interface{} + _ca = append(_ca, _a0, _a1) + _ca = append(_ca, _va...) + ret := _m.Called(_ca...) + + var r0 *ec2.GetSpotPlacementScoresOutput + if rf, ok := ret.Get(0).(func(context.Context, *ec2.GetSpotPlacementScoresInput, ...request.Option) *ec2.GetSpotPlacementScoresOutput); ok { + r0 = rf(_a0, _a1, _a2...) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*ec2.GetSpotPlacementScoresOutput) + } + } + + var r1 error + if rf, ok := ret.Get(1).(func(context.Context, *ec2.GetSpotPlacementScoresInput, ...request.Option) error); ok { + r1 = rf(_a0, _a1, _a2...) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + // GetSubnetCidrReservations provides a mock function with given fields: _a0 func (_m *EC2API) GetSubnetCidrReservations(_a0 *ec2.GetSubnetCidrReservationsInput) (*ec2.GetSubnetCidrReservationsOutput, error) { ret := _m.Called(_a0) @@ -31250,6 +31745,197 @@ func (_m *EC2API) GetTransitGatewayRouteTablePropagationsWithContext(_a0 context return r0, r1 } +// GetVpnConnectionDeviceSampleConfiguration provides a mock function with given fields: _a0 +func (_m *EC2API) GetVpnConnectionDeviceSampleConfiguration(_a0 *ec2.GetVpnConnectionDeviceSampleConfigurationInput) (*ec2.GetVpnConnectionDeviceSampleConfigurationOutput, error) { + ret := _m.Called(_a0) + + var r0 *ec2.GetVpnConnectionDeviceSampleConfigurationOutput + if rf, ok := ret.Get(0).(func(*ec2.GetVpnConnectionDeviceSampleConfigurationInput) *ec2.GetVpnConnectionDeviceSampleConfigurationOutput); ok { + r0 = rf(_a0) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*ec2.GetVpnConnectionDeviceSampleConfigurationOutput) + } + } + + var r1 error + if rf, ok := ret.Get(1).(func(*ec2.GetVpnConnectionDeviceSampleConfigurationInput) error); ok { + r1 = rf(_a0) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// GetVpnConnectionDeviceSampleConfigurationRequest provides a mock function with given fields: _a0 +func (_m *EC2API) GetVpnConnectionDeviceSampleConfigurationRequest(_a0 *ec2.GetVpnConnectionDeviceSampleConfigurationInput) (*request.Request, *ec2.GetVpnConnectionDeviceSampleConfigurationOutput) { + ret := _m.Called(_a0) + + var r0 *request.Request + if rf, ok := ret.Get(0).(func(*ec2.GetVpnConnectionDeviceSampleConfigurationInput) *request.Request); ok { + r0 = rf(_a0) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*request.Request) + } + } + + var r1 *ec2.GetVpnConnectionDeviceSampleConfigurationOutput + if rf, ok := ret.Get(1).(func(*ec2.GetVpnConnectionDeviceSampleConfigurationInput) *ec2.GetVpnConnectionDeviceSampleConfigurationOutput); ok { + r1 = rf(_a0) + } else { + if ret.Get(1) != nil { + r1 = ret.Get(1).(*ec2.GetVpnConnectionDeviceSampleConfigurationOutput) + } + } + + return r0, r1 +} + +// GetVpnConnectionDeviceSampleConfigurationWithContext provides a mock function with given fields: _a0, _a1, _a2 +func (_m *EC2API) GetVpnConnectionDeviceSampleConfigurationWithContext(_a0 context.Context, _a1 *ec2.GetVpnConnectionDeviceSampleConfigurationInput, _a2 ...request.Option) (*ec2.GetVpnConnectionDeviceSampleConfigurationOutput, error) { + _va := make([]interface{}, len(_a2)) + for _i := range _a2 { + _va[_i] = _a2[_i] + } + var _ca []interface{} + _ca = append(_ca, _a0, _a1) + _ca = append(_ca, _va...) + ret := _m.Called(_ca...) + + var r0 *ec2.GetVpnConnectionDeviceSampleConfigurationOutput + if rf, ok := ret.Get(0).(func(context.Context, *ec2.GetVpnConnectionDeviceSampleConfigurationInput, ...request.Option) *ec2.GetVpnConnectionDeviceSampleConfigurationOutput); ok { + r0 = rf(_a0, _a1, _a2...) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*ec2.GetVpnConnectionDeviceSampleConfigurationOutput) + } + } + + var r1 error + if rf, ok := ret.Get(1).(func(context.Context, *ec2.GetVpnConnectionDeviceSampleConfigurationInput, ...request.Option) error); ok { + r1 = rf(_a0, _a1, _a2...) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// GetVpnConnectionDeviceTypes provides a mock function with given fields: _a0 +func (_m *EC2API) GetVpnConnectionDeviceTypes(_a0 *ec2.GetVpnConnectionDeviceTypesInput) (*ec2.GetVpnConnectionDeviceTypesOutput, error) { + ret := _m.Called(_a0) + + var r0 *ec2.GetVpnConnectionDeviceTypesOutput + if rf, ok := ret.Get(0).(func(*ec2.GetVpnConnectionDeviceTypesInput) *ec2.GetVpnConnectionDeviceTypesOutput); ok { + r0 = rf(_a0) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*ec2.GetVpnConnectionDeviceTypesOutput) + } + } + + var r1 error + if rf, ok := ret.Get(1).(func(*ec2.GetVpnConnectionDeviceTypesInput) error); ok { + r1 = rf(_a0) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// GetVpnConnectionDeviceTypesPages provides a mock function with given fields: _a0, _a1 +func (_m *EC2API) GetVpnConnectionDeviceTypesPages(_a0 *ec2.GetVpnConnectionDeviceTypesInput, _a1 func(*ec2.GetVpnConnectionDeviceTypesOutput, bool) bool) error { + ret := _m.Called(_a0, _a1) + + var r0 error + if rf, ok := ret.Get(0).(func(*ec2.GetVpnConnectionDeviceTypesInput, func(*ec2.GetVpnConnectionDeviceTypesOutput, bool) bool) error); ok { + r0 = rf(_a0, _a1) + } else { + r0 = ret.Error(0) + } + + return r0 +} + +// GetVpnConnectionDeviceTypesPagesWithContext provides a mock function with given fields: _a0, _a1, _a2, _a3 +func (_m *EC2API) GetVpnConnectionDeviceTypesPagesWithContext(_a0 context.Context, _a1 *ec2.GetVpnConnectionDeviceTypesInput, _a2 func(*ec2.GetVpnConnectionDeviceTypesOutput, bool) bool, _a3 ...request.Option) error { + _va := make([]interface{}, len(_a3)) + for _i := range _a3 { + _va[_i] = _a3[_i] + } + var _ca []interface{} + _ca = append(_ca, _a0, _a1, _a2) + _ca = append(_ca, _va...) + ret := _m.Called(_ca...) + + var r0 error + if rf, ok := ret.Get(0).(func(context.Context, *ec2.GetVpnConnectionDeviceTypesInput, func(*ec2.GetVpnConnectionDeviceTypesOutput, bool) bool, ...request.Option) error); ok { + r0 = rf(_a0, _a1, _a2, _a3...) + } else { + r0 = ret.Error(0) + } + + return r0 +} + +// GetVpnConnectionDeviceTypesRequest provides a mock function with given fields: _a0 +func (_m *EC2API) GetVpnConnectionDeviceTypesRequest(_a0 *ec2.GetVpnConnectionDeviceTypesInput) (*request.Request, *ec2.GetVpnConnectionDeviceTypesOutput) { + ret := _m.Called(_a0) + + var r0 *request.Request + if rf, ok := ret.Get(0).(func(*ec2.GetVpnConnectionDeviceTypesInput) *request.Request); ok { + r0 = rf(_a0) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*request.Request) + } + } + + var r1 *ec2.GetVpnConnectionDeviceTypesOutput + if rf, ok := ret.Get(1).(func(*ec2.GetVpnConnectionDeviceTypesInput) *ec2.GetVpnConnectionDeviceTypesOutput); ok { + r1 = rf(_a0) + } else { + if ret.Get(1) != nil { + r1 = ret.Get(1).(*ec2.GetVpnConnectionDeviceTypesOutput) + } + } + + return r0, r1 +} + +// GetVpnConnectionDeviceTypesWithContext provides a mock function with given fields: _a0, _a1, _a2 +func (_m *EC2API) GetVpnConnectionDeviceTypesWithContext(_a0 context.Context, _a1 *ec2.GetVpnConnectionDeviceTypesInput, _a2 ...request.Option) (*ec2.GetVpnConnectionDeviceTypesOutput, error) { + _va := make([]interface{}, len(_a2)) + for _i := range _a2 { + _va[_i] = _a2[_i] + } + var _ca []interface{} + _ca = append(_ca, _a0, _a1) + _ca = append(_ca, _va...) + ret := _m.Called(_ca...) + + var r0 *ec2.GetVpnConnectionDeviceTypesOutput + if rf, ok := ret.Get(0).(func(context.Context, *ec2.GetVpnConnectionDeviceTypesInput, ...request.Option) *ec2.GetVpnConnectionDeviceTypesOutput); ok { + r0 = rf(_a0, _a1, _a2...) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*ec2.GetVpnConnectionDeviceTypesOutput) + } + } + + var r1 error + if rf, ok := ret.Get(1).(func(context.Context, *ec2.GetVpnConnectionDeviceTypesInput, ...request.Option) error); ok { + r1 = rf(_a0, _a1, _a2...) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + // ImportClientVpnClientCertificateRevocationList provides a mock function with given fields: _a0 func (_m *EC2API) ImportClientVpnClientCertificateRevocationList(_a0 *ec2.ImportClientVpnClientCertificateRevocationListInput) (*ec2.ImportClientVpnClientCertificateRevocationListOutput, error) { ret := _m.Called(_a0) @@ -31897,6 +32583,84 @@ func (_m *EC2API) ModifyCapacityReservation(_a0 *ec2.ModifyCapacityReservationIn return r0, r1 } +// ModifyCapacityReservationFleet provides a mock function with given fields: _a0 +func (_m *EC2API) ModifyCapacityReservationFleet(_a0 *ec2.ModifyCapacityReservationFleetInput) (*ec2.ModifyCapacityReservationFleetOutput, error) { + ret := _m.Called(_a0) + + var r0 *ec2.ModifyCapacityReservationFleetOutput + if rf, ok := ret.Get(0).(func(*ec2.ModifyCapacityReservationFleetInput) *ec2.ModifyCapacityReservationFleetOutput); ok { + r0 = rf(_a0) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*ec2.ModifyCapacityReservationFleetOutput) + } + } + + var r1 error + if rf, ok := ret.Get(1).(func(*ec2.ModifyCapacityReservationFleetInput) error); ok { + r1 = rf(_a0) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// ModifyCapacityReservationFleetRequest provides a mock function with given fields: _a0 +func (_m *EC2API) ModifyCapacityReservationFleetRequest(_a0 *ec2.ModifyCapacityReservationFleetInput) (*request.Request, *ec2.ModifyCapacityReservationFleetOutput) { + ret := _m.Called(_a0) + + var r0 *request.Request + if rf, ok := ret.Get(0).(func(*ec2.ModifyCapacityReservationFleetInput) *request.Request); ok { + r0 = rf(_a0) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*request.Request) + } + } + + var r1 *ec2.ModifyCapacityReservationFleetOutput + if rf, ok := ret.Get(1).(func(*ec2.ModifyCapacityReservationFleetInput) *ec2.ModifyCapacityReservationFleetOutput); ok { + r1 = rf(_a0) + } else { + if ret.Get(1) != nil { + r1 = ret.Get(1).(*ec2.ModifyCapacityReservationFleetOutput) + } + } + + return r0, r1 +} + +// ModifyCapacityReservationFleetWithContext provides a mock function with given fields: _a0, _a1, _a2 +func (_m *EC2API) ModifyCapacityReservationFleetWithContext(_a0 context.Context, _a1 *ec2.ModifyCapacityReservationFleetInput, _a2 ...request.Option) (*ec2.ModifyCapacityReservationFleetOutput, error) { + _va := make([]interface{}, len(_a2)) + for _i := range _a2 { + _va[_i] = _a2[_i] + } + var _ca []interface{} + _ca = append(_ca, _a0, _a1) + _ca = append(_ca, _va...) + ret := _m.Called(_ca...) + + var r0 *ec2.ModifyCapacityReservationFleetOutput + if rf, ok := ret.Get(0).(func(context.Context, *ec2.ModifyCapacityReservationFleetInput, ...request.Option) *ec2.ModifyCapacityReservationFleetOutput); ok { + r0 = rf(_a0, _a1, _a2...) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*ec2.ModifyCapacityReservationFleetOutput) + } + } + + var r1 error + if rf, ok := ret.Get(1).(func(context.Context, *ec2.ModifyCapacityReservationFleetInput, ...request.Option) error); ok { + r1 = rf(_a0, _a1, _a2...) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + // ModifyCapacityReservationRequest provides a mock function with given fields: _a0 func (_m *EC2API) ModifyCapacityReservationRequest(_a0 *ec2.ModifyCapacityReservationInput) (*request.Request, *ec2.ModifyCapacityReservationOutput) { ret := _m.Called(_a0) From ef6720657f84dd5e3a0b365d27cc09e7f7159c49 Mon Sep 17 00:00:00 2001 From: cpu1 Date: Fri, 29 Oct 2021 14:32:58 +0530 Subject: [PATCH 036/124] Add release notes for 0.72 --- docs/release_notes/0.72.0.md | 9 +++++++++ 1 file changed, 9 insertions(+) create mode 100644 docs/release_notes/0.72.0.md diff --git a/docs/release_notes/0.72.0.md b/docs/release_notes/0.72.0.md new file mode 100644 index 0000000000..f0c40ec118 --- /dev/null +++ b/docs/release_notes/0.72.0.md @@ -0,0 +1,9 @@ +# Release 0.72.0 + +## Features + +- Native Bottlerocket support in managed nodegroups (#4381) + +## Bug Fixes + +- Add ARM support and fix AMI resolution for Ubuntu (#4367) From d850600924162fedeb62ecec5ddcaeaad8a31826 Mon Sep 17 00:00:00 2001 From: weaveworksbot Date: Fri, 29 Oct 2021 12:01:56 +0000 Subject: [PATCH 037/124] Prepare for next development iteration --- pkg/version/release.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkg/version/release.go b/pkg/version/release.go index f6d556e291..dfaa1692f0 100644 --- a/pkg/version/release.go +++ b/pkg/version/release.go @@ -3,7 +3,7 @@ package version // This file was generated by release_generate.go; DO NOT EDIT. // Version is the version number in semver format X.Y.Z -var Version = "0.72.0" +var Version = "0.73.0" // PreReleaseID can be empty for releases, "rc.X" for release candidates and "dev" for snapshots var PreReleaseID = "dev" From be7492484e6c8b6bbccbe69d0a295867f58f33c8 Mon Sep 17 00:00:00 2001 From: cpu1 Date: Mon, 1 Nov 2021 17:37:58 +0530 Subject: [PATCH 038/124] Clean up generation of aws-node manifest --- Makefile | 4 ---- 1 file changed, 4 deletions(-) diff --git a/Makefile b/Makefile index 99203c2687..c916fca40c 100644 --- a/Makefile +++ b/Makefile @@ -160,13 +160,10 @@ delete-integration-test-dev-cluster: build ## Delete the test cluster for use wh ##@ Code Generation -## Important: pkg/addons/default/generate.go depends on pkg/addons/default/assets/aws-node.yaml If this file is -## not present, the generation of assets will not fail but will not contain it. .PHONY: generate-always generate-always: pkg/addons/default/assets/aws-node.yaml ## Generate code (required for every build) go generate ./pkg/apis/eksctl.io/v1alpha5/generate.go go generate ./pkg/nodebootstrap - go generate ./pkg/addons/default/generate.go go generate ./pkg/addons go generate ./pkg/authconfigmap go generate ./pkg/eks @@ -195,7 +192,6 @@ pkg/addons/default/assets/aws-node.yaml: .PHONY: update-aws-node update-aws-node: ## Re-download the aws-node manifests from AWS go generate ./pkg/addons/default/aws_node_generate.go - go generate ./pkg/addons/default/generate.go deep_copy_helper_input = $(shell $(call godeps_cmd,./pkg/apis/...) | sed 's|$(generated_code_deep_copy_helper)||' ) $(generated_code_deep_copy_helper): $(deep_copy_helper_input) ## Generate Kubernetes API helpers From 000ca5a037818a3190a55ca74c47e80f23bfcb71 Mon Sep 17 00:00:00 2001 From: Jake Klein Date: Mon, 1 Nov 2021 12:12:46 +0000 Subject: [PATCH 039/124] update aws-node (#4391) --- pkg/addons/default/assets/aws-node.yaml | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/pkg/addons/default/assets/aws-node.yaml b/pkg/addons/default/assets/aws-node.yaml index 638400f8dc..3e08ab2322 100644 --- a/pkg/addons/default/assets/aws-node.yaml +++ b/pkg/addons/default/assets/aws-node.yaml @@ -64,7 +64,7 @@ - "list" - "watch" --- -"apiVersion": "apiextensions.k8s.io/v1beta1" +"apiVersion": "apiextensions.k8s.io/v1" "kind": "CustomResourceDefinition" "metadata": "name": "eniconfigs.crd.k8s.amazonaws.com" @@ -74,9 +74,14 @@ "kind": "ENIConfig" "plural": "eniconfigs" "singular": "eniconfig" + "preserveUnknownFields": false "scope": "Cluster" "versions": - "name": "v1alpha1" + "schema": + "openAPIV3Schema": + "type": "object" + "x-kubernetes-preserve-unknown-fields": true "served": true "storage": true --- @@ -257,3 +262,4 @@ "maxUnavailable": "10%" "type": "RollingUpdate" ... + From bca0dd966edab577dfffa2e1b44a374ed4f3e33e Mon Sep 17 00:00:00 2001 From: Jake Klein Date: Mon, 1 Nov 2021 12:25:21 +0000 Subject: [PATCH 040/124] reduce API calls in upgrade cluster (#4366) * reduce API calls in upgrade cluster * Update pkg/eks/eks.go Co-authored-by: Chetan Patwal Co-authored-by: Chetan Patwal --- pkg/actions/cluster/cluster.go | 8 +- pkg/actions/cluster/owned.go | 6 +- pkg/actions/cluster/owned_test.go | 4 +- pkg/actions/fargate/create_test.go | 4 - pkg/cfn/manager/api.go | 17 ++- pkg/cfn/manager/fakes/fake_stack_manager.go | 140 ++++++++++---------- pkg/cfn/manager/interface.go | 2 +- pkg/eks/eks.go | 13 +- 8 files changed, 99 insertions(+), 95 deletions(-) diff --git a/pkg/actions/cluster/cluster.go b/pkg/actions/cluster/cluster.go index a14fd7f0ae..b3d9825860 100644 --- a/pkg/actions/cluster/cluster.go +++ b/pkg/actions/cluster/cluster.go @@ -20,7 +20,7 @@ type Cluster interface { func New(cfg *api.ClusterConfig, ctl *eks.ClusterProvider) (Cluster, error) { clusterExists := true - err := ctl.RefreshClusterStatus(cfg) + err := ctl.RefreshClusterStatusIfStale(cfg) if err != nil { if awsError, ok := errors.Unwrap(errors.Unwrap(err)).(awserr.Error); ok && awsError.Code() == awseks.ErrCodeResourceNotFoundException { @@ -31,14 +31,14 @@ func New(cfg *api.ClusterConfig, ctl *eks.ClusterProvider) (Cluster, error) { } stackManager := ctl.NewStackManager(cfg) - hasClusterStack, err := stackManager.HasClusterStack() + clusterStack, err := stackManager.GetClusterStackIfExists() if err != nil { return nil, err } - if hasClusterStack { + if clusterStack != nil { logger.Debug("cluster %q was created by eksctl", cfg.Metadata.Name) - return NewOwnedCluster(cfg, ctl, stackManager), nil + return NewOwnedCluster(cfg, ctl, clusterStack, stackManager), nil } if !clusterExists { diff --git a/pkg/actions/cluster/owned.go b/pkg/actions/cluster/owned.go index 1d13de26e9..41ea0c57d8 100644 --- a/pkg/actions/cluster/owned.go +++ b/pkg/actions/cluster/owned.go @@ -18,14 +18,16 @@ import ( type OwnedCluster struct { cfg *api.ClusterConfig ctl *eks.ClusterProvider + clusterStack *manager.Stack stackManager manager.StackManager newClientSet func() (kubernetes.Interface, error) } -func NewOwnedCluster(cfg *api.ClusterConfig, ctl *eks.ClusterProvider, stackManager manager.StackManager) *OwnedCluster { +func NewOwnedCluster(cfg *api.ClusterConfig, ctl *eks.ClusterProvider, clusterStack *manager.Stack, stackManager manager.StackManager) *OwnedCluster { return &OwnedCluster{ cfg: cfg, ctl: ctl, + clusterStack: clusterStack, stackManager: stackManager, newClientSet: func() (kubernetes.Interface, error) { return ctl.NewStdClientSet(cfg) @@ -34,7 +36,7 @@ func NewOwnedCluster(cfg *api.ClusterConfig, ctl *eks.ClusterProvider, stackMana } func (c *OwnedCluster) Upgrade(dryRun bool) error { - if err := c.ctl.LoadClusterVPC(c.cfg, c.stackManager); err != nil { + if err := vpc.UseFromClusterStack(c.ctl.Provider, c.clusterStack, c.cfg); err != nil { return errors.Wrapf(err, "getting VPC configuration for cluster %q", c.cfg.Metadata.Name) } diff --git a/pkg/actions/cluster/owned_test.go b/pkg/actions/cluster/owned_test.go index 9d0cfe3fdf..ccbef90259 100644 --- a/pkg/actions/cluster/owned_test.go +++ b/pkg/actions/cluster/owned_test.go @@ -91,7 +91,7 @@ var _ = Describe("Delete", func() { }}}, }, nil) - c := cluster.NewOwnedCluster(cfg, ctl, fakeStackManager) + c := cluster.NewOwnedCluster(cfg, ctl, nil, fakeStackManager) fakeClientSet = fake.NewSimpleClientset() c.SetNewClientSet(func() (kubernetes.Interface, error) { @@ -135,7 +135,7 @@ var _ = Describe("Delete", func() { }}}, }, nil) - c := cluster.NewOwnedCluster(cfg, ctl, fakeStackManager) + c := cluster.NewOwnedCluster(cfg, ctl, nil, fakeStackManager) err := c.Delete(time.Microsecond, false, false) Expect(err).NotTo(HaveOccurred()) diff --git a/pkg/actions/fargate/create_test.go b/pkg/actions/fargate/create_test.go index 45c8e9ea7c..14a61ed31a 100644 --- a/pkg/actions/fargate/create_test.go +++ b/pkg/actions/fargate/create_test.go @@ -63,10 +63,6 @@ var _ = Describe("Fargate", func() { }) Context("owned cluster", func() { - BeforeEach(func() { - fakeStackManager.HasClusterStackReturns(true, nil) - }) - When("creating a farage role without specifying a role", func() { When("the fargate role doesn't exist", func() { BeforeEach(func() { diff --git a/pkg/cfn/manager/api.go b/pkg/cfn/manager/api.go index ae177e89eb..14a40f8ba4 100644 --- a/pkg/cfn/manager/api.go +++ b/pkg/cfn/manager/api.go @@ -555,30 +555,35 @@ func (c *StackCollection) DescribeStacks() ([]*Stack, error) { return stacks, nil } -func (c *StackCollection) HasClusterStack() (bool, error) { +func (c *StackCollection) GetClusterStackIfExists() (*Stack, error) { clusterStackNames, err := c.ListClusterStackNames() if err != nil { - return false, err + return nil, err } - return c.HasClusterStackUsingCachedList(clusterStackNames) + return c.getClusterStackUsingCachedList(clusterStackNames) } func (c *StackCollection) HasClusterStackUsingCachedList(clusterStackNames []string) (bool, error) { + stack, err := c.getClusterStackUsingCachedList(clusterStackNames) + return stack != nil, err +} + +func (c *StackCollection) getClusterStackUsingCachedList(clusterStackNames []string) (*Stack, error) { clusterStackName := c.MakeClusterStackName() for _, stack := range clusterStackNames { if stack == clusterStackName { stack, err := c.DescribeStack(&cloudformation.Stack{StackName: &clusterStackName}) if err != nil { - return false, err + return nil, err } for _, tag := range stack.Tags { if matchesClusterName(*tag.Key, *tag.Value, c.spec.Metadata.Name) { - return true, nil + return stack, nil } } } } - return false, nil + return nil, nil } // DescribeStackEvents describes the events that have occurred on the stack diff --git a/pkg/cfn/manager/fakes/fake_stack_manager.go b/pkg/cfn/manager/fakes/fake_stack_manager.go index 4a5b102d9c..7a82774855 100644 --- a/pkg/cfn/manager/fakes/fake_stack_manager.go +++ b/pkg/cfn/manager/fakes/fake_stack_manager.go @@ -280,6 +280,18 @@ type FakeStackManager struct { result1 string result2 error } + GetClusterStackIfExistsStub func() (*cloudformation.Stack, error) + getClusterStackIfExistsMutex sync.RWMutex + getClusterStackIfExistsArgsForCall []struct { + } + getClusterStackIfExistsReturns struct { + result1 *cloudformation.Stack + result2 error + } + getClusterStackIfExistsReturnsOnCall map[int]struct { + result1 *cloudformation.Stack + result2 error + } GetFargateStackStub func() (*cloudformation.Stack, error) getFargateStackMutex sync.RWMutex getFargateStackArgsForCall []struct { @@ -390,18 +402,6 @@ type FakeStackManager struct { result1 []*manager.NodeGroupSummary result2 error } - HasClusterStackStub func() (bool, error) - hasClusterStackMutex sync.RWMutex - hasClusterStackArgsForCall []struct { - } - hasClusterStackReturns struct { - result1 bool - result2 error - } - hasClusterStackReturnsOnCall map[int]struct { - result1 bool - result2 error - } HasClusterStackUsingCachedListStub func([]string) (bool, error) hasClusterStackUsingCachedListMutex sync.RWMutex hasClusterStackUsingCachedListArgsForCall []struct { @@ -1997,6 +1997,62 @@ func (fake *FakeStackManager) GetAutoScalingGroupNameReturnsOnCall(i int, result }{result1, result2} } +func (fake *FakeStackManager) GetClusterStackIfExists() (*cloudformation.Stack, error) { + fake.getClusterStackIfExistsMutex.Lock() + ret, specificReturn := fake.getClusterStackIfExistsReturnsOnCall[len(fake.getClusterStackIfExistsArgsForCall)] + fake.getClusterStackIfExistsArgsForCall = append(fake.getClusterStackIfExistsArgsForCall, struct { + }{}) + stub := fake.GetClusterStackIfExistsStub + fakeReturns := fake.getClusterStackIfExistsReturns + fake.recordInvocation("GetClusterStackIfExists", []interface{}{}) + fake.getClusterStackIfExistsMutex.Unlock() + if stub != nil { + return stub() + } + if specificReturn { + return ret.result1, ret.result2 + } + return fakeReturns.result1, fakeReturns.result2 +} + +func (fake *FakeStackManager) GetClusterStackIfExistsCallCount() int { + fake.getClusterStackIfExistsMutex.RLock() + defer fake.getClusterStackIfExistsMutex.RUnlock() + return len(fake.getClusterStackIfExistsArgsForCall) +} + +func (fake *FakeStackManager) GetClusterStackIfExistsCalls(stub func() (*cloudformation.Stack, error)) { + fake.getClusterStackIfExistsMutex.Lock() + defer fake.getClusterStackIfExistsMutex.Unlock() + fake.GetClusterStackIfExistsStub = stub +} + +func (fake *FakeStackManager) GetClusterStackIfExistsReturns(result1 *cloudformation.Stack, result2 error) { + fake.getClusterStackIfExistsMutex.Lock() + defer fake.getClusterStackIfExistsMutex.Unlock() + fake.GetClusterStackIfExistsStub = nil + fake.getClusterStackIfExistsReturns = struct { + result1 *cloudformation.Stack + result2 error + }{result1, result2} +} + +func (fake *FakeStackManager) GetClusterStackIfExistsReturnsOnCall(i int, result1 *cloudformation.Stack, result2 error) { + fake.getClusterStackIfExistsMutex.Lock() + defer fake.getClusterStackIfExistsMutex.Unlock() + fake.GetClusterStackIfExistsStub = nil + if fake.getClusterStackIfExistsReturnsOnCall == nil { + fake.getClusterStackIfExistsReturnsOnCall = make(map[int]struct { + result1 *cloudformation.Stack + result2 error + }) + } + fake.getClusterStackIfExistsReturnsOnCall[i] = struct { + result1 *cloudformation.Stack + result2 error + }{result1, result2} +} + func (fake *FakeStackManager) GetFargateStack() (*cloudformation.Stack, error) { fake.getFargateStackMutex.Lock() ret, specificReturn := fake.getFargateStackReturnsOnCall[len(fake.getFargateStackArgsForCall)] @@ -2543,62 +2599,6 @@ func (fake *FakeStackManager) GetUnmanagedNodeGroupSummariesReturnsOnCall(i int, }{result1, result2} } -func (fake *FakeStackManager) HasClusterStack() (bool, error) { - fake.hasClusterStackMutex.Lock() - ret, specificReturn := fake.hasClusterStackReturnsOnCall[len(fake.hasClusterStackArgsForCall)] - fake.hasClusterStackArgsForCall = append(fake.hasClusterStackArgsForCall, struct { - }{}) - stub := fake.HasClusterStackStub - fakeReturns := fake.hasClusterStackReturns - fake.recordInvocation("HasClusterStack", []interface{}{}) - fake.hasClusterStackMutex.Unlock() - if stub != nil { - return stub() - } - if specificReturn { - return ret.result1, ret.result2 - } - return fakeReturns.result1, fakeReturns.result2 -} - -func (fake *FakeStackManager) HasClusterStackCallCount() int { - fake.hasClusterStackMutex.RLock() - defer fake.hasClusterStackMutex.RUnlock() - return len(fake.hasClusterStackArgsForCall) -} - -func (fake *FakeStackManager) HasClusterStackCalls(stub func() (bool, error)) { - fake.hasClusterStackMutex.Lock() - defer fake.hasClusterStackMutex.Unlock() - fake.HasClusterStackStub = stub -} - -func (fake *FakeStackManager) HasClusterStackReturns(result1 bool, result2 error) { - fake.hasClusterStackMutex.Lock() - defer fake.hasClusterStackMutex.Unlock() - fake.HasClusterStackStub = nil - fake.hasClusterStackReturns = struct { - result1 bool - result2 error - }{result1, result2} -} - -func (fake *FakeStackManager) HasClusterStackReturnsOnCall(i int, result1 bool, result2 error) { - fake.hasClusterStackMutex.Lock() - defer fake.hasClusterStackMutex.Unlock() - fake.HasClusterStackStub = nil - if fake.hasClusterStackReturnsOnCall == nil { - fake.hasClusterStackReturnsOnCall = make(map[int]struct { - result1 bool - result2 error - }) - } - fake.hasClusterStackReturnsOnCall[i] = struct { - result1 bool - result2 error - }{result1, result2} -} - func (fake *FakeStackManager) HasClusterStackUsingCachedList(arg1 []string) (bool, error) { var arg1Copy []string if arg1 != nil { @@ -4219,6 +4219,8 @@ func (fake *FakeStackManager) Invocations() map[string][][]interface{} { defer fake.fixClusterCompatibilityMutex.RUnlock() fake.getAutoScalingGroupNameMutex.RLock() defer fake.getAutoScalingGroupNameMutex.RUnlock() + fake.getClusterStackIfExistsMutex.RLock() + defer fake.getClusterStackIfExistsMutex.RUnlock() fake.getFargateStackMutex.RLock() defer fake.getFargateStackMutex.RUnlock() fake.getIAMAddonNameMutex.RLock() @@ -4237,8 +4239,6 @@ func (fake *FakeStackManager) Invocations() map[string][][]interface{} { defer fake.getStackTemplateMutex.RUnlock() fake.getUnmanagedNodeGroupSummariesMutex.RLock() defer fake.getUnmanagedNodeGroupSummariesMutex.RUnlock() - fake.hasClusterStackMutex.RLock() - defer fake.hasClusterStackMutex.RUnlock() fake.hasClusterStackUsingCachedListMutex.RLock() defer fake.hasClusterStackUsingCachedListMutex.RUnlock() fake.listClusterStackNamesMutex.RLock() diff --git a/pkg/cfn/manager/interface.go b/pkg/cfn/manager/interface.go index 4bdf4b9c17..ed6485f0e8 100644 --- a/pkg/cfn/manager/interface.go +++ b/pkg/cfn/manager/interface.go @@ -39,7 +39,7 @@ type StackManager interface { DeleteStackBySpec(s *Stack) (*Stack, error) DeleteStackBySpecSync(s *Stack, errs chan error) error DescribeStacks() ([]*Stack, error) - HasClusterStack() (bool, error) + GetClusterStackIfExists() (*Stack, error) HasClusterStackUsingCachedList(clusterStackNames []string) (bool, error) DescribeStackEvents(i *Stack) ([]*cloudformation.StackEvent, error) LookupCloudTrailEvents(i *Stack) ([]*cloudtrail.Event, error) diff --git a/pkg/eks/eks.go b/pkg/eks/eks.go index 80af3471c3..14a5d0abd7 100644 --- a/pkg/eks/eks.go +++ b/pkg/eks/eks.go @@ -81,7 +81,7 @@ func (c *ClusterProvider) RefreshClusterStatus(spec *api.ClusterConfig) error { // SupportsManagedNodes reports whether an existing cluster supports Managed Nodes // The minimum required control plane version and platform version are 1.14 and eks.3 respectively func (c *ClusterProvider) SupportsManagedNodes(clusterConfig *api.ClusterConfig) (bool, error) { - if err := c.maybeRefreshClusterStatus(clusterConfig); err != nil { + if err := c.RefreshClusterStatusIfStale(clusterConfig); err != nil { return false, err } @@ -126,7 +126,7 @@ func ClusterSupportsManagedNodes(cluster *awseks.Cluster) (bool, error) { // SupportsFargate reports whether an existing cluster supports Fargate. func (c *ClusterProvider) SupportsFargate(clusterConfig *api.ClusterConfig) (bool, error) { - if err := c.maybeRefreshClusterStatus(clusterConfig); err != nil { + if err := c.RefreshClusterStatusIfStale(clusterConfig); err != nil { return false, err } return ClusterSupportsFargate(c.Status.ClusterInfo.Cluster) @@ -179,7 +179,8 @@ func PlatformVersion(platformVersion string) (int, error) { return version, nil } -func (c *ClusterProvider) maybeRefreshClusterStatus(spec *api.ClusterConfig) error { +// RefreshClusterStatusIfStale refreshes the cluster status if enough time has passed since the last refresh +func (c *ClusterProvider) RefreshClusterStatusIfStale(spec *api.ClusterConfig) error { if c.clusterInfoNeedsUpdate() { return c.RefreshClusterStatus(spec) } @@ -188,7 +189,7 @@ func (c *ClusterProvider) maybeRefreshClusterStatus(spec *api.ClusterConfig) err // CanDelete return true when a cluster can be deleted, otherwise it returns false along with an error explaining the reason func (c *ClusterProvider) CanDelete(spec *api.ClusterConfig) (bool, error) { - err := c.maybeRefreshClusterStatus(spec) + err := c.RefreshClusterStatusIfStale(spec) if err != nil { if awsError, ok := errors.Unwrap(errors.Unwrap(err)).(awserr.Error); ok && awsError.Code() == awseks.ErrCodeResourceNotFoundException { @@ -202,7 +203,7 @@ func (c *ClusterProvider) CanDelete(spec *api.ClusterConfig) (bool, error) { // CanOperate returns true when a cluster can be operated, otherwise it returns false along with an error explaining the reason func (c *ClusterProvider) CanOperate(spec *api.ClusterConfig) (bool, error) { - err := c.maybeRefreshClusterStatus(spec) + err := c.RefreshClusterStatusIfStale(spec) if err != nil { return false, errors.Wrapf(err, "unable to fetch cluster status to determine operability") } @@ -217,7 +218,7 @@ func (c *ClusterProvider) CanOperate(spec *api.ClusterConfig) (bool, error) { // CanUpdate return true when a cluster or add-ons can be updated, otherwise it returns false along with an error explaining the reason func (c *ClusterProvider) CanUpdate(spec *api.ClusterConfig) (bool, error) { - err := c.maybeRefreshClusterStatus(spec) + err := c.RefreshClusterStatusIfStale(spec) if err != nil { return false, errors.Wrapf(err, "fetching cluster status to determine update status") } From 79d2df722c5f8218329f8c3e0bec4b7ab8d8b494 Mon Sep 17 00:00:00 2001 From: Jake Klein Date: Mon, 1 Nov 2021 14:46:16 +0000 Subject: [PATCH 041/124] clarify up-to-date nodegroup message (#4393) --- pkg/eks/nodegroup_service.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkg/eks/nodegroup_service.go b/pkg/eks/nodegroup_service.go index 239037b658..ad73d84447 100644 --- a/pkg/eks/nodegroup_service.go +++ b/pkg/eks/nodegroup_service.go @@ -269,7 +269,7 @@ func (m *NodeGroupService) ValidateExistingNodeGroupsForCompatibility(cfg *api.C numIncompatibleNodeGroups := len(incompatibleNodeGroups) if numIncompatibleNodeGroups == 0 { - logger.Info("all nodegroups have up-to-date configuration") + logger.Info("all nodegroups have up-to-date cloudformation templates") return nil } From ec969f2d27ba37e1ea33bef00875e8b84b83ea5b Mon Sep 17 00:00:00 2001 From: Jake Klein Date: Mon, 1 Nov 2021 17:13:53 +0000 Subject: [PATCH 042/124] make 1.21 default (#4394) --- pkg/apis/eksctl.io/v1alpha5/assets/schema.json | 6 +++--- pkg/apis/eksctl.io/v1alpha5/types.go | 2 +- pkg/ctl/cmdutils/filter/nodegroup_filter_test.go | 2 +- userdocs/src/introduction.md | 2 +- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/pkg/apis/eksctl.io/v1alpha5/assets/schema.json b/pkg/apis/eksctl.io/v1alpha5/assets/schema.json index e878111454..708830b0cb 100755 --- a/pkg/apis/eksctl.io/v1alpha5/assets/schema.json +++ b/pkg/apis/eksctl.io/v1alpha5/assets/schema.json @@ -481,9 +481,9 @@ }, "version": { "type": "string", - "description": "Valid variants are: `\"1.17\"`, `\"1.18\"`, `\"1.19\"`, `\"1.20\"` (default), `\"1.21\"`.", - "x-intellij-html-description": "Valid variants are: "1.17", "1.18", "1.19", "1.20" (default), "1.21".", - "default": "1.20", + "description": "Valid variants are: `\"1.17\"`, `\"1.18\"`, `\"1.19\"`, `\"1.20\"`, `\"1.21\"` (default).", + "x-intellij-html-description": "Valid variants are: "1.17", "1.18", "1.19", "1.20", "1.21" (default).", + "default": "1.21", "enum": [ "1.17", "1.18", diff --git a/pkg/apis/eksctl.io/v1alpha5/types.go b/pkg/apis/eksctl.io/v1alpha5/types.go index 1a9c225499..a393d21c44 100644 --- a/pkg/apis/eksctl.io/v1alpha5/types.go +++ b/pkg/apis/eksctl.io/v1alpha5/types.go @@ -43,7 +43,7 @@ const ( Version1_21 = "1.21" // DefaultVersion (default) - DefaultVersion = Version1_20 + DefaultVersion = Version1_21 LatestVersion = Version1_21 ) diff --git a/pkg/ctl/cmdutils/filter/nodegroup_filter_test.go b/pkg/ctl/cmdutils/filter/nodegroup_filter_test.go index c56469fb08..aa3608c352 100644 --- a/pkg/ctl/cmdutils/filter/nodegroup_filter_test.go +++ b/pkg/ctl/cmdutils/filter/nodegroup_filter_test.go @@ -339,7 +339,7 @@ const expected = ` "metadata": { "name": "test-3x3-ngs", "region": "eu-central-1", - "version": "1.20" + "version": "1.21" }, "iam": { "withOIDC": false diff --git a/userdocs/src/introduction.md b/userdocs/src/introduction.md index bcbffb674e..f26e71f80f 100644 --- a/userdocs/src/introduction.md +++ b/userdocs/src/introduction.md @@ -23,7 +23,7 @@ eksctl create cluster --name=cluster-1 --nodes=4 ``` -EKS supports versions `1.16`, `1.17`, `1.18`, `1.19`, `1.20` (default) and `1.21`. +EKS supports versions `1.16`, `1.17`, `1.18`, `1.19`, `1.20` and `1.21` (default). With `eksctl` you can deploy any of the supported versions by passing `--version`. ``` From cdd8d1bb2de4afc6d1979952a4dc9732c0884d3c Mon Sep 17 00:00:00 2001 From: cpu1 Date: Mon, 1 Nov 2021 17:13:32 +0530 Subject: [PATCH 043/124] Add support for Windows Server 20H2 --- integration/tests/windows/windows_test.go | 6 +++++ pkg/ami/auto_resolver.go | 3 +++ pkg/ami/ssm_resolver.go | 12 +++++++++ pkg/ami/ssm_resolver_test.go | 27 +++++++++++++++++++ .../eksctl.io/v1alpha5/gpu_validation_test.go | 5 ++++ pkg/apis/eksctl.io/v1alpha5/types.go | 2 ++ pkg/apis/eksctl.io/v1alpha5/validation.go | 3 ++- .../eksctl.io/v1alpha5/validation_test.go | 2 +- 8 files changed, 58 insertions(+), 2 deletions(-) diff --git a/integration/tests/windows/windows_test.go b/integration/tests/windows/windows_test.go index 67b08e1994..dbb5c7cbe0 100644 --- a/integration/tests/windows/windows_test.go +++ b/integration/tests/windows/windows_test.go @@ -52,6 +52,12 @@ var _ = Describe("(Integration) [Windows Nodegroups]", func() { AMIFamily: api.NodeImageFamilyWindowsServer2019FullContainer, }, }, + { + NodeGroupBase: &api.NodeGroupBase{ + Name: "windows", + AMIFamily: api.NodeImageFamilyWindowsServer20H2CoreContainer, + }, + }, } clusterConfig.ManagedNodeGroups = []*api.ManagedNodeGroup{ { diff --git a/pkg/ami/auto_resolver.go b/pkg/ami/auto_resolver.go index 8b3a362bc9..f0f0c398f1 100644 --- a/pkg/ami/auto_resolver.go +++ b/pkg/ami/auto_resolver.go @@ -41,6 +41,9 @@ func MakeImageSearchPatterns(version string) map[string]map[int]string { api.NodeImageFamilyWindowsServer2004CoreContainer: { ImageClassGeneral: fmt.Sprintf("Windows_Server-2004-English-Core-EKS_Optimized-%v-*", version), }, + api.NodeImageFamilyWindowsServer20H2CoreContainer: { + ImageClassGeneral: fmt.Sprintf("Windows_Server-20H2-English-Core-EKS_Optimized-%v-*", version), + }, } } diff --git a/pkg/ami/ssm_resolver.go b/pkg/ami/ssm_resolver.go index 9b63352bff..4cec1ada8e 100644 --- a/pkg/ami/ssm_resolver.go +++ b/pkg/ami/ssm_resolver.go @@ -3,6 +3,8 @@ package ami import ( "fmt" + "github.com/pkg/errors" + "github.com/aws/aws-sdk-go/aws" "github.com/aws/aws-sdk-go/service/eks" "github.com/aws/aws-sdk-go/service/ssm" @@ -65,6 +67,16 @@ func MakeSSMParameterName(version, instanceType, imageFamily string) (string, er return fmt.Sprintf("/aws/service/ami-windows-latest/Windows_Server-2019-English-Full-EKS_Optimized-%s/%s", version, fieldName), nil case api.NodeImageFamilyWindowsServer2004CoreContainer: return fmt.Sprintf("/aws/service/ami-windows-latest/Windows_Server-2004-English-Core-EKS_Optimized-%s/%s", version, fieldName), nil + case api.NodeImageFamilyWindowsServer20H2CoreContainer: + const minVersion = api.Version1_21 + supportsWindows20H2, err := utils.IsMinVersion(minVersion, version) + if err != nil { + return "", err + } + if !supportsWindows20H2 { + return "", errors.Errorf("Windows Server 20H2 Core requires EKS version %s and above", minVersion) + } + return fmt.Sprintf("/aws/service/ami-windows-latest/Windows_Server-20H2-English-Core-EKS_Optimized-%s/%s", version, fieldName), nil case api.NodeImageFamilyBottlerocket: return fmt.Sprintf("/aws/service/bottlerocket/aws-k8s-%s/%s/latest/%s", version, instanceEC2ArchName(instanceType), fieldName), nil case api.NodeImageFamilyUbuntu2004, api.NodeImageFamilyUbuntu1804: diff --git a/pkg/ami/ssm_resolver_test.go b/pkg/ami/ssm_resolver_test.go index 6bba8b8895..dbf332b89e 100644 --- a/pkg/ami/ssm_resolver_test.go +++ b/pkg/ami/ssm_resolver_test.go @@ -156,6 +156,33 @@ var _ = Describe("AMI Auto Resolution", func() { Expect(err).To(HaveOccurred()) }) }) + + Context("Windows Server 20H2 Core", func() { + var p *mockprovider.MockProvider + + BeforeEach(func() { + p = mockprovider.NewMockProvider() + }) + + It("should return a valid AMI", func() { + addMockGetParameter(p, "/aws/service/ami-windows-latest/Windows_Server-20H2-English-Core-EKS_Optimized-1.21/image_id", expectedAmi) + + resolver := NewSSMResolver(p.MockSSM()) + resolvedAmi, err = resolver.Resolve(region, "1.21", instanceType, "WindowsServer20H2CoreContainer") + + Expect(err).NotTo(HaveOccurred()) + Expect(resolvedAmi).To(BeEquivalentTo(expectedAmi)) + Expect(p.MockSSM().AssertNumberOfCalls(GinkgoT(), "GetParameter", 1)).To(BeTrue()) + }) + + It("should return an error for EKS versions below 1.21", func() { + resolver := NewSSMResolver(p.MockSSM()) + _, err := resolver.Resolve(region, "1.20", instanceType, "WindowsServer20H2CoreContainer") + Expect(err).To(HaveOccurred()) + Expect(err).To(MatchError(ContainSubstring("Windows Server 20H2 Core requires EKS version 1.21 and above"))) + }) + }) + }) Context("and Ubuntu family", func() { diff --git a/pkg/apis/eksctl.io/v1alpha5/gpu_validation_test.go b/pkg/apis/eksctl.io/v1alpha5/gpu_validation_test.go index 984023d3a9..b3eb5797d6 100644 --- a/pkg/apis/eksctl.io/v1alpha5/gpu_validation_test.go +++ b/pkg/apis/eksctl.io/v1alpha5/gpu_validation_test.go @@ -87,5 +87,10 @@ var _ = Describe("GPU instance support", func() { gpuInstanceType: "p3.2xlarge", expectUnsupportedErr: true, }), + Entry("Windows20H2Core", gpuInstanceEntry{ + amiFamily: api.NodeImageFamilyWindowsServer20H2CoreContainer, + gpuInstanceType: "g4dn.xlarge", + expectUnsupportedErr: true, + }), ) }) diff --git a/pkg/apis/eksctl.io/v1alpha5/types.go b/pkg/apis/eksctl.io/v1alpha5/types.go index a393d21c44..602c676716 100644 --- a/pkg/apis/eksctl.io/v1alpha5/types.go +++ b/pkg/apis/eksctl.io/v1alpha5/types.go @@ -183,6 +183,7 @@ const ( NodeImageFamilyWindowsServer2019CoreContainer = "WindowsServer2019CoreContainer" NodeImageFamilyWindowsServer2019FullContainer = "WindowsServer2019FullContainer" NodeImageFamilyWindowsServer2004CoreContainer = "WindowsServer2004CoreContainer" + NodeImageFamilyWindowsServer20H2CoreContainer = "WindowsServer20H2CoreContainer" ) // Container runtime values. @@ -467,6 +468,7 @@ func supportedAMIFamilies() []string { NodeImageFamilyWindowsServer2019CoreContainer, NodeImageFamilyWindowsServer2019FullContainer, NodeImageFamilyWindowsServer2004CoreContainer, + NodeImageFamilyWindowsServer20H2CoreContainer, } } diff --git a/pkg/apis/eksctl.io/v1alpha5/validation.go b/pkg/apis/eksctl.io/v1alpha5/validation.go index 5d2bd40cdb..30b2f61775 100644 --- a/pkg/apis/eksctl.io/v1alpha5/validation.go +++ b/pkg/apis/eksctl.io/v1alpha5/validation.go @@ -927,7 +927,8 @@ func IsWindowsImage(imageFamily string) bool { switch imageFamily { case NodeImageFamilyWindowsServer2019CoreContainer, NodeImageFamilyWindowsServer2019FullContainer, - NodeImageFamilyWindowsServer2004CoreContainer: + NodeImageFamilyWindowsServer2004CoreContainer, + NodeImageFamilyWindowsServer20H2CoreContainer: return true default: diff --git a/pkg/apis/eksctl.io/v1alpha5/validation_test.go b/pkg/apis/eksctl.io/v1alpha5/validation_test.go index 5c973267f5..2aa763a055 100644 --- a/pkg/apis/eksctl.io/v1alpha5/validation_test.go +++ b/pkg/apis/eksctl.io/v1alpha5/validation_test.go @@ -993,7 +993,7 @@ var _ = Describe("ClusterConfig validation", func() { It("fails when the AMIFamily is not supported", func() { ng.AMIFamily = "SomeTrash" err := api.ValidateNodeGroup(0, ng) - Expect(err).To(MatchError("AMI Family SomeTrash is not supported - use one of: AmazonLinux2, Ubuntu2004, Ubuntu1804, Bottlerocket, WindowsServer2019CoreContainer, WindowsServer2019FullContainer, WindowsServer2004CoreContainer")) + Expect(err).To(MatchError("AMI Family SomeTrash is not supported - use one of: AmazonLinux2, Ubuntu2004, Ubuntu1804, Bottlerocket, WindowsServer2019CoreContainer, WindowsServer2019FullContainer, WindowsServer2004CoreContainer, WindowsServer20H2CoreContainer")) }) }) From d2f4ced765434f84e894e8003bca3ed22356fb33 Mon Sep 17 00:00:00 2001 From: cpu1 Date: Mon, 1 Nov 2021 17:31:03 +0530 Subject: [PATCH 044/124] Update schema --- pkg/apis/eksctl.io/v1alpha5/assets/schema.json | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/pkg/apis/eksctl.io/v1alpha5/assets/schema.json b/pkg/apis/eksctl.io/v1alpha5/assets/schema.json index 708830b0cb..059627be07 100755 --- a/pkg/apis/eksctl.io/v1alpha5/assets/schema.json +++ b/pkg/apis/eksctl.io/v1alpha5/assets/schema.json @@ -895,8 +895,8 @@ }, "amiFamily": { "type": "string", - "description": "Valid variants are: `\"AmazonLinux2\"` (default), `\"Ubuntu2004\"`, `\"Ubuntu1804\"`, `\"Bottlerocket\"`, `\"WindowsServer2019CoreContainer\"`, `\"WindowsServer2019FullContainer\"`, `\"WindowsServer2004CoreContainer\"`.", - "x-intellij-html-description": "Valid variants are: "AmazonLinux2" (default), "Ubuntu2004", "Ubuntu1804", "Bottlerocket", "WindowsServer2019CoreContainer", "WindowsServer2019FullContainer", "WindowsServer2004CoreContainer".", + "description": "Valid variants are: `\"AmazonLinux2\"` (default), `\"Ubuntu2004\"`, `\"Ubuntu1804\"`, `\"Bottlerocket\"`, `\"WindowsServer2019CoreContainer\"`, `\"WindowsServer2019FullContainer\"`, `\"WindowsServer2004CoreContainer\"`, `\"WindowsServer20H2CoreContainer\"`.", + "x-intellij-html-description": "Valid variants are: "AmazonLinux2" (default), "Ubuntu2004", "Ubuntu1804", "Bottlerocket", "WindowsServer2019CoreContainer", "WindowsServer2019FullContainer", "WindowsServer2004CoreContainer", "WindowsServer20H2CoreContainer".", "default": "AmazonLinux2", "enum": [ "AmazonLinux2", @@ -905,7 +905,8 @@ "Bottlerocket", "WindowsServer2019CoreContainer", "WindowsServer2019FullContainer", - "WindowsServer2004CoreContainer" + "WindowsServer2004CoreContainer", + "WindowsServer20H2CoreContainer" ] }, "asgSuspendProcesses": { @@ -1199,8 +1200,8 @@ }, "amiFamily": { "type": "string", - "description": "Valid variants are: `\"AmazonLinux2\"` (default), `\"Ubuntu2004\"`, `\"Ubuntu1804\"`, `\"Bottlerocket\"`, `\"WindowsServer2019CoreContainer\"`, `\"WindowsServer2019FullContainer\"`, `\"WindowsServer2004CoreContainer\"`.", - "x-intellij-html-description": "Valid variants are: "AmazonLinux2" (default), "Ubuntu2004", "Ubuntu1804", "Bottlerocket", "WindowsServer2019CoreContainer", "WindowsServer2019FullContainer", "WindowsServer2004CoreContainer".", + "description": "Valid variants are: `\"AmazonLinux2\"` (default), `\"Ubuntu2004\"`, `\"Ubuntu1804\"`, `\"Bottlerocket\"`, `\"WindowsServer2019CoreContainer\"`, `\"WindowsServer2019FullContainer\"`, `\"WindowsServer2004CoreContainer\"`, `\"WindowsServer20H2CoreContainer\"`.", + "x-intellij-html-description": "Valid variants are: "AmazonLinux2" (default), "Ubuntu2004", "Ubuntu1804", "Bottlerocket", "WindowsServer2019CoreContainer", "WindowsServer2019FullContainer", "WindowsServer2004CoreContainer", "WindowsServer20H2CoreContainer".", "default": "AmazonLinux2", "enum": [ "AmazonLinux2", @@ -1209,7 +1210,8 @@ "Bottlerocket", "WindowsServer2019CoreContainer", "WindowsServer2019FullContainer", - "WindowsServer2004CoreContainer" + "WindowsServer2004CoreContainer", + "WindowsServer20H2CoreContainer" ] }, "asgMetricsCollection": { From 41121de0d92ebab86c9002303f71de5f2e31fcc1 Mon Sep 17 00:00:00 2001 From: cpu1 Date: Mon, 1 Nov 2021 17:42:44 +0530 Subject: [PATCH 045/124] Update doc --- userdocs/src/usage/custom-ami-support.md | 1 + userdocs/src/usage/windows-worker-nodes.md | 2 ++ 2 files changed, 3 insertions(+) diff --git a/userdocs/src/usage/custom-ami-support.md b/userdocs/src/usage/custom-ami-support.md index 6a47b27ffa..da5b3f449c 100644 --- a/userdocs/src/usage/custom-ami-support.md +++ b/userdocs/src/usage/custom-ami-support.md @@ -68,6 +68,7 @@ The `--node-ami-family` can take following keywords: | WindowsServer2019FullContainer | Indicates that the EKS AMI image based on Windows Server 2019 Full Container should be used. | | WindowsServer2019CoreContainer | Indicates that the EKS AMI image based on Windows Server 2019 Core Container should be used. | | WindowsServer2004CoreContainer | Indicates that the EKS AMI image based on Windows Server 2004 Core Container should be used. | +| WindowsServer20H2CoreContainer | Indicates that the EKS AMI image based on Windows Server 20H2 Core Container should be used. | CLI flag example: ```sh diff --git a/userdocs/src/usage/windows-worker-nodes.md b/userdocs/src/usage/windows-worker-nodes.md index 96bd63ba20..e9c28aeee0 100644 --- a/userdocs/src/usage/windows-worker-nodes.md +++ b/userdocs/src/usage/windows-worker-nodes.md @@ -64,7 +64,9 @@ To ensure workloads are scheduled on the right OS, they must have a `nodeSelecto nodeSelector: kubernetes.io/os: windows kubernetes.io/arch: amd64 +``` +```yaml # Targeting Linux nodeSelector: kubernetes.io/os: linux From 013cd78088c82b3ecb27320320c4f384b423266f Mon Sep 17 00:00:00 2001 From: Abhinav Pathak <31713659+abhipth@users.noreply.github.com> Date: Tue, 2 Nov 2021 02:18:43 -0700 Subject: [PATCH 046/124] Bump vpc-resource-controller/webhook dep to v0.2.7 (#4335) Co-authored-by: Chetan Patwal --- pkg/addons/assets/vpc-admission-webhook-dep.yaml | 2 +- pkg/addons/assets/vpc-resource-controller-dep.yaml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/pkg/addons/assets/vpc-admission-webhook-dep.yaml b/pkg/addons/assets/vpc-admission-webhook-dep.yaml index 2c08acab80..87fdadbc71 100644 --- a/pkg/addons/assets/vpc-admission-webhook-dep.yaml +++ b/pkg/addons/assets/vpc-admission-webhook-dep.yaml @@ -26,7 +26,7 @@ spec: - -alsologtostderr - -v=4 - 2>&1 - image: '%s.dkr.ecr.%s.%s/eks/vpc-admission-webhook:v0.2.6' + image: '%s.dkr.ecr.%s.%s/eks/vpc-admission-webhook:v0.2.7' imagePullPolicy: Always volumeMounts: - name: webhook-certs diff --git a/pkg/addons/assets/vpc-resource-controller-dep.yaml b/pkg/addons/assets/vpc-resource-controller-dep.yaml index 3966657e1b..2f45bea66d 100644 --- a/pkg/addons/assets/vpc-resource-controller-dep.yaml +++ b/pkg/addons/assets/vpc-resource-controller-dep.yaml @@ -24,7 +24,7 @@ spec: - /vpc-resource-controller args: - -stderrthreshold=info - image: '%s.dkr.ecr.%s.%s/eks/windows-vpc-resource-controller:v0.2.6' + image: '%s.dkr.ecr.%s.%s/eks/windows-vpc-resource-controller:v0.2.7' imagePullPolicy: Always livenessProbe: failureThreshold: 5 From 6659f2b6e98ea018281a06dc9f09d9a0c46833e9 Mon Sep 17 00:00:00 2001 From: nikimanoledaki <18622989+nikimanoledaki@users.noreply.github.com> Date: Mon, 25 Oct 2021 16:38:21 +0200 Subject: [PATCH 047/124] Scale managed ng with --name flag --- pkg/actions/nodegroup/scale.go | 6 ++-- pkg/actions/nodegroup/scale_test.go | 14 ++++---- pkg/apis/eksctl.io/v1alpha5/nodegroups.go | 24 ++++++++++--- pkg/ctl/cmdutils/scale.go | 14 ++++---- pkg/ctl/cmdutils/scale_test.go | 41 +++++++++++++++++++++-- pkg/ctl/scale/nodegroup.go | 8 ++--- pkg/ctl/scale/nodegroup_test.go | 4 +-- 7 files changed, 80 insertions(+), 31 deletions(-) diff --git a/pkg/actions/nodegroup/scale.go b/pkg/actions/nodegroup/scale.go index 5d8d405b03..31c61d4e9f 100644 --- a/pkg/actions/nodegroup/scale.go +++ b/pkg/actions/nodegroup/scale.go @@ -16,7 +16,7 @@ import ( api "github.com/weaveworks/eksctl/pkg/apis/eksctl.io/v1alpha5" ) -func (m *Manager) Scale(ng *api.NodeGroup) error { +func (m *Manager) Scale(ng *api.NodeGroupBase) error { logger.Info("scaling nodegroup %q in cluster %s", ng.Name, m.cfg.Metadata.Name) nodegroupStackInfos, err := m.stackManager.DescribeNodeGroupStacksAndResources() @@ -48,7 +48,7 @@ func (m *Manager) Scale(ng *api.NodeGroup) error { return nil } -func (m *Manager) scaleUnmanagedNodeGroup(ng *api.NodeGroup, stackInfo manager.StackInfo) error { +func (m *Manager) scaleUnmanagedNodeGroup(ng *api.NodeGroupBase, stackInfo manager.StackInfo) error { asgName := "" for _, resource := range stackInfo.Resources { if *resource.LogicalResourceId == "NodeGroup" { @@ -86,7 +86,7 @@ func (m *Manager) scaleUnmanagedNodeGroup(ng *api.NodeGroup, stackInfo manager.S return nil } -func (m *Manager) scaleManagedNodeGroup(ng *api.NodeGroup) error { +func (m *Manager) scaleManagedNodeGroup(ng *api.NodeGroupBase) error { scalingConfig := &eks.NodegroupScalingConfig{} if ng.MaxSize != nil { diff --git a/pkg/actions/nodegroup/scale_test.go b/pkg/actions/nodegroup/scale_test.go index 03f2f1db82..1150f5d5ca 100644 --- a/pkg/actions/nodegroup/scale_test.go +++ b/pkg/actions/nodegroup/scale_test.go @@ -26,7 +26,7 @@ var _ = Describe("Scale", func() { clusterName, ngName string p *mockprovider.MockProvider cfg *api.ClusterConfig - ng *api.NodeGroup + ng *api.NodeGroupBase m *nodegroup.Manager fakeStackManager *fakes.FakeStackManager ) @@ -37,13 +37,11 @@ var _ = Describe("Scale", func() { cfg = api.NewClusterConfig() cfg.Metadata.Name = clusterName - ng = &api.NodeGroup{ - NodeGroupBase: &api.NodeGroupBase{ - Name: ngName, - ScalingConfig: &api.ScalingConfig{ - MinSize: aws.Int(1), - DesiredCapacity: aws.Int(3), - }, + ng = &api.NodeGroupBase{ + Name: ngName, + ScalingConfig: &api.ScalingConfig{ + MinSize: aws.Int(1), + DesiredCapacity: aws.Int(3), }, } m = nodegroup.New(cfg, &eks.ClusterProvider{Provider: p}, nil) diff --git a/pkg/apis/eksctl.io/v1alpha5/nodegroups.go b/pkg/apis/eksctl.io/v1alpha5/nodegroups.go index 00382c7ca2..51de68cebb 100644 --- a/pkg/apis/eksctl.io/v1alpha5/nodegroups.go +++ b/pkg/apis/eksctl.io/v1alpha5/nodegroups.go @@ -1,5 +1,7 @@ package v1alpha5 +import "fmt" + // HasInstanceType returns whether some node in the group fulfils the type check func HasInstanceType(nodeGroup *NodeGroup, hasType func(string) bool) bool { if hasType(nodeGroup.InstanceType) { @@ -44,14 +46,28 @@ func ClusterHasInstanceType(cfg *ClusterConfig, hasType func(string) bool) bool return false } -// HasNodegroup returns true if this clusterConfig contains a managed or un-managed nodegroup with the given name -func (c *ClusterConfig) FindNodegroup(name string) *NodeGroup { +// FindNodegroup checks if the clusterConfig contains a nodegroup with the given name +func (c *ClusterConfig) FindNodegroup(name string) (*NodeGroupBase, error) { + var foundNg []*NodeGroupBase for _, ng := range c.NodeGroups { if name == ng.NameString() { - return ng + foundNg = append(foundNg, ng.NodeGroupBase) } } - return nil + + for _, ng := range c.ManagedNodeGroups { + if name == ng.NameString() { + foundNg = append(foundNg, ng.NodeGroupBase) + } + } + + if len(foundNg) == 0 { + return nil, fmt.Errorf("nodegroup %s not found in config file", name) + } else if len(foundNg) > 1 { + return nil, fmt.Errorf("found more than 1 nodegroup with name %s", name) + } + + return foundNg[0], nil } // GetAllNodeGroupNames collects and returns names for both managed and unmanaged nodegroups diff --git a/pkg/ctl/cmdutils/scale.go b/pkg/ctl/cmdutils/scale.go index 2cf6a38e82..cf84068825 100644 --- a/pkg/ctl/cmdutils/scale.go +++ b/pkg/ctl/cmdutils/scale.go @@ -7,7 +7,7 @@ import ( ) // NewScaleNodeGroupLoader will load config or use flags for 'eksctl scale nodegroup' -func NewScaleNodeGroupLoader(cmd *Cmd, ng *api.NodeGroup) ClusterConfigLoader { +func NewScaleNodeGroupLoader(cmd *Cmd, ng *api.NodeGroupBase) ClusterConfigLoader { l := newCommonClusterConfigLoader(cmd) l.flagsIncompatibleWithConfigFile.Insert( @@ -22,9 +22,9 @@ func NewScaleNodeGroupLoader(cmd *Cmd, ng *api.NodeGroup) ClusterConfigLoader { return err } - loadedNG := l.ClusterConfig.FindNodegroup(ng.Name) - if loadedNG == nil { - return fmt.Errorf("node group %s not found", ng.Name) + loadedNG, err := l.ClusterConfig.FindNodegroup(ng.Name) + if err != nil { + return err } if err := validateNumberOfNodes(loadedNG); err != nil { @@ -54,7 +54,7 @@ func NewScaleNodeGroupLoader(cmd *Cmd, ng *api.NodeGroup) ClusterConfigLoader { return l } -func validateNameArgument(cmd *Cmd, ng *api.NodeGroup) error { +func validateNameArgument(cmd *Cmd, ng *api.NodeGroupBase) error { if ng.Name != "" && cmd.NameArg != "" { return ErrFlagAndArg("--name", ng.Name, cmd.NameArg) } @@ -70,7 +70,7 @@ func validateNameArgument(cmd *Cmd, ng *api.NodeGroup) error { return nil } -func validateNumberOfNodes(ng *api.NodeGroup) error { +func validateNumberOfNodes(ng *api.NodeGroupBase) error { if ng.ScalingConfig == nil { ng.ScalingConfig = &api.ScalingConfig{} } @@ -103,7 +103,7 @@ func validateNumberOfNodes(ng *api.NodeGroup) error { } //only 1 of desired/min/max has to be set on the cli -func validateNumberOfNodesCLI(ng *api.NodeGroup) error { +func validateNumberOfNodesCLI(ng *api.NodeGroupBase) error { if ng.ScalingConfig == nil { ng.ScalingConfig = &api.ScalingConfig{} } diff --git a/pkg/ctl/cmdutils/scale_test.go b/pkg/ctl/cmdutils/scale_test.go index 185a547674..ae4602c636 100644 --- a/pkg/ctl/cmdutils/scale_test.go +++ b/pkg/ctl/cmdutils/scale_test.go @@ -43,7 +43,7 @@ var _ = Describe("scale node group config file loader", func() { NameArg: params.name, } - ng := api.NewNodeGroup() + ng := api.NewNodeGroup().BaseNodeGroup() err := NewScaleNodeGroupLoader(cmd, ng).Load() if params.err != nil { Expect(err).To(HaveOccurred()) @@ -60,7 +60,7 @@ var _ = Describe("scale node group config file loader", func() { }), Entry("no node group matched", scaleNodeGroupCase{ name: "123123", - err: fmt.Errorf("node group 123123 not found"), + err: fmt.Errorf("nodegroup 123123 not found in config file"), }), Entry("with no desired capacity", scaleNodeGroupCase{ name: "ng-no-desired-capacity", @@ -101,7 +101,7 @@ var _ = Describe("scale node group config file loader", func() { NameArg: params.name, } - ng := api.NewNodeGroup() + ng := api.NewNodeGroup().BaseNodeGroup() ng.MinSize = params.minSize ng.MaxSize = params.maxSize ng.DesiredCapacity = params.desiredSize @@ -166,4 +166,39 @@ var _ = Describe("scale node group config file loader", func() { err: fmt.Errorf("at least one of minimum, maximum and desired nodes must be set"), }), ) + + Describe("for managed nodegroups", func() { + Context("when using a config file", func() { + It("setting --name finds that individual nodegroup", func() { + ngName := "mng-ng" + ng := &api.NodeGroupBase{ + Name: ngName, + ScalingConfig: &api.ScalingConfig{ + DesiredCapacity: aws.Int(2), + }, + } + + config := api.NewClusterConfig() + config.Metadata.Name = "test-cluster" + config.ManagedNodeGroups = []*api.ManagedNodeGroup{ + { + NodeGroupBase: &api.NodeGroupBase{ + Name: ngName, + ScalingConfig: &api.ScalingConfig{ + DesiredCapacity: aws.Int(2), + }, + }, + }, + } + cmd := &Cmd{ + CobraCommand: newCmd(), + ClusterConfig: config, + ProviderConfig: api.ProviderConfig{}, + } + + err := NewScaleNodeGroupLoader(cmd, ng).Load() + Expect(err).NotTo(HaveOccurred()) + }) + }) + }) }) diff --git a/pkg/ctl/scale/nodegroup.go b/pkg/ctl/scale/nodegroup.go index 9720798388..de5cba9ff4 100644 --- a/pkg/ctl/scale/nodegroup.go +++ b/pkg/ctl/scale/nodegroup.go @@ -11,14 +11,14 @@ import ( ) func scaleNodeGroupCmd(cmd *cmdutils.Cmd) { - scaleNodeGroupWithRunFunc(cmd, func(cmd *cmdutils.Cmd, ng *api.NodeGroup) error { + scaleNodeGroupWithRunFunc(cmd, func(cmd *cmdutils.Cmd, ng *api.NodeGroupBase) error { return doScaleNodeGroup(cmd, ng) }) } -func scaleNodeGroupWithRunFunc(cmd *cmdutils.Cmd, runFunc func(cmd *cmdutils.Cmd, ng *api.NodeGroup) error) { +func scaleNodeGroupWithRunFunc(cmd *cmdutils.Cmd, runFunc func(cmd *cmdutils.Cmd, ng *api.NodeGroupBase) error) { cfg := api.NewClusterConfig() - ng := cfg.NewNodeGroup() + ng := cfg.NewNodeGroup().BaseNodeGroup() cmd.ClusterConfig = cfg cmd.SetDescription("nodegroup", "Scale a nodegroup", "", "ng") @@ -56,7 +56,7 @@ func scaleNodeGroupWithRunFunc(cmd *cmdutils.Cmd, runFunc func(cmd *cmdutils.Cmd cmdutils.AddCommonFlagsForAWS(cmd.FlagSetGroup, &cmd.ProviderConfig, true) } -func doScaleNodeGroup(cmd *cmdutils.Cmd, ng *api.NodeGroup) error { +func doScaleNodeGroup(cmd *cmdutils.Cmd, ng *api.NodeGroupBase) error { if err := cmdutils.NewScaleNodeGroupLoader(cmd, ng).Load(); err != nil { return err } diff --git a/pkg/ctl/scale/nodegroup_test.go b/pkg/ctl/scale/nodegroup_test.go index 38e4ef0b07..a6a9f359f2 100644 --- a/pkg/ctl/scale/nodegroup_test.go +++ b/pkg/ctl/scale/nodegroup_test.go @@ -13,12 +13,12 @@ import ( var _ = Describe("scale", func() { Describe("nodegroup", func() { - DescribeTable("create cluster successfully", + DescribeTable("scales a nodegroup successfully", func(args ...string) { cmd := newMockEmptyCmd(args...) count := 0 cmdutils.AddResourceCmd(cmdutils.NewGrouping(), cmd.parentCmd, func(cmd *cmdutils.Cmd) { - scaleNodeGroupWithRunFunc(cmd, func(cmd *cmdutils.Cmd, ng *v1alpha5.NodeGroup) error { + scaleNodeGroupWithRunFunc(cmd, func(cmd *cmdutils.Cmd, ng *v1alpha5.NodeGroupBase) error { if len(ng.Name) != 0 { Expect(ng.Name).To(Or(Equal("nodeGroup"), Equal(""))) } else { From d44394cf96ea6fd4918b26a47146ddada3d02b58 Mon Sep 17 00:00:00 2001 From: Jake Klein Date: Wed, 3 Nov 2021 10:09:13 +0000 Subject: [PATCH 048/124] remove aws-cleanup and integration workflows (#4247) * remove aws-cleanup and integration workflows * remove integration check from release candidate workflow * remove unused slack action2 --- .github/actions/notify-slack/action.yaml | 48 ------------------- .github/aws-nuke-config.yaml | 15 ------ .github/workflows/aws-cleanup.yaml | 34 -------------- .github/workflows/integration-tests.yaml | 59 ------------------------ .github/workflows/release-candidate.yaml | 27 +---------- 5 files changed, 1 insertion(+), 182 deletions(-) delete mode 100644 .github/actions/notify-slack/action.yaml delete mode 100644 .github/aws-nuke-config.yaml delete mode 100644 .github/workflows/aws-cleanup.yaml delete mode 100644 .github/workflows/integration-tests.yaml diff --git a/.github/actions/notify-slack/action.yaml b/.github/actions/notify-slack/action.yaml deleted file mode 100644 index 7ce383f8d8..0000000000 --- a/.github/actions/notify-slack/action.yaml +++ /dev/null @@ -1,48 +0,0 @@ -name: "Notify slack" -description: "Send a message by webhook" -inputs: - webhook-url: - description: "Webhook URL to send the message to" - required: true - message: - description: "Message text" - required: true - channel: - description: "Slack channel" - required: true -outputs: {} -runs: - using: "composite" - steps: - - name: Notify slack - shell: bash - env: - msg: | - { - "channel": "${{ inputs.channel }}", - "blocks": [ - { - "type": "section", - "text": { - "type": "mrkdwn", - "text": "${{ inputs.message }}" - } - }, - { - "type": "actions", - "elements": [ - { - "type": "button", - "text": { - "type": "plain_text", - "text": "View run" - }, - "url": "https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }}" - } - ] - } - ] - } - # Using curl here is just hard to read (and - # https://github.com/curl/curl/issues/1978) - run: printenv msg | http --body --check-status "${{ inputs.webhook-url }}" diff --git a/.github/aws-nuke-config.yaml b/.github/aws-nuke-config.yaml deleted file mode 100644 index c85279c907..0000000000 --- a/.github/aws-nuke-config.yaml +++ /dev/null @@ -1,15 +0,0 @@ ---- -regions: - - "us-west-2" - -account-blocklist: - - "we-dont-have-a-prod-account-to-blacklist-but-this-field-is-mandatory" - -accounts: - AWS_ACCOUNT_ID_REPLACE_ME: - filters: - CloudFormationStack: - - "EC2RoleWatchDog" - - "Create-PatchBaseline" - - "PVRE-ComplianceReporting" - - "aws-sam-cli-managed-default" diff --git a/.github/workflows/aws-cleanup.yaml b/.github/workflows/aws-cleanup.yaml deleted file mode 100644 index 0c66512366..0000000000 --- a/.github/workflows/aws-cleanup.yaml +++ /dev/null @@ -1,34 +0,0 @@ -name: AWS cleanup - -on: - schedule: - - cron: '0 0 * * 0' - workflow_dispatch: {} - -jobs: - cleanup: - name: Cleanup AWS resources - environment: "Integration tests" - runs-on: ubuntu-latest - steps: - - name: Checkout - uses: actions/checkout@v2 - - name: Run AWS nuke - timeout-minutes: 1200 - env: - AWS_ACCESS_KEY_ID: "${{ secrets.AWS_ACCESS_KEY_ID }}" - AWS_SECRET_ACCESS_KEY: "${{ secrets.AWS_SECRET_ACCESS_KEY }}" - AWS_ACCOUNT_ID: "${{ secrets.AWS_ACCOUNT_ID }}" - working-directory: .github - # Cloudformation deletes are slow and not in parallel, so your better off deleting all EKS resources first as they - # run in parallel. - run: | - sed -i "s/AWS_ACCOUNT_ID_REPLACE_ME/$AWS_ACCOUNT_ID/" aws-nuke-config.yaml - wget https://github.com/rebuy-de/aws-nuke/releases/download/v2.15.0-rc.3/aws-nuke-v2.15.0.rc.3-linux-amd64.tar.gz - tar -xvf aws-nuke-v2.15.0.rc.3-linux-amd64.tar.gz - mv aws-nuke-v2.15.0.rc.3-linux-amd64 aws-nuke - chmod +x aws-nuke - ./aws-nuke -c aws-nuke-config.yaml --force --no-dry-run --target=EKSNodegroups,EKSFargateProfiles,EKSCluster - ./aws-nuke -c aws-nuke-config.yaml --force --no-dry-run --target=CloudFormationStack - ./aws-nuke -c aws-nuke-config.yaml --force --no-dry-run --target=EC2VPC - diff --git a/.github/workflows/integration-tests.yaml b/.github/workflows/integration-tests.yaml deleted file mode 100644 index 07afa27a3d..0000000000 --- a/.github/workflows/integration-tests.yaml +++ /dev/null @@ -1,59 +0,0 @@ -name: Integration tests - -on: - schedule: - - cron: '0 */12 * * 1,2,3,4,5,6' - workflow_dispatch: {} - -jobs: - it: - name: Run integration tests - environment: "Integration tests" - runs-on: ubuntu-latest - container: weaveworks/eksctl-build:83999a3391d78ed18a2e6093328d1122c927956f - env: - SSH: "/root/.ssh" - steps: - - name: Checkout - uses: actions/checkout@v2 - - name: Cache go-build and mod - uses: actions/cache@v2 - with: - path: | - ~/.cache/go-build/ - ~/go/pkg/mod/ - key: ${{ hashFiles('go.sum') }} - - name: Setup SSH known hosts - shell: bash - run: | - mkdir -p ${SSH} && chmod 700 ${SSH} - ssh-keyscan github.com >> ${SSH}/known_hosts - - name: Setup SSH key - shell: bash - env: - SSH_AUTH_SOCK: /tmp/ssh_agent.sock - run: | - ssh-agent -a $SSH_AUTH_SOCK > /dev/null - ssh-add - <<< "${{ secrets.EKSCTLBOT_SSH_KEY }}" - - name: Run integration tests - env: - SSH_AUTH_SOCK: /tmp/ssh_agent.sock - AWS_ACCESS_KEY_ID: "${{ secrets.AWS_ACCESS_KEY_ID }}" - AWS_SECRET_ACCESS_KEY: "${{ secrets.AWS_SECRET_ACCESS_KEY }}" - TEST_V: "1" - GITHUB_TOKEN: "${{ secrets.EKSCTLBOT_TOKEN }}" - run: make integration-test - - name: Notify slack on success - if: success() && github.event_name == 'schedule' - uses: ./.github/actions/notify-slack - with: - webhook-url: "${{ secrets.SLACK_WEBHOOK }}" - message: ":deal-with-it-parrot: An integration test run succeeded!" - channel: team-pitch-black - - name: Notify slack on failure - if: failure() && github.event_name == 'schedule' - uses: ./.github/actions/notify-slack - with: - webhook-url: "${{ secrets.SLACK_WEBHOOK }}" - message: ":ahhhhhhhhh: An integration test run failed!" - channel: team-pitch-black diff --git a/.github/workflows/release-candidate.yaml b/.github/workflows/release-candidate.yaml index 060c6c3935..762e2fc4a9 100644 --- a/.github/workflows/release-candidate.yaml +++ b/.github/workflows/release-candidate.yaml @@ -1,11 +1,7 @@ name: Release candidate on: - workflow_dispatch: - inputs: - skipIntegrationTests: - description: 'Skip check for successful integration tests:' - default: 'false' + workflow_dispatch: {} jobs: rc: @@ -13,27 +9,6 @@ jobs: runs-on: ubuntu-latest container: weaveworks/eksctl-build:83999a3391d78ed18a2e6093328d1122c927956f steps: - - uses: actions/github-script@v3 - name: Get integration tests status - id: it-status - with: - github-token: ${{ secrets.WEAVEWORKSBOT_TOKEN }} - script: | - // There's no other way to identify the integration test job - // GH branch protections are also just a string - // must be in sync with integration-tests.yaml - const integrationTestsCheckName = "Run integration tests"; - const { data } = await github.checks.listForRef({ - ...context.repo, - ref: "${{ github.sha }}", - check_name: integrationTestsCheckName, - }); - return data.check_runs.some(cr => - cr.status === "completed" && cr.conclusion === "success" - ); - - name: Fail if integration tests not passed - if: "!fromJson(steps.it-status.outputs.result) && !fromJson(github.event.inputs.skipIntegrationTests)" - run: echo "Integration tests haven't passed yet!" && exit 1 - name: Checkout uses: actions/checkout@v2 with: From 49fcf1ef7c9d802b36bc8abdd14bf2c728896b58 Mon Sep 17 00:00:00 2001 From: cpu1 Date: Tue, 5 Oct 2021 13:47:50 +0530 Subject: [PATCH 049/124] Support CloudWatch log retention --- .../eksctl.io/v1alpha5/assets/schema.json | 8 +- pkg/apis/eksctl.io/v1alpha5/cloudwatch.go | 9 +- pkg/apis/eksctl.io/v1alpha5/schema.go | 274 ++++++++++++++++++ pkg/apis/eksctl.io/v1alpha5/types.go | 3 + pkg/apis/eksctl.io/v1alpha5/validation.go | 41 ++- pkg/eks/api.go | 13 +- pkg/eks/tasks.go | 23 ++ 7 files changed, 356 insertions(+), 15 deletions(-) create mode 100644 pkg/apis/eksctl.io/v1alpha5/schema.go diff --git a/pkg/apis/eksctl.io/v1alpha5/assets/schema.json b/pkg/apis/eksctl.io/v1alpha5/assets/schema.json index 059627be07..8f5b5215ff 100755 --- a/pkg/apis/eksctl.io/v1alpha5/assets/schema.json +++ b/pkg/apis/eksctl.io/v1alpha5/assets/schema.json @@ -125,10 +125,16 @@ "type": "array", "description": "Types of logging to enable (see [CloudWatch docs](/usage/cloudwatch-cluster-logging/#clusterconfig-examples)). Valid entries are: `\"api\"`, `\"audit\"`, `\"authenticator\"`, `\"controllerManager\"`, `\"scheduler\"`, `\"all\"`, `\"*\"`.", "x-intellij-html-description": "Types of logging to enable (see CloudWatch docs). Valid entries are: "api", "audit", "authenticator", "controllerManager", "scheduler", "all", "*"." + }, + "logRetentionInDays": { + "type": "integer", + "description": "sets the number of days to retain the logs for (see [CloudWatch docs](https://docs.aws.amazon.com/AmazonCloudWatch/latest/logs/WhatIsCloudWatchLogs.html)) . Valid values are: 1, 3, 5, 7, 14, 30, 60, 90, 120, 150, 180, 365, 400, 545, 731, 1827, and 3653.", + "x-intellij-html-description": "sets the number of days to retain the logs for (see CloudWatch docs) . Valid values are: 1, 3, 5, 7, 14, 30, 60, 90, 120, 150, 180, 365, 400, 545, 731, 1827, and 3653." } }, "preferredOrder": [ - "enableTypes" + "enableTypes", + "logRetentionInDays" ], "additionalProperties": false, "description": "container config parameters related to cluster logging", diff --git a/pkg/apis/eksctl.io/v1alpha5/cloudwatch.go b/pkg/apis/eksctl.io/v1alpha5/cloudwatch.go index 94af1a98d3..128eaaeb93 100644 --- a/pkg/apis/eksctl.io/v1alpha5/cloudwatch.go +++ b/pkg/apis/eksctl.io/v1alpha5/cloudwatch.go @@ -17,6 +17,8 @@ const ( wildcardLogging = "*" ) +var LogRetentionInDaysValues = []int{1, 3, 5, 7, 14, 30, 60, 90, 120, 150, 180, 365, 400, 545, 731, 1827, 3653} + // ClusterCloudWatchLogging container config parameters related to cluster logging type ClusterCloudWatchLogging struct { @@ -24,9 +26,14 @@ type ClusterCloudWatchLogging struct { // Valid entries are `CloudWatchLogging` constants //+optional EnableTypes []string `json:"enableTypes,omitempty"` + // LogRetentionInDays sets the number of days to retain the logs for (see [CloudWatch docs](https://docs.aws.amazon.com/AmazonCloudWatch/latest/logs/WhatIsCloudWatchLogs.html)) . + // Valid values are: 1, 3, 5, 7, 14, 30, 60, 90, 120, 150, 180, 365, 400, 545, 731, + // 1827, and 3653. + //+optional + LogRetentionInDays int `json:"logRetentionInDays,omitempty"` } -// SupportedCloudWatchClusterLogTypes retuls all supported logging facilities +// SupportedCloudWatchClusterLogTypes returns all supported logging facilities func SupportedCloudWatchClusterLogTypes() []string { return []string{apiLogging, auditLogging, authenticatorLogging, controllerManagerLogging, schedulerLogging} } diff --git a/pkg/apis/eksctl.io/v1alpha5/schema.go b/pkg/apis/eksctl.io/v1alpha5/schema.go new file mode 100644 index 0000000000..dec6b506fc --- /dev/null +++ b/pkg/apis/eksctl.io/v1alpha5/schema.go @@ -0,0 +1,274 @@ +// Code generated by go-bindata. DO NOT EDIT. +// sources: +// assets/schema.json (88.349kB) + +package v1alpha5 + +import ( + "bytes" + "compress/gzip" + "crypto/sha256" + "fmt" + "io" + "io/ioutil" + "os" + "path/filepath" + "strings" + "time" +) + +func bindataRead(data []byte, name string) ([]byte, error) { + gz, err := gzip.NewReader(bytes.NewBuffer(data)) + if err != nil { + return nil, fmt.Errorf("read %q: %w", name, err) + } + + var buf bytes.Buffer + _, err = io.Copy(&buf, gz) + clErr := gz.Close() + + if err != nil { + return nil, fmt.Errorf("read %q: %w", name, err) + } + if clErr != nil { + return nil, err + } + + return buf.Bytes(), nil +} + +type asset struct { + bytes []byte + info os.FileInfo + digest [sha256.Size]byte +} + +type bindataFileInfo struct { + name string + size int64 + mode os.FileMode + modTime time.Time +} + +func (fi bindataFileInfo) Name() string { + return fi.name +} +func (fi bindataFileInfo) Size() int64 { + return fi.size +} +func (fi bindataFileInfo) Mode() os.FileMode { + return fi.mode +} +func (fi bindataFileInfo) ModTime() time.Time { + return fi.modTime +} +func (fi bindataFileInfo) IsDir() bool { + return false +} +func (fi bindataFileInfo) Sys() interface{} { + return nil +} + +var _schemaJson = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\xec\x7d\xfd\x73\x1b\x37\xb2\xe0\xef\xfb\x57\xa0\x98\xad\xf7\xec\x57\x1c\xd1\xb2\x93\x6c\x92\xcd\xa9\x8e\x96\x14\x87\xe7\x48\xe2\x89\x72\x72\x17\xcb\xb5\x06\x67\x40\x12\xab\x21\x30\x0b\x60\x24\x31\xcf\xb9\xbf\xfd\x0a\x5f\xf3\x89\x19\xce\x97\x6c\x6d\x95\x7e\xb1\xa9\x99\x41\xa3\xd1\x68\x74\x37\x1a\xdd\x8d\xff\xfe\x0b\x00\xa3\xbf\x32\xb4\x1a\xfd\x00\x46\x5f\x4d\x02\xb4\xc2\x04\x0b\x4c\x09\x9f\x1c\x87\x31\x17\x88\x1d\x53\xb2\xc2\xeb\xd1\x58\x7e\x28\x76\x11\x92\x1f\xd2\xe5\x3f\x91\x2f\xf4\xb3\xbf\x72\x7f\x83\xb6\x50\x3e\xde\x08\x11\xfd\x30\x99\xfc\x93\x53\xe2\xe9\xa7\x07\x94\xad\x27\x01\x83\x2b\xe1\xbd\xf8\xdb\x44\x3f\xfb\x4a\xb7\xcb\x74\x35\xfa\x01\x48\x3c\x00\x18\x4d\x7f\x5f\xc4\x4b\x82\xc4\x19\x8c\x22\x4c\xd6\xc9\x0b\x00\x46\x30\x08\xd4\xd7\x30\x9c\x33\x1a\x21\x26\x30\xe2\x99\xf7\x95\xc3\xb0\x20\x17\x11\xf2\x47\xe6\xe3\x3f\xc7\x16\xaa\x63\x44\xea\x79\x80\xb8\xcf\x70\x24\x41\xa8\x91\xd1\x30\xe0\x80\x2b\x40\x40\x50\x30\xfd\x1d\x6c\x35\x8a\xfc\x00\xcc\x56\x40\x6c\x10\xb8\x41\x3b\x80\x39\x80\x04\x4c\x7f\x1f\x03\xb1\x81\x02\xc0\x90\x53\xb0\x44\x3e\xdd\x22\xae\xbe\x21\x70\x8b\x00\xd5\xdf\x1b\x68\x54\x6c\x10\xbb\xc3\x1c\x81\x98\xa3\x04\x90\xa0\x80\xa1\x15\x62\xf2\x87\xd8\x60\xdb\xf7\x41\x8a\xe1\xbd\x87\x89\x40\x61\x88\xff\xe9\x6d\xc4\x36\xf4\x1e\x3f\xc6\x01\x5a\xc1\x38\x14\x12\xbb\xff\xfe\x53\x4f\x85\x99\x88\x51\x6e\x92\x32\x93\x1e\x55\x4c\x35\xfc\x23\xf7\x77\x66\x22\xb9\x60\x92\x71\xc6\xd9\x77\x05\xd2\xf8\x90\x80\x25\x02\x74\x8b\x85\x40\x01\xc0\x65\x62\xe4\x9b\xef\xa1\x74\x03\x70\x09\xb4\x3f\x53\xc0\x23\x1f\x07\xac\x38\x0a\x37\x0b\xaf\xb1\xd8\xc4\xcb\x03\x9f\x6e\x3f\xdd\x21\x78\x8b\xee\x28\xbb\xe1\x9f\xd0\x0d\xf7\x45\xf8\x29\xba\x59\x7f\x8a\x05\x0e\xf9\x27\x1c\x49\x7a\xcf\xe6\xe7\x48\xb8\x7b\xc4\xc1\x1e\xaa\xa5\xad\x4a\x0b\x25\x52\x93\xcb\x50\x70\xc1\x02\x24\xf1\x7e\x9f\x83\x3b\xce\xcd\x4d\x71\x94\xe6\xcf\x0f\xe3\x3d\x8b\x79\x05\x43\x8e\xf2\x8c\x11\x04\x8a\xca\x09\x47\x30\xf4\xaf\x18\x33\x14\xe4\x31\x90\x5c\x5a\xee\xa5\x92\x7b\x84\x80\xfe\x66\x4e\x43\xec\xef\x9a\xcd\xc0\x8c\x84\x98\xa0\x13\xea\xc7\x5b\x44\x44\x2d\x77\xe9\x85\x07\x41\xa4\xc0\x83\xc0\xb4\x91\xcb\x42\xf7\xdb\x8a\xb9\xf6\x43\x73\xce\x74\x76\x84\xd3\xcb\x73\x5e\x1c\x25\x16\x68\x5b\x7c\x58\xc3\x0e\x39\xe0\x99\xef\x20\x63\x70\x57\x4b\x8d\x10\x73\x21\xc5\x87\x44\xc2\x8a\x91\xd9\xf4\x4c\x8f\x07\x4b\x19\xd3\x89\x2c\x2d\xc0\x3a\xe9\xa3\xf8\xa5\xe9\x5a\xc8\xb4\x8b\x10\xdb\x62\xce\x25\x4f\xbc\xa6\x31\x09\x20\x2b\x31\x50\x0b\x41\x34\xbd\x3c\xb7\xc8\x67\x00\x83\xa5\x81\xac\x06\xc1\x39\xf5\x31\x14\xa8\x15\x79\x5a\x01\x76\x0e\x94\x23\x76\x8b\x7d\x34\xf5\x7d\x1a\x13\x71\x49\x43\x34\xbd\x3c\xef\x42\x31\x01\xd7\x25\xee\xdb\xab\xca\x3b\x31\x63\x41\x85\xbb\x08\x7e\xb5\x41\x60\x8b\x04\x0c\xa0\x80\x8a\x08\x51\x14\xee\xb4\xc2\x42\xc0\xd7\xf6\x8e\x21\x8e\x64\xb0\x3b\x2c\x36\xc0\x87\x02\xad\x29\xc3\x7f\x40\x09\x05\x40\x12\x00\xca\xd6\x90\x98\x07\x07\xe0\x14\xfa\x1b\x20\xe0\x1a\xf8\x94\xc8\x66\x8a\x21\xa1\x52\x00\xf2\x63\x48\x00\x8d\xf4\x68\xc1\x2d\x0c\x63\x34\x06\x4b\x2a\x36\xf2\xa3\xbb\x0d\xf6\x37\x60\x47\x63\xa0\x64\x0d\x3a\x68\x35\xc9\xff\x5e\x83\x71\x28\xff\x22\xab\xdc\x22\xc6\x71\x4e\xda\x37\xe6\xb2\x3b\x14\x86\x6f\x09\xbd\x23\x73\x23\x00\x9a\x89\xf5\xdf\x4a\xcd\xea\xb8\x67\x45\x99\x11\x2a\x98\x48\x02\x6d\xb7\x94\xe4\xa4\x4e\xab\xe9\xdb\x0f\xad\xa3\x36\x56\xb2\xcd\x41\xd6\xbd\xab\xbb\x4e\x7f\x54\xbc\x1b\xed\x91\x8d\xb5\x53\x54\x94\x12\xad\xac\x84\x7a\x4b\x5d\x2e\x81\xd3\xb7\x0b\x00\xa5\xf9\x20\x79\x79\x85\xd7\x31\x53\x3c\xde\xd2\x82\xae\x83\x94\xb3\x54\xec\x76\x29\xa4\x71\xf0\x1b\x14\xfe\xa6\x89\x1d\x6b\x96\xe9\x2f\x74\xbd\xce\x6f\x77\x6a\x98\xb6\xd4\x91\x6d\xdd\x91\x5f\x0a\x38\x0c\x32\x0b\x3e\x25\x02\x62\xc2\x0d\xc1\x40\x04\x19\xdc\x22\x81\x18\x07\x0c\x85\x50\xda\xc9\x82\x82\x0c\xad\x9a\x4e\x4a\x6b\xc0\xf5\x73\x54\x26\x7c\xe5\x54\x21\x02\x97\x21\xba\xda\x45\x65\xe1\xd2\xcc\x9a\x1a\xe7\xdf\x22\x12\x6f\x73\x13\x61\xc9\x1d\xe1\xc2\xa7\xf2\x61\x1c\x60\xe1\x7a\x2c\x36\x88\x08\xec\x43\x41\x59\xf9\xb5\x24\x16\xa3\x61\x88\xd8\x19\x24\x70\x8d\x1c\x9f\xc8\x2d\x79\x10\x87\xae\x57\x30\x0c\xcb\x0f\xff\x6b\x94\x7b\xf2\x61\x00\x13\x51\x91\x54\x6a\x90\x50\x4f\x86\x9c\x40\x4d\x6c\xf0\x8c\x23\x04\xde\xa7\xd3\x25\xed\x5f\xfe\xe1\xd9\x24\xe6\x70\x8d\x26\xbe\x7c\x7e\x27\x9f\x7b\x86\x87\x3d\x03\x62\xf2\x95\x79\xa0\xb9\xc4\x43\xf7\x70\x1b\x85\x88\x3f\x7f\x7e\x00\x7e\x85\x21\x0e\x00\x22\x82\x49\x3b\x11\x32\xf4\x03\xf8\x78\x2d\xa9\x7e\x3d\xfa\x38\x56\x3f\x25\xad\xd3\x3f\x32\x14\xb6\x0f\x4b\x74\xb5\x2f\x12\x6a\x26\xcd\xc3\xd0\xfe\xfc\xaf\xeb\xd1\xc7\x96\x0a\x7e\x0f\x61\x7e\x84\x60\xc3\xd0\xea\x7f\x5c\x8f\x3a\x13\xe4\x7a\x74\x54\xa0\xee\x8f\x13\x78\xe4\xa6\xd2\x8f\x3e\x0d\xd0\xd1\x7f\xfc\x2b\xa6\xe2\xef\x30\xc2\xfa\xc7\x8f\x13\xf5\x74\x9c\x7f\x2b\x29\x58\xfb\x3e\x43\xd4\x9a\xef\x4a\x74\xae\xf9\x36\x21\x7d\x5d\xbf\x61\x58\xf3\xf6\xbf\x72\xef\x0e\xdc\x86\x46\x48\xd7\x97\x48\x48\xe4\x29\x99\x91\x13\xb8\x2b\x09\x03\xcb\xf8\x72\x6a\x8b\x4b\xae\xc8\xfa\x1c\x09\xe3\x65\x89\xb7\x4b\xc4\xe4\x5c\x07\x70\xc7\xb5\x2f\x45\xca\x39\xf5\x32\xa4\x6b\x0e\xa4\xb9\x50\xb1\x1c\x36\x42\x44\xfc\x87\xc9\x44\xfe\x75\x00\xef\xf8\x01\xdc\xc2\x3f\x28\x39\xf0\xe9\x76\x32\x55\x3f\xd3\x26\x13\x29\x23\xb9\x98\x48\x98\x93\xdf\x36\x50\xcc\x78\x4e\x1a\xf2\x03\xc9\x89\xcf\x9f\x03\xcb\x02\xca\xca\x33\x1c\x70\x38\x06\xaf\xc6\xe0\x9b\x31\xf8\xdb\x18\x1c\x7e\x3d\x06\xaf\x5e\x8c\xc1\xb7\x2f\xc6\xe0\xfb\x17\x63\x70\xf8\x52\xfe\xf3\x8d\xfc\xe7\xbb\x17\x63\xf0\xea\xdb\x6f\xc6\xe0\xeb\x17\x2f\xc6\xe0\x9b\xaf\x65\x83\x57\x87\xf2\xc5\xcb\xbf\x8d\x95\x19\xf9\xea\xdb\x6f\x5e\xb5\x5b\x0b\x5d\x28\x95\xae\x8f\xe1\x29\x54\xb1\x70\x3e\x07\xd9\x3a\xaa\xf9\xac\xfe\xaa\x67\xe8\x21\x2d\x00\xc4\xea\x35\xb5\xdd\xa7\x18\x39\xd5\xd6\x0e\x68\x0b\xde\x69\x0d\x68\x07\xf7\x5e\x1f\x93\xdd\x6b\x65\xa9\x77\x83\x49\xde\xf7\x15\xe1\x5f\x8d\xb9\xdd\xdc\x1b\x25\x2d\xcb\xa6\x36\x45\x85\x8f\x5b\x79\xc9\x1a\xea\x62\xb7\xc3\x28\x45\xbc\x85\x3f\xc3\x69\xc3\x8c\xb4\x63\xf2\x00\xd3\xc9\xed\x21\x0c\xa3\x0d\xfc\x26\x8b\xda\x07\x77\xff\xb7\x10\x87\x70\x89\x43\x2c\x76\xbf\x53\xd2\xd5\xc6\xea\x43\x02\xdf\x65\xb9\xd7\x10\xbd\x6c\xf0\xd7\x89\xfa\x45\x41\x74\xf3\x38\x8a\x28\x13\x4d\x8c\x99\xe7\xad\x24\xe5\xa2\xa5\x65\x90\x97\x64\x06\x2d\x29\xcc\xdc\x54\x5a\x41\xb6\x86\x02\xcd\x19\x5d\xe1\xb0\xf1\x34\xb9\x29\xf8\x53\x0e\x56\xaf\xc9\x5b\x63\xd1\x6c\xd6\xde\xe0\x7a\x17\xd1\x4f\xbf\xbc\xfb\x3f\xe0\xd7\x43\x70\x72\x3a\xbf\x3c\x3d\x9e\x5e\xcd\x2e\xce\xc1\xf9\xc5\xd5\xec\xf8\xf4\x00\x58\x35\x92\xfa\xe3\x27\xa9\x3f\x7e\xa2\xd9\x7e\x82\x39\x8f\x11\x9f\xbc\xfc\xfe\xdb\x57\xe0\x0d\x16\x00\xdd\x47\x94\x23\x9e\xdf\x3a\x2a\x25\xf5\x53\x18\xdf\x83\xdb\x43\xeb\x58\x41\x90\x85\x18\x31\x80\x05\x32\x1f\xd1\x15\x58\x63\x41\xa3\x76\x8e\x85\xc7\x39\x82\xaa\x59\x93\xef\x9a\x4e\xdc\x45\x91\x12\x85\x91\xef\x43\xf4\xa5\x42\xf4\x0e\x87\xa1\xfc\x44\x60\x12\x23\xa9\x24\x96\xea\x20\x2b\x00\x98\x80\x55\x2c\x62\x86\x0c\xce\x20\x0a\x21\xe1\x63\xc0\x50\x14\x42\x5f\x19\xe0\x1b\xa4\x28\x92\xef\x00\x2e\xe9\x6d\x3b\xff\xec\x17\x45\xd4\x39\x13\x18\x6e\x5b\x49\xbd\xd9\xf4\xac\xea\x8c\x49\xda\x12\x62\x37\x67\xf4\x16\x07\x88\xf5\x93\x10\xb3\x02\xb4\x5e\x32\x42\x29\xeb\xde\xda\x2d\x6f\x35\xec\x55\x6c\x37\xf1\x12\x31\x82\x04\xe2\xe7\x48\xc8\x65\x56\x32\x37\x6a\x86\xff\xb6\xa2\xb1\xb3\xa7\xad\xda\x23\x05\xe7\x34\x40\x6f\x18\x8d\xcb\xeb\xaa\x15\xe5\xcf\x0a\xd0\x86\x38\x0c\x52\x3a\x50\x42\x5c\x2b\xfc\x80\xd2\x4d\x89\x06\x54\xf8\x63\xb2\xf6\x48\xf2\xc5\x73\xb5\x0e\xde\x9b\x91\x81\xf4\x45\xd2\x08\xdd\x70\xcf\xbc\x56\xed\xf8\x10\xda\xd2\x81\xc9\xf5\xe8\xa8\x88\xb8\xd4\x91\x0a\xbf\x52\xfb\x32\x52\xd7\xa3\xa3\xf2\x20\xaa\x95\x6c\x62\x6a\xb6\x59\x92\x67\x48\xc0\x8a\xd3\xae\x61\x58\x62\x50\x5e\xf8\x89\x32\x80\xc9\x8a\xb2\x6d\x7a\x14\x61\xbd\x12\x40\xed\x73\x1d\xb3\xed\x62\x91\x76\xba\x71\x5f\xaf\x0d\x79\xa1\xc9\x24\x46\x0c\xdf\x42\x81\xcc\xec\x34\x9b\xca\x79\xbe\x4d\x1d\x01\x61\x18\xd2\xbb\x54\x85\x48\xa9\x0f\xc1\x2a\x0e\xc3\x9d\x67\x7a\x4e\x76\x3f\x98\x98\xd3\x19\x42\x15\xfb\x81\x0d\xe4\x80\xc6\x42\x9d\x07\x02\x49\x30\x29\x64\x00\xf4\x7d\xc4\xb9\xde\x6a\x5a\x10\xfa\x99\x0a\x20\xf9\x6d\x01\xcc\xb9\x01\x07\x98\x1b\x4f\x54\x00\x6e\x31\x04\xbf\xce\x8f\x01\x22\x41\x44\x31\x11\xed\x8c\x95\xc7\x3b\x0a\xe7\x9c\x72\xe4\x33\x24\xf8\x29\xf1\xd9\xce\x8e\xa1\xc1\xb4\x2e\x4a\xcd\x9c\xd0\x6f\x23\xbf\xd5\x8a\xff\x75\x7e\xdc\xd5\x1b\x50\xb3\x71\x75\xc9\xa1\x06\x0a\xad\x60\x4c\xd4\x9a\x04\x85\x31\x8f\x4b\x9b\xe1\xea\x65\xe4\x16\x6b\xb5\x6a\xb0\x66\xf7\x52\xbb\x03\x75\xef\x0d\x6b\xb9\xa1\xb0\x23\x29\x9b\xba\x83\xf8\x56\x20\xe0\x58\x8a\x2c\xb3\x6c\xc6\xc6\x36\xd4\xe6\x1f\x0a\xf4\x51\xaf\x21\x18\x98\xce\x67\x8d\xbd\x2a\x7d\x00\xa7\x7c\xe1\x29\xc9\xe8\x99\x73\x47\xcf\x98\x5d\x29\xf3\xe5\x18\x5c\x7d\xab\x6c\x62\xeb\x35\xc8\xcb\x8f\xf4\x50\x78\x94\x78\x13\x72\x1f\x18\xf0\x55\x76\x99\x5d\x16\x1f\x5c\xae\x9f\xd3\x64\xb5\x37\x38\x00\x32\x8c\x38\x55\xb2\xa4\xca\x8e\x5c\x52\x1a\x22\x58\xb1\xbe\xa3\x78\x19\x62\xbf\x2d\x80\x56\xeb\x3a\x8f\x64\x55\xdf\x83\x70\xa1\x3e\x1f\xb5\xd2\x19\x46\x58\x09\x56\xc4\x12\x19\x6a\xc5\x6e\x46\xe1\xb6\x3c\x7c\x6d\x09\xdc\x35\xc5\x72\xa3\xd2\x60\x72\xad\x60\xa0\xc1\xe9\x3d\xf2\x63\x09\xae\x59\xd0\x4b\x9d\x8a\x66\x34\x34\x3b\xb6\xe5\x0e\x44\x34\xd0\x61\x49\x1a\x6f\xa9\x88\xa6\xf3\x19\x3f\x00\x57\x1b\xcc\x81\xfa\x14\x73\x00\x83\x40\x7b\x2e\xe5\x0e\x2e\x35\xff\xc1\xe5\xeb\xe9\xb1\xda\x20\xc2\x58\x6c\x92\x00\x8e\x03\xa0\x4c\xea\x39\x0d\x40\x82\x36\x90\x78\xd7\x1f\x0a\xa0\x1b\x6e\xbd\xdc\x31\x47\x6c\x1d\xe3\x00\x4d\x22\x1a\x78\xc8\x02\xf1\x24\x3e\xfa\x28\xa0\x95\x3a\xff\x4c\x23\x6e\xe6\xd9\x6f\x33\xcc\xeb\xd1\x51\x99\x8a\xfb\xbd\x60\x05\x76\x99\x0f\x1a\x1e\xe6\x0c\xdd\x92\x14\x91\x94\x32\x18\x48\x22\x83\x64\x3c\x8a\xa8\x1f\x0d\x57\x9c\xbe\x5d\x00\xe3\x61\x03\x8b\x82\xb7\xd1\xb4\xf6\x8c\xbb\xaf\xe5\xa6\xa9\x1f\x62\x25\x13\xbb\x88\xcc\xf5\xe8\xc8\x81\x7b\xf5\x64\xe4\xa3\x59\xfa\xed\x71\x52\xa9\xb1\xc8\x41\x1d\x62\xcb\x63\xf0\x94\xeb\x41\x21\xaa\x0e\x28\x18\x92\x63\x34\xe7\x57\x46\xde\x99\x09\x9c\x4d\xcf\x80\xc1\x02\xd8\xc1\x7d\x78\x36\xc1\x70\x6b\x20\x59\x40\x93\xaf\x14\x21\x3d\xa9\x9e\x3d\x73\xc2\xab\xec\x9b\x76\xd3\xda\x12\xbf\xcc\x3c\xb6\x40\xe9\x7a\x74\xe4\x1a\xd7\xde\xd9\xed\x11\x82\x98\x81\xf0\x99\x16\x28\x0c\x43\x60\xad\x5e\x6f\x09\xa5\x3c\x54\x7f\x60\xc4\x0d\x45\x95\x80\x34\x26\x8f\x9e\x6d\x29\x1e\x53\xf4\x80\x45\xaf\x5e\x92\xcf\xa6\x67\x56\xc4\xbd\xe3\x88\xbd\x51\x22\x4e\xcb\xdb\x7f\xd8\x38\xb2\x7f\x18\xd4\x30\xe2\x1d\x24\xfa\x90\x63\x6c\x26\xb6\xbb\x8c\xe9\x7a\x74\x54\x41\xbf\x6a\xc6\xba\x8d\xfc\x4b\xc4\x69\xcc\x7c\x74\x9c\x04\x1a\xb8\x83\xc2\x8b\xc6\x59\xed\xbe\x5c\x85\xc7\x99\xec\x89\x24\x9e\x6f\x07\x08\x92\x23\x30\xd1\xb7\x2c\xd6\x0b\x4a\x6e\x39\xd3\x28\x87\x64\x99\xe9\x27\xca\xad\xdb\xce\xb1\xfc\xb0\x9d\xa7\x31\x9c\x82\xc5\xc8\x49\x54\xb9\xde\x2f\x66\x27\xc7\x7d\x28\xa8\xf7\xe4\xe9\x18\x24\x3c\x10\x99\xcd\x23\x80\x1c\xdc\xa1\x30\x94\xff\xcf\x2e\x17\xd3\x44\xef\xe8\x73\x7c\x70\x7c\x3e\x03\x51\x18\xaf\x31\x69\xe7\x91\x1f\xa8\xcf\x8e\x66\x7b\x41\xc8\x35\x17\x5e\xfb\x6d\x92\x02\xbc\x16\x96\x8b\x6b\x5a\x6b\xd4\x6e\xc3\xa5\x35\xe0\xde\x43\x8a\x20\x39\x59\x50\x08\x86\x97\xb1\x40\x26\x5a\xd9\x2f\xf8\x0a\x1a\x26\x59\xec\x81\x56\xb1\xbb\x50\x6e\xd7\x26\x29\x4b\x84\x50\x01\xf3\xf9\x6e\xf5\x14\x78\x90\x78\xf8\xbd\x51\xd8\x21\x5c\xa2\xf0\x71\xa3\xd8\x35\x7b\x43\xb6\xe3\x11\xf4\x9b\x37\x6e\xb5\x88\x8b\x81\xd7\x69\x77\x65\xf2\x8e\xdd\x8c\x31\xe0\xe2\xc8\xba\xb9\xef\x10\xf0\x21\xd1\xe9\x7a\x89\x4d\x77\xa1\x88\x2f\xd9\x57\xc9\xb3\xa2\xf5\xd7\x72\xf5\xf4\xee\xae\x62\x79\x15\xcc\xf0\x26\x0b\xed\x8b\x66\x77\xa5\xe9\x8f\xf9\x01\x0e\x9b\xf5\x55\xd9\x8b\x93\xef\x9f\xb2\xc1\x9a\x64\xcb\xf5\xf7\xf7\x64\xd2\xae\x94\x77\xa3\x30\x5d\xa8\x17\x4f\xb4\x06\xee\x1c\x6a\xa7\x93\x45\xab\xe5\xdc\x4e\xcd\x2f\x96\x12\xa7\xdd\xd1\x03\xd2\xb5\x47\x8f\x4e\xd2\xc8\x79\x3a\xdf\xaf\xab\x6a\x8f\xcc\x23\xe4\xe3\x15\xf6\xf5\x9c\xab\x64\x6c\x4c\xb8\x40\x30\xb0\x48\xab\xe0\xad\x44\xf6\x7a\x6b\x44\x10\x53\x9b\xaf\xa4\x45\xbb\x03\xf1\x21\x3a\xac\xa4\xc6\x05\x09\x7b\x6d\xae\x34\x76\x3b\x80\x57\x80\x92\x70\x97\xac\xf4\x82\x3b\x41\xa3\xc2\x37\x34\x0e\x03\xb0\x44\xc9\x7e\x54\x4e\x1f\x8d\x85\xfe\x1b\x93\xf5\xc4\xea\x5e\x13\x32\xd3\x87\x8f\x3e\x33\x6a\x6e\x4f\x87\x80\x22\x6e\x18\x4f\x55\xa5\x62\x17\x1a\x86\x13\xfe\xa3\x4a\xe6\x94\x1b\x7e\x89\x50\xb2\x1b\xeb\x25\x05\x5a\x01\x6b\x60\xa3\x0e\x96\x91\xd8\xd1\x18\x75\x1d\xdd\xd6\x65\xf5\xd5\xa6\xe7\x55\xa5\xfc\xe5\x15\xe7\x1e\xa5\x50\xe6\x53\x97\xa8\x74\x09\x8c\x22\x07\x0e\xb9\x85\xd4\x39\x97\x85\xd9\x4e\xf3\x6a\x21\x09\x7a\xa5\x0f\xb6\x87\xdf\xc8\x0e\x5e\x14\x17\x7a\xa5\x35\xcc\x5a\xfa\x4d\x5b\x31\x99\x05\x3e\xe0\x84\x68\xd6\xc8\x5a\x71\x55\x2b\xb1\x61\x05\x94\xbd\xf0\x5c\x04\x2f\x6e\xea\x6b\xaa\x4e\x64\x19\x16\xad\xdb\x45\xfe\x3f\x0e\x97\x40\xde\x83\xc8\x96\x58\x30\x69\xf8\x24\x3c\x8a\xd7\x84\x32\xed\xcd\xfd\xa8\xdd\xb9\x2d\x13\xd9\xea\x61\xea\x1c\x2c\x0d\x38\x49\xbe\x7a\x00\x97\x40\xdd\xa8\x0d\x7b\x14\x1d\x47\x4d\x06\x57\x68\xea\x36\x7d\x34\x63\x74\xc7\x4f\x39\x1b\x7f\x5b\x00\x0d\x08\x6c\x28\x37\x86\x01\xe6\x9d\x90\x6e\x02\xef\xf1\x5b\x00\xea\xa0\x59\xee\x7e\xe0\xda\x8c\x46\xfb\x1c\x1d\x07\x10\xad\xa8\xd3\x19\xee\x60\x45\x0e\xea\x46\x6d\x13\xcc\x18\x86\x44\xa4\x19\xac\x87\x07\x87\x7f\xb3\xb9\xa6\x87\x07\x87\xdf\x65\x7e\x7f\x9f\xfe\x7e\xf9\xe2\x7a\xf4\x11\x3c\x33\x88\x3e\xb7\x4f\x0f\x5b\x27\xa7\xba\xb0\xc8\x66\x53\x4a\x74\x6a\x92\x2d\x25\x86\xf5\xaf\xbf\xaf\x7d\xfd\xf2\x45\xee\x75\x76\x44\x85\x0f\x0f\x0b\x69\x9d\x55\x13\x26\x61\x36\x89\xff\x96\x03\x2b\xe6\x72\xcb\xd1\x38\x9e\x7d\x5f\x7e\x56\xe8\x43\x3f\x3b\xac\x08\x23\x6f\xa5\x8b\x2b\x94\x91\x83\xf5\x8a\xcb\xf9\x21\x7d\x91\x49\xbe\xbe\xde\x26\x86\x99\x68\xce\xf6\x41\x41\x8d\x80\xb9\xd4\xf9\xf9\xf4\xaa\x89\xad\xb4\x86\x02\xdd\xc1\x3e\xee\x8b\x8a\xb5\xf9\x33\x5e\x6f\xc2\xdd\x54\x47\x18\x86\x48\x2e\x41\x6b\xf4\x21\x0e\x20\xd8\xa8\xf7\x00\xda\x0f\xc0\xf9\xf4\x0a\x18\x6c\xd4\x12\x5d\x60\xb2\x76\xb4\xe3\xea\x71\xf6\xeb\xc2\xd2\x3e\xc1\xdc\x76\x18\xe8\x9f\x5c\x7e\x3d\xec\x52\x2f\x8c\x2e\xbf\x30\x5b\x8c\x33\x0b\x53\x0f\xb8\x06\x54\xfd\xd0\xb3\xa0\x0c\x0d\xf2\xb0\x6a\xa8\x91\x91\x09\x1a\x8b\x26\x52\xa1\x40\x83\xe2\x22\x77\x00\x02\xc0\xce\xce\x10\xab\xdf\xb2\xee\x20\x8b\x56\x12\xd5\xcf\x47\xf5\xee\xe3\x91\x4c\x13\xd7\x02\xd4\xd5\xfd\xda\x84\x59\x36\xdb\x2e\x17\xeb\x45\x3a\x55\xae\x0e\x7d\xec\x0b\xb0\xd5\x74\xd8\x41\x94\xb1\x18\x70\xab\x94\x44\xb7\x93\x00\x68\xe8\xa6\xe6\x62\xdb\xb3\x9b\x1a\x40\xae\xc9\xfc\x75\x7e\xdc\xe8\x1c\x26\x16\x74\x1a\x86\xd4\x87\x02\xcd\xe6\xb7\xdf\xf6\xf1\xfb\x4d\x73\xb0\x7e\xfd\x16\xc8\x0d\x19\xe2\x42\x6f\xb0\xe7\xb7\xdf\x82\xe3\xd9\xc9\x25\x58\x86\xd4\xbf\xd1\x4e\xda\xc9\x37\xdf\x02\x39\x43\xf8\x3e\x71\xe9\x48\xbc\x5b\xf9\x84\x86\xea\xd4\xc9\x95\x9f\xbf\xfc\xa3\x5f\x1d\xf4\x5c\xd3\x7b\x29\x54\xba\xd6\x3f\x8b\x90\x49\xd7\x52\x99\x1c\x69\xda\xc5\x7c\x96\xc4\x1e\xde\x46\xbe\x47\x74\xea\x80\xaa\x4c\x92\x64\xd8\xe8\xcf\x3d\x41\x3d\xb1\x41\xd9\x78\x72\x18\x61\x4f\x87\xff\x7a\x49\x7e\xc6\x00\x69\x5e\xc3\x20\x62\x53\xbb\x4a\x03\xae\x8e\x3c\x42\xf7\x82\x41\xc9\x3b\x5f\xee\x24\x4e\x45\x70\x25\x92\x47\x33\xb2\x3d\xe6\x90\xd3\x3e\x06\xe8\x60\x7d\x00\xa0\x7e\x23\xbf\xb6\x42\xc2\x48\x06\x20\x01\x90\x1d\x80\x81\xb7\xa1\x65\xc1\xd3\x64\x52\x1e\x0a\x07\x27\xcd\x5b\xd4\x3e\xcd\x1e\x97\xa9\x64\x92\xc5\x06\x32\x9d\x51\xb2\x40\x7e\xcc\xb0\xd8\xa9\xcc\x92\xcb\xd8\x91\x00\xdf\x56\xaa\x49\xab\xd5\x87\xa1\xb4\x8a\x82\x00\x70\x03\x1f\xa8\xb4\x08\xc0\xe2\xd0\x9c\x5e\x92\x00\xac\x18\xdd\x2a\x91\x62\x0c\x94\xc4\xfa\x2d\x34\x92\xdf\x2a\x0f\xb6\xc2\x5a\xa7\x4a\xe5\x3f\x31\x11\xd8\x26\xf7\x2a\x26\xd9\xd4\x44\x1d\xf5\x49\xb7\xdb\x98\x60\x3f\x77\xe4\x95\x0b\x0c\x53\xbd\xe4\xda\x19\xa0\xba\x3c\x20\xf0\xd5\x4e\x02\x2c\x91\xb5\xb4\x02\x70\xb7\x41\x04\xc4\xd2\x6e\x33\x7b\xe7\x64\x37\x9d\xc7\x8e\xb7\xb3\x4e\x9f\x88\xd8\x84\x88\x0d\x42\xf7\x08\x6c\x58\x42\x21\xb3\xa9\xaa\xb1\xb7\x74\xaa\xc9\x97\x95\x72\x3a\x5f\x30\xd5\xd2\x9a\x0d\xe4\x8c\x65\x44\xb5\xb1\x78\x6e\xbe\xe3\x52\x6a\x27\x09\x26\xad\x98\xb0\x57\x47\x4e\x22\xf2\xac\xa4\xe9\xb1\x23\x7d\x06\x6f\xa0\x3e\xb6\xd5\x9c\x37\x97\x8c\x97\x13\x63\xcf\x95\x68\x4d\xb9\x55\x72\xde\x12\x89\x3b\x84\x88\x83\x5d\x15\x9b\xb6\xa2\xcd\xc3\x60\xe0\x26\x9a\x5b\x50\xf7\x20\x9f\xd6\x3a\xc8\xd3\x35\x4d\x83\x9c\x3c\x58\xbc\x69\xad\xee\x6a\x40\xb9\x07\x54\xda\x37\x81\xbd\xeb\x72\xe1\x52\xc5\x05\x5c\x6e\xd0\x4e\x7b\x31\xa7\xbf\x1b\xda\x93\x5b\x44\x30\x22\x3e\x32\xe1\xe8\xca\x15\x6c\x52\xa3\x3f\x3c\x9b\xd8\x24\xe9\x09\x43\x4a\xfa\x78\x18\x6e\x3d\x48\x02\xef\x36\xf2\x27\xcf\xb3\x01\xb2\xef\x8d\x74\xba\xc7\xda\xa7\xfc\xeb\xfc\x98\x57\xda\x7e\x31\x47\x9e\xfd\x52\x82\xf2\x54\x6d\x79\xcf\x8f\xb9\xa0\x5b\x2f\x77\x30\xf6\xbc\x9d\x5a\xd8\x3b\xc2\x8c\x39\x58\x3b\xb8\xeb\xd1\x51\x96\x16\x3a\xeb\x3f\x1d\xee\x5e\xab\xb2\xc5\x10\xaf\x47\x47\x0e\xe2\xc9\x1e\x3b\x57\xfd\xca\x97\x66\x57\x7b\x8e\x4a\x21\xe3\xe0\x3b\xb7\xd1\xda\x60\xc5\xb5\xb3\xa1\xc6\x35\xbb\xc6\x82\x86\xaa\xdb\xcf\xd4\xea\xa0\x01\x37\xde\xeb\x90\x2e\x61\x68\xaf\x43\x50\xc5\x6f\xc2\x10\xf8\x1b\x1c\x06\x1d\x77\xe0\x4d\x20\xe6\xb6\xe2\x85\xd2\x49\x03\x17\xc8\x1f\xe6\x34\xcd\x26\x70\x45\x1a\xc9\x76\xeb\xb7\x0a\x86\xdb\xe2\x18\x34\x6d\x73\x36\x3d\x53\x51\x3a\xff\xc9\xc1\xf4\xf2\x5c\x6a\x6e\x13\xc9\xca\x62\xa2\x93\x1a\x29\x11\xd4\xa2\xd6\x6e\x58\x6d\x61\x57\xd8\x06\x21\xf2\x05\xed\x59\x5b\x27\xcf\x42\x0b\x03\x73\x08\xb3\x4b\x6b\x38\x1d\xaa\x68\x8d\x6f\x8d\x33\x90\x62\x31\xa4\x50\x1d\xaf\xd9\x92\x9d\x3d\xc8\xd9\xaf\x27\x37\x71\x9d\x31\x54\x2d\xd8\xe7\x4a\x9a\xf9\x31\x63\x88\x88\x42\xf4\x41\xaf\x05\xd1\x02\x6c\x1b\x53\xe2\x33\xdb\xe2\x16\x57\x13\x00\x67\x98\x3f\xa0\xc0\xa8\x4c\xa0\x2a\x0d\xa8\x60\x67\x7b\xe9\x8c\x9a\x4e\xb9\xf5\x31\x13\xaa\xae\xaf\x21\x94\x20\x9b\x9f\x13\x8c\x95\xb4\xb4\x4e\x01\xeb\x79\xb3\x3b\x3b\x55\x46\xcb\x94\xce\x6a\x47\xf2\x47\x82\xb2\x73\x3a\x1f\xd5\x41\xfc\xbb\xcc\x81\x79\x1a\x5a\x60\x0e\xcd\x5b\x91\xbc\x05\xa4\xaa\xc3\xf6\x56\xf6\x51\xf1\xd4\xd4\xa5\x49\x9c\x92\xb7\xde\x58\x2a\x9e\xab\xf2\x5c\x50\x65\x3f\x1b\x44\xcb\x3c\x6e\x38\x4d\x48\x3b\x91\x03\x1b\xb2\x90\x48\xba\x44\xfc\xb9\x85\x6b\x33\xc1\xda\xb1\x93\x1a\x4b\x25\x51\x33\x8d\x2c\x16\x9d\x3d\xd3\xd8\x6c\xf9\xf2\xa9\x4b\x39\x1a\x66\x8a\x19\x28\xcc\x40\xc2\x3d\x19\xbd\x5f\xd0\x56\xed\x04\xd4\x00\x3d\x34\x8c\xad\x6a\x92\x36\xd5\x90\x16\x09\x38\xed\x8c\xd3\x42\x76\x40\x4a\x34\x86\xdf\x43\x64\x54\xa5\x75\x0d\xba\xc0\x7b\xd8\x4e\x4d\x97\x77\x57\xa3\x29\x59\xdc\x61\x7c\xdf\xa8\xbc\x4a\xe8\x50\x57\x15\x66\x69\x18\xdf\xff\x14\xe6\xe5\xa7\x23\x4c\x91\x80\x4c\x54\x21\x8c\xa4\xea\xd5\x6c\xa8\x50\x4f\x7e\x45\x90\x73\x75\x46\xa0\x30\x90\x4f\x54\x85\xcd\x25\xa5\x82\x0b\x06\x23\x55\xf8\xcb\x78\x52\x39\x42\x49\x81\xd4\x55\x18\xdf\xfb\xc1\x01\xa6\x2a\x45\x7d\xa2\x34\x74\x36\xc5\x8d\x12\xa5\xc0\x57\x65\x44\xf7\xc5\x42\x3e\x26\xc4\x9d\xcb\x7d\x8d\x45\x52\x6e\xb3\x9f\x15\xcc\x50\x44\x39\x16\x94\xed\x92\x08\x43\x13\x7c\x7b\x00\x8e\xf5\xad\x79\x08\x8b\x0d\x62\xe0\x8d\x3a\xe2\x04\x54\xfd\x0a\xe1\xb2\xbd\x69\xdc\xa7\xaf\x8e\x82\x20\x4b\xa8\x71\x91\xd7\x07\x91\x04\xa6\xdc\x24\xd4\x75\x60\x33\x95\x5c\xf5\x01\x41\xae\xd4\x39\x54\x05\x5f\x33\x64\x50\xda\x7a\xa5\x87\x79\x11\x71\x70\x45\x69\x78\x83\x05\x78\x66\x6a\xcc\x3e\x6f\x2e\x2e\x1e\x1a\x8f\x92\x4c\xf9\xa9\x20\x2f\x1a\xdc\xfe\xe9\x56\xe0\xad\x6f\xfa\x84\x85\x45\xa9\xbc\xb6\x90\x2b\xb7\x5c\xba\x70\x2b\x16\x65\x63\x82\x0e\xd4\x4b\xcd\x8d\x9a\x6f\x70\xa3\x64\xd9\x04\x68\xd9\x93\x54\x23\xa3\xed\xc7\x75\x02\x40\x3b\xb6\x2c\x83\x08\xaa\xd2\xc8\x24\x07\x41\xf0\xba\xd0\xa9\x14\x4a\xb9\xf2\x32\xb6\x74\xf5\xe9\x49\x3b\x41\x30\x54\x9f\x4e\xb9\x28\x09\x08\xf3\xa6\x6b\x0d\x89\x2e\xec\xd7\xad\x68\x94\x84\xb8\x29\xdc\x7e\x46\xe1\x16\x58\x40\x00\xab\xc3\x90\x7f\xc6\xc4\x57\x4b\x4f\x1d\x29\xc2\xa4\x04\xb7\x19\xa9\x29\x92\x35\x18\x01\x1f\x02\x21\x27\x75\xa5\xc0\x68\x46\xd9\x4b\xf9\x65\x2b\xaa\x9a\x4b\x73\x2c\x66\x94\x80\x1d\x8d\xd9\x03\xb0\x5b\x9b\x8e\x3a\x2a\x1d\x96\x1f\x7d\xca\x95\xe3\x9a\x45\xfd\xd9\x95\x91\x22\x84\x14\x66\x46\xe6\x4b\xab\x23\xad\xe6\x47\x02\x10\x62\x72\x23\xdf\x63\xe1\xd2\x19\x07\xe0\xfd\x1b\x5d\xd9\x5c\x55\xff\xf9\xf0\x6c\xa2\xcb\x67\x7a\xff\x8a\xb1\x7f\xc3\x05\xcc\x95\x2c\x1b\x52\x7b\xf5\x46\x3c\x73\x1e\x54\xc6\xf9\x7a\x74\x94\x1d\x57\x1a\x21\x94\x91\xda\x17\x51\xa3\x30\xc9\x55\xde\xf2\xae\x59\x2f\xca\x46\xef\xbe\x5e\x5e\x16\xd9\x78\xc0\x25\x52\x86\xdd\x71\x55\x28\x6a\x7c\x71\x2e\xb7\x96\x4d\x6b\xa6\x39\xa7\x02\xfd\xa0\xb3\x6f\x94\xeb\xcf\x14\x5c\x55\x32\x97\x86\x81\x36\x5a\x81\xc8\xdd\xdd\xf3\x90\x5c\xff\x59\x06\x92\x63\xfc\x52\xa1\xff\xbd\xfe\x21\x65\xcf\x35\x76\x0d\x19\xeb\x6f\xe0\xb8\x7e\x8a\x03\xff\x7a\xf4\xf1\x07\x5d\x2e\xca\x56\x43\x4b\xea\x46\x0d\x1a\x65\x2f\xfb\xca\xc5\xb0\x37\xeb\xd5\x1d\xae\x2e\x81\x0d\x11\x76\xee\x9e\x04\x4a\xd0\xc5\xaa\xba\xe4\x6f\x85\xc1\x34\x3b\x39\xae\xbe\xee\xe1\xcf\x52\x27\x55\xe9\xb6\x25\x7a\xe4\xd9\x3f\x09\x6f\x40\xf6\x44\x3f\x09\xa4\x52\x9f\xa5\xf5\xf6\x6a\xef\x48\x59\x86\x74\x39\xd9\x42\x4c\xd2\xe0\x81\x97\x7f\xf3\x24\x59\x3d\xdb\xef\xc1\x0e\x6e\xc3\x16\x9b\xac\x76\x23\x28\xd7\xd2\x1b\x04\x5f\x15\xed\x50\x41\x9a\x4c\x20\x42\xb2\x6c\xf3\x95\x73\x1a\x6c\xd8\x5a\x6f\xc8\x2c\x59\x76\x99\x8d\xd1\xff\x5a\x5c\x9c\x4f\xfe\xef\xf4\xec\x97\xa4\x34\x0e\x1f\x03\x1e\xfb\x1b\x00\x39\x50\x81\x0a\x8e\x6b\xc1\x28\x73\x5f\xd6\xdb\x74\x5e\x1e\x0e\x81\x9a\x6d\xdc\x4c\x5a\xd1\xc4\x77\xfa\xcd\x2b\x2f\x95\x8d\xe2\x29\xf3\x37\x58\x20\x5f\xc4\xac\x8f\xd8\x3b\x9e\xbf\x03\x59\x50\xf6\x80\xeb\xf4\xf8\xa5\xb6\xef\x89\x94\xed\xbb\x08\xa5\xd7\xde\x15\x24\xe4\xfd\x77\xdf\xfe\xe3\xdb\xaf\xaf\x47\x1f\xd5\x6d\x98\xdb\x20\xfd\xcd\xb6\xea\x77\x2b\x19\xd9\x13\x9f\xac\x38\xd5\x88\xe5\x93\x82\x72\x77\x45\x4a\x5c\x6b\x5e\x4b\xf4\x73\xaf\x9b\x88\x5d\xdd\x69\x31\x0d\x48\x75\x55\x7a\x28\x3b\xd8\x7f\xbd\xcc\x3a\xaa\x3e\xab\x6e\x74\x03\xa5\x2e\xf7\x82\x8a\x97\x2b\xbe\x99\xbf\xe3\x07\x60\x26\x54\x21\xaf\xa5\x3a\x03\x92\x1a\xff\x45\xc6\x57\x4c\x28\xf1\xde\xcc\xdf\xe5\x09\xdf\x32\x78\xf7\x01\xba\x77\x92\x69\x8b\xb6\xb4\x57\x5d\xa2\x3c\xa2\x1a\x1c\xb8\xda\x20\x10\x13\x2c\x6c\x30\xb1\x32\x70\xdf\xe0\xd7\x3d\x48\xb0\x0f\xb2\x73\x74\xb7\xc7\xf3\x77\x0f\xc2\x05\x1a\xf0\x10\x13\xaa\x21\x75\xb4\x32\x8a\x68\xd8\xe9\x2c\xae\x83\x71\xb5\x0c\x1c\x64\x6f\xa0\x35\x41\x4e\xd8\xd8\x03\x37\x6b\x55\xb7\xd4\x2a\xf5\xb0\x72\x9a\xa0\xea\x2e\xa8\x06\x0a\xc1\x38\xc2\x67\xf3\xdb\xaf\x8f\x67\x27\x97\x7d\x14\xc2\xec\xe4\x12\x30\x48\xd6\xc9\xe1\x1a\x62\x08\x7c\xb4\x65\x4a\xe6\x1f\x95\xa4\x05\x90\x73\xbc\x26\x28\x68\x27\xdc\x9d\xb0\xb5\xd0\x4d\x3a\x30\xc2\xb6\xd0\x4d\x47\xbe\x2a\xd2\x65\x10\x26\x49\x6f\x28\x37\xfb\xa6\x34\x18\xb4\x35\x93\x34\x81\x95\x63\x92\x5f\x60\x4c\xfc\xcd\x15\xda\x46\x61\x3e\x87\xb2\x62\x13\x85\x83\xe6\x5b\xa8\xbd\x19\x34\x75\x8c\xa3\x11\x03\xc2\x60\x06\x66\x27\xad\x78\xc3\xd1\xdc\x2d\x09\x7b\x57\x57\x28\xf6\x64\x20\x82\x93\x8c\x20\xce\xe6\x8f\x84\x15\xdf\x5f\x5d\x9c\x5c\xd8\xdb\x34\xc1\x5f\x4d\xeb\x31\xf8\xeb\x2f\xaa\xb2\x75\xaf\xc1\x3f\x10\x4a\x1d\x17\x51\x3e\xc2\xf8\xb6\xea\xf6\xdb\xba\xa5\x94\x63\xe1\xd2\xc5\x73\x03\xc7\xb6\xc2\x2d\xee\x5d\x8f\x6f\x07\xde\xeb\xf8\x6d\x30\x3d\x9b\x65\x2e\xa4\xd7\x31\xdd\x70\x8b\xd3\x8b\x15\xc6\xe0\x23\x8c\x05\xf5\x38\xdf\x7e\x34\xbf\x3f\x8e\xe5\x56\xe0\x23\x17\x50\x60\xbf\x9d\x01\x6c\xbb\x2f\x5f\xf0\x5a\xee\xfa\x7a\x74\x94\x41\x52\x6e\xde\x6c\x5e\xbc\x45\xa8\x50\x5b\x43\x3e\x4e\x1e\x51\x66\x9e\x6a\x34\xad\x91\xeb\x5c\x75\x70\x8b\x7f\x82\x5b\x5c\x5d\xda\xaf\xbb\x87\x45\x57\xd8\xfe\x05\x93\xf8\xfe\x65\xb9\x72\xc9\xbb\x65\x4c\x44\xfc\xf2\xc5\x8b\xaf\x6d\x85\x13\xfd\xe4\xf0\xbb\xf4\xc9\x6b\x2a\x44\x88\x18\xf5\x6f\x50\x72\xab\xff\x6f\x98\x04\xf4\x8e\x2f\x54\x2a\xe7\xcb\x17\x87\xdf\x1f\x53\xa6\x2a\x55\xab\x2b\xa5\x2b\xbf\xfa\x29\x0e\xc3\x7d\x5f\xbd\xf8\xba\x08\x6b\xd8\x62\x0b\x59\x82\x34\x2a\x81\x92\xd2\xa8\xa6\xa0\x4a\x4a\xb6\x9a\x8f\xb2\x94\xac\xf9\xac\x9e\xb8\x6d\x1a\xe6\xe8\xdd\xbc\x61\x61\x0a\x1a\xd6\x7f\xc9\x12\xb6\xc9\x5e\xae\xf2\x7b\x00\x32\x7c\xe9\x7e\x23\x09\x5d\x7c\x93\xa5\x6e\xf1\x5d\x3d\x49\xf7\x7e\x9d\xa3\xe3\x9e\xaf\x0b\xc4\xdb\xbf\x03\x85\x7c\xbd\x88\x79\x84\x48\x30\x67\xd4\x47\x9c\x3f\xf0\xdd\xdd\xb5\xd2\x19\x21\xf0\x9e\xa1\x10\xdd\x42\x22\x54\xec\x68\x40\x7d\x5e\x7f\x85\xc6\xf4\xb7\x85\xaa\x68\xfa\x93\x0d\x91\x71\x5c\x3e\x71\xc7\xbd\xa4\x2a\xbc\x17\x47\x01\x14\x48\x97\x66\x56\x97\x4f\x7c\xe5\xaf\x48\xfa\x9e\xe7\x3e\xf0\x18\x0d\x43\x4c\xd6\xfa\x99\xc7\x35\xa5\x22\x4b\xa9\x3e\x59\xec\x8f\x76\x50\xd7\xa3\xa3\xd2\x1c\x54\x27\xc3\x7f\xde\x9b\xdf\x6b\x4d\x3f\xbc\xc5\x42\xdf\x3b\xaa\x63\xe2\x6c\x29\xdc\xe9\xef\xa9\x8e\x97\x4a\x92\xfb\x30\x54\xb9\x5d\x7f\x50\x82\x3c\x78\x07\x19\xf2\xb4\x4e\xd5\x2f\xda\xcd\xaa\xee\xb6\xa4\xd1\x9b\x74\x64\x6e\x22\x2d\x61\x5b\x4d\xed\x65\x56\xca\x34\x3a\x3e\x4c\x0c\xb1\x4a\x01\x55\xed\x4d\x48\x22\x87\x57\x94\x81\x6c\xfb\x0e\x69\xa4\xcd\xa1\x3a\x07\x1e\x20\x2e\x2d\xc7\x63\x18\x41\x1f\x8b\x4a\x4b\xc5\x7a\x4b\xdc\x30\x74\x16\xf6\xec\xec\x64\x71\x7b\xd8\x27\xf1\xdf\xd8\xb1\x3c\xad\x28\x62\x4c\xf8\xa4\x3e\xa2\x2d\x52\x69\xc2\x78\x55\x97\x2f\x81\xa0\x37\x88\xb4\x23\xdb\x90\x5d\xa5\xda\x32\x35\xdb\x2b\x68\x34\xa7\x81\x04\xd4\x87\x48\x26\x91\x5a\x5d\xcb\x71\x76\xb2\x48\x07\xa0\xbc\x03\xc4\x94\x2d\xcc\x6e\x89\x23\x1a\xb4\x23\xce\x10\x5d\x34\x21\x0a\x5a\xf2\x8b\x48\xe0\x2d\xfe\x03\x55\x6e\xa2\xdb\xdc\x8c\xf3\xfe\xf4\xf5\x42\x39\x00\xb6\xe6\x5a\xbc\xbd\x2a\xee\xf4\xf8\x65\x59\x05\xa0\x25\xf7\xa8\xc5\xab\xc3\xdd\x50\x16\x9d\xc6\x3a\xa9\x21\x16\xd7\xa3\xa3\xe2\x00\x6b\x8a\xa9\xac\xe0\xa9\xbe\xc4\xb7\x0f\x65\x75\x15\x05\xe3\x83\x85\xf7\x78\x1b\x6f\x75\xfe\x3e\x0a\x32\x5e\xcc\xd3\x9f\xa6\x9e\xbd\x31\xd8\x66\xff\xf8\x90\xa9\xac\x3d\x53\xf8\x41\xdd\xa2\x84\xb9\xa9\x11\xd1\x8a\x9c\x0f\x85\x83\x9b\x6c\x0a\xc4\x09\x12\x10\x87\x28\x38\xa3\x04\x0b\xaa\x14\x69\x0f\x22\xea\x79\x50\x4e\xcd\xc0\x00\x06\xdb\x14\x72\x1b\x5a\xec\x01\xe5\x1c\x12\x86\xdb\x96\x2a\x6d\x36\x3d\xab\x00\x65\x7c\xb2\x0d\xaa\xf7\xd7\xb6\x9f\xab\x62\x50\x7d\x20\x38\x0e\xfe\x6a\x46\x56\x3a\x2e\x6c\xa6\xa7\x6d\x48\x88\x54\xa8\x4e\x97\x74\x47\x4d\xbd\x1f\x6e\xed\xd8\xaf\xf6\x07\x6d\xec\x6d\xff\xe5\xcc\xc9\x94\x0c\x10\xd8\x1b\x4a\xf2\x87\x55\x1d\xa9\x5a\x09\xce\x49\x8c\x2f\x9f\x14\xd5\xe0\xca\xa9\x0a\xaf\x35\xa8\xe6\xf4\x82\xa7\xbb\xe1\x44\x90\xb4\xb4\x42\xd1\x4b\x6a\xcc\x1f\x9b\x8a\x99\xdc\xf0\xdf\x75\x92\xba\x74\xe5\xa4\xce\x16\xde\xcf\x69\xc0\xe7\x88\x49\xb9\xd5\xc9\x70\xdd\xc2\xfb\x05\xfe\xa3\x63\x5b\x4c\x3a\xb7\xed\x7a\x51\x17\xbd\x45\x8c\xe1\x00\x25\x41\xdb\xc7\x74\xbb\x85\xa4\xcf\x01\xc4\x85\x01\x99\x94\x30\xff\x4f\x9e\x46\xd4\x47\x2a\x5d\x44\x7d\xde\x6a\xba\x13\xa0\x8e\x1a\xe6\x55\xf0\x9d\x03\x4e\x52\x88\x1b\xc6\xdf\x27\x9f\x37\x3f\xd5\x4d\xb3\x94\x75\x85\x2b\x4c\x4c\x6a\x9c\xb6\x19\xd2\x1b\x49\x78\x04\xef\xda\x9e\xdd\xf5\xec\xca\x4d\x13\x56\x9a\xff\x2f\x27\xcc\xf5\x4d\xc6\x48\x62\xbd\xa2\x0c\x15\xa6\xd6\xca\xe1\x64\x73\xd5\x25\x54\xb6\x63\x17\x15\xb4\x53\x85\xf2\xce\x93\x8d\xcb\x00\x66\xdd\x7b\x5b\x7d\x2f\xdd\x0e\xd5\xd6\xf5\x31\x9f\x7b\x26\x3d\xda\x5b\x51\xe6\x29\x0e\x86\xa1\x97\x88\x3c\x5d\xfa\xa9\x9b\xb0\x35\x78\x35\xaa\xc0\xd3\x08\x99\xeb\xd1\x51\x79\x8c\xaa\xe0\x4f\x0d\x92\x19\xfd\xa6\x36\x80\x55\xe9\x0d\x21\x82\x1c\xfd\xda\xfb\x7c\x52\x25\xc5\x9f\xcd\x92\x43\x3d\x1b\x01\xf5\x36\xd9\x2f\xa1\x40\x7d\xa0\x95\x4c\x2b\x82\xb6\x85\xed\x1c\x69\xae\xa6\x50\xc3\x9c\xcf\xc4\x20\x5f\xbc\xa9\xaa\xec\x15\xd1\x92\x6c\xec\xb2\xbf\x83\x40\x42\xea\xc8\x70\xcd\x80\x34\x63\x08\xce\x37\x6d\x69\xb3\xf8\xb9\x7e\x88\x69\x79\x6c\xce\x37\xb6\xee\x9c\x36\x32\x30\xef\x3a\xe4\xa6\x40\xdd\x83\xfc\xc2\x35\x47\xb4\x6b\xb5\xec\x22\xed\x52\xad\x74\x1f\x2c\x27\x01\x1e\x55\x95\x8e\x69\x14\x85\xd8\x94\xd7\x90\x2b\x3d\x75\x30\x83\x37\x69\xd1\x4b\x5a\x8a\xa8\xe4\xe0\x59\x52\xde\xf2\xf9\x18\x14\xc0\x48\xe9\x70\x6e\xd9\x20\xa9\xd5\x51\x03\xcb\x42\x6a\x45\xfd\x47\x8d\x7b\x83\x2d\x8e\x80\xae\x8a\xcb\xad\xea\x35\x25\x82\xe0\x0a\xe6\xaa\x46\x76\x5f\x1e\x1a\x29\x95\xc9\x11\x45\xe1\xce\x8e\xb9\x9b\xa4\xd8\x0b\xcc\x49\x17\x7d\x84\x54\x0a\x65\x6b\x42\x86\x77\xd9\xa6\x0d\x05\xe3\x86\xde\x29\xe5\xa5\x9a\x82\x04\x54\xcb\xa8\xd5\x46\x00\x9d\xc3\xbd\xa5\x61\xbc\x45\xa7\xc4\x67\xbb\x48\xec\xf7\x58\xd6\xc0\x98\x5d\xcc\x2b\xbd\xeb\xb5\x7b\x32\xdd\xfc\xed\x96\xbf\x45\xbb\xd9\x49\x97\xdd\x99\x86\xd0\xd5\x35\xa6\x5b\x37\xd9\x52\xd6\xcd\xe9\x1a\xaf\xe1\x72\x27\x5a\xfa\x50\x2a\x5a\xa5\xeb\xf7\xbb\x17\x35\x38\x5f\x6d\x18\x8d\xd7\x9b\x28\xae\xb4\x44\x1a\x10\xbe\x81\x4f\xab\x43\x98\xcc\x3a\x52\xd1\x31\x98\x83\x37\xe6\x6a\x94\x79\xcc\x22\xca\x11\x58\x2c\x4e\xc6\xfa\x8b\x57\xd5\x5f\x98\xed\x99\x09\xb6\xd6\xb6\x9e\xcd\xda\xdf\xe0\xf5\x06\x88\x64\xe8\x85\x08\x1c\x4c\x0f\x0d\x58\x95\xb3\x23\xcd\x46\x14\x00\xc9\x9c\x49\xcf\xdc\xb7\x9f\x1c\xd3\x30\x00\x3f\x9f\x98\xc7\xc2\x3e\x4e\xe9\x0a\x92\x53\x12\xf9\xd9\xb0\x81\x33\xeb\xa8\x10\x2f\x53\x45\xac\x7c\xa3\x57\x4d\x1a\x75\xa4\x5f\xb6\x27\x4c\x0f\x4b\x3d\xb9\x49\x9a\x6d\xc5\xfd\x72\xab\x94\xca\xb9\x2f\x45\xf9\xcb\x86\x84\xcf\xa8\xb7\x75\xf4\xaa\x49\x6c\xcc\x3a\x2a\x85\xc4\x14\x5b\x4a\xed\x47\x0f\x8b\x8f\xb8\x5f\x7e\x24\x1e\xe4\x7a\xa4\x34\x66\xad\xca\xf1\x5c\x1b\xa3\xe0\x30\x72\xab\xdd\xff\x55\x07\x0b\x35\xc7\xd3\x0e\x07\x9c\xc3\x9f\xe7\x16\xab\x85\x5d\x46\xd9\x17\x5c\xeb\x28\x28\x5a\xaf\x85\x03\x96\x3c\x09\x47\xd5\x1b\xbf\x6a\x0f\xe6\x9e\xe0\xa1\xaa\x73\x53\xb7\x28\x75\xeb\xa5\x1a\x95\x5b\xad\x0a\xdd\x3a\xb6\x4e\x0d\xec\xf3\x56\x35\x71\x69\x56\xc6\x17\x54\x1f\xaa\x3b\x1d\x87\xee\x23\xd1\xba\x13\xa5\xcc\xbb\xa5\x3b\xb6\xa3\xfa\x94\xb0\xf2\xb4\xa5\xb8\x67\x2f\xdb\xc0\x55\xd6\x5f\xf5\x81\x40\xb5\x1f\xc5\xbc\xe8\x17\xb1\xcf\x50\xc4\x10\x47\x44\x5f\xec\x72\xfa\x76\xe1\x65\x6b\xf2\xeb\xbd\x81\x8a\x9d\x56\x2a\x46\xda\x79\x52\xae\xcb\x6d\x45\x14\x49\x21\x8f\x91\x4e\x10\x0c\x94\x98\xbf\x53\xae\x7f\xc6\x32\x04\xde\x1f\xa3\xf1\x40\x08\xa8\xfe\x93\xc0\x6a\x24\x18\xf6\xf9\x31\x0d\xe5\xfc\xe7\xbd\x50\x15\x91\xd5\x6b\x06\x49\x1c\x42\xb9\xaa\x9b\x07\x58\x67\x1b\x75\xb9\x72\x43\xa3\xf9\xa0\x3e\x83\x8e\x3a\x24\x3b\x32\x07\xc6\x83\x30\xa3\xaa\x96\xb4\xd4\xd7\x87\xdb\x1d\xae\xde\x6f\x8c\x55\x9d\xaf\xf7\x7e\xee\xfa\xf5\xe1\x02\x1c\xd3\xe9\xf4\x20\xf7\xcc\x98\xfc\x84\x59\x0a\xe1\x21\x8d\xae\xd0\xac\x19\xc6\xa0\x61\x8c\x4d\x50\xbf\x1e\x1d\x39\x28\x57\xae\xc0\xf1\x94\x77\xf0\x94\x77\xf0\x94\x77\xf0\x94\x77\xf0\x94\x77\xf0\xf8\xf3\x0e\xea\x2c\x1a\xd0\xda\xbf\x5a\x86\xd6\xda\x9a\xd8\xb3\xb3\x79\x4a\x8b\x78\x4a\x8b\x78\x4a\x8b\x68\x38\xab\x4f\x69\x11\x8d\xc8\xd4\x33\x2d\xc2\x0f\x21\xe7\xd8\xff\x85\xc2\xe0\x35\x0c\xe5\x36\x9e\x9d\xc3\xed\x17\xe4\xb6\xa9\xb9\x00\x12\x01\x55\x87\x7a\x69\x90\xe2\xa6\xbc\x64\xac\x0a\x53\xeb\xfd\x44\xfb\x33\xaa\xd6\xc0\x2b\x68\xa6\x22\x6f\x4e\xce\x2b\x0f\x60\x1a\xd8\x9d\xef\x8f\xb5\x8d\x0c\x83\x80\x21\x5e\x7d\x43\x96\xbd\x27\x4a\xf7\xe9\x05\x84\x7b\xa6\xc9\xf3\xb4\xb2\xee\xc9\xf9\x02\x84\x94\xde\xe4\xfd\x6e\xfb\xe9\xb1\x37\x74\xa6\xba\xf7\xeb\xd1\x51\x7e\x04\x2a\x4e\xc6\x89\x91\x9b\x88\x56\xd3\x5f\xc6\x44\xe0\x5e\xd7\x0d\x65\xef\x2a\x60\x1a\x1a\x78\x76\x7c\x39\x7b\x9e\x0d\xb4\x4c\xfa\xe3\xb6\xf2\x2b\xc9\xfb\x22\xdb\xdd\x89\xd0\xb6\x1f\x37\x0d\xa2\xf8\x98\xa1\x00\x97\x0f\x86\x5b\x8c\x3e\x73\x18\xf9\xfe\xea\x15\x78\x47\x42\x29\x38\x51\xd0\x2d\x25\x64\x19\x33\x2e\xe0\x32\x44\x5e\x84\x98\xda\x2b\x13\x1f\x79\xc9\x09\xb8\x17\x5b\xf0\xde\x96\x06\x48\x3b\x05\xc6\xe0\x56\x6d\x1e\x28\x09\x77\x8a\x06\x57\x9e\xc4\x3f\x3d\x37\xef\x7a\xb8\xda\x2f\xaf\xa4\xc3\x50\xae\x47\x47\x59\x12\xea\xbd\xeb\xbe\xc1\x39\xa7\xf6\x29\xdd\xec\x29\xdd\xec\x29\xdd\xec\x29\xdd\xac\x82\xb2\x4f\xe9\x66\x4f\xe9\x66\x55\xa7\xc2\x4f\xe9\x66\xff\xa6\xe9\x66\xfc\x04\x73\xed\x18\x70\xb8\xa2\xf6\xb1\x86\x13\x86\xb3\xbb\x9b\x78\x89\x42\x24\x4e\xd5\x7d\xac\x2d\x02\xe7\x0a\xb5\x5a\x1b\x6c\x4e\xf0\x1f\x08\x7c\x34\xdd\x7d\x4c\xea\xe3\xe6\x3c\xff\xf8\x0f\x4c\xd6\x9e\xd8\x20\xcf\x7c\x37\x69\x27\xd3\x2b\x0e\x14\xca\x60\x93\xfd\x86\x44\x4a\x3b\x61\xcd\x2b\xeb\x87\x4e\x8b\xd4\xfe\xdb\x26\xc2\x3d\xa5\x7a\x3d\xa5\x7a\x3d\xa5\x7a\x3d\xa5\x7a\x3d\xa5\x7a\xfd\x1b\xa7\x7a\x3d\x50\x02\xd4\x53\xbe\xd0\x53\xbe\xd0\x53\xbe\x50\x53\xea\x3f\x6a\xdc\x3b\xe7\x0b\xb9\x57\xbc\xfe\xf6\x37\xa9\x3e\xf6\x64\x4d\x3c\x82\x84\x1f\x01\xd9\x1a\x09\x35\x07\xd3\xcb\xf3\xc7\x70\xce\xa4\x31\x32\xf6\xcb\xb0\xa7\x4c\x8d\x40\x3b\xc9\xf4\x94\x17\x55\x67\xc2\xd4\xc0\x78\xca\x8b\x7a\xca\x8b\x7a\xca\x8b\x7a\xca\x8b\x7a\xca\x8b\x7a\xca\x8b\x02\x4f\x79\x51\xe0\x29\x2f\x2a\x43\xb6\x2f\x92\x17\x95\x77\xe9\xe7\x27\xb9\x1c\x73\x9a\x79\x9f\x09\x0f\xc9\x3e\xad\x8a\xd8\xaa\x31\xb2\xcb\x1b\x8b\x2a\x53\x33\xd7\x51\x12\xe6\x54\x7f\xfa\x90\x6d\x53\x8c\xea\x31\xaf\x86\xb8\x77\x27\x7f\x8b\x65\x1a\x83\x09\xc4\x06\x0a\x75\x1f\x4c\xb2\xc7\x56\x77\x53\x96\x77\x35\xcd\xee\xe4\xe9\xde\x8f\xea\xa6\x94\x48\xf2\xda\x1d\x5b\x58\x99\x28\xa2\x79\x6b\x1a\x6c\x31\x49\xc3\xa1\xbb\x18\xc4\x36\x20\x70\xf0\xe3\xa1\xe4\x5a\x1a\x48\x76\xe0\x7d\x76\x8d\x24\x41\x88\xce\x6b\x14\xb3\x5f\x7a\x94\xe7\xfe\x9e\x7c\x95\xe9\xc4\xa3\x2b\xcf\x42\x6a\xb7\xef\xcf\xa1\x56\x7b\x47\x62\x27\x64\xae\x47\x47\xce\xe1\x16\x4e\x9d\x5a\x69\x60\xe7\x7c\xbb\xa6\x71\xc0\xb5\xa4\xbc\xca\x39\x3e\x2f\x05\x8d\x2e\xa1\xb4\xd4\x5c\x5b\xc1\x66\xcb\xa8\x53\x17\xee\x15\x34\x9b\x9e\x35\x59\x38\x50\x08\xe8\x6f\xe6\x2a\x16\xfb\xc1\x7d\x0b\xce\x15\x97\xda\x37\xea\xde\xed\xe9\xe5\x79\x9f\xf3\xe4\x4b\x3a\x08\x88\xbe\x41\x05\x12\xc6\x1c\xb1\x2d\xe6\xd2\xe4\xe6\xaf\x69\x4c\x02\xb8\xf7\x32\x3d\x27\xc8\x3b\x2c\x36\xd3\x20\xa0\x64\x6e\xef\xc0\x6c\x1d\x40\x91\x6f\xde\x71\xc9\x95\x38\xa5\x7e\x0e\x6b\xe6\xa6\x8e\xe6\x2d\x68\x59\x4b\xa3\x01\xd7\xbd\x0a\x3d\x9b\x9e\x65\xb5\x1a\x5d\x01\x98\xae\xc1\x96\x8b\x7c\x3f\xbc\xca\x15\x5d\xc5\x07\xd5\xcb\x3b\x5c\xce\xc8\x9a\x21\x5e\x19\x2d\x5b\xab\x0d\x61\x14\x9d\xa1\xf2\x21\x4a\x97\x78\xb8\x55\x1c\x86\xf6\x68\x43\x50\x30\x35\x90\x5b\x9d\x00\xd6\x83\xaa\x1b\xc1\x9c\xa1\x5b\x8c\xee\x1e\x6e\x20\xc0\xf6\x30\xdc\x80\x12\x90\xee\x81\xc5\x82\x2e\x7c\x18\xee\xb7\x73\x9a\x0c\x2a\xb9\x63\x57\xc7\xeb\xda\xd8\x75\x9b\x38\xd2\xf6\xa8\xb6\x31\x54\xe7\xd0\x7c\xc4\x84\xbe\xd1\x6c\x90\xb1\x49\xa5\x6a\xf6\xdb\xca\xf8\x0c\x02\xc0\x90\x4f\x59\xa0\x88\x7d\x49\x63\x81\xc0\x37\xaf\x00\x26\x80\x4a\xa9\xa7\x0e\x9e\x68\x78\xab\x2f\x60\x3f\x39\x5f\xbc\x38\x04\xfe\x06\x86\x21\x22\x6b\x74\x00\xce\x28\x43\x00\x93\x34\x25\xda\x38\x6a\x56\x52\x2c\x81\xf7\x1b\xc4\x50\x6a\xc7\xc9\x91\x98\xba\x04\xec\x00\x53\x15\x73\x39\xc9\x29\xf8\x09\xf4\xb7\x68\x12\x10\xfe\xe2\x70\xc2\x24\x2a\xdf\xbc\x9a\x7c\xc5\x91\xf0\xe2\xc8\x83\x1e\x86\x5b\x8f\xd1\x10\x75\x8b\xf9\xfc\x9c\x03\x2f\x9b\x8d\x43\x8d\xfd\x7a\x74\x24\x89\x5a\x1d\xa3\xa4\x52\xd4\x7f\x83\xc2\xdf\x2b\xa7\x9c\xcd\xd1\x72\xaf\x6c\x6c\xca\x65\x04\xdd\x81\xd3\xd7\x0b\x70\xbc\x98\x81\x67\xa7\x21\xe4\x02\xfb\xe0\x75\x48\xfd\x1b\xb0\x10\x92\x7c\x89\xad\xaa\xfe\x86\x6b\x04\x66\x44\x20\xb6\x82\x3e\x7a\x0e\x02\x86\x6f\x3b\x2e\xb4\xc1\x3a\x77\x53\x68\xd5\x4d\x7b\xa0\x7b\x81\x18\x81\x61\x4d\xd2\x4f\x13\x0a\xc3\xc0\x58\xc6\x16\x9e\x17\x10\x0e\x22\x46\xff\x89\x7c\x91\xdc\x0c\xae\x24\x8c\xce\xf3\x4d\x58\xbb\x15\x2d\x7b\x74\xe3\x1c\xfd\x8a\x57\x06\x95\xd6\x52\x0d\x6f\xe1\x1a\xbd\x8e\x71\x18\xf4\x13\x7f\x2a\x2c\x59\xe3\xab\xf4\xcb\xe9\xf1\x65\xca\x17\x29\x2f\x5c\xa2\x35\xe6\x82\xed\x9e\x1b\x05\x74\x00\xae\x36\x98\x03\xcc\x41\xcc\xd1\x2a\x0e\x15\x80\xa5\x44\x07\x93\xf5\x58\xfd\x65\x2e\xba\x1f\x03\x08\x8e\x67\x2a\x37\x41\x0a\x0f\xb9\xd1\x27\x08\x69\xe1\x12\xc5\x7c\x03\xd4\x48\xd4\x9f\xa7\xc7\x97\xed\xe6\xe2\x91\xe1\xee\x9c\xa8\xfb\x4b\x58\x69\xd0\x97\x67\xb8\x95\xad\x9d\xe3\x01\xb7\xd2\xaf\x58\x67\x15\x6a\xd4\x61\xd3\x55\x1b\x49\x05\xe1\x58\xe0\xe9\x82\x60\x18\x3b\x8d\xcd\x22\x99\xdc\xe2\xfa\x21\x8c\x74\x69\x21\x27\xab\xb5\xab\x65\x9e\x07\x52\x61\x8e\xef\x89\x60\xae\xba\x3d\x38\x57\xf9\xa9\x44\x81\x2a\x43\xde\x37\xce\xfc\x4b\x64\x12\x30\x87\x88\x58\xb3\x40\x01\x33\x50\x55\xcc\x5a\x5d\x82\x48\x36\x93\x18\xf9\x2f\x27\x31\x47\x6c\xad\x52\x44\x2c\x2c\xcf\xc2\x32\x89\x6e\x6a\xd5\xa9\xd2\xcf\xdd\x52\xdb\x4a\x51\x6c\x83\xa2\x77\x3d\x3a\x72\x11\x21\x09\x6a\xab\x43\xbc\x59\x64\xdb\xe7\xbb\x57\xc5\xd9\xfd\x16\xde\xcf\x19\xae\x66\x17\x9d\xb4\x52\x39\x30\x4a\x40\x80\xb6\x90\x04\x20\x52\x50\x9c\x7d\x50\x72\xa2\xbe\x79\x0d\x39\x6a\x9a\xbc\x57\xd1\xa1\xfb\xc8\xdc\x76\x30\x47\xcc\x47\x44\xc0\x35\x9a\x2e\xe9\x2d\xea\xd1\x5f\x8e\xc5\x2e\xd5\xfd\xe9\xef\x5f\x78\x87\x2f\x5e\x7c\x68\xc5\x9c\x35\x2d\xd3\x31\x1d\xbe\x70\x8f\x4a\xf2\xd6\x34\x0c\xa9\xaf\x8c\xe1\x85\x60\x50\xa0\x75\x27\x17\x91\x84\x64\xc5\xd1\x9c\xd2\x72\xc0\x7e\x07\x6a\x1c\x7a\x2f\xbb\x11\xc3\xd1\x30\xa5\xc5\xcb\xae\x0a\xb1\xaa\x5e\x5e\xc2\xdf\xfb\xf8\xb1\x25\x3b\xd5\x52\x77\xff\x24\x8e\xeb\x24\xf7\x80\x6a\xcf\xed\x30\x7e\x9f\x17\x5b\x49\x18\xb2\x7c\x9c\x26\xf3\x4e\x9a\x57\x26\xab\xeb\xac\x14\x5f\x5c\xe8\xe5\x7a\x74\x94\x47\xa7\xa6\x7e\xd8\xe2\x4d\x33\xaf\x96\x72\x45\xce\x4e\xbe\x5c\x24\x9c\xc6\x00\x71\x90\x4e\x1d\xb0\x67\xd6\x3a\x44\x8d\xf7\x0b\x14\xec\xd4\x81\x53\x38\xdc\x61\xb1\xf9\x85\xfa\x30\xec\xb5\x99\x50\xe8\x00\x58\xc0\x01\x48\xc6\x0f\x35\x22\xd9\x48\x65\x70\x4e\x85\xbd\x35\xdf\x84\xae\x94\xaa\x33\xb6\x33\x03\x1e\x1e\x81\x54\x48\x09\x16\xbb\x73\x84\x25\x29\x17\x1b\xc8\xfa\xe5\xb1\x9a\xa1\xa8\x2a\x7f\xf9\xc1\x70\x05\x1b\xc0\x2d\x25\x6b\x65\x8c\xa6\xb8\xea\x84\xd1\x6e\x99\x13\xc3\x77\x58\x45\xab\x56\x32\x3d\x5d\xc5\x6e\x12\x3b\x79\x78\x10\xd9\xe9\x53\x22\x18\x0d\x79\x69\x45\xd5\x04\xf2\x37\x39\x44\x6d\x0a\xb3\x42\xf8\x2d\x7e\x6e\xe6\xd2\x0f\x69\x2f\x47\xf6\x6c\x05\xa4\xc6\xba\x93\xfb\x64\x39\x7d\x6a\x9a\x17\x8b\x9f\x0b\xb2\x3d\x62\xf4\x16\x07\x28\x30\xdb\xe9\x60\x0c\xa8\xd8\x20\x76\x87\x39\x02\x58\xc8\xa7\x78\x4d\x28\x43\xc1\x01\xb8\x20\xe1\x0e\x50\x82\x00\x5d\x81\x79\xbc\x0c\xb1\xff\x16\xed\xe6\x50\x6c\xc6\xe9\x9f\x2a\xe0\x3b\xf9\xeb\x1c\x6e\x91\x75\x20\x26\x11\xb0\xed\x72\xaa\x1e\xf1\x30\xdc\xde\x30\xb5\x91\x59\xf0\x52\x02\x74\xfb\x9d\x5b\xc9\xb5\xfb\x5e\x8e\x9b\x12\x41\x4d\xee\x44\xcc\x31\x59\x83\xc5\xe2\xec\xc3\xb3\x09\x96\x7c\x19\xc4\x2a\x52\xe6\x2b\xce\x37\x9e\xf6\x95\xb4\x73\x29\x57\xf4\x9b\xd1\xfd\x15\xdd\x5c\x8f\x8e\xaa\x70\xab\xf6\xe8\x46\x96\xbe\x3d\x82\x5b\xf5\x1c\x81\x1b\xa4\x10\x5d\x22\xa9\x48\xd3\xa4\x04\x8d\x8a\xc4\xec\x06\xed\xfc\x0d\xc4\xe4\x00\x64\x19\x4a\x89\x0f\xbd\x6c\x6f\x61\x18\xa3\x2c\x9f\xb4\x22\xdc\x03\xa2\x51\x4f\xba\x06\x27\xd8\x0d\xc9\x47\x24\x93\x63\xa2\xd2\x34\x1e\x09\x29\x1f\x12\xa5\x7a\xb2\x4a\x71\xd0\x83\xac\x57\x1b\x04\x22\x28\x36\x16\x53\x89\x63\xd4\x8b\x45\x8c\xe8\x4b\x86\x62\x54\xb3\xb2\x0e\xaf\x47\xff\x6f\x72\xc0\xf9\x66\x82\x83\x7f\x30\x0e\x0f\xa2\x78\x79\x3d\xca\x0a\x40\xd9\x41\xbf\x49\xf9\xbc\x03\xd2\x51\xc7\xa5\x41\xe9\xc7\xfb\x07\xe6\xde\x3c\xab\x7c\xa4\x45\x36\xe0\x74\xf6\xc0\x99\xb4\x5d\x0d\x26\xa5\xf9\x2b\xb9\xd2\x29\x40\x2b\x45\xc3\x7e\x0a\x38\x75\xd7\x80\x7b\x57\x69\x6f\x2a\x9b\x34\xcd\x79\xcc\xab\x6e\x15\x29\xd8\x27\xca\xa2\x0d\x74\xb7\x4d\xa6\xaf\x8d\x6a\x12\x80\xb8\x5a\x21\xbf\x61\x7a\xfa\xcd\x77\xfc\x00\xd3\x4f\x30\xc2\x9f\x7c\xca\xd0\xa7\xdb\xc3\x03\xd5\xcf\xa9\x86\xe1\xe4\xd2\x9b\xbd\xca\xd0\xd9\x4c\xad\x81\xc6\x0d\x5b\x71\xe3\x4d\x9e\xbb\x74\x4f\xe3\x12\x45\x06\x61\x98\x6c\xb1\x7f\xf0\x36\x5e\x22\x46\x90\x8a\x2e\x55\xd3\xd3\x94\x31\xea\xa1\xb8\x19\xe0\x9d\x3b\xa7\xac\x92\x0f\xb6\xf0\xfe\x1d\x31\x21\xfe\x61\xaf\xac\x24\x8e\x44\x52\x67\x28\x53\x5b\xc8\x24\xc7\x6e\xa0\x30\x86\xa7\x4f\xb7\x08\xc4\x69\x9f\xe0\x6e\x83\x88\x4e\x22\x93\x86\x56\x26\xd6\x16\x3c\xb3\x75\x08\x02\x00\xb9\x81\xd9\xce\x0e\xfc\x6c\x48\x39\xb9\x39\x4f\xdc\xd4\x7d\xf7\xa8\xc9\x1c\x25\x68\x3e\x32\x52\x67\x11\xeb\x28\x03\x0a\xdc\xde\x64\xaa\x06\xdb\xc0\xab\x88\x65\xb7\x4b\x32\x19\x7c\x97\x48\xdc\x2e\xb0\x73\xb2\xe3\x62\x76\x72\x3c\x0b\x10\x11\x58\xec\xe6\x7a\xf7\xc9\x1a\x5e\x8c\x90\x3d\x37\xe2\x3c\x46\xec\xdd\xe5\x2f\xf9\xb3\x53\x8c\x88\x98\x9d\xb4\x38\x37\xb4\x2d\x3a\x28\x0f\xed\xc0\x38\x0e\x21\xae\xdc\xb3\xee\x6f\xde\xa3\xbc\x56\x42\x81\x0e\x8d\xbb\x96\xd6\xb1\x93\xa3\x46\xfd\xb8\x0b\x1f\x7d\xe9\xba\x07\x7b\x11\x8c\x39\x62\x72\x1e\x3a\x73\x90\x05\xd0\x92\x87\x5a\x89\xb0\x76\xeb\xae\x72\x74\xd5\x58\x57\x2c\xa8\xaa\x85\x52\xcd\x8b\xc5\xa9\x1f\xd0\x14\x57\x86\x72\x84\x7c\x15\x88\x4c\x80\x94\x60\xd6\x71\xc6\xb2\x85\x7a\x4f\xdf\x2e\x00\x8c\xc5\xe6\x0f\xd2\xe1\xe8\xa8\x65\x07\x79\x99\x1a\x21\x06\xf3\x25\xf6\xaa\x1d\xa4\x09\x19\x7e\x0a\xe3\xfb\x29\x2b\xaf\x92\xcf\x57\x30\x21\x3d\xbc\xf1\x75\x8a\x1e\x08\x31\x41\x00\xb2\xb5\xca\x18\xb2\xde\x61\x04\x24\xaa\x20\x80\x68\x4b\x09\x38\x39\x9d\x5f\x9e\x1e\x4f\xaf\x4e\x4f\x5a\x19\x0c\xbd\x3b\x73\xae\xc1\x94\x9a\x3f\xa3\x70\x6b\xe7\xe1\xdf\x84\xaa\x12\x65\x60\x71\x7e\x78\xba\x56\x76\xe7\xa4\xac\x04\x86\x85\xfd\xfc\x0c\x12\xbc\x42\xbc\xba\xac\x75\x13\xf7\xf0\xb1\x02\xa9\x7c\xd4\x2a\x8a\x4d\x4d\xf4\xd6\x42\xb6\x1e\x98\x37\x58\x80\x4b\x14\x51\x40\x89\x3e\x95\x0d\xc3\xae\xb4\x19\xa4\x43\x27\x75\x54\x7a\x71\x0f\x4f\x9b\xec\x53\xc1\x90\x48\xdc\x20\x14\x01\xc1\xa0\x7f\x23\x05\x90\x44\xf2\x3f\x39\xe0\x3b\xe2\x4b\x21\xa4\x22\xd6\xfe\xae\x5d\x4e\x98\x03\x29\x74\x6f\x61\x88\x88\x90\x2d\x4d\xaa\xad\x34\xf8\x3c\x6f\x8d\x85\x27\x5b\x79\x02\xae\xd5\x98\xf5\x23\x42\x05\xe2\x1e\x43\x2b\x80\x89\xa6\x40\x47\x6a\x3e\x16\x9c\x2b\x2d\x2a\x1e\xc1\xea\x50\xa2\x06\x93\x72\xac\x0f\x13\x41\x02\x4b\x6e\x56\x98\xaa\x6b\x6d\xf9\x42\xe1\xa2\xaf\xe5\x2b\x2e\x28\x74\xb0\x3e\x00\xab\x1e\xf4\x7d\x80\xee\x2b\x8c\x48\x18\x5c\x90\xea\x2b\xb6\x1a\x9d\xd2\x11\x2e\x58\xec\x0b\x8d\x91\xa0\x40\x02\xf5\x54\x45\xf5\x2d\x0d\x74\xfd\x24\x5d\x8d\x58\xa1\x1a\xa0\x28\xa4\x3b\xe5\x73\x85\x3c\xf3\x6d\x47\x4a\x3d\x70\xef\xcd\x42\xe7\xee\xb0\xd8\xc8\x29\xe8\x4b\x46\xeb\x0a\x1c\x44\x1b\x34\x02\xd8\xd1\x16\xad\xd2\x08\x25\xb1\xe8\x5c\x96\x2e\xca\xb9\x98\xd2\xa9\xdc\x13\x53\xa9\x99\xea\x1f\xc4\xf6\x34\x07\xe4\x92\x9a\xf9\x7d\xb6\xad\x49\xcc\x50\x08\x45\x7a\x72\x40\x2d\xa5\xd5\x8d\x19\x89\x88\x4c\x83\x14\x92\x85\x2b\x05\x29\x43\x11\xe5\x58\x50\xb6\x93\x22\x4e\x8a\xc0\xe6\x3e\x80\xcf\x8f\x59\xce\xda\x9d\x3b\xca\x9d\xd6\x5c\x1d\x4a\xe3\xa8\x55\xbe\x6a\x2b\x9e\x4c\xc1\x0f\x32\xe7\x69\x25\xd4\x72\x15\xd4\x24\xb5\xa8\xf1\x3c\x35\x83\x96\xa7\xad\x2e\x52\x62\x54\x41\xbb\xfd\xc4\x29\x09\x22\x8a\x89\x58\xe8\xeb\x18\x3a\x5a\xc0\xe3\xfc\x5b\x67\xd5\x1b\x1b\x27\x5f\x26\x49\x8a\x56\x1a\xeb\x5c\x7e\x19\xd2\x35\x1f\xe5\x1e\x7e\x18\xc0\xf0\x4e\xc9\x9d\x89\x4a\x43\x86\x28\xf6\x92\x0a\xe3\x9c\xdc\xc6\x5c\x80\x25\x02\xb6\x0e\xbe\xb4\x91\x6d\xf5\x50\x9b\xad\xa1\xcb\x2c\x21\x22\x98\x82\x69\xea\x4f\xe5\x07\x6e\xaf\x6e\xcc\x0c\xd7\x3e\x92\x83\x6c\x7d\x67\xe3\x67\x18\x43\xb6\x54\x52\x7e\x30\x35\xf7\x22\x66\xc6\x57\xf3\x95\x1c\x72\xe1\x8e\x44\xa7\xea\x44\xfd\xaf\x5b\xb0\xb9\x65\x4a\xcd\x2b\xd9\xb7\x02\x50\xa5\xe3\xec\x6c\xb9\xd8\x6e\x75\x7c\xbb\xc2\xad\x31\x1a\x5a\x49\x34\x54\x2e\x67\x53\xb3\xc4\x07\x91\x7a\xd9\x5b\x90\xca\x2e\xe5\x7d\xa3\x6f\x73\xc7\x52\x73\xe8\x05\xa9\xa8\x12\xf7\x9b\x88\x43\x1a\x8b\x28\x16\x3d\xe3\x20\x2e\x14\x10\x10\x60\xa6\xca\x07\xed\x92\x2d\xb4\xbd\xf9\x2f\x90\xbf\x24\x4a\x40\x98\x1b\xcd\x39\x78\xb6\x56\xd5\xd2\x04\x4a\xde\x99\xfd\x78\xbb\x83\x95\x07\xed\x3b\xc3\xa4\x07\x93\x1f\xff\x15\x63\xff\x86\x0b\xc8\x84\x27\x95\xbe\x27\x8d\xb5\x8a\x98\x27\x86\x74\x79\xb6\x1e\x44\xa5\x2b\x35\x8c\xff\x2d\x3b\x05\x0b\xd9\xab\x45\xf6\x00\x1c\xeb\x20\x35\x08\x96\x0c\x12\x7f\x33\x06\x72\x3b\xa8\xae\xde\x52\x1b\xf8\x0d\xe4\x9b\x8c\x01\xdb\x4e\xa4\x0e\xd9\xaf\x93\x36\x3a\x40\xa1\x07\x65\x54\x9c\x1e\x65\xe0\xdd\xe5\x2f\xa0\x1a\xdb\x56\x83\xee\x02\xd2\x24\x1f\xf2\x72\x91\x3b\x18\x45\x5e\x80\x6e\x87\x28\x4e\x67\x88\xe5\x62\xad\xb1\x73\x15\x0f\x6d\xcb\xeb\xcb\x60\xd4\x5d\x37\x10\xa4\x2b\x20\x5d\x54\xd4\x28\x54\x7b\xd9\x5b\xd6\x46\x86\x41\x90\xf5\x1a\xa5\xa6\x72\x27\xe3\xfd\xa1\x50\xc9\xc9\xce\x4b\x14\xd1\x26\x82\x53\xaf\x80\x9e\xc1\x63\x6b\x2c\xcc\x52\x02\x31\x09\x10\xb3\xd5\x22\x0d\xde\x05\xf1\x8f\xa5\xa2\xbd\xc3\x61\xa8\x03\x54\xe5\x92\x93\xbb\x96\xff\x50\xce\x3a\x14\x8c\xb5\x4f\x63\x0b\x55\xdb\x8e\x1b\xe2\xe1\xb0\x82\xdb\xe8\xef\xfb\x30\x73\x5b\x3b\x5b\x88\xfb\xfa\x0a\x15\x0c\x83\xb7\xc5\xcd\xee\xe6\x8c\xb0\xf2\x37\x90\xac\x11\xef\xe3\xdd\xeb\xd6\x8b\x73\xd0\xab\x30\xbe\x1f\x20\x1a\x31\x55\x83\xd9\x99\x53\x6e\x9f\xba\x69\xbb\x63\x72\xd2\xc8\x38\xf5\x8a\x4d\xfa\x30\xd0\xc3\x60\xe1\xa4\x5b\x04\xc5\xe6\xcb\x9d\x5d\x5c\xa2\x10\x0a\x7c\xab\x83\x26\xf5\x1d\xaa\x26\xd1\xa2\xe0\x19\xd0\x14\x30\x2f\x2e\x22\x9e\xfa\x18\xd4\xe0\xcd\x45\x5b\x92\x6f\x56\x98\x04\xd9\x70\xa6\x9c\xfb\x5d\x95\x19\x37\xf4\x79\x7f\xad\x2a\x11\x7a\x7c\xc7\x05\xda\x5e\x8f\xc6\xe0\x7a\xb4\x84\x1c\x5d\x8f\x3e\x74\x9d\xbb\x2f\x3a\x1c\xbd\x11\xca\x0c\xc9\xc6\x81\xea\xff\xe5\xd0\xf4\xaf\x0f\xfb\x99\x42\x1b\xc7\x8b\xc5\xcf\xfd\x63\x7c\xe7\x99\x70\x58\x6b\x74\x9b\x70\x57\x7b\xd4\x29\x47\x12\x8b\x0d\x22\x02\xfb\xf2\x75\x47\xea\xf7\xeb\xc9\x49\x88\x98\xf5\x11\xa4\x57\x66\xe2\x25\x12\xd2\x30\x32\xb8\x95\xf8\x40\xcd\xb9\x09\xb4\xc9\xe9\xdd\xdc\x62\x6f\x2d\x45\x1e\xaa\xeb\x6a\xbb\x6d\x8d\xc5\xff\x4c\xeb\x23\xfe\x40\xd9\x7a\x22\x7b\xac\xb0\xe3\x0a\x41\x02\x3d\x35\x96\x04\xf1\xe0\x0a\xab\x53\x27\x1d\x2d\x57\xc9\x7b\xe3\x92\xbd\x54\x12\xdd\x2e\x1d\x58\xa4\x6c\xc9\x38\xa8\x5d\xeb\x43\x5b\xc0\x7b\x7d\xc6\xb0\x28\x1e\x93\x3b\xa0\xb5\x74\x7c\x18\x4f\xf5\xfe\x5e\x73\x76\xed\x02\xf9\x0c\x09\x6e\xaa\x1d\x37\x2a\x6e\x71\x83\x76\xd3\xcb\xf3\xe6\xd1\x69\xe6\xfb\x87\x8a\x4f\x76\xe2\x32\xbc\xff\xe6\xed\xd9\x02\xa0\x84\x4a\x49\x5c\xcb\x40\xfe\x9b\x2a\xe8\xb9\xb9\xfa\x0d\x85\xe1\x5b\x42\xef\xda\x15\x07\x1c\xa4\x84\x9c\xaa\x9b\x94\x2b\x8f\x54\xae\xf3\x76\x00\x16\x08\x81\xf7\xe9\x03\x30\xfd\x6d\x01\x02\xea\xf3\xfa\x72\x23\xe8\x86\xdb\xcb\x68\x33\xa5\x3c\xca\xe0\x55\xa5\x91\x76\x4e\x8b\xe6\x68\x37\x2b\x3d\xd2\x06\xd5\xeb\xd1\x91\x83\x14\x3f\x4e\xe0\x51\x75\xb5\xfc\x9a\x73\x52\x78\xc7\xb3\x95\xad\x8f\x75\x26\xea\xe0\xd3\xaa\x13\xf7\x54\x06\xe0\x1d\xf7\x42\x0a\x03\xcf\x54\x34\x60\x9e\x9f\xf4\x69\xa6\x5a\x22\x04\x2c\x46\x5d\x67\xba\xb6\x9f\x41\xe6\xbc\xcd\x98\x7a\xf0\xc1\xde\x81\x5c\x8f\x8e\xca\x14\xeb\xcc\x10\x03\x15\x50\x54\xe4\xca\x96\xf1\x4b\x68\x67\x26\x39\xf7\x2e\x3f\xc7\x9d\xaa\xff\x75\x99\xce\x1a\xfc\x06\xaa\x49\x78\x3d\x3a\x2a\x0d\xb4\xf3\xd4\xa0\x25\x3f\x5e\xcc\x1e\x7e\x89\xa2\x25\xf7\x7c\x8e\xcb\x0b\x53\xb2\xa2\x7d\xa9\x8b\xfe\x15\x66\x2e\x53\xee\xfb\x26\xd9\x85\x79\x1c\xaf\xf9\xa4\xdc\xd6\x96\x6b\xd4\x7f\x79\x51\x52\xa6\x77\xc0\x95\x59\x35\x94\xda\x4a\xe5\x3d\x50\x97\xd2\xd9\x4d\xa4\xee\xb3\xbe\xfa\x4c\xb3\xbe\xaa\x9b\xf5\x55\xcd\xac\x17\xa4\xd8\x32\xa4\x6b\xb5\x32\x74\xa5\x3d\x9e\xa4\x77\x63\xb2\x4e\x01\xed\x08\xdc\x62\xdf\x8b\xec\xd5\x32\x98\xac\x87\x9c\xf7\x8a\xc1\x94\xe7\x7d\x28\xe4\xed\xcc\x97\x09\xd5\x7d\xe6\x07\xac\x81\x99\x2f\x4c\x59\x53\x90\xd2\x4c\x7a\xee\xfb\xc6\x8b\x3c\xdb\x4a\x92\x72\x39\xd1\x5e\x58\x2d\x2c\x45\x2c\x28\xc3\x30\x54\x2b\xea\x60\x1b\x74\x99\xef\x96\xe3\x68\xb5\xce\xdb\x61\x7f\x3d\x3a\x2a\x11\xa9\xf3\x54\x7f\xe9\xc2\x9d\xed\x26\x62\x90\x4e\x86\x3a\x92\x6f\x57\xef\xb2\xda\xde\xad\x58\x78\x15\xa6\x51\x9d\x5a\xae\x13\xde\x83\x6c\x29\xd5\xd1\xbc\xaa\x80\x23\xe5\x9d\x4f\xb7\x5b\x4a\xd2\x82\xd9\x6d\x6a\x57\xee\x87\x94\xdb\x2a\xa6\x8b\xe7\xd3\x1d\x82\xb7\xe8\x8e\xb2\x1b\xfe\x49\xdf\xcd\xfd\x29\xba\x59\x7f\x8a\x05\x0e\xf9\x27\x1c\x11\x24\x0e\x66\xf3\xf3\xfc\x05\x2c\x15\x3e\xaa\x12\x0f\x13\x30\x9b\x03\x18\x04\x0c\x71\x55\x4a\xe8\x78\x76\x72\x09\x08\x15\xed\xe2\xbb\xf6\x80\xc9\x8d\x6b\x4f\x56\x75\xf5\x18\x72\x50\xf2\xf7\x82\x66\x1a\x95\x4f\x08\xf6\x5d\xbc\x70\x95\xa6\x15\x67\xd7\x81\xfb\xac\xa0\x94\x97\x03\x49\x10\x22\x0e\x62\xb2\x85\x8c\x6f\x60\xa8\x2e\xbf\x5c\x52\xb1\x01\x5b\x18\xbd\xd7\xa8\x7f\xd0\xff\xa9\xd3\xca\xf7\x1f\x0a\x1d\x37\xa5\x71\xff\x9e\xfe\x62\x17\xfc\x9f\x7f\xf9\xf3\x2f\xff\x3f\x00\x00\xff\xff\x2a\x17\xcc\xa5\x1d\x59\x01\x00") + +func schemaJsonBytes() ([]byte, error) { + return bindataRead( + _schemaJson, + "schema.json", + ) +} + +func schemaJson() (*asset, error) { + bytes, err := schemaJsonBytes() + if err != nil { + return nil, err + } + + info := bindataFileInfo{name: "schema.json", size: 0, mode: os.FileMode(0), modTime: time.Unix(0, 0)} + a := &asset{bytes: bytes, info: info, digest: [32]uint8{0x7b, 0xec, 0xac, 0xa, 0x8e, 0x25, 0x3b, 0x1, 0x19, 0x5f, 0x34, 0x5a, 0x9c, 0xc6, 0x85, 0x5f, 0xe8, 0x92, 0xa4, 0x32, 0x70, 0xaa, 0x45, 0x3e, 0x7b, 0xc4, 0x60, 0x90, 0x63, 0x92, 0xfb, 0x80}} + return a, nil +} + +// Asset loads and returns the asset for the given name. +// It returns an error if the asset could not be found or +// could not be loaded. +func Asset(name string) ([]byte, error) { + canonicalName := strings.Replace(name, "\\", "/", -1) + if f, ok := _bindata[canonicalName]; ok { + a, err := f() + if err != nil { + return nil, fmt.Errorf("Asset %s can't read by error: %v", name, err) + } + return a.bytes, nil + } + return nil, fmt.Errorf("Asset %s not found", name) +} + +// AssetString returns the asset contents as a string (instead of a []byte). +func AssetString(name string) (string, error) { + data, err := Asset(name) + return string(data), err +} + +// MustAsset is like Asset but panics when Asset would return an error. +// It simplifies safe initialization of global variables. +func MustAsset(name string) []byte { + a, err := Asset(name) + if err != nil { + panic("asset: Asset(" + name + "): " + err.Error()) + } + + return a +} + +// MustAssetString is like AssetString but panics when Asset would return an +// error. It simplifies safe initialization of global variables. +func MustAssetString(name string) string { + return string(MustAsset(name)) +} + +// AssetInfo loads and returns the asset info for the given name. +// It returns an error if the asset could not be found or +// could not be loaded. +func AssetInfo(name string) (os.FileInfo, error) { + canonicalName := strings.Replace(name, "\\", "/", -1) + if f, ok := _bindata[canonicalName]; ok { + a, err := f() + if err != nil { + return nil, fmt.Errorf("AssetInfo %s can't read by error: %v", name, err) + } + return a.info, nil + } + return nil, fmt.Errorf("AssetInfo %s not found", name) +} + +// AssetDigest returns the digest of the file with the given name. It returns an +// error if the asset could not be found or the digest could not be loaded. +func AssetDigest(name string) ([sha256.Size]byte, error) { + canonicalName := strings.Replace(name, "\\", "/", -1) + if f, ok := _bindata[canonicalName]; ok { + a, err := f() + if err != nil { + return [sha256.Size]byte{}, fmt.Errorf("AssetDigest %s can't read by error: %v", name, err) + } + return a.digest, nil + } + return [sha256.Size]byte{}, fmt.Errorf("AssetDigest %s not found", name) +} + +// Digests returns a map of all known files and their checksums. +func Digests() (map[string][sha256.Size]byte, error) { + mp := make(map[string][sha256.Size]byte, len(_bindata)) + for name := range _bindata { + a, err := _bindata[name]() + if err != nil { + return nil, err + } + mp[name] = a.digest + } + return mp, nil +} + +// AssetNames returns the names of the assets. +func AssetNames() []string { + names := make([]string, 0, len(_bindata)) + for name := range _bindata { + names = append(names, name) + } + return names +} + +// _bindata is a table, holding each asset generator, mapped to its name. +var _bindata = map[string]func() (*asset, error){ + "schema.json": schemaJson, +} + +// AssetDebug is true if the assets were built with the debug flag enabled. +const AssetDebug = false + +// AssetDir returns the file names below a certain +// directory embedded in the file by go-bindata. +// For example if you run go-bindata on data/... and data contains the +// following hierarchy: +// data/ +// foo.txt +// img/ +// a.png +// b.png +// then AssetDir("data") would return []string{"foo.txt", "img"}, +// AssetDir("data/img") would return []string{"a.png", "b.png"}, +// AssetDir("foo.txt") and AssetDir("notexist") would return an error, and +// AssetDir("") will return []string{"data"}. +func AssetDir(name string) ([]string, error) { + node := _bintree + if len(name) != 0 { + canonicalName := strings.Replace(name, "\\", "/", -1) + pathList := strings.Split(canonicalName, "/") + for _, p := range pathList { + node = node.Children[p] + if node == nil { + return nil, fmt.Errorf("Asset %s not found", name) + } + } + } + if node.Func != nil { + return nil, fmt.Errorf("Asset %s not found", name) + } + rv := make([]string, 0, len(node.Children)) + for childName := range node.Children { + rv = append(rv, childName) + } + return rv, nil +} + +type bintree struct { + Func func() (*asset, error) + Children map[string]*bintree +} + +var _bintree = &bintree{nil, map[string]*bintree{ + "schema.json": {schemaJson, map[string]*bintree{}}, +}} + +// RestoreAsset restores an asset under the given directory. +func RestoreAsset(dir, name string) error { + data, err := Asset(name) + if err != nil { + return err + } + info, err := AssetInfo(name) + if err != nil { + return err + } + err = os.MkdirAll(_filePath(dir, filepath.Dir(name)), os.FileMode(0755)) + if err != nil { + return err + } + err = ioutil.WriteFile(_filePath(dir, name), data, info.Mode()) + if err != nil { + return err + } + return os.Chtimes(_filePath(dir, name), info.ModTime(), info.ModTime()) +} + +// RestoreAssets restores an asset under the given directory recursively. +func RestoreAssets(dir, name string) error { + children, err := AssetDir(name) + // File + if err != nil { + return RestoreAsset(dir, name) + } + // Dir + for _, child := range children { + err = RestoreAssets(dir, filepath.Join(name, child)) + if err != nil { + return err + } + } + return nil +} + +func _filePath(dir, name string) string { + canonicalName := strings.Replace(name, "\\", "/", -1) + return filepath.Join(append([]string{dir}, strings.Split(canonicalName, "/")...)...) +} diff --git a/pkg/apis/eksctl.io/v1alpha5/types.go b/pkg/apis/eksctl.io/v1alpha5/types.go index 602c676716..99bf3ba3f1 100644 --- a/pkg/apis/eksctl.io/v1alpha5/types.go +++ b/pkg/apis/eksctl.io/v1alpha5/types.go @@ -8,6 +8,8 @@ import ( "strings" "time" + "github.com/aws/aws-sdk-go/service/cloudwatchlogs/cloudwatchlogsiface" + "github.com/aws/aws-sdk-go/aws/client" "github.com/aws/aws-sdk-go/aws/session" "github.com/aws/aws-sdk-go/service/autoscaling/autoscalingiface" @@ -599,6 +601,7 @@ type ClusterProvider interface { SSM() ssmiface.SSMAPI IAM() iamiface.IAMAPI CloudTrail() cloudtrailiface.CloudTrailAPI + CloudWatchLogs() cloudwatchlogsiface.CloudWatchLogsAPI Region() string Profile() string WaitTimeout() time.Duration diff --git a/pkg/apis/eksctl.io/v1alpha5/validation.go b/pkg/apis/eksctl.io/v1alpha5/validation.go index 30b2f61775..416a38fe65 100644 --- a/pkg/apis/eksctl.io/v1alpha5/validation.go +++ b/pkg/apis/eksctl.io/v1alpha5/validation.go @@ -118,18 +118,8 @@ func ValidateClusterConfig(cfg *ClusterConfig) error { } } - if cfg.HasClusterCloudWatchLogging() { - for i, logType := range cfg.CloudWatch.ClusterLogging.EnableTypes { - isUnknown := true - for _, knownLogType := range SupportedCloudWatchClusterLogTypes() { - if logType == knownLogType { - isUnknown = false - } - } - if isUnknown { - return fmt.Errorf("log type %q (cloudWatch.clusterLogging.enableTypes[%d]) is unknown", logType, i) - } - } + if err := validateCloudWatchLogging(cfg); err != nil { + return err } if cfg.VPC != nil && len(cfg.VPC.ExtraCIDRs) > 0 { @@ -160,6 +150,33 @@ func ValidateClusterConfig(cfg *ClusterConfig) error { return nil } +func validateCloudWatchLogging(clusterConfig *ClusterConfig) error { + if !clusterConfig.HasClusterCloudWatchLogging() { + return nil + } + for i, logType := range clusterConfig.CloudWatch.ClusterLogging.EnableTypes { + isUnknown := true + for _, knownLogType := range SupportedCloudWatchClusterLogTypes() { + if logType == knownLogType { + isUnknown = false + } + } + if isUnknown { + return errors.Errorf("log type %q (cloudWatch.clusterLogging.enableTypes[%d]) is unknown", logType, i) + } + } + if logRetentionDays := clusterConfig.CloudWatch.ClusterLogging.LogRetentionInDays; logRetentionDays != 0 { + for _, v := range LogRetentionInDaysValues { + if v == logRetentionDays { + return nil + } + } + return errors.Errorf("invalid value %q for logRetentionInDays; supported values are %v", logRetentionDays, LogRetentionInDaysValues) + } + + return nil +} + // ValidateClusterEndpointConfig checks the endpoint configuration for potential issues func (c *ClusterConfig) ValidateClusterEndpointConfig() error { if !c.HasClusterEndpointAccess() { diff --git a/pkg/eks/api.go b/pkg/eks/api.go index 2cfee9c18d..438fbe9c23 100644 --- a/pkg/eks/api.go +++ b/pkg/eks/api.go @@ -6,6 +6,10 @@ import ( "os" "time" + "github.com/aws/aws-sdk-go/service/cloudwatchlogs" + + "github.com/aws/aws-sdk-go/service/cloudwatchlogs/cloudwatchlogsiface" + "github.com/aws/aws-sdk-go/aws" "github.com/aws/aws-sdk-go/aws/client" "github.com/aws/aws-sdk-go/aws/credentials" @@ -82,7 +86,8 @@ type ProviderServices struct { ssm ssmiface.SSMAPI iam iamiface.IAMAPI - cloudtrail cloudtrailiface.CloudTrailAPI + cloudtrail cloudtrailiface.CloudTrailAPI + cloudwatchlogs cloudwatchlogsiface.CloudWatchLogsAPI session *session.Session } @@ -125,6 +130,11 @@ func (p ProviderServices) IAM() iamiface.IAMAPI { return p.iam } // CloudTrail returns a representation of the CloudTrail API func (p ProviderServices) CloudTrail() cloudtrailiface.CloudTrailAPI { return p.cloudtrail } +// CloudWatch returns a representation of the CloudWatch API. +func (p ProviderServices) CloudWatchLogs() cloudwatchlogsiface.CloudWatchLogsAPI { + return p.cloudwatchlogs +} + // Region returns provider-level region setting func (p ProviderServices) Region() string { return p.spec.Region } @@ -189,6 +199,7 @@ func New(spec *api.ProviderConfig, clusterSpec *api.ClusterConfig) (*ClusterProv provider.ssm = ssm.New(s) provider.iam = iam.New(s) provider.cloudtrail = cloudtrail.New(s) + provider.cloudwatchlogs = cloudwatchlogs.New(s) c.Status = &ProviderStatus{ sessionCreds: s.Config.Credentials, diff --git a/pkg/eks/tasks.go b/pkg/eks/tasks.go index 48ff4d7145..0d10e45c16 100644 --- a/pkg/eks/tasks.go +++ b/pkg/eks/tasks.go @@ -5,6 +5,9 @@ import ( "fmt" "time" + "github.com/aws/aws-sdk-go/aws" + "github.com/aws/aws-sdk-go/service/cloudwatchlogs" + "github.com/weaveworks/eksctl/pkg/actions/identityproviders" "github.com/weaveworks/eksctl/pkg/actions/irsa" @@ -225,7 +228,27 @@ func (c *ClusterProvider) CreateExtraClusterConfigTasks(cfg *api.ClusterConfig, spec: cfg, call: c.UpdateClusterConfigForLogging, }) + + if logRetentionDays := cfg.CloudWatch.ClusterLogging.LogRetentionInDays; logRetentionDays != 0 { + newTasks.Append(&clusterConfigTask{ + info: "update CloudWatch log retention", + spec: cfg, + call: func(clusterConfig *api.ClusterConfig) error { + _, err := c.Provider.CloudWatchLogs().PutRetentionPolicy(&cloudwatchlogs.PutRetentionPolicyInput{ + // The format for log group name is documented here: https://docs.aws.amazon.com/eks/latest/userguide/control-plane-logs.html + LogGroupName: aws.String(fmt.Sprintf("/aws/eks/%s/cluster", cfg.Metadata.Name)), + RetentionInDays: aws.Int64(int64(logRetentionDays)), + }) + if err != nil { + return errors.Wrap(err, "error updating log retention settings") + } + logger.Info("set log retention to %d days for CloudWatch logging", logRetentionDays) + return nil + }, + }) + } } + c.maybeAppendTasksForEndpointAccessUpdates(cfg, newTasks) if len(cfg.VPC.PublicAccessCIDRs) > 0 { From bd4660faa9e2ada95f9de3021e9d51ac0bddb9de Mon Sep 17 00:00:00 2001 From: cpu1 Date: Tue, 5 Oct 2021 13:49:53 +0530 Subject: [PATCH 050/124] Add integration test for CloudWatch log retention --- .../cloudwatch_logging_test.go | 56 +++++++++++++++++++ .../testdata/cloudwatch-cluster.yaml | 11 ++++ .../tests/crud/creategetdelete_test.go | 12 +--- pkg/testutils/testutils.go | 15 +++++ 4 files changed, 83 insertions(+), 11 deletions(-) create mode 100644 integration/tests/cloudwatch_logging/cloudwatch_logging_test.go create mode 100644 integration/tests/cloudwatch_logging/testdata/cloudwatch-cluster.yaml diff --git a/integration/tests/cloudwatch_logging/cloudwatch_logging_test.go b/integration/tests/cloudwatch_logging/cloudwatch_logging_test.go new file mode 100644 index 0000000000..98f766353e --- /dev/null +++ b/integration/tests/cloudwatch_logging/cloudwatch_logging_test.go @@ -0,0 +1,56 @@ +//go:build integration +// +build integration + +package cloudwatch_logging + +import ( + "testing" + + api "github.com/weaveworks/eksctl/pkg/apis/eksctl.io/v1alpha5" + + "github.com/pkg/errors" + "github.com/weaveworks/eksctl/pkg/testutils" + + . "github.com/weaveworks/eksctl/integration/runner" + + . "github.com/onsi/ginkgo" + . "github.com/onsi/gomega" + + "github.com/weaveworks/eksctl/integration/tests" +) + +var params *tests.Params + +func init() { + // Call testing.Init() prior to tests.NewParams(), as otherwise -test.* will not be recognised. See also: https://golang.org/doc/go1.13#testing + testing.Init() + if err := api.Register(); err != nil { + panic(errors.Wrap(err, "unexpected error registering API scheme")) + } + params = tests.NewParams("cloudwatch") +} + +func TestCloudWatchLogging(t *testing.T) { + testutils.RegisterAndRun(t) +} + +var _ = Describe("(Integration) [CloudWatch Logging test]", func() { + Describe("CloudWatch logging", func() { + It("should create a cluster with CloudWatch logging enabled and log retention set", func() { + cmd := params.EksctlCreateCmd. + WithArgs( + "cluster", + "--config-file=-", + "--verbose=4", + ). + WithoutArg("--region", params.Region). + WithStdin(testutils.ClusterConfigReaderFromFile(params.ClusterName, params.Region, "testdata/cloudwatch-cluster.yaml")) + + Expect(cmd).To(RunSuccessfullyWithOutputString(ContainSubstring("set log retention to 545 days for CloudWatch logging"))) + }) + }) +}) + +var _ = AfterSuite(func() { + params.DeleteClusters() +}) diff --git a/integration/tests/cloudwatch_logging/testdata/cloudwatch-cluster.yaml b/integration/tests/cloudwatch_logging/testdata/cloudwatch-cluster.yaml new file mode 100644 index 0000000000..1ccf17a749 --- /dev/null +++ b/integration/tests/cloudwatch_logging/testdata/cloudwatch-cluster.yaml @@ -0,0 +1,11 @@ +apiVersion: eksctl.io/v1alpha5 +kind: ClusterConfig + +# name is generated +metadata: + name: + +cloudWatch: + clusterLogging: + enableTypes: ["audit", "authenticator", "controllerManager"] + logRetentionInDays: 545 diff --git a/integration/tests/crud/creategetdelete_test.go b/integration/tests/crud/creategetdelete_test.go index b1ffaaffdd..47e9e17c27 100644 --- a/integration/tests/crud/creategetdelete_test.go +++ b/integration/tests/crud/creategetdelete_test.go @@ -4,7 +4,6 @@ package crud import ( - "bytes" "context" "encoding/json" "fmt" @@ -218,15 +217,6 @@ var _ = Describe("(Integration) Create, Get, Scale & Delete", func() { Context("and create a new nodegroup with taints and maxPods", func() { It("should have taints and maxPods set", func() { - data, err := os.ReadFile("testdata/taints-max-pods.yaml") - Expect(err).ToNot(HaveOccurred()) - clusterConfig, err := eks.ParseConfig(data) - Expect(err).ToNot(HaveOccurred()) - clusterConfig.Metadata.Name = params.ClusterName - clusterConfig.Metadata.Region = params.Region - - data, err = json.Marshal(clusterConfig) - Expect(err).ToNot(HaveOccurred()) By("creating a new nodegroup with taints and maxPods set") cmd := params.EksctlCreateCmd. WithArgs( @@ -235,7 +225,7 @@ var _ = Describe("(Integration) Create, Get, Scale & Delete", func() { "--verbose", "4", ). WithoutArg("--region", params.Region). - WithStdin(bytes.NewReader(data)) + WithStdin(testutils.ClusterConfigReaderFromFile(params.ClusterName, params.Region, "testdata/taints-max-pods.yaml")) Expect(cmd).To(RunSuccessfully()) config, err := clientcmd.BuildConfigFromFlags("", params.KubeconfigPath) diff --git a/pkg/testutils/testutils.go b/pkg/testutils/testutils.go index e313025db4..7f3c39a88a 100644 --- a/pkg/testutils/testutils.go +++ b/pkg/testutils/testutils.go @@ -4,10 +4,12 @@ import ( "bytes" "encoding/json" "io" + "os" . "github.com/onsi/gomega" "github.com/weaveworks/eksctl/pkg/apis/eksctl.io/v1alpha5" + "github.com/weaveworks/eksctl/pkg/eks" ) func ClusterConfigReader(clusterConfig *v1alpha5.ClusterConfig) io.Reader { @@ -15,3 +17,16 @@ func ClusterConfigReader(clusterConfig *v1alpha5.ClusterConfig) io.Reader { Expect(err).ToNot(HaveOccurred()) return bytes.NewReader(data) } + +func ClusterConfigReaderFromFile(clusterName, region, filename string) io.Reader { + data, err := os.ReadFile(filename) + Expect(err).ToNot(HaveOccurred()) + clusterConfig, err := eks.ParseConfig(data) + Expect(err).ToNot(HaveOccurred()) + clusterConfig.Metadata.Name = clusterName + clusterConfig.Metadata.Region = region + + data, err = json.Marshal(clusterConfig) + Expect(err).ToNot(HaveOccurred()) + return bytes.NewReader(data) +} From 2bdab08a461fc835c679b9f5d8f934fa493e6ec0 Mon Sep 17 00:00:00 2001 From: cpu1 Date: Tue, 5 Oct 2021 15:02:47 +0530 Subject: [PATCH 051/124] Add test for validation --- pkg/apis/eksctl.io/v1alpha5/validation.go | 6 ++- .../eksctl.io/v1alpha5/validation_test.go | 41 +++++++++++++++++++ 2 files changed, 46 insertions(+), 1 deletion(-) diff --git a/pkg/apis/eksctl.io/v1alpha5/validation.go b/pkg/apis/eksctl.io/v1alpha5/validation.go index 416a38fe65..42444e1fea 100644 --- a/pkg/apis/eksctl.io/v1alpha5/validation.go +++ b/pkg/apis/eksctl.io/v1alpha5/validation.go @@ -152,8 +152,12 @@ func ValidateClusterConfig(cfg *ClusterConfig) error { func validateCloudWatchLogging(clusterConfig *ClusterConfig) error { if !clusterConfig.HasClusterCloudWatchLogging() { + if clusterConfig.CloudWatch.ClusterLogging.LogRetentionInDays != 0 { + return errors.New("cannot set cloudWatch.clusterLogging.logRetentionInDays without enabling log types") + } return nil } + for i, logType := range clusterConfig.CloudWatch.ClusterLogging.EnableTypes { isUnknown := true for _, knownLogType := range SupportedCloudWatchClusterLogTypes() { @@ -171,7 +175,7 @@ func validateCloudWatchLogging(clusterConfig *ClusterConfig) error { return nil } } - return errors.Errorf("invalid value %q for logRetentionInDays; supported values are %v", logRetentionDays, LogRetentionInDaysValues) + return errors.Errorf("invalid value %d for logRetentionInDays; supported values are %v", logRetentionDays, LogRetentionInDaysValues) } return nil diff --git a/pkg/apis/eksctl.io/v1alpha5/validation_test.go b/pkg/apis/eksctl.io/v1alpha5/validation_test.go index 2aa763a055..f35ff2dc88 100644 --- a/pkg/apis/eksctl.io/v1alpha5/validation_test.go +++ b/pkg/apis/eksctl.io/v1alpha5/validation_test.go @@ -482,6 +482,47 @@ var _ = Describe("ClusterConfig validation", func() { }) }) + type logRetentionEntry struct { + logging *api.ClusterCloudWatchLogging + + expectedErr string + } + + DescribeTable("CloudWatch log retention", func(l logRetentionEntry) { + clusterConfig := api.NewClusterConfig() + clusterConfig.CloudWatch.ClusterLogging = l.logging + err := api.ValidateClusterConfig(clusterConfig) + if l.expectedErr != "" { + Expect(err).To(HaveOccurred()) + Expect(err).To(MatchError(ContainSubstring(l.expectedErr))) + return + } + + Expect(err).ToNot(HaveOccurred()) + }, + Entry("invalid value", logRetentionEntry{ + logging: &api.ClusterCloudWatchLogging{ + LogRetentionInDays: 42, + EnableTypes: []string{"api"}, + }, + expectedErr: `invalid value 42 for logRetentionInDays; supported values are [1 3 5 7`, + }), + + Entry("valid value", logRetentionEntry{ + logging: &api.ClusterCloudWatchLogging{ + LogRetentionInDays: 545, + EnableTypes: []string{"api"}, + }, + }), + + Entry("log retention without enableTypes", logRetentionEntry{ + logging: &api.ClusterCloudWatchLogging{ + LogRetentionInDays: 545, + }, + expectedErr: "cannot set cloudWatch.clusterLogging.logRetentionInDays without enabling log types", + }), + ) + Describe("cluster endpoint access config", func() { var ( cfg *api.ClusterConfig From 10b82182efb27441e5ccd98fc3ab85f4ac0032d7 Mon Sep 17 00:00:00 2001 From: cpu1 Date: Tue, 5 Oct 2021 15:23:25 +0530 Subject: [PATCH 052/124] Generate mocks --- pkg/eks/mocks/CloudWatchLogsAPI.go | 3539 +++++++++++++++++++ pkg/eks/mocks/mocks.go | 1 + pkg/testutils/mockprovider/mock_provider.go | 11 + 3 files changed, 3551 insertions(+) create mode 100644 pkg/eks/mocks/CloudWatchLogsAPI.go diff --git a/pkg/eks/mocks/CloudWatchLogsAPI.go b/pkg/eks/mocks/CloudWatchLogsAPI.go new file mode 100644 index 0000000000..20b63495c1 --- /dev/null +++ b/pkg/eks/mocks/CloudWatchLogsAPI.go @@ -0,0 +1,3539 @@ +// Code generated by mockery v1.0.0. DO NOT EDIT. + +package mocks + +import ( + cloudwatchlogs "github.com/aws/aws-sdk-go/service/cloudwatchlogs" + + context "context" + + mock "github.com/stretchr/testify/mock" + + request "github.com/aws/aws-sdk-go/aws/request" +) + +// CloudWatchLogsAPI is an autogenerated mock type for the CloudWatchLogsAPI type +type CloudWatchLogsAPI struct { + mock.Mock +} + +// AssociateKmsKey provides a mock function with given fields: _a0 +func (_m *CloudWatchLogsAPI) AssociateKmsKey(_a0 *cloudwatchlogs.AssociateKmsKeyInput) (*cloudwatchlogs.AssociateKmsKeyOutput, error) { + ret := _m.Called(_a0) + + var r0 *cloudwatchlogs.AssociateKmsKeyOutput + if rf, ok := ret.Get(0).(func(*cloudwatchlogs.AssociateKmsKeyInput) *cloudwatchlogs.AssociateKmsKeyOutput); ok { + r0 = rf(_a0) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*cloudwatchlogs.AssociateKmsKeyOutput) + } + } + + var r1 error + if rf, ok := ret.Get(1).(func(*cloudwatchlogs.AssociateKmsKeyInput) error); ok { + r1 = rf(_a0) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// AssociateKmsKeyRequest provides a mock function with given fields: _a0 +func (_m *CloudWatchLogsAPI) AssociateKmsKeyRequest(_a0 *cloudwatchlogs.AssociateKmsKeyInput) (*request.Request, *cloudwatchlogs.AssociateKmsKeyOutput) { + ret := _m.Called(_a0) + + var r0 *request.Request + if rf, ok := ret.Get(0).(func(*cloudwatchlogs.AssociateKmsKeyInput) *request.Request); ok { + r0 = rf(_a0) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*request.Request) + } + } + + var r1 *cloudwatchlogs.AssociateKmsKeyOutput + if rf, ok := ret.Get(1).(func(*cloudwatchlogs.AssociateKmsKeyInput) *cloudwatchlogs.AssociateKmsKeyOutput); ok { + r1 = rf(_a0) + } else { + if ret.Get(1) != nil { + r1 = ret.Get(1).(*cloudwatchlogs.AssociateKmsKeyOutput) + } + } + + return r0, r1 +} + +// AssociateKmsKeyWithContext provides a mock function with given fields: _a0, _a1, _a2 +func (_m *CloudWatchLogsAPI) AssociateKmsKeyWithContext(_a0 context.Context, _a1 *cloudwatchlogs.AssociateKmsKeyInput, _a2 ...request.Option) (*cloudwatchlogs.AssociateKmsKeyOutput, error) { + _va := make([]interface{}, len(_a2)) + for _i := range _a2 { + _va[_i] = _a2[_i] + } + var _ca []interface{} + _ca = append(_ca, _a0, _a1) + _ca = append(_ca, _va...) + ret := _m.Called(_ca...) + + var r0 *cloudwatchlogs.AssociateKmsKeyOutput + if rf, ok := ret.Get(0).(func(context.Context, *cloudwatchlogs.AssociateKmsKeyInput, ...request.Option) *cloudwatchlogs.AssociateKmsKeyOutput); ok { + r0 = rf(_a0, _a1, _a2...) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*cloudwatchlogs.AssociateKmsKeyOutput) + } + } + + var r1 error + if rf, ok := ret.Get(1).(func(context.Context, *cloudwatchlogs.AssociateKmsKeyInput, ...request.Option) error); ok { + r1 = rf(_a0, _a1, _a2...) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// CancelExportTask provides a mock function with given fields: _a0 +func (_m *CloudWatchLogsAPI) CancelExportTask(_a0 *cloudwatchlogs.CancelExportTaskInput) (*cloudwatchlogs.CancelExportTaskOutput, error) { + ret := _m.Called(_a0) + + var r0 *cloudwatchlogs.CancelExportTaskOutput + if rf, ok := ret.Get(0).(func(*cloudwatchlogs.CancelExportTaskInput) *cloudwatchlogs.CancelExportTaskOutput); ok { + r0 = rf(_a0) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*cloudwatchlogs.CancelExportTaskOutput) + } + } + + var r1 error + if rf, ok := ret.Get(1).(func(*cloudwatchlogs.CancelExportTaskInput) error); ok { + r1 = rf(_a0) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// CancelExportTaskRequest provides a mock function with given fields: _a0 +func (_m *CloudWatchLogsAPI) CancelExportTaskRequest(_a0 *cloudwatchlogs.CancelExportTaskInput) (*request.Request, *cloudwatchlogs.CancelExportTaskOutput) { + ret := _m.Called(_a0) + + var r0 *request.Request + if rf, ok := ret.Get(0).(func(*cloudwatchlogs.CancelExportTaskInput) *request.Request); ok { + r0 = rf(_a0) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*request.Request) + } + } + + var r1 *cloudwatchlogs.CancelExportTaskOutput + if rf, ok := ret.Get(1).(func(*cloudwatchlogs.CancelExportTaskInput) *cloudwatchlogs.CancelExportTaskOutput); ok { + r1 = rf(_a0) + } else { + if ret.Get(1) != nil { + r1 = ret.Get(1).(*cloudwatchlogs.CancelExportTaskOutput) + } + } + + return r0, r1 +} + +// CancelExportTaskWithContext provides a mock function with given fields: _a0, _a1, _a2 +func (_m *CloudWatchLogsAPI) CancelExportTaskWithContext(_a0 context.Context, _a1 *cloudwatchlogs.CancelExportTaskInput, _a2 ...request.Option) (*cloudwatchlogs.CancelExportTaskOutput, error) { + _va := make([]interface{}, len(_a2)) + for _i := range _a2 { + _va[_i] = _a2[_i] + } + var _ca []interface{} + _ca = append(_ca, _a0, _a1) + _ca = append(_ca, _va...) + ret := _m.Called(_ca...) + + var r0 *cloudwatchlogs.CancelExportTaskOutput + if rf, ok := ret.Get(0).(func(context.Context, *cloudwatchlogs.CancelExportTaskInput, ...request.Option) *cloudwatchlogs.CancelExportTaskOutput); ok { + r0 = rf(_a0, _a1, _a2...) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*cloudwatchlogs.CancelExportTaskOutput) + } + } + + var r1 error + if rf, ok := ret.Get(1).(func(context.Context, *cloudwatchlogs.CancelExportTaskInput, ...request.Option) error); ok { + r1 = rf(_a0, _a1, _a2...) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// CreateExportTask provides a mock function with given fields: _a0 +func (_m *CloudWatchLogsAPI) CreateExportTask(_a0 *cloudwatchlogs.CreateExportTaskInput) (*cloudwatchlogs.CreateExportTaskOutput, error) { + ret := _m.Called(_a0) + + var r0 *cloudwatchlogs.CreateExportTaskOutput + if rf, ok := ret.Get(0).(func(*cloudwatchlogs.CreateExportTaskInput) *cloudwatchlogs.CreateExportTaskOutput); ok { + r0 = rf(_a0) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*cloudwatchlogs.CreateExportTaskOutput) + } + } + + var r1 error + if rf, ok := ret.Get(1).(func(*cloudwatchlogs.CreateExportTaskInput) error); ok { + r1 = rf(_a0) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// CreateExportTaskRequest provides a mock function with given fields: _a0 +func (_m *CloudWatchLogsAPI) CreateExportTaskRequest(_a0 *cloudwatchlogs.CreateExportTaskInput) (*request.Request, *cloudwatchlogs.CreateExportTaskOutput) { + ret := _m.Called(_a0) + + var r0 *request.Request + if rf, ok := ret.Get(0).(func(*cloudwatchlogs.CreateExportTaskInput) *request.Request); ok { + r0 = rf(_a0) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*request.Request) + } + } + + var r1 *cloudwatchlogs.CreateExportTaskOutput + if rf, ok := ret.Get(1).(func(*cloudwatchlogs.CreateExportTaskInput) *cloudwatchlogs.CreateExportTaskOutput); ok { + r1 = rf(_a0) + } else { + if ret.Get(1) != nil { + r1 = ret.Get(1).(*cloudwatchlogs.CreateExportTaskOutput) + } + } + + return r0, r1 +} + +// CreateExportTaskWithContext provides a mock function with given fields: _a0, _a1, _a2 +func (_m *CloudWatchLogsAPI) CreateExportTaskWithContext(_a0 context.Context, _a1 *cloudwatchlogs.CreateExportTaskInput, _a2 ...request.Option) (*cloudwatchlogs.CreateExportTaskOutput, error) { + _va := make([]interface{}, len(_a2)) + for _i := range _a2 { + _va[_i] = _a2[_i] + } + var _ca []interface{} + _ca = append(_ca, _a0, _a1) + _ca = append(_ca, _va...) + ret := _m.Called(_ca...) + + var r0 *cloudwatchlogs.CreateExportTaskOutput + if rf, ok := ret.Get(0).(func(context.Context, *cloudwatchlogs.CreateExportTaskInput, ...request.Option) *cloudwatchlogs.CreateExportTaskOutput); ok { + r0 = rf(_a0, _a1, _a2...) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*cloudwatchlogs.CreateExportTaskOutput) + } + } + + var r1 error + if rf, ok := ret.Get(1).(func(context.Context, *cloudwatchlogs.CreateExportTaskInput, ...request.Option) error); ok { + r1 = rf(_a0, _a1, _a2...) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// CreateLogGroup provides a mock function with given fields: _a0 +func (_m *CloudWatchLogsAPI) CreateLogGroup(_a0 *cloudwatchlogs.CreateLogGroupInput) (*cloudwatchlogs.CreateLogGroupOutput, error) { + ret := _m.Called(_a0) + + var r0 *cloudwatchlogs.CreateLogGroupOutput + if rf, ok := ret.Get(0).(func(*cloudwatchlogs.CreateLogGroupInput) *cloudwatchlogs.CreateLogGroupOutput); ok { + r0 = rf(_a0) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*cloudwatchlogs.CreateLogGroupOutput) + } + } + + var r1 error + if rf, ok := ret.Get(1).(func(*cloudwatchlogs.CreateLogGroupInput) error); ok { + r1 = rf(_a0) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// CreateLogGroupRequest provides a mock function with given fields: _a0 +func (_m *CloudWatchLogsAPI) CreateLogGroupRequest(_a0 *cloudwatchlogs.CreateLogGroupInput) (*request.Request, *cloudwatchlogs.CreateLogGroupOutput) { + ret := _m.Called(_a0) + + var r0 *request.Request + if rf, ok := ret.Get(0).(func(*cloudwatchlogs.CreateLogGroupInput) *request.Request); ok { + r0 = rf(_a0) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*request.Request) + } + } + + var r1 *cloudwatchlogs.CreateLogGroupOutput + if rf, ok := ret.Get(1).(func(*cloudwatchlogs.CreateLogGroupInput) *cloudwatchlogs.CreateLogGroupOutput); ok { + r1 = rf(_a0) + } else { + if ret.Get(1) != nil { + r1 = ret.Get(1).(*cloudwatchlogs.CreateLogGroupOutput) + } + } + + return r0, r1 +} + +// CreateLogGroupWithContext provides a mock function with given fields: _a0, _a1, _a2 +func (_m *CloudWatchLogsAPI) CreateLogGroupWithContext(_a0 context.Context, _a1 *cloudwatchlogs.CreateLogGroupInput, _a2 ...request.Option) (*cloudwatchlogs.CreateLogGroupOutput, error) { + _va := make([]interface{}, len(_a2)) + for _i := range _a2 { + _va[_i] = _a2[_i] + } + var _ca []interface{} + _ca = append(_ca, _a0, _a1) + _ca = append(_ca, _va...) + ret := _m.Called(_ca...) + + var r0 *cloudwatchlogs.CreateLogGroupOutput + if rf, ok := ret.Get(0).(func(context.Context, *cloudwatchlogs.CreateLogGroupInput, ...request.Option) *cloudwatchlogs.CreateLogGroupOutput); ok { + r0 = rf(_a0, _a1, _a2...) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*cloudwatchlogs.CreateLogGroupOutput) + } + } + + var r1 error + if rf, ok := ret.Get(1).(func(context.Context, *cloudwatchlogs.CreateLogGroupInput, ...request.Option) error); ok { + r1 = rf(_a0, _a1, _a2...) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// CreateLogStream provides a mock function with given fields: _a0 +func (_m *CloudWatchLogsAPI) CreateLogStream(_a0 *cloudwatchlogs.CreateLogStreamInput) (*cloudwatchlogs.CreateLogStreamOutput, error) { + ret := _m.Called(_a0) + + var r0 *cloudwatchlogs.CreateLogStreamOutput + if rf, ok := ret.Get(0).(func(*cloudwatchlogs.CreateLogStreamInput) *cloudwatchlogs.CreateLogStreamOutput); ok { + r0 = rf(_a0) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*cloudwatchlogs.CreateLogStreamOutput) + } + } + + var r1 error + if rf, ok := ret.Get(1).(func(*cloudwatchlogs.CreateLogStreamInput) error); ok { + r1 = rf(_a0) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// CreateLogStreamRequest provides a mock function with given fields: _a0 +func (_m *CloudWatchLogsAPI) CreateLogStreamRequest(_a0 *cloudwatchlogs.CreateLogStreamInput) (*request.Request, *cloudwatchlogs.CreateLogStreamOutput) { + ret := _m.Called(_a0) + + var r0 *request.Request + if rf, ok := ret.Get(0).(func(*cloudwatchlogs.CreateLogStreamInput) *request.Request); ok { + r0 = rf(_a0) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*request.Request) + } + } + + var r1 *cloudwatchlogs.CreateLogStreamOutput + if rf, ok := ret.Get(1).(func(*cloudwatchlogs.CreateLogStreamInput) *cloudwatchlogs.CreateLogStreamOutput); ok { + r1 = rf(_a0) + } else { + if ret.Get(1) != nil { + r1 = ret.Get(1).(*cloudwatchlogs.CreateLogStreamOutput) + } + } + + return r0, r1 +} + +// CreateLogStreamWithContext provides a mock function with given fields: _a0, _a1, _a2 +func (_m *CloudWatchLogsAPI) CreateLogStreamWithContext(_a0 context.Context, _a1 *cloudwatchlogs.CreateLogStreamInput, _a2 ...request.Option) (*cloudwatchlogs.CreateLogStreamOutput, error) { + _va := make([]interface{}, len(_a2)) + for _i := range _a2 { + _va[_i] = _a2[_i] + } + var _ca []interface{} + _ca = append(_ca, _a0, _a1) + _ca = append(_ca, _va...) + ret := _m.Called(_ca...) + + var r0 *cloudwatchlogs.CreateLogStreamOutput + if rf, ok := ret.Get(0).(func(context.Context, *cloudwatchlogs.CreateLogStreamInput, ...request.Option) *cloudwatchlogs.CreateLogStreamOutput); ok { + r0 = rf(_a0, _a1, _a2...) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*cloudwatchlogs.CreateLogStreamOutput) + } + } + + var r1 error + if rf, ok := ret.Get(1).(func(context.Context, *cloudwatchlogs.CreateLogStreamInput, ...request.Option) error); ok { + r1 = rf(_a0, _a1, _a2...) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// DeleteDestination provides a mock function with given fields: _a0 +func (_m *CloudWatchLogsAPI) DeleteDestination(_a0 *cloudwatchlogs.DeleteDestinationInput) (*cloudwatchlogs.DeleteDestinationOutput, error) { + ret := _m.Called(_a0) + + var r0 *cloudwatchlogs.DeleteDestinationOutput + if rf, ok := ret.Get(0).(func(*cloudwatchlogs.DeleteDestinationInput) *cloudwatchlogs.DeleteDestinationOutput); ok { + r0 = rf(_a0) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*cloudwatchlogs.DeleteDestinationOutput) + } + } + + var r1 error + if rf, ok := ret.Get(1).(func(*cloudwatchlogs.DeleteDestinationInput) error); ok { + r1 = rf(_a0) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// DeleteDestinationRequest provides a mock function with given fields: _a0 +func (_m *CloudWatchLogsAPI) DeleteDestinationRequest(_a0 *cloudwatchlogs.DeleteDestinationInput) (*request.Request, *cloudwatchlogs.DeleteDestinationOutput) { + ret := _m.Called(_a0) + + var r0 *request.Request + if rf, ok := ret.Get(0).(func(*cloudwatchlogs.DeleteDestinationInput) *request.Request); ok { + r0 = rf(_a0) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*request.Request) + } + } + + var r1 *cloudwatchlogs.DeleteDestinationOutput + if rf, ok := ret.Get(1).(func(*cloudwatchlogs.DeleteDestinationInput) *cloudwatchlogs.DeleteDestinationOutput); ok { + r1 = rf(_a0) + } else { + if ret.Get(1) != nil { + r1 = ret.Get(1).(*cloudwatchlogs.DeleteDestinationOutput) + } + } + + return r0, r1 +} + +// DeleteDestinationWithContext provides a mock function with given fields: _a0, _a1, _a2 +func (_m *CloudWatchLogsAPI) DeleteDestinationWithContext(_a0 context.Context, _a1 *cloudwatchlogs.DeleteDestinationInput, _a2 ...request.Option) (*cloudwatchlogs.DeleteDestinationOutput, error) { + _va := make([]interface{}, len(_a2)) + for _i := range _a2 { + _va[_i] = _a2[_i] + } + var _ca []interface{} + _ca = append(_ca, _a0, _a1) + _ca = append(_ca, _va...) + ret := _m.Called(_ca...) + + var r0 *cloudwatchlogs.DeleteDestinationOutput + if rf, ok := ret.Get(0).(func(context.Context, *cloudwatchlogs.DeleteDestinationInput, ...request.Option) *cloudwatchlogs.DeleteDestinationOutput); ok { + r0 = rf(_a0, _a1, _a2...) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*cloudwatchlogs.DeleteDestinationOutput) + } + } + + var r1 error + if rf, ok := ret.Get(1).(func(context.Context, *cloudwatchlogs.DeleteDestinationInput, ...request.Option) error); ok { + r1 = rf(_a0, _a1, _a2...) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// DeleteLogGroup provides a mock function with given fields: _a0 +func (_m *CloudWatchLogsAPI) DeleteLogGroup(_a0 *cloudwatchlogs.DeleteLogGroupInput) (*cloudwatchlogs.DeleteLogGroupOutput, error) { + ret := _m.Called(_a0) + + var r0 *cloudwatchlogs.DeleteLogGroupOutput + if rf, ok := ret.Get(0).(func(*cloudwatchlogs.DeleteLogGroupInput) *cloudwatchlogs.DeleteLogGroupOutput); ok { + r0 = rf(_a0) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*cloudwatchlogs.DeleteLogGroupOutput) + } + } + + var r1 error + if rf, ok := ret.Get(1).(func(*cloudwatchlogs.DeleteLogGroupInput) error); ok { + r1 = rf(_a0) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// DeleteLogGroupRequest provides a mock function with given fields: _a0 +func (_m *CloudWatchLogsAPI) DeleteLogGroupRequest(_a0 *cloudwatchlogs.DeleteLogGroupInput) (*request.Request, *cloudwatchlogs.DeleteLogGroupOutput) { + ret := _m.Called(_a0) + + var r0 *request.Request + if rf, ok := ret.Get(0).(func(*cloudwatchlogs.DeleteLogGroupInput) *request.Request); ok { + r0 = rf(_a0) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*request.Request) + } + } + + var r1 *cloudwatchlogs.DeleteLogGroupOutput + if rf, ok := ret.Get(1).(func(*cloudwatchlogs.DeleteLogGroupInput) *cloudwatchlogs.DeleteLogGroupOutput); ok { + r1 = rf(_a0) + } else { + if ret.Get(1) != nil { + r1 = ret.Get(1).(*cloudwatchlogs.DeleteLogGroupOutput) + } + } + + return r0, r1 +} + +// DeleteLogGroupWithContext provides a mock function with given fields: _a0, _a1, _a2 +func (_m *CloudWatchLogsAPI) DeleteLogGroupWithContext(_a0 context.Context, _a1 *cloudwatchlogs.DeleteLogGroupInput, _a2 ...request.Option) (*cloudwatchlogs.DeleteLogGroupOutput, error) { + _va := make([]interface{}, len(_a2)) + for _i := range _a2 { + _va[_i] = _a2[_i] + } + var _ca []interface{} + _ca = append(_ca, _a0, _a1) + _ca = append(_ca, _va...) + ret := _m.Called(_ca...) + + var r0 *cloudwatchlogs.DeleteLogGroupOutput + if rf, ok := ret.Get(0).(func(context.Context, *cloudwatchlogs.DeleteLogGroupInput, ...request.Option) *cloudwatchlogs.DeleteLogGroupOutput); ok { + r0 = rf(_a0, _a1, _a2...) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*cloudwatchlogs.DeleteLogGroupOutput) + } + } + + var r1 error + if rf, ok := ret.Get(1).(func(context.Context, *cloudwatchlogs.DeleteLogGroupInput, ...request.Option) error); ok { + r1 = rf(_a0, _a1, _a2...) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// DeleteLogStream provides a mock function with given fields: _a0 +func (_m *CloudWatchLogsAPI) DeleteLogStream(_a0 *cloudwatchlogs.DeleteLogStreamInput) (*cloudwatchlogs.DeleteLogStreamOutput, error) { + ret := _m.Called(_a0) + + var r0 *cloudwatchlogs.DeleteLogStreamOutput + if rf, ok := ret.Get(0).(func(*cloudwatchlogs.DeleteLogStreamInput) *cloudwatchlogs.DeleteLogStreamOutput); ok { + r0 = rf(_a0) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*cloudwatchlogs.DeleteLogStreamOutput) + } + } + + var r1 error + if rf, ok := ret.Get(1).(func(*cloudwatchlogs.DeleteLogStreamInput) error); ok { + r1 = rf(_a0) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// DeleteLogStreamRequest provides a mock function with given fields: _a0 +func (_m *CloudWatchLogsAPI) DeleteLogStreamRequest(_a0 *cloudwatchlogs.DeleteLogStreamInput) (*request.Request, *cloudwatchlogs.DeleteLogStreamOutput) { + ret := _m.Called(_a0) + + var r0 *request.Request + if rf, ok := ret.Get(0).(func(*cloudwatchlogs.DeleteLogStreamInput) *request.Request); ok { + r0 = rf(_a0) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*request.Request) + } + } + + var r1 *cloudwatchlogs.DeleteLogStreamOutput + if rf, ok := ret.Get(1).(func(*cloudwatchlogs.DeleteLogStreamInput) *cloudwatchlogs.DeleteLogStreamOutput); ok { + r1 = rf(_a0) + } else { + if ret.Get(1) != nil { + r1 = ret.Get(1).(*cloudwatchlogs.DeleteLogStreamOutput) + } + } + + return r0, r1 +} + +// DeleteLogStreamWithContext provides a mock function with given fields: _a0, _a1, _a2 +func (_m *CloudWatchLogsAPI) DeleteLogStreamWithContext(_a0 context.Context, _a1 *cloudwatchlogs.DeleteLogStreamInput, _a2 ...request.Option) (*cloudwatchlogs.DeleteLogStreamOutput, error) { + _va := make([]interface{}, len(_a2)) + for _i := range _a2 { + _va[_i] = _a2[_i] + } + var _ca []interface{} + _ca = append(_ca, _a0, _a1) + _ca = append(_ca, _va...) + ret := _m.Called(_ca...) + + var r0 *cloudwatchlogs.DeleteLogStreamOutput + if rf, ok := ret.Get(0).(func(context.Context, *cloudwatchlogs.DeleteLogStreamInput, ...request.Option) *cloudwatchlogs.DeleteLogStreamOutput); ok { + r0 = rf(_a0, _a1, _a2...) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*cloudwatchlogs.DeleteLogStreamOutput) + } + } + + var r1 error + if rf, ok := ret.Get(1).(func(context.Context, *cloudwatchlogs.DeleteLogStreamInput, ...request.Option) error); ok { + r1 = rf(_a0, _a1, _a2...) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// DeleteMetricFilter provides a mock function with given fields: _a0 +func (_m *CloudWatchLogsAPI) DeleteMetricFilter(_a0 *cloudwatchlogs.DeleteMetricFilterInput) (*cloudwatchlogs.DeleteMetricFilterOutput, error) { + ret := _m.Called(_a0) + + var r0 *cloudwatchlogs.DeleteMetricFilterOutput + if rf, ok := ret.Get(0).(func(*cloudwatchlogs.DeleteMetricFilterInput) *cloudwatchlogs.DeleteMetricFilterOutput); ok { + r0 = rf(_a0) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*cloudwatchlogs.DeleteMetricFilterOutput) + } + } + + var r1 error + if rf, ok := ret.Get(1).(func(*cloudwatchlogs.DeleteMetricFilterInput) error); ok { + r1 = rf(_a0) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// DeleteMetricFilterRequest provides a mock function with given fields: _a0 +func (_m *CloudWatchLogsAPI) DeleteMetricFilterRequest(_a0 *cloudwatchlogs.DeleteMetricFilterInput) (*request.Request, *cloudwatchlogs.DeleteMetricFilterOutput) { + ret := _m.Called(_a0) + + var r0 *request.Request + if rf, ok := ret.Get(0).(func(*cloudwatchlogs.DeleteMetricFilterInput) *request.Request); ok { + r0 = rf(_a0) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*request.Request) + } + } + + var r1 *cloudwatchlogs.DeleteMetricFilterOutput + if rf, ok := ret.Get(1).(func(*cloudwatchlogs.DeleteMetricFilterInput) *cloudwatchlogs.DeleteMetricFilterOutput); ok { + r1 = rf(_a0) + } else { + if ret.Get(1) != nil { + r1 = ret.Get(1).(*cloudwatchlogs.DeleteMetricFilterOutput) + } + } + + return r0, r1 +} + +// DeleteMetricFilterWithContext provides a mock function with given fields: _a0, _a1, _a2 +func (_m *CloudWatchLogsAPI) DeleteMetricFilterWithContext(_a0 context.Context, _a1 *cloudwatchlogs.DeleteMetricFilterInput, _a2 ...request.Option) (*cloudwatchlogs.DeleteMetricFilterOutput, error) { + _va := make([]interface{}, len(_a2)) + for _i := range _a2 { + _va[_i] = _a2[_i] + } + var _ca []interface{} + _ca = append(_ca, _a0, _a1) + _ca = append(_ca, _va...) + ret := _m.Called(_ca...) + + var r0 *cloudwatchlogs.DeleteMetricFilterOutput + if rf, ok := ret.Get(0).(func(context.Context, *cloudwatchlogs.DeleteMetricFilterInput, ...request.Option) *cloudwatchlogs.DeleteMetricFilterOutput); ok { + r0 = rf(_a0, _a1, _a2...) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*cloudwatchlogs.DeleteMetricFilterOutput) + } + } + + var r1 error + if rf, ok := ret.Get(1).(func(context.Context, *cloudwatchlogs.DeleteMetricFilterInput, ...request.Option) error); ok { + r1 = rf(_a0, _a1, _a2...) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// DeleteQueryDefinition provides a mock function with given fields: _a0 +func (_m *CloudWatchLogsAPI) DeleteQueryDefinition(_a0 *cloudwatchlogs.DeleteQueryDefinitionInput) (*cloudwatchlogs.DeleteQueryDefinitionOutput, error) { + ret := _m.Called(_a0) + + var r0 *cloudwatchlogs.DeleteQueryDefinitionOutput + if rf, ok := ret.Get(0).(func(*cloudwatchlogs.DeleteQueryDefinitionInput) *cloudwatchlogs.DeleteQueryDefinitionOutput); ok { + r0 = rf(_a0) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*cloudwatchlogs.DeleteQueryDefinitionOutput) + } + } + + var r1 error + if rf, ok := ret.Get(1).(func(*cloudwatchlogs.DeleteQueryDefinitionInput) error); ok { + r1 = rf(_a0) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// DeleteQueryDefinitionRequest provides a mock function with given fields: _a0 +func (_m *CloudWatchLogsAPI) DeleteQueryDefinitionRequest(_a0 *cloudwatchlogs.DeleteQueryDefinitionInput) (*request.Request, *cloudwatchlogs.DeleteQueryDefinitionOutput) { + ret := _m.Called(_a0) + + var r0 *request.Request + if rf, ok := ret.Get(0).(func(*cloudwatchlogs.DeleteQueryDefinitionInput) *request.Request); ok { + r0 = rf(_a0) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*request.Request) + } + } + + var r1 *cloudwatchlogs.DeleteQueryDefinitionOutput + if rf, ok := ret.Get(1).(func(*cloudwatchlogs.DeleteQueryDefinitionInput) *cloudwatchlogs.DeleteQueryDefinitionOutput); ok { + r1 = rf(_a0) + } else { + if ret.Get(1) != nil { + r1 = ret.Get(1).(*cloudwatchlogs.DeleteQueryDefinitionOutput) + } + } + + return r0, r1 +} + +// DeleteQueryDefinitionWithContext provides a mock function with given fields: _a0, _a1, _a2 +func (_m *CloudWatchLogsAPI) DeleteQueryDefinitionWithContext(_a0 context.Context, _a1 *cloudwatchlogs.DeleteQueryDefinitionInput, _a2 ...request.Option) (*cloudwatchlogs.DeleteQueryDefinitionOutput, error) { + _va := make([]interface{}, len(_a2)) + for _i := range _a2 { + _va[_i] = _a2[_i] + } + var _ca []interface{} + _ca = append(_ca, _a0, _a1) + _ca = append(_ca, _va...) + ret := _m.Called(_ca...) + + var r0 *cloudwatchlogs.DeleteQueryDefinitionOutput + if rf, ok := ret.Get(0).(func(context.Context, *cloudwatchlogs.DeleteQueryDefinitionInput, ...request.Option) *cloudwatchlogs.DeleteQueryDefinitionOutput); ok { + r0 = rf(_a0, _a1, _a2...) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*cloudwatchlogs.DeleteQueryDefinitionOutput) + } + } + + var r1 error + if rf, ok := ret.Get(1).(func(context.Context, *cloudwatchlogs.DeleteQueryDefinitionInput, ...request.Option) error); ok { + r1 = rf(_a0, _a1, _a2...) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// DeleteResourcePolicy provides a mock function with given fields: _a0 +func (_m *CloudWatchLogsAPI) DeleteResourcePolicy(_a0 *cloudwatchlogs.DeleteResourcePolicyInput) (*cloudwatchlogs.DeleteResourcePolicyOutput, error) { + ret := _m.Called(_a0) + + var r0 *cloudwatchlogs.DeleteResourcePolicyOutput + if rf, ok := ret.Get(0).(func(*cloudwatchlogs.DeleteResourcePolicyInput) *cloudwatchlogs.DeleteResourcePolicyOutput); ok { + r0 = rf(_a0) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*cloudwatchlogs.DeleteResourcePolicyOutput) + } + } + + var r1 error + if rf, ok := ret.Get(1).(func(*cloudwatchlogs.DeleteResourcePolicyInput) error); ok { + r1 = rf(_a0) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// DeleteResourcePolicyRequest provides a mock function with given fields: _a0 +func (_m *CloudWatchLogsAPI) DeleteResourcePolicyRequest(_a0 *cloudwatchlogs.DeleteResourcePolicyInput) (*request.Request, *cloudwatchlogs.DeleteResourcePolicyOutput) { + ret := _m.Called(_a0) + + var r0 *request.Request + if rf, ok := ret.Get(0).(func(*cloudwatchlogs.DeleteResourcePolicyInput) *request.Request); ok { + r0 = rf(_a0) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*request.Request) + } + } + + var r1 *cloudwatchlogs.DeleteResourcePolicyOutput + if rf, ok := ret.Get(1).(func(*cloudwatchlogs.DeleteResourcePolicyInput) *cloudwatchlogs.DeleteResourcePolicyOutput); ok { + r1 = rf(_a0) + } else { + if ret.Get(1) != nil { + r1 = ret.Get(1).(*cloudwatchlogs.DeleteResourcePolicyOutput) + } + } + + return r0, r1 +} + +// DeleteResourcePolicyWithContext provides a mock function with given fields: _a0, _a1, _a2 +func (_m *CloudWatchLogsAPI) DeleteResourcePolicyWithContext(_a0 context.Context, _a1 *cloudwatchlogs.DeleteResourcePolicyInput, _a2 ...request.Option) (*cloudwatchlogs.DeleteResourcePolicyOutput, error) { + _va := make([]interface{}, len(_a2)) + for _i := range _a2 { + _va[_i] = _a2[_i] + } + var _ca []interface{} + _ca = append(_ca, _a0, _a1) + _ca = append(_ca, _va...) + ret := _m.Called(_ca...) + + var r0 *cloudwatchlogs.DeleteResourcePolicyOutput + if rf, ok := ret.Get(0).(func(context.Context, *cloudwatchlogs.DeleteResourcePolicyInput, ...request.Option) *cloudwatchlogs.DeleteResourcePolicyOutput); ok { + r0 = rf(_a0, _a1, _a2...) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*cloudwatchlogs.DeleteResourcePolicyOutput) + } + } + + var r1 error + if rf, ok := ret.Get(1).(func(context.Context, *cloudwatchlogs.DeleteResourcePolicyInput, ...request.Option) error); ok { + r1 = rf(_a0, _a1, _a2...) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// DeleteRetentionPolicy provides a mock function with given fields: _a0 +func (_m *CloudWatchLogsAPI) DeleteRetentionPolicy(_a0 *cloudwatchlogs.DeleteRetentionPolicyInput) (*cloudwatchlogs.DeleteRetentionPolicyOutput, error) { + ret := _m.Called(_a0) + + var r0 *cloudwatchlogs.DeleteRetentionPolicyOutput + if rf, ok := ret.Get(0).(func(*cloudwatchlogs.DeleteRetentionPolicyInput) *cloudwatchlogs.DeleteRetentionPolicyOutput); ok { + r0 = rf(_a0) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*cloudwatchlogs.DeleteRetentionPolicyOutput) + } + } + + var r1 error + if rf, ok := ret.Get(1).(func(*cloudwatchlogs.DeleteRetentionPolicyInput) error); ok { + r1 = rf(_a0) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// DeleteRetentionPolicyRequest provides a mock function with given fields: _a0 +func (_m *CloudWatchLogsAPI) DeleteRetentionPolicyRequest(_a0 *cloudwatchlogs.DeleteRetentionPolicyInput) (*request.Request, *cloudwatchlogs.DeleteRetentionPolicyOutput) { + ret := _m.Called(_a0) + + var r0 *request.Request + if rf, ok := ret.Get(0).(func(*cloudwatchlogs.DeleteRetentionPolicyInput) *request.Request); ok { + r0 = rf(_a0) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*request.Request) + } + } + + var r1 *cloudwatchlogs.DeleteRetentionPolicyOutput + if rf, ok := ret.Get(1).(func(*cloudwatchlogs.DeleteRetentionPolicyInput) *cloudwatchlogs.DeleteRetentionPolicyOutput); ok { + r1 = rf(_a0) + } else { + if ret.Get(1) != nil { + r1 = ret.Get(1).(*cloudwatchlogs.DeleteRetentionPolicyOutput) + } + } + + return r0, r1 +} + +// DeleteRetentionPolicyWithContext provides a mock function with given fields: _a0, _a1, _a2 +func (_m *CloudWatchLogsAPI) DeleteRetentionPolicyWithContext(_a0 context.Context, _a1 *cloudwatchlogs.DeleteRetentionPolicyInput, _a2 ...request.Option) (*cloudwatchlogs.DeleteRetentionPolicyOutput, error) { + _va := make([]interface{}, len(_a2)) + for _i := range _a2 { + _va[_i] = _a2[_i] + } + var _ca []interface{} + _ca = append(_ca, _a0, _a1) + _ca = append(_ca, _va...) + ret := _m.Called(_ca...) + + var r0 *cloudwatchlogs.DeleteRetentionPolicyOutput + if rf, ok := ret.Get(0).(func(context.Context, *cloudwatchlogs.DeleteRetentionPolicyInput, ...request.Option) *cloudwatchlogs.DeleteRetentionPolicyOutput); ok { + r0 = rf(_a0, _a1, _a2...) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*cloudwatchlogs.DeleteRetentionPolicyOutput) + } + } + + var r1 error + if rf, ok := ret.Get(1).(func(context.Context, *cloudwatchlogs.DeleteRetentionPolicyInput, ...request.Option) error); ok { + r1 = rf(_a0, _a1, _a2...) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// DeleteSubscriptionFilter provides a mock function with given fields: _a0 +func (_m *CloudWatchLogsAPI) DeleteSubscriptionFilter(_a0 *cloudwatchlogs.DeleteSubscriptionFilterInput) (*cloudwatchlogs.DeleteSubscriptionFilterOutput, error) { + ret := _m.Called(_a0) + + var r0 *cloudwatchlogs.DeleteSubscriptionFilterOutput + if rf, ok := ret.Get(0).(func(*cloudwatchlogs.DeleteSubscriptionFilterInput) *cloudwatchlogs.DeleteSubscriptionFilterOutput); ok { + r0 = rf(_a0) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*cloudwatchlogs.DeleteSubscriptionFilterOutput) + } + } + + var r1 error + if rf, ok := ret.Get(1).(func(*cloudwatchlogs.DeleteSubscriptionFilterInput) error); ok { + r1 = rf(_a0) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// DeleteSubscriptionFilterRequest provides a mock function with given fields: _a0 +func (_m *CloudWatchLogsAPI) DeleteSubscriptionFilterRequest(_a0 *cloudwatchlogs.DeleteSubscriptionFilterInput) (*request.Request, *cloudwatchlogs.DeleteSubscriptionFilterOutput) { + ret := _m.Called(_a0) + + var r0 *request.Request + if rf, ok := ret.Get(0).(func(*cloudwatchlogs.DeleteSubscriptionFilterInput) *request.Request); ok { + r0 = rf(_a0) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*request.Request) + } + } + + var r1 *cloudwatchlogs.DeleteSubscriptionFilterOutput + if rf, ok := ret.Get(1).(func(*cloudwatchlogs.DeleteSubscriptionFilterInput) *cloudwatchlogs.DeleteSubscriptionFilterOutput); ok { + r1 = rf(_a0) + } else { + if ret.Get(1) != nil { + r1 = ret.Get(1).(*cloudwatchlogs.DeleteSubscriptionFilterOutput) + } + } + + return r0, r1 +} + +// DeleteSubscriptionFilterWithContext provides a mock function with given fields: _a0, _a1, _a2 +func (_m *CloudWatchLogsAPI) DeleteSubscriptionFilterWithContext(_a0 context.Context, _a1 *cloudwatchlogs.DeleteSubscriptionFilterInput, _a2 ...request.Option) (*cloudwatchlogs.DeleteSubscriptionFilterOutput, error) { + _va := make([]interface{}, len(_a2)) + for _i := range _a2 { + _va[_i] = _a2[_i] + } + var _ca []interface{} + _ca = append(_ca, _a0, _a1) + _ca = append(_ca, _va...) + ret := _m.Called(_ca...) + + var r0 *cloudwatchlogs.DeleteSubscriptionFilterOutput + if rf, ok := ret.Get(0).(func(context.Context, *cloudwatchlogs.DeleteSubscriptionFilterInput, ...request.Option) *cloudwatchlogs.DeleteSubscriptionFilterOutput); ok { + r0 = rf(_a0, _a1, _a2...) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*cloudwatchlogs.DeleteSubscriptionFilterOutput) + } + } + + var r1 error + if rf, ok := ret.Get(1).(func(context.Context, *cloudwatchlogs.DeleteSubscriptionFilterInput, ...request.Option) error); ok { + r1 = rf(_a0, _a1, _a2...) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// DescribeDestinations provides a mock function with given fields: _a0 +func (_m *CloudWatchLogsAPI) DescribeDestinations(_a0 *cloudwatchlogs.DescribeDestinationsInput) (*cloudwatchlogs.DescribeDestinationsOutput, error) { + ret := _m.Called(_a0) + + var r0 *cloudwatchlogs.DescribeDestinationsOutput + if rf, ok := ret.Get(0).(func(*cloudwatchlogs.DescribeDestinationsInput) *cloudwatchlogs.DescribeDestinationsOutput); ok { + r0 = rf(_a0) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*cloudwatchlogs.DescribeDestinationsOutput) + } + } + + var r1 error + if rf, ok := ret.Get(1).(func(*cloudwatchlogs.DescribeDestinationsInput) error); ok { + r1 = rf(_a0) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// DescribeDestinationsPages provides a mock function with given fields: _a0, _a1 +func (_m *CloudWatchLogsAPI) DescribeDestinationsPages(_a0 *cloudwatchlogs.DescribeDestinationsInput, _a1 func(*cloudwatchlogs.DescribeDestinationsOutput, bool) bool) error { + ret := _m.Called(_a0, _a1) + + var r0 error + if rf, ok := ret.Get(0).(func(*cloudwatchlogs.DescribeDestinationsInput, func(*cloudwatchlogs.DescribeDestinationsOutput, bool) bool) error); ok { + r0 = rf(_a0, _a1) + } else { + r0 = ret.Error(0) + } + + return r0 +} + +// DescribeDestinationsPagesWithContext provides a mock function with given fields: _a0, _a1, _a2, _a3 +func (_m *CloudWatchLogsAPI) DescribeDestinationsPagesWithContext(_a0 context.Context, _a1 *cloudwatchlogs.DescribeDestinationsInput, _a2 func(*cloudwatchlogs.DescribeDestinationsOutput, bool) bool, _a3 ...request.Option) error { + _va := make([]interface{}, len(_a3)) + for _i := range _a3 { + _va[_i] = _a3[_i] + } + var _ca []interface{} + _ca = append(_ca, _a0, _a1, _a2) + _ca = append(_ca, _va...) + ret := _m.Called(_ca...) + + var r0 error + if rf, ok := ret.Get(0).(func(context.Context, *cloudwatchlogs.DescribeDestinationsInput, func(*cloudwatchlogs.DescribeDestinationsOutput, bool) bool, ...request.Option) error); ok { + r0 = rf(_a0, _a1, _a2, _a3...) + } else { + r0 = ret.Error(0) + } + + return r0 +} + +// DescribeDestinationsRequest provides a mock function with given fields: _a0 +func (_m *CloudWatchLogsAPI) DescribeDestinationsRequest(_a0 *cloudwatchlogs.DescribeDestinationsInput) (*request.Request, *cloudwatchlogs.DescribeDestinationsOutput) { + ret := _m.Called(_a0) + + var r0 *request.Request + if rf, ok := ret.Get(0).(func(*cloudwatchlogs.DescribeDestinationsInput) *request.Request); ok { + r0 = rf(_a0) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*request.Request) + } + } + + var r1 *cloudwatchlogs.DescribeDestinationsOutput + if rf, ok := ret.Get(1).(func(*cloudwatchlogs.DescribeDestinationsInput) *cloudwatchlogs.DescribeDestinationsOutput); ok { + r1 = rf(_a0) + } else { + if ret.Get(1) != nil { + r1 = ret.Get(1).(*cloudwatchlogs.DescribeDestinationsOutput) + } + } + + return r0, r1 +} + +// DescribeDestinationsWithContext provides a mock function with given fields: _a0, _a1, _a2 +func (_m *CloudWatchLogsAPI) DescribeDestinationsWithContext(_a0 context.Context, _a1 *cloudwatchlogs.DescribeDestinationsInput, _a2 ...request.Option) (*cloudwatchlogs.DescribeDestinationsOutput, error) { + _va := make([]interface{}, len(_a2)) + for _i := range _a2 { + _va[_i] = _a2[_i] + } + var _ca []interface{} + _ca = append(_ca, _a0, _a1) + _ca = append(_ca, _va...) + ret := _m.Called(_ca...) + + var r0 *cloudwatchlogs.DescribeDestinationsOutput + if rf, ok := ret.Get(0).(func(context.Context, *cloudwatchlogs.DescribeDestinationsInput, ...request.Option) *cloudwatchlogs.DescribeDestinationsOutput); ok { + r0 = rf(_a0, _a1, _a2...) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*cloudwatchlogs.DescribeDestinationsOutput) + } + } + + var r1 error + if rf, ok := ret.Get(1).(func(context.Context, *cloudwatchlogs.DescribeDestinationsInput, ...request.Option) error); ok { + r1 = rf(_a0, _a1, _a2...) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// DescribeExportTasks provides a mock function with given fields: _a0 +func (_m *CloudWatchLogsAPI) DescribeExportTasks(_a0 *cloudwatchlogs.DescribeExportTasksInput) (*cloudwatchlogs.DescribeExportTasksOutput, error) { + ret := _m.Called(_a0) + + var r0 *cloudwatchlogs.DescribeExportTasksOutput + if rf, ok := ret.Get(0).(func(*cloudwatchlogs.DescribeExportTasksInput) *cloudwatchlogs.DescribeExportTasksOutput); ok { + r0 = rf(_a0) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*cloudwatchlogs.DescribeExportTasksOutput) + } + } + + var r1 error + if rf, ok := ret.Get(1).(func(*cloudwatchlogs.DescribeExportTasksInput) error); ok { + r1 = rf(_a0) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// DescribeExportTasksRequest provides a mock function with given fields: _a0 +func (_m *CloudWatchLogsAPI) DescribeExportTasksRequest(_a0 *cloudwatchlogs.DescribeExportTasksInput) (*request.Request, *cloudwatchlogs.DescribeExportTasksOutput) { + ret := _m.Called(_a0) + + var r0 *request.Request + if rf, ok := ret.Get(0).(func(*cloudwatchlogs.DescribeExportTasksInput) *request.Request); ok { + r0 = rf(_a0) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*request.Request) + } + } + + var r1 *cloudwatchlogs.DescribeExportTasksOutput + if rf, ok := ret.Get(1).(func(*cloudwatchlogs.DescribeExportTasksInput) *cloudwatchlogs.DescribeExportTasksOutput); ok { + r1 = rf(_a0) + } else { + if ret.Get(1) != nil { + r1 = ret.Get(1).(*cloudwatchlogs.DescribeExportTasksOutput) + } + } + + return r0, r1 +} + +// DescribeExportTasksWithContext provides a mock function with given fields: _a0, _a1, _a2 +func (_m *CloudWatchLogsAPI) DescribeExportTasksWithContext(_a0 context.Context, _a1 *cloudwatchlogs.DescribeExportTasksInput, _a2 ...request.Option) (*cloudwatchlogs.DescribeExportTasksOutput, error) { + _va := make([]interface{}, len(_a2)) + for _i := range _a2 { + _va[_i] = _a2[_i] + } + var _ca []interface{} + _ca = append(_ca, _a0, _a1) + _ca = append(_ca, _va...) + ret := _m.Called(_ca...) + + var r0 *cloudwatchlogs.DescribeExportTasksOutput + if rf, ok := ret.Get(0).(func(context.Context, *cloudwatchlogs.DescribeExportTasksInput, ...request.Option) *cloudwatchlogs.DescribeExportTasksOutput); ok { + r0 = rf(_a0, _a1, _a2...) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*cloudwatchlogs.DescribeExportTasksOutput) + } + } + + var r1 error + if rf, ok := ret.Get(1).(func(context.Context, *cloudwatchlogs.DescribeExportTasksInput, ...request.Option) error); ok { + r1 = rf(_a0, _a1, _a2...) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// DescribeLogGroups provides a mock function with given fields: _a0 +func (_m *CloudWatchLogsAPI) DescribeLogGroups(_a0 *cloudwatchlogs.DescribeLogGroupsInput) (*cloudwatchlogs.DescribeLogGroupsOutput, error) { + ret := _m.Called(_a0) + + var r0 *cloudwatchlogs.DescribeLogGroupsOutput + if rf, ok := ret.Get(0).(func(*cloudwatchlogs.DescribeLogGroupsInput) *cloudwatchlogs.DescribeLogGroupsOutput); ok { + r0 = rf(_a0) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*cloudwatchlogs.DescribeLogGroupsOutput) + } + } + + var r1 error + if rf, ok := ret.Get(1).(func(*cloudwatchlogs.DescribeLogGroupsInput) error); ok { + r1 = rf(_a0) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// DescribeLogGroupsPages provides a mock function with given fields: _a0, _a1 +func (_m *CloudWatchLogsAPI) DescribeLogGroupsPages(_a0 *cloudwatchlogs.DescribeLogGroupsInput, _a1 func(*cloudwatchlogs.DescribeLogGroupsOutput, bool) bool) error { + ret := _m.Called(_a0, _a1) + + var r0 error + if rf, ok := ret.Get(0).(func(*cloudwatchlogs.DescribeLogGroupsInput, func(*cloudwatchlogs.DescribeLogGroupsOutput, bool) bool) error); ok { + r0 = rf(_a0, _a1) + } else { + r0 = ret.Error(0) + } + + return r0 +} + +// DescribeLogGroupsPagesWithContext provides a mock function with given fields: _a0, _a1, _a2, _a3 +func (_m *CloudWatchLogsAPI) DescribeLogGroupsPagesWithContext(_a0 context.Context, _a1 *cloudwatchlogs.DescribeLogGroupsInput, _a2 func(*cloudwatchlogs.DescribeLogGroupsOutput, bool) bool, _a3 ...request.Option) error { + _va := make([]interface{}, len(_a3)) + for _i := range _a3 { + _va[_i] = _a3[_i] + } + var _ca []interface{} + _ca = append(_ca, _a0, _a1, _a2) + _ca = append(_ca, _va...) + ret := _m.Called(_ca...) + + var r0 error + if rf, ok := ret.Get(0).(func(context.Context, *cloudwatchlogs.DescribeLogGroupsInput, func(*cloudwatchlogs.DescribeLogGroupsOutput, bool) bool, ...request.Option) error); ok { + r0 = rf(_a0, _a1, _a2, _a3...) + } else { + r0 = ret.Error(0) + } + + return r0 +} + +// DescribeLogGroupsRequest provides a mock function with given fields: _a0 +func (_m *CloudWatchLogsAPI) DescribeLogGroupsRequest(_a0 *cloudwatchlogs.DescribeLogGroupsInput) (*request.Request, *cloudwatchlogs.DescribeLogGroupsOutput) { + ret := _m.Called(_a0) + + var r0 *request.Request + if rf, ok := ret.Get(0).(func(*cloudwatchlogs.DescribeLogGroupsInput) *request.Request); ok { + r0 = rf(_a0) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*request.Request) + } + } + + var r1 *cloudwatchlogs.DescribeLogGroupsOutput + if rf, ok := ret.Get(1).(func(*cloudwatchlogs.DescribeLogGroupsInput) *cloudwatchlogs.DescribeLogGroupsOutput); ok { + r1 = rf(_a0) + } else { + if ret.Get(1) != nil { + r1 = ret.Get(1).(*cloudwatchlogs.DescribeLogGroupsOutput) + } + } + + return r0, r1 +} + +// DescribeLogGroupsWithContext provides a mock function with given fields: _a0, _a1, _a2 +func (_m *CloudWatchLogsAPI) DescribeLogGroupsWithContext(_a0 context.Context, _a1 *cloudwatchlogs.DescribeLogGroupsInput, _a2 ...request.Option) (*cloudwatchlogs.DescribeLogGroupsOutput, error) { + _va := make([]interface{}, len(_a2)) + for _i := range _a2 { + _va[_i] = _a2[_i] + } + var _ca []interface{} + _ca = append(_ca, _a0, _a1) + _ca = append(_ca, _va...) + ret := _m.Called(_ca...) + + var r0 *cloudwatchlogs.DescribeLogGroupsOutput + if rf, ok := ret.Get(0).(func(context.Context, *cloudwatchlogs.DescribeLogGroupsInput, ...request.Option) *cloudwatchlogs.DescribeLogGroupsOutput); ok { + r0 = rf(_a0, _a1, _a2...) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*cloudwatchlogs.DescribeLogGroupsOutput) + } + } + + var r1 error + if rf, ok := ret.Get(1).(func(context.Context, *cloudwatchlogs.DescribeLogGroupsInput, ...request.Option) error); ok { + r1 = rf(_a0, _a1, _a2...) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// DescribeLogStreams provides a mock function with given fields: _a0 +func (_m *CloudWatchLogsAPI) DescribeLogStreams(_a0 *cloudwatchlogs.DescribeLogStreamsInput) (*cloudwatchlogs.DescribeLogStreamsOutput, error) { + ret := _m.Called(_a0) + + var r0 *cloudwatchlogs.DescribeLogStreamsOutput + if rf, ok := ret.Get(0).(func(*cloudwatchlogs.DescribeLogStreamsInput) *cloudwatchlogs.DescribeLogStreamsOutput); ok { + r0 = rf(_a0) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*cloudwatchlogs.DescribeLogStreamsOutput) + } + } + + var r1 error + if rf, ok := ret.Get(1).(func(*cloudwatchlogs.DescribeLogStreamsInput) error); ok { + r1 = rf(_a0) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// DescribeLogStreamsPages provides a mock function with given fields: _a0, _a1 +func (_m *CloudWatchLogsAPI) DescribeLogStreamsPages(_a0 *cloudwatchlogs.DescribeLogStreamsInput, _a1 func(*cloudwatchlogs.DescribeLogStreamsOutput, bool) bool) error { + ret := _m.Called(_a0, _a1) + + var r0 error + if rf, ok := ret.Get(0).(func(*cloudwatchlogs.DescribeLogStreamsInput, func(*cloudwatchlogs.DescribeLogStreamsOutput, bool) bool) error); ok { + r0 = rf(_a0, _a1) + } else { + r0 = ret.Error(0) + } + + return r0 +} + +// DescribeLogStreamsPagesWithContext provides a mock function with given fields: _a0, _a1, _a2, _a3 +func (_m *CloudWatchLogsAPI) DescribeLogStreamsPagesWithContext(_a0 context.Context, _a1 *cloudwatchlogs.DescribeLogStreamsInput, _a2 func(*cloudwatchlogs.DescribeLogStreamsOutput, bool) bool, _a3 ...request.Option) error { + _va := make([]interface{}, len(_a3)) + for _i := range _a3 { + _va[_i] = _a3[_i] + } + var _ca []interface{} + _ca = append(_ca, _a0, _a1, _a2) + _ca = append(_ca, _va...) + ret := _m.Called(_ca...) + + var r0 error + if rf, ok := ret.Get(0).(func(context.Context, *cloudwatchlogs.DescribeLogStreamsInput, func(*cloudwatchlogs.DescribeLogStreamsOutput, bool) bool, ...request.Option) error); ok { + r0 = rf(_a0, _a1, _a2, _a3...) + } else { + r0 = ret.Error(0) + } + + return r0 +} + +// DescribeLogStreamsRequest provides a mock function with given fields: _a0 +func (_m *CloudWatchLogsAPI) DescribeLogStreamsRequest(_a0 *cloudwatchlogs.DescribeLogStreamsInput) (*request.Request, *cloudwatchlogs.DescribeLogStreamsOutput) { + ret := _m.Called(_a0) + + var r0 *request.Request + if rf, ok := ret.Get(0).(func(*cloudwatchlogs.DescribeLogStreamsInput) *request.Request); ok { + r0 = rf(_a0) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*request.Request) + } + } + + var r1 *cloudwatchlogs.DescribeLogStreamsOutput + if rf, ok := ret.Get(1).(func(*cloudwatchlogs.DescribeLogStreamsInput) *cloudwatchlogs.DescribeLogStreamsOutput); ok { + r1 = rf(_a0) + } else { + if ret.Get(1) != nil { + r1 = ret.Get(1).(*cloudwatchlogs.DescribeLogStreamsOutput) + } + } + + return r0, r1 +} + +// DescribeLogStreamsWithContext provides a mock function with given fields: _a0, _a1, _a2 +func (_m *CloudWatchLogsAPI) DescribeLogStreamsWithContext(_a0 context.Context, _a1 *cloudwatchlogs.DescribeLogStreamsInput, _a2 ...request.Option) (*cloudwatchlogs.DescribeLogStreamsOutput, error) { + _va := make([]interface{}, len(_a2)) + for _i := range _a2 { + _va[_i] = _a2[_i] + } + var _ca []interface{} + _ca = append(_ca, _a0, _a1) + _ca = append(_ca, _va...) + ret := _m.Called(_ca...) + + var r0 *cloudwatchlogs.DescribeLogStreamsOutput + if rf, ok := ret.Get(0).(func(context.Context, *cloudwatchlogs.DescribeLogStreamsInput, ...request.Option) *cloudwatchlogs.DescribeLogStreamsOutput); ok { + r0 = rf(_a0, _a1, _a2...) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*cloudwatchlogs.DescribeLogStreamsOutput) + } + } + + var r1 error + if rf, ok := ret.Get(1).(func(context.Context, *cloudwatchlogs.DescribeLogStreamsInput, ...request.Option) error); ok { + r1 = rf(_a0, _a1, _a2...) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// DescribeMetricFilters provides a mock function with given fields: _a0 +func (_m *CloudWatchLogsAPI) DescribeMetricFilters(_a0 *cloudwatchlogs.DescribeMetricFiltersInput) (*cloudwatchlogs.DescribeMetricFiltersOutput, error) { + ret := _m.Called(_a0) + + var r0 *cloudwatchlogs.DescribeMetricFiltersOutput + if rf, ok := ret.Get(0).(func(*cloudwatchlogs.DescribeMetricFiltersInput) *cloudwatchlogs.DescribeMetricFiltersOutput); ok { + r0 = rf(_a0) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*cloudwatchlogs.DescribeMetricFiltersOutput) + } + } + + var r1 error + if rf, ok := ret.Get(1).(func(*cloudwatchlogs.DescribeMetricFiltersInput) error); ok { + r1 = rf(_a0) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// DescribeMetricFiltersPages provides a mock function with given fields: _a0, _a1 +func (_m *CloudWatchLogsAPI) DescribeMetricFiltersPages(_a0 *cloudwatchlogs.DescribeMetricFiltersInput, _a1 func(*cloudwatchlogs.DescribeMetricFiltersOutput, bool) bool) error { + ret := _m.Called(_a0, _a1) + + var r0 error + if rf, ok := ret.Get(0).(func(*cloudwatchlogs.DescribeMetricFiltersInput, func(*cloudwatchlogs.DescribeMetricFiltersOutput, bool) bool) error); ok { + r0 = rf(_a0, _a1) + } else { + r0 = ret.Error(0) + } + + return r0 +} + +// DescribeMetricFiltersPagesWithContext provides a mock function with given fields: _a0, _a1, _a2, _a3 +func (_m *CloudWatchLogsAPI) DescribeMetricFiltersPagesWithContext(_a0 context.Context, _a1 *cloudwatchlogs.DescribeMetricFiltersInput, _a2 func(*cloudwatchlogs.DescribeMetricFiltersOutput, bool) bool, _a3 ...request.Option) error { + _va := make([]interface{}, len(_a3)) + for _i := range _a3 { + _va[_i] = _a3[_i] + } + var _ca []interface{} + _ca = append(_ca, _a0, _a1, _a2) + _ca = append(_ca, _va...) + ret := _m.Called(_ca...) + + var r0 error + if rf, ok := ret.Get(0).(func(context.Context, *cloudwatchlogs.DescribeMetricFiltersInput, func(*cloudwatchlogs.DescribeMetricFiltersOutput, bool) bool, ...request.Option) error); ok { + r0 = rf(_a0, _a1, _a2, _a3...) + } else { + r0 = ret.Error(0) + } + + return r0 +} + +// DescribeMetricFiltersRequest provides a mock function with given fields: _a0 +func (_m *CloudWatchLogsAPI) DescribeMetricFiltersRequest(_a0 *cloudwatchlogs.DescribeMetricFiltersInput) (*request.Request, *cloudwatchlogs.DescribeMetricFiltersOutput) { + ret := _m.Called(_a0) + + var r0 *request.Request + if rf, ok := ret.Get(0).(func(*cloudwatchlogs.DescribeMetricFiltersInput) *request.Request); ok { + r0 = rf(_a0) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*request.Request) + } + } + + var r1 *cloudwatchlogs.DescribeMetricFiltersOutput + if rf, ok := ret.Get(1).(func(*cloudwatchlogs.DescribeMetricFiltersInput) *cloudwatchlogs.DescribeMetricFiltersOutput); ok { + r1 = rf(_a0) + } else { + if ret.Get(1) != nil { + r1 = ret.Get(1).(*cloudwatchlogs.DescribeMetricFiltersOutput) + } + } + + return r0, r1 +} + +// DescribeMetricFiltersWithContext provides a mock function with given fields: _a0, _a1, _a2 +func (_m *CloudWatchLogsAPI) DescribeMetricFiltersWithContext(_a0 context.Context, _a1 *cloudwatchlogs.DescribeMetricFiltersInput, _a2 ...request.Option) (*cloudwatchlogs.DescribeMetricFiltersOutput, error) { + _va := make([]interface{}, len(_a2)) + for _i := range _a2 { + _va[_i] = _a2[_i] + } + var _ca []interface{} + _ca = append(_ca, _a0, _a1) + _ca = append(_ca, _va...) + ret := _m.Called(_ca...) + + var r0 *cloudwatchlogs.DescribeMetricFiltersOutput + if rf, ok := ret.Get(0).(func(context.Context, *cloudwatchlogs.DescribeMetricFiltersInput, ...request.Option) *cloudwatchlogs.DescribeMetricFiltersOutput); ok { + r0 = rf(_a0, _a1, _a2...) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*cloudwatchlogs.DescribeMetricFiltersOutput) + } + } + + var r1 error + if rf, ok := ret.Get(1).(func(context.Context, *cloudwatchlogs.DescribeMetricFiltersInput, ...request.Option) error); ok { + r1 = rf(_a0, _a1, _a2...) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// DescribeQueries provides a mock function with given fields: _a0 +func (_m *CloudWatchLogsAPI) DescribeQueries(_a0 *cloudwatchlogs.DescribeQueriesInput) (*cloudwatchlogs.DescribeQueriesOutput, error) { + ret := _m.Called(_a0) + + var r0 *cloudwatchlogs.DescribeQueriesOutput + if rf, ok := ret.Get(0).(func(*cloudwatchlogs.DescribeQueriesInput) *cloudwatchlogs.DescribeQueriesOutput); ok { + r0 = rf(_a0) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*cloudwatchlogs.DescribeQueriesOutput) + } + } + + var r1 error + if rf, ok := ret.Get(1).(func(*cloudwatchlogs.DescribeQueriesInput) error); ok { + r1 = rf(_a0) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// DescribeQueriesRequest provides a mock function with given fields: _a0 +func (_m *CloudWatchLogsAPI) DescribeQueriesRequest(_a0 *cloudwatchlogs.DescribeQueriesInput) (*request.Request, *cloudwatchlogs.DescribeQueriesOutput) { + ret := _m.Called(_a0) + + var r0 *request.Request + if rf, ok := ret.Get(0).(func(*cloudwatchlogs.DescribeQueriesInput) *request.Request); ok { + r0 = rf(_a0) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*request.Request) + } + } + + var r1 *cloudwatchlogs.DescribeQueriesOutput + if rf, ok := ret.Get(1).(func(*cloudwatchlogs.DescribeQueriesInput) *cloudwatchlogs.DescribeQueriesOutput); ok { + r1 = rf(_a0) + } else { + if ret.Get(1) != nil { + r1 = ret.Get(1).(*cloudwatchlogs.DescribeQueriesOutput) + } + } + + return r0, r1 +} + +// DescribeQueriesWithContext provides a mock function with given fields: _a0, _a1, _a2 +func (_m *CloudWatchLogsAPI) DescribeQueriesWithContext(_a0 context.Context, _a1 *cloudwatchlogs.DescribeQueriesInput, _a2 ...request.Option) (*cloudwatchlogs.DescribeQueriesOutput, error) { + _va := make([]interface{}, len(_a2)) + for _i := range _a2 { + _va[_i] = _a2[_i] + } + var _ca []interface{} + _ca = append(_ca, _a0, _a1) + _ca = append(_ca, _va...) + ret := _m.Called(_ca...) + + var r0 *cloudwatchlogs.DescribeQueriesOutput + if rf, ok := ret.Get(0).(func(context.Context, *cloudwatchlogs.DescribeQueriesInput, ...request.Option) *cloudwatchlogs.DescribeQueriesOutput); ok { + r0 = rf(_a0, _a1, _a2...) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*cloudwatchlogs.DescribeQueriesOutput) + } + } + + var r1 error + if rf, ok := ret.Get(1).(func(context.Context, *cloudwatchlogs.DescribeQueriesInput, ...request.Option) error); ok { + r1 = rf(_a0, _a1, _a2...) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// DescribeQueryDefinitions provides a mock function with given fields: _a0 +func (_m *CloudWatchLogsAPI) DescribeQueryDefinitions(_a0 *cloudwatchlogs.DescribeQueryDefinitionsInput) (*cloudwatchlogs.DescribeQueryDefinitionsOutput, error) { + ret := _m.Called(_a0) + + var r0 *cloudwatchlogs.DescribeQueryDefinitionsOutput + if rf, ok := ret.Get(0).(func(*cloudwatchlogs.DescribeQueryDefinitionsInput) *cloudwatchlogs.DescribeQueryDefinitionsOutput); ok { + r0 = rf(_a0) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*cloudwatchlogs.DescribeQueryDefinitionsOutput) + } + } + + var r1 error + if rf, ok := ret.Get(1).(func(*cloudwatchlogs.DescribeQueryDefinitionsInput) error); ok { + r1 = rf(_a0) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// DescribeQueryDefinitionsRequest provides a mock function with given fields: _a0 +func (_m *CloudWatchLogsAPI) DescribeQueryDefinitionsRequest(_a0 *cloudwatchlogs.DescribeQueryDefinitionsInput) (*request.Request, *cloudwatchlogs.DescribeQueryDefinitionsOutput) { + ret := _m.Called(_a0) + + var r0 *request.Request + if rf, ok := ret.Get(0).(func(*cloudwatchlogs.DescribeQueryDefinitionsInput) *request.Request); ok { + r0 = rf(_a0) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*request.Request) + } + } + + var r1 *cloudwatchlogs.DescribeQueryDefinitionsOutput + if rf, ok := ret.Get(1).(func(*cloudwatchlogs.DescribeQueryDefinitionsInput) *cloudwatchlogs.DescribeQueryDefinitionsOutput); ok { + r1 = rf(_a0) + } else { + if ret.Get(1) != nil { + r1 = ret.Get(1).(*cloudwatchlogs.DescribeQueryDefinitionsOutput) + } + } + + return r0, r1 +} + +// DescribeQueryDefinitionsWithContext provides a mock function with given fields: _a0, _a1, _a2 +func (_m *CloudWatchLogsAPI) DescribeQueryDefinitionsWithContext(_a0 context.Context, _a1 *cloudwatchlogs.DescribeQueryDefinitionsInput, _a2 ...request.Option) (*cloudwatchlogs.DescribeQueryDefinitionsOutput, error) { + _va := make([]interface{}, len(_a2)) + for _i := range _a2 { + _va[_i] = _a2[_i] + } + var _ca []interface{} + _ca = append(_ca, _a0, _a1) + _ca = append(_ca, _va...) + ret := _m.Called(_ca...) + + var r0 *cloudwatchlogs.DescribeQueryDefinitionsOutput + if rf, ok := ret.Get(0).(func(context.Context, *cloudwatchlogs.DescribeQueryDefinitionsInput, ...request.Option) *cloudwatchlogs.DescribeQueryDefinitionsOutput); ok { + r0 = rf(_a0, _a1, _a2...) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*cloudwatchlogs.DescribeQueryDefinitionsOutput) + } + } + + var r1 error + if rf, ok := ret.Get(1).(func(context.Context, *cloudwatchlogs.DescribeQueryDefinitionsInput, ...request.Option) error); ok { + r1 = rf(_a0, _a1, _a2...) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// DescribeResourcePolicies provides a mock function with given fields: _a0 +func (_m *CloudWatchLogsAPI) DescribeResourcePolicies(_a0 *cloudwatchlogs.DescribeResourcePoliciesInput) (*cloudwatchlogs.DescribeResourcePoliciesOutput, error) { + ret := _m.Called(_a0) + + var r0 *cloudwatchlogs.DescribeResourcePoliciesOutput + if rf, ok := ret.Get(0).(func(*cloudwatchlogs.DescribeResourcePoliciesInput) *cloudwatchlogs.DescribeResourcePoliciesOutput); ok { + r0 = rf(_a0) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*cloudwatchlogs.DescribeResourcePoliciesOutput) + } + } + + var r1 error + if rf, ok := ret.Get(1).(func(*cloudwatchlogs.DescribeResourcePoliciesInput) error); ok { + r1 = rf(_a0) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// DescribeResourcePoliciesRequest provides a mock function with given fields: _a0 +func (_m *CloudWatchLogsAPI) DescribeResourcePoliciesRequest(_a0 *cloudwatchlogs.DescribeResourcePoliciesInput) (*request.Request, *cloudwatchlogs.DescribeResourcePoliciesOutput) { + ret := _m.Called(_a0) + + var r0 *request.Request + if rf, ok := ret.Get(0).(func(*cloudwatchlogs.DescribeResourcePoliciesInput) *request.Request); ok { + r0 = rf(_a0) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*request.Request) + } + } + + var r1 *cloudwatchlogs.DescribeResourcePoliciesOutput + if rf, ok := ret.Get(1).(func(*cloudwatchlogs.DescribeResourcePoliciesInput) *cloudwatchlogs.DescribeResourcePoliciesOutput); ok { + r1 = rf(_a0) + } else { + if ret.Get(1) != nil { + r1 = ret.Get(1).(*cloudwatchlogs.DescribeResourcePoliciesOutput) + } + } + + return r0, r1 +} + +// DescribeResourcePoliciesWithContext provides a mock function with given fields: _a0, _a1, _a2 +func (_m *CloudWatchLogsAPI) DescribeResourcePoliciesWithContext(_a0 context.Context, _a1 *cloudwatchlogs.DescribeResourcePoliciesInput, _a2 ...request.Option) (*cloudwatchlogs.DescribeResourcePoliciesOutput, error) { + _va := make([]interface{}, len(_a2)) + for _i := range _a2 { + _va[_i] = _a2[_i] + } + var _ca []interface{} + _ca = append(_ca, _a0, _a1) + _ca = append(_ca, _va...) + ret := _m.Called(_ca...) + + var r0 *cloudwatchlogs.DescribeResourcePoliciesOutput + if rf, ok := ret.Get(0).(func(context.Context, *cloudwatchlogs.DescribeResourcePoliciesInput, ...request.Option) *cloudwatchlogs.DescribeResourcePoliciesOutput); ok { + r0 = rf(_a0, _a1, _a2...) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*cloudwatchlogs.DescribeResourcePoliciesOutput) + } + } + + var r1 error + if rf, ok := ret.Get(1).(func(context.Context, *cloudwatchlogs.DescribeResourcePoliciesInput, ...request.Option) error); ok { + r1 = rf(_a0, _a1, _a2...) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// DescribeSubscriptionFilters provides a mock function with given fields: _a0 +func (_m *CloudWatchLogsAPI) DescribeSubscriptionFilters(_a0 *cloudwatchlogs.DescribeSubscriptionFiltersInput) (*cloudwatchlogs.DescribeSubscriptionFiltersOutput, error) { + ret := _m.Called(_a0) + + var r0 *cloudwatchlogs.DescribeSubscriptionFiltersOutput + if rf, ok := ret.Get(0).(func(*cloudwatchlogs.DescribeSubscriptionFiltersInput) *cloudwatchlogs.DescribeSubscriptionFiltersOutput); ok { + r0 = rf(_a0) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*cloudwatchlogs.DescribeSubscriptionFiltersOutput) + } + } + + var r1 error + if rf, ok := ret.Get(1).(func(*cloudwatchlogs.DescribeSubscriptionFiltersInput) error); ok { + r1 = rf(_a0) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// DescribeSubscriptionFiltersPages provides a mock function with given fields: _a0, _a1 +func (_m *CloudWatchLogsAPI) DescribeSubscriptionFiltersPages(_a0 *cloudwatchlogs.DescribeSubscriptionFiltersInput, _a1 func(*cloudwatchlogs.DescribeSubscriptionFiltersOutput, bool) bool) error { + ret := _m.Called(_a0, _a1) + + var r0 error + if rf, ok := ret.Get(0).(func(*cloudwatchlogs.DescribeSubscriptionFiltersInput, func(*cloudwatchlogs.DescribeSubscriptionFiltersOutput, bool) bool) error); ok { + r0 = rf(_a0, _a1) + } else { + r0 = ret.Error(0) + } + + return r0 +} + +// DescribeSubscriptionFiltersPagesWithContext provides a mock function with given fields: _a0, _a1, _a2, _a3 +func (_m *CloudWatchLogsAPI) DescribeSubscriptionFiltersPagesWithContext(_a0 context.Context, _a1 *cloudwatchlogs.DescribeSubscriptionFiltersInput, _a2 func(*cloudwatchlogs.DescribeSubscriptionFiltersOutput, bool) bool, _a3 ...request.Option) error { + _va := make([]interface{}, len(_a3)) + for _i := range _a3 { + _va[_i] = _a3[_i] + } + var _ca []interface{} + _ca = append(_ca, _a0, _a1, _a2) + _ca = append(_ca, _va...) + ret := _m.Called(_ca...) + + var r0 error + if rf, ok := ret.Get(0).(func(context.Context, *cloudwatchlogs.DescribeSubscriptionFiltersInput, func(*cloudwatchlogs.DescribeSubscriptionFiltersOutput, bool) bool, ...request.Option) error); ok { + r0 = rf(_a0, _a1, _a2, _a3...) + } else { + r0 = ret.Error(0) + } + + return r0 +} + +// DescribeSubscriptionFiltersRequest provides a mock function with given fields: _a0 +func (_m *CloudWatchLogsAPI) DescribeSubscriptionFiltersRequest(_a0 *cloudwatchlogs.DescribeSubscriptionFiltersInput) (*request.Request, *cloudwatchlogs.DescribeSubscriptionFiltersOutput) { + ret := _m.Called(_a0) + + var r0 *request.Request + if rf, ok := ret.Get(0).(func(*cloudwatchlogs.DescribeSubscriptionFiltersInput) *request.Request); ok { + r0 = rf(_a0) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*request.Request) + } + } + + var r1 *cloudwatchlogs.DescribeSubscriptionFiltersOutput + if rf, ok := ret.Get(1).(func(*cloudwatchlogs.DescribeSubscriptionFiltersInput) *cloudwatchlogs.DescribeSubscriptionFiltersOutput); ok { + r1 = rf(_a0) + } else { + if ret.Get(1) != nil { + r1 = ret.Get(1).(*cloudwatchlogs.DescribeSubscriptionFiltersOutput) + } + } + + return r0, r1 +} + +// DescribeSubscriptionFiltersWithContext provides a mock function with given fields: _a0, _a1, _a2 +func (_m *CloudWatchLogsAPI) DescribeSubscriptionFiltersWithContext(_a0 context.Context, _a1 *cloudwatchlogs.DescribeSubscriptionFiltersInput, _a2 ...request.Option) (*cloudwatchlogs.DescribeSubscriptionFiltersOutput, error) { + _va := make([]interface{}, len(_a2)) + for _i := range _a2 { + _va[_i] = _a2[_i] + } + var _ca []interface{} + _ca = append(_ca, _a0, _a1) + _ca = append(_ca, _va...) + ret := _m.Called(_ca...) + + var r0 *cloudwatchlogs.DescribeSubscriptionFiltersOutput + if rf, ok := ret.Get(0).(func(context.Context, *cloudwatchlogs.DescribeSubscriptionFiltersInput, ...request.Option) *cloudwatchlogs.DescribeSubscriptionFiltersOutput); ok { + r0 = rf(_a0, _a1, _a2...) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*cloudwatchlogs.DescribeSubscriptionFiltersOutput) + } + } + + var r1 error + if rf, ok := ret.Get(1).(func(context.Context, *cloudwatchlogs.DescribeSubscriptionFiltersInput, ...request.Option) error); ok { + r1 = rf(_a0, _a1, _a2...) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// DisassociateKmsKey provides a mock function with given fields: _a0 +func (_m *CloudWatchLogsAPI) DisassociateKmsKey(_a0 *cloudwatchlogs.DisassociateKmsKeyInput) (*cloudwatchlogs.DisassociateKmsKeyOutput, error) { + ret := _m.Called(_a0) + + var r0 *cloudwatchlogs.DisassociateKmsKeyOutput + if rf, ok := ret.Get(0).(func(*cloudwatchlogs.DisassociateKmsKeyInput) *cloudwatchlogs.DisassociateKmsKeyOutput); ok { + r0 = rf(_a0) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*cloudwatchlogs.DisassociateKmsKeyOutput) + } + } + + var r1 error + if rf, ok := ret.Get(1).(func(*cloudwatchlogs.DisassociateKmsKeyInput) error); ok { + r1 = rf(_a0) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// DisassociateKmsKeyRequest provides a mock function with given fields: _a0 +func (_m *CloudWatchLogsAPI) DisassociateKmsKeyRequest(_a0 *cloudwatchlogs.DisassociateKmsKeyInput) (*request.Request, *cloudwatchlogs.DisassociateKmsKeyOutput) { + ret := _m.Called(_a0) + + var r0 *request.Request + if rf, ok := ret.Get(0).(func(*cloudwatchlogs.DisassociateKmsKeyInput) *request.Request); ok { + r0 = rf(_a0) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*request.Request) + } + } + + var r1 *cloudwatchlogs.DisassociateKmsKeyOutput + if rf, ok := ret.Get(1).(func(*cloudwatchlogs.DisassociateKmsKeyInput) *cloudwatchlogs.DisassociateKmsKeyOutput); ok { + r1 = rf(_a0) + } else { + if ret.Get(1) != nil { + r1 = ret.Get(1).(*cloudwatchlogs.DisassociateKmsKeyOutput) + } + } + + return r0, r1 +} + +// DisassociateKmsKeyWithContext provides a mock function with given fields: _a0, _a1, _a2 +func (_m *CloudWatchLogsAPI) DisassociateKmsKeyWithContext(_a0 context.Context, _a1 *cloudwatchlogs.DisassociateKmsKeyInput, _a2 ...request.Option) (*cloudwatchlogs.DisassociateKmsKeyOutput, error) { + _va := make([]interface{}, len(_a2)) + for _i := range _a2 { + _va[_i] = _a2[_i] + } + var _ca []interface{} + _ca = append(_ca, _a0, _a1) + _ca = append(_ca, _va...) + ret := _m.Called(_ca...) + + var r0 *cloudwatchlogs.DisassociateKmsKeyOutput + if rf, ok := ret.Get(0).(func(context.Context, *cloudwatchlogs.DisassociateKmsKeyInput, ...request.Option) *cloudwatchlogs.DisassociateKmsKeyOutput); ok { + r0 = rf(_a0, _a1, _a2...) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*cloudwatchlogs.DisassociateKmsKeyOutput) + } + } + + var r1 error + if rf, ok := ret.Get(1).(func(context.Context, *cloudwatchlogs.DisassociateKmsKeyInput, ...request.Option) error); ok { + r1 = rf(_a0, _a1, _a2...) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// FilterLogEvents provides a mock function with given fields: _a0 +func (_m *CloudWatchLogsAPI) FilterLogEvents(_a0 *cloudwatchlogs.FilterLogEventsInput) (*cloudwatchlogs.FilterLogEventsOutput, error) { + ret := _m.Called(_a0) + + var r0 *cloudwatchlogs.FilterLogEventsOutput + if rf, ok := ret.Get(0).(func(*cloudwatchlogs.FilterLogEventsInput) *cloudwatchlogs.FilterLogEventsOutput); ok { + r0 = rf(_a0) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*cloudwatchlogs.FilterLogEventsOutput) + } + } + + var r1 error + if rf, ok := ret.Get(1).(func(*cloudwatchlogs.FilterLogEventsInput) error); ok { + r1 = rf(_a0) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// FilterLogEventsPages provides a mock function with given fields: _a0, _a1 +func (_m *CloudWatchLogsAPI) FilterLogEventsPages(_a0 *cloudwatchlogs.FilterLogEventsInput, _a1 func(*cloudwatchlogs.FilterLogEventsOutput, bool) bool) error { + ret := _m.Called(_a0, _a1) + + var r0 error + if rf, ok := ret.Get(0).(func(*cloudwatchlogs.FilterLogEventsInput, func(*cloudwatchlogs.FilterLogEventsOutput, bool) bool) error); ok { + r0 = rf(_a0, _a1) + } else { + r0 = ret.Error(0) + } + + return r0 +} + +// FilterLogEventsPagesWithContext provides a mock function with given fields: _a0, _a1, _a2, _a3 +func (_m *CloudWatchLogsAPI) FilterLogEventsPagesWithContext(_a0 context.Context, _a1 *cloudwatchlogs.FilterLogEventsInput, _a2 func(*cloudwatchlogs.FilterLogEventsOutput, bool) bool, _a3 ...request.Option) error { + _va := make([]interface{}, len(_a3)) + for _i := range _a3 { + _va[_i] = _a3[_i] + } + var _ca []interface{} + _ca = append(_ca, _a0, _a1, _a2) + _ca = append(_ca, _va...) + ret := _m.Called(_ca...) + + var r0 error + if rf, ok := ret.Get(0).(func(context.Context, *cloudwatchlogs.FilterLogEventsInput, func(*cloudwatchlogs.FilterLogEventsOutput, bool) bool, ...request.Option) error); ok { + r0 = rf(_a0, _a1, _a2, _a3...) + } else { + r0 = ret.Error(0) + } + + return r0 +} + +// FilterLogEventsRequest provides a mock function with given fields: _a0 +func (_m *CloudWatchLogsAPI) FilterLogEventsRequest(_a0 *cloudwatchlogs.FilterLogEventsInput) (*request.Request, *cloudwatchlogs.FilterLogEventsOutput) { + ret := _m.Called(_a0) + + var r0 *request.Request + if rf, ok := ret.Get(0).(func(*cloudwatchlogs.FilterLogEventsInput) *request.Request); ok { + r0 = rf(_a0) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*request.Request) + } + } + + var r1 *cloudwatchlogs.FilterLogEventsOutput + if rf, ok := ret.Get(1).(func(*cloudwatchlogs.FilterLogEventsInput) *cloudwatchlogs.FilterLogEventsOutput); ok { + r1 = rf(_a0) + } else { + if ret.Get(1) != nil { + r1 = ret.Get(1).(*cloudwatchlogs.FilterLogEventsOutput) + } + } + + return r0, r1 +} + +// FilterLogEventsWithContext provides a mock function with given fields: _a0, _a1, _a2 +func (_m *CloudWatchLogsAPI) FilterLogEventsWithContext(_a0 context.Context, _a1 *cloudwatchlogs.FilterLogEventsInput, _a2 ...request.Option) (*cloudwatchlogs.FilterLogEventsOutput, error) { + _va := make([]interface{}, len(_a2)) + for _i := range _a2 { + _va[_i] = _a2[_i] + } + var _ca []interface{} + _ca = append(_ca, _a0, _a1) + _ca = append(_ca, _va...) + ret := _m.Called(_ca...) + + var r0 *cloudwatchlogs.FilterLogEventsOutput + if rf, ok := ret.Get(0).(func(context.Context, *cloudwatchlogs.FilterLogEventsInput, ...request.Option) *cloudwatchlogs.FilterLogEventsOutput); ok { + r0 = rf(_a0, _a1, _a2...) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*cloudwatchlogs.FilterLogEventsOutput) + } + } + + var r1 error + if rf, ok := ret.Get(1).(func(context.Context, *cloudwatchlogs.FilterLogEventsInput, ...request.Option) error); ok { + r1 = rf(_a0, _a1, _a2...) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// GetLogEvents provides a mock function with given fields: _a0 +func (_m *CloudWatchLogsAPI) GetLogEvents(_a0 *cloudwatchlogs.GetLogEventsInput) (*cloudwatchlogs.GetLogEventsOutput, error) { + ret := _m.Called(_a0) + + var r0 *cloudwatchlogs.GetLogEventsOutput + if rf, ok := ret.Get(0).(func(*cloudwatchlogs.GetLogEventsInput) *cloudwatchlogs.GetLogEventsOutput); ok { + r0 = rf(_a0) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*cloudwatchlogs.GetLogEventsOutput) + } + } + + var r1 error + if rf, ok := ret.Get(1).(func(*cloudwatchlogs.GetLogEventsInput) error); ok { + r1 = rf(_a0) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// GetLogEventsPages provides a mock function with given fields: _a0, _a1 +func (_m *CloudWatchLogsAPI) GetLogEventsPages(_a0 *cloudwatchlogs.GetLogEventsInput, _a1 func(*cloudwatchlogs.GetLogEventsOutput, bool) bool) error { + ret := _m.Called(_a0, _a1) + + var r0 error + if rf, ok := ret.Get(0).(func(*cloudwatchlogs.GetLogEventsInput, func(*cloudwatchlogs.GetLogEventsOutput, bool) bool) error); ok { + r0 = rf(_a0, _a1) + } else { + r0 = ret.Error(0) + } + + return r0 +} + +// GetLogEventsPagesWithContext provides a mock function with given fields: _a0, _a1, _a2, _a3 +func (_m *CloudWatchLogsAPI) GetLogEventsPagesWithContext(_a0 context.Context, _a1 *cloudwatchlogs.GetLogEventsInput, _a2 func(*cloudwatchlogs.GetLogEventsOutput, bool) bool, _a3 ...request.Option) error { + _va := make([]interface{}, len(_a3)) + for _i := range _a3 { + _va[_i] = _a3[_i] + } + var _ca []interface{} + _ca = append(_ca, _a0, _a1, _a2) + _ca = append(_ca, _va...) + ret := _m.Called(_ca...) + + var r0 error + if rf, ok := ret.Get(0).(func(context.Context, *cloudwatchlogs.GetLogEventsInput, func(*cloudwatchlogs.GetLogEventsOutput, bool) bool, ...request.Option) error); ok { + r0 = rf(_a0, _a1, _a2, _a3...) + } else { + r0 = ret.Error(0) + } + + return r0 +} + +// GetLogEventsRequest provides a mock function with given fields: _a0 +func (_m *CloudWatchLogsAPI) GetLogEventsRequest(_a0 *cloudwatchlogs.GetLogEventsInput) (*request.Request, *cloudwatchlogs.GetLogEventsOutput) { + ret := _m.Called(_a0) + + var r0 *request.Request + if rf, ok := ret.Get(0).(func(*cloudwatchlogs.GetLogEventsInput) *request.Request); ok { + r0 = rf(_a0) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*request.Request) + } + } + + var r1 *cloudwatchlogs.GetLogEventsOutput + if rf, ok := ret.Get(1).(func(*cloudwatchlogs.GetLogEventsInput) *cloudwatchlogs.GetLogEventsOutput); ok { + r1 = rf(_a0) + } else { + if ret.Get(1) != nil { + r1 = ret.Get(1).(*cloudwatchlogs.GetLogEventsOutput) + } + } + + return r0, r1 +} + +// GetLogEventsWithContext provides a mock function with given fields: _a0, _a1, _a2 +func (_m *CloudWatchLogsAPI) GetLogEventsWithContext(_a0 context.Context, _a1 *cloudwatchlogs.GetLogEventsInput, _a2 ...request.Option) (*cloudwatchlogs.GetLogEventsOutput, error) { + _va := make([]interface{}, len(_a2)) + for _i := range _a2 { + _va[_i] = _a2[_i] + } + var _ca []interface{} + _ca = append(_ca, _a0, _a1) + _ca = append(_ca, _va...) + ret := _m.Called(_ca...) + + var r0 *cloudwatchlogs.GetLogEventsOutput + if rf, ok := ret.Get(0).(func(context.Context, *cloudwatchlogs.GetLogEventsInput, ...request.Option) *cloudwatchlogs.GetLogEventsOutput); ok { + r0 = rf(_a0, _a1, _a2...) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*cloudwatchlogs.GetLogEventsOutput) + } + } + + var r1 error + if rf, ok := ret.Get(1).(func(context.Context, *cloudwatchlogs.GetLogEventsInput, ...request.Option) error); ok { + r1 = rf(_a0, _a1, _a2...) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// GetLogGroupFields provides a mock function with given fields: _a0 +func (_m *CloudWatchLogsAPI) GetLogGroupFields(_a0 *cloudwatchlogs.GetLogGroupFieldsInput) (*cloudwatchlogs.GetLogGroupFieldsOutput, error) { + ret := _m.Called(_a0) + + var r0 *cloudwatchlogs.GetLogGroupFieldsOutput + if rf, ok := ret.Get(0).(func(*cloudwatchlogs.GetLogGroupFieldsInput) *cloudwatchlogs.GetLogGroupFieldsOutput); ok { + r0 = rf(_a0) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*cloudwatchlogs.GetLogGroupFieldsOutput) + } + } + + var r1 error + if rf, ok := ret.Get(1).(func(*cloudwatchlogs.GetLogGroupFieldsInput) error); ok { + r1 = rf(_a0) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// GetLogGroupFieldsRequest provides a mock function with given fields: _a0 +func (_m *CloudWatchLogsAPI) GetLogGroupFieldsRequest(_a0 *cloudwatchlogs.GetLogGroupFieldsInput) (*request.Request, *cloudwatchlogs.GetLogGroupFieldsOutput) { + ret := _m.Called(_a0) + + var r0 *request.Request + if rf, ok := ret.Get(0).(func(*cloudwatchlogs.GetLogGroupFieldsInput) *request.Request); ok { + r0 = rf(_a0) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*request.Request) + } + } + + var r1 *cloudwatchlogs.GetLogGroupFieldsOutput + if rf, ok := ret.Get(1).(func(*cloudwatchlogs.GetLogGroupFieldsInput) *cloudwatchlogs.GetLogGroupFieldsOutput); ok { + r1 = rf(_a0) + } else { + if ret.Get(1) != nil { + r1 = ret.Get(1).(*cloudwatchlogs.GetLogGroupFieldsOutput) + } + } + + return r0, r1 +} + +// GetLogGroupFieldsWithContext provides a mock function with given fields: _a0, _a1, _a2 +func (_m *CloudWatchLogsAPI) GetLogGroupFieldsWithContext(_a0 context.Context, _a1 *cloudwatchlogs.GetLogGroupFieldsInput, _a2 ...request.Option) (*cloudwatchlogs.GetLogGroupFieldsOutput, error) { + _va := make([]interface{}, len(_a2)) + for _i := range _a2 { + _va[_i] = _a2[_i] + } + var _ca []interface{} + _ca = append(_ca, _a0, _a1) + _ca = append(_ca, _va...) + ret := _m.Called(_ca...) + + var r0 *cloudwatchlogs.GetLogGroupFieldsOutput + if rf, ok := ret.Get(0).(func(context.Context, *cloudwatchlogs.GetLogGroupFieldsInput, ...request.Option) *cloudwatchlogs.GetLogGroupFieldsOutput); ok { + r0 = rf(_a0, _a1, _a2...) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*cloudwatchlogs.GetLogGroupFieldsOutput) + } + } + + var r1 error + if rf, ok := ret.Get(1).(func(context.Context, *cloudwatchlogs.GetLogGroupFieldsInput, ...request.Option) error); ok { + r1 = rf(_a0, _a1, _a2...) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// GetLogRecord provides a mock function with given fields: _a0 +func (_m *CloudWatchLogsAPI) GetLogRecord(_a0 *cloudwatchlogs.GetLogRecordInput) (*cloudwatchlogs.GetLogRecordOutput, error) { + ret := _m.Called(_a0) + + var r0 *cloudwatchlogs.GetLogRecordOutput + if rf, ok := ret.Get(0).(func(*cloudwatchlogs.GetLogRecordInput) *cloudwatchlogs.GetLogRecordOutput); ok { + r0 = rf(_a0) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*cloudwatchlogs.GetLogRecordOutput) + } + } + + var r1 error + if rf, ok := ret.Get(1).(func(*cloudwatchlogs.GetLogRecordInput) error); ok { + r1 = rf(_a0) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// GetLogRecordRequest provides a mock function with given fields: _a0 +func (_m *CloudWatchLogsAPI) GetLogRecordRequest(_a0 *cloudwatchlogs.GetLogRecordInput) (*request.Request, *cloudwatchlogs.GetLogRecordOutput) { + ret := _m.Called(_a0) + + var r0 *request.Request + if rf, ok := ret.Get(0).(func(*cloudwatchlogs.GetLogRecordInput) *request.Request); ok { + r0 = rf(_a0) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*request.Request) + } + } + + var r1 *cloudwatchlogs.GetLogRecordOutput + if rf, ok := ret.Get(1).(func(*cloudwatchlogs.GetLogRecordInput) *cloudwatchlogs.GetLogRecordOutput); ok { + r1 = rf(_a0) + } else { + if ret.Get(1) != nil { + r1 = ret.Get(1).(*cloudwatchlogs.GetLogRecordOutput) + } + } + + return r0, r1 +} + +// GetLogRecordWithContext provides a mock function with given fields: _a0, _a1, _a2 +func (_m *CloudWatchLogsAPI) GetLogRecordWithContext(_a0 context.Context, _a1 *cloudwatchlogs.GetLogRecordInput, _a2 ...request.Option) (*cloudwatchlogs.GetLogRecordOutput, error) { + _va := make([]interface{}, len(_a2)) + for _i := range _a2 { + _va[_i] = _a2[_i] + } + var _ca []interface{} + _ca = append(_ca, _a0, _a1) + _ca = append(_ca, _va...) + ret := _m.Called(_ca...) + + var r0 *cloudwatchlogs.GetLogRecordOutput + if rf, ok := ret.Get(0).(func(context.Context, *cloudwatchlogs.GetLogRecordInput, ...request.Option) *cloudwatchlogs.GetLogRecordOutput); ok { + r0 = rf(_a0, _a1, _a2...) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*cloudwatchlogs.GetLogRecordOutput) + } + } + + var r1 error + if rf, ok := ret.Get(1).(func(context.Context, *cloudwatchlogs.GetLogRecordInput, ...request.Option) error); ok { + r1 = rf(_a0, _a1, _a2...) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// GetQueryResults provides a mock function with given fields: _a0 +func (_m *CloudWatchLogsAPI) GetQueryResults(_a0 *cloudwatchlogs.GetQueryResultsInput) (*cloudwatchlogs.GetQueryResultsOutput, error) { + ret := _m.Called(_a0) + + var r0 *cloudwatchlogs.GetQueryResultsOutput + if rf, ok := ret.Get(0).(func(*cloudwatchlogs.GetQueryResultsInput) *cloudwatchlogs.GetQueryResultsOutput); ok { + r0 = rf(_a0) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*cloudwatchlogs.GetQueryResultsOutput) + } + } + + var r1 error + if rf, ok := ret.Get(1).(func(*cloudwatchlogs.GetQueryResultsInput) error); ok { + r1 = rf(_a0) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// GetQueryResultsRequest provides a mock function with given fields: _a0 +func (_m *CloudWatchLogsAPI) GetQueryResultsRequest(_a0 *cloudwatchlogs.GetQueryResultsInput) (*request.Request, *cloudwatchlogs.GetQueryResultsOutput) { + ret := _m.Called(_a0) + + var r0 *request.Request + if rf, ok := ret.Get(0).(func(*cloudwatchlogs.GetQueryResultsInput) *request.Request); ok { + r0 = rf(_a0) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*request.Request) + } + } + + var r1 *cloudwatchlogs.GetQueryResultsOutput + if rf, ok := ret.Get(1).(func(*cloudwatchlogs.GetQueryResultsInput) *cloudwatchlogs.GetQueryResultsOutput); ok { + r1 = rf(_a0) + } else { + if ret.Get(1) != nil { + r1 = ret.Get(1).(*cloudwatchlogs.GetQueryResultsOutput) + } + } + + return r0, r1 +} + +// GetQueryResultsWithContext provides a mock function with given fields: _a0, _a1, _a2 +func (_m *CloudWatchLogsAPI) GetQueryResultsWithContext(_a0 context.Context, _a1 *cloudwatchlogs.GetQueryResultsInput, _a2 ...request.Option) (*cloudwatchlogs.GetQueryResultsOutput, error) { + _va := make([]interface{}, len(_a2)) + for _i := range _a2 { + _va[_i] = _a2[_i] + } + var _ca []interface{} + _ca = append(_ca, _a0, _a1) + _ca = append(_ca, _va...) + ret := _m.Called(_ca...) + + var r0 *cloudwatchlogs.GetQueryResultsOutput + if rf, ok := ret.Get(0).(func(context.Context, *cloudwatchlogs.GetQueryResultsInput, ...request.Option) *cloudwatchlogs.GetQueryResultsOutput); ok { + r0 = rf(_a0, _a1, _a2...) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*cloudwatchlogs.GetQueryResultsOutput) + } + } + + var r1 error + if rf, ok := ret.Get(1).(func(context.Context, *cloudwatchlogs.GetQueryResultsInput, ...request.Option) error); ok { + r1 = rf(_a0, _a1, _a2...) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// ListTagsLogGroup provides a mock function with given fields: _a0 +func (_m *CloudWatchLogsAPI) ListTagsLogGroup(_a0 *cloudwatchlogs.ListTagsLogGroupInput) (*cloudwatchlogs.ListTagsLogGroupOutput, error) { + ret := _m.Called(_a0) + + var r0 *cloudwatchlogs.ListTagsLogGroupOutput + if rf, ok := ret.Get(0).(func(*cloudwatchlogs.ListTagsLogGroupInput) *cloudwatchlogs.ListTagsLogGroupOutput); ok { + r0 = rf(_a0) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*cloudwatchlogs.ListTagsLogGroupOutput) + } + } + + var r1 error + if rf, ok := ret.Get(1).(func(*cloudwatchlogs.ListTagsLogGroupInput) error); ok { + r1 = rf(_a0) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// ListTagsLogGroupRequest provides a mock function with given fields: _a0 +func (_m *CloudWatchLogsAPI) ListTagsLogGroupRequest(_a0 *cloudwatchlogs.ListTagsLogGroupInput) (*request.Request, *cloudwatchlogs.ListTagsLogGroupOutput) { + ret := _m.Called(_a0) + + var r0 *request.Request + if rf, ok := ret.Get(0).(func(*cloudwatchlogs.ListTagsLogGroupInput) *request.Request); ok { + r0 = rf(_a0) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*request.Request) + } + } + + var r1 *cloudwatchlogs.ListTagsLogGroupOutput + if rf, ok := ret.Get(1).(func(*cloudwatchlogs.ListTagsLogGroupInput) *cloudwatchlogs.ListTagsLogGroupOutput); ok { + r1 = rf(_a0) + } else { + if ret.Get(1) != nil { + r1 = ret.Get(1).(*cloudwatchlogs.ListTagsLogGroupOutput) + } + } + + return r0, r1 +} + +// ListTagsLogGroupWithContext provides a mock function with given fields: _a0, _a1, _a2 +func (_m *CloudWatchLogsAPI) ListTagsLogGroupWithContext(_a0 context.Context, _a1 *cloudwatchlogs.ListTagsLogGroupInput, _a2 ...request.Option) (*cloudwatchlogs.ListTagsLogGroupOutput, error) { + _va := make([]interface{}, len(_a2)) + for _i := range _a2 { + _va[_i] = _a2[_i] + } + var _ca []interface{} + _ca = append(_ca, _a0, _a1) + _ca = append(_ca, _va...) + ret := _m.Called(_ca...) + + var r0 *cloudwatchlogs.ListTagsLogGroupOutput + if rf, ok := ret.Get(0).(func(context.Context, *cloudwatchlogs.ListTagsLogGroupInput, ...request.Option) *cloudwatchlogs.ListTagsLogGroupOutput); ok { + r0 = rf(_a0, _a1, _a2...) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*cloudwatchlogs.ListTagsLogGroupOutput) + } + } + + var r1 error + if rf, ok := ret.Get(1).(func(context.Context, *cloudwatchlogs.ListTagsLogGroupInput, ...request.Option) error); ok { + r1 = rf(_a0, _a1, _a2...) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// PutDestination provides a mock function with given fields: _a0 +func (_m *CloudWatchLogsAPI) PutDestination(_a0 *cloudwatchlogs.PutDestinationInput) (*cloudwatchlogs.PutDestinationOutput, error) { + ret := _m.Called(_a0) + + var r0 *cloudwatchlogs.PutDestinationOutput + if rf, ok := ret.Get(0).(func(*cloudwatchlogs.PutDestinationInput) *cloudwatchlogs.PutDestinationOutput); ok { + r0 = rf(_a0) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*cloudwatchlogs.PutDestinationOutput) + } + } + + var r1 error + if rf, ok := ret.Get(1).(func(*cloudwatchlogs.PutDestinationInput) error); ok { + r1 = rf(_a0) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// PutDestinationPolicy provides a mock function with given fields: _a0 +func (_m *CloudWatchLogsAPI) PutDestinationPolicy(_a0 *cloudwatchlogs.PutDestinationPolicyInput) (*cloudwatchlogs.PutDestinationPolicyOutput, error) { + ret := _m.Called(_a0) + + var r0 *cloudwatchlogs.PutDestinationPolicyOutput + if rf, ok := ret.Get(0).(func(*cloudwatchlogs.PutDestinationPolicyInput) *cloudwatchlogs.PutDestinationPolicyOutput); ok { + r0 = rf(_a0) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*cloudwatchlogs.PutDestinationPolicyOutput) + } + } + + var r1 error + if rf, ok := ret.Get(1).(func(*cloudwatchlogs.PutDestinationPolicyInput) error); ok { + r1 = rf(_a0) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// PutDestinationPolicyRequest provides a mock function with given fields: _a0 +func (_m *CloudWatchLogsAPI) PutDestinationPolicyRequest(_a0 *cloudwatchlogs.PutDestinationPolicyInput) (*request.Request, *cloudwatchlogs.PutDestinationPolicyOutput) { + ret := _m.Called(_a0) + + var r0 *request.Request + if rf, ok := ret.Get(0).(func(*cloudwatchlogs.PutDestinationPolicyInput) *request.Request); ok { + r0 = rf(_a0) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*request.Request) + } + } + + var r1 *cloudwatchlogs.PutDestinationPolicyOutput + if rf, ok := ret.Get(1).(func(*cloudwatchlogs.PutDestinationPolicyInput) *cloudwatchlogs.PutDestinationPolicyOutput); ok { + r1 = rf(_a0) + } else { + if ret.Get(1) != nil { + r1 = ret.Get(1).(*cloudwatchlogs.PutDestinationPolicyOutput) + } + } + + return r0, r1 +} + +// PutDestinationPolicyWithContext provides a mock function with given fields: _a0, _a1, _a2 +func (_m *CloudWatchLogsAPI) PutDestinationPolicyWithContext(_a0 context.Context, _a1 *cloudwatchlogs.PutDestinationPolicyInput, _a2 ...request.Option) (*cloudwatchlogs.PutDestinationPolicyOutput, error) { + _va := make([]interface{}, len(_a2)) + for _i := range _a2 { + _va[_i] = _a2[_i] + } + var _ca []interface{} + _ca = append(_ca, _a0, _a1) + _ca = append(_ca, _va...) + ret := _m.Called(_ca...) + + var r0 *cloudwatchlogs.PutDestinationPolicyOutput + if rf, ok := ret.Get(0).(func(context.Context, *cloudwatchlogs.PutDestinationPolicyInput, ...request.Option) *cloudwatchlogs.PutDestinationPolicyOutput); ok { + r0 = rf(_a0, _a1, _a2...) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*cloudwatchlogs.PutDestinationPolicyOutput) + } + } + + var r1 error + if rf, ok := ret.Get(1).(func(context.Context, *cloudwatchlogs.PutDestinationPolicyInput, ...request.Option) error); ok { + r1 = rf(_a0, _a1, _a2...) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// PutDestinationRequest provides a mock function with given fields: _a0 +func (_m *CloudWatchLogsAPI) PutDestinationRequest(_a0 *cloudwatchlogs.PutDestinationInput) (*request.Request, *cloudwatchlogs.PutDestinationOutput) { + ret := _m.Called(_a0) + + var r0 *request.Request + if rf, ok := ret.Get(0).(func(*cloudwatchlogs.PutDestinationInput) *request.Request); ok { + r0 = rf(_a0) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*request.Request) + } + } + + var r1 *cloudwatchlogs.PutDestinationOutput + if rf, ok := ret.Get(1).(func(*cloudwatchlogs.PutDestinationInput) *cloudwatchlogs.PutDestinationOutput); ok { + r1 = rf(_a0) + } else { + if ret.Get(1) != nil { + r1 = ret.Get(1).(*cloudwatchlogs.PutDestinationOutput) + } + } + + return r0, r1 +} + +// PutDestinationWithContext provides a mock function with given fields: _a0, _a1, _a2 +func (_m *CloudWatchLogsAPI) PutDestinationWithContext(_a0 context.Context, _a1 *cloudwatchlogs.PutDestinationInput, _a2 ...request.Option) (*cloudwatchlogs.PutDestinationOutput, error) { + _va := make([]interface{}, len(_a2)) + for _i := range _a2 { + _va[_i] = _a2[_i] + } + var _ca []interface{} + _ca = append(_ca, _a0, _a1) + _ca = append(_ca, _va...) + ret := _m.Called(_ca...) + + var r0 *cloudwatchlogs.PutDestinationOutput + if rf, ok := ret.Get(0).(func(context.Context, *cloudwatchlogs.PutDestinationInput, ...request.Option) *cloudwatchlogs.PutDestinationOutput); ok { + r0 = rf(_a0, _a1, _a2...) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*cloudwatchlogs.PutDestinationOutput) + } + } + + var r1 error + if rf, ok := ret.Get(1).(func(context.Context, *cloudwatchlogs.PutDestinationInput, ...request.Option) error); ok { + r1 = rf(_a0, _a1, _a2...) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// PutLogEvents provides a mock function with given fields: _a0 +func (_m *CloudWatchLogsAPI) PutLogEvents(_a0 *cloudwatchlogs.PutLogEventsInput) (*cloudwatchlogs.PutLogEventsOutput, error) { + ret := _m.Called(_a0) + + var r0 *cloudwatchlogs.PutLogEventsOutput + if rf, ok := ret.Get(0).(func(*cloudwatchlogs.PutLogEventsInput) *cloudwatchlogs.PutLogEventsOutput); ok { + r0 = rf(_a0) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*cloudwatchlogs.PutLogEventsOutput) + } + } + + var r1 error + if rf, ok := ret.Get(1).(func(*cloudwatchlogs.PutLogEventsInput) error); ok { + r1 = rf(_a0) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// PutLogEventsRequest provides a mock function with given fields: _a0 +func (_m *CloudWatchLogsAPI) PutLogEventsRequest(_a0 *cloudwatchlogs.PutLogEventsInput) (*request.Request, *cloudwatchlogs.PutLogEventsOutput) { + ret := _m.Called(_a0) + + var r0 *request.Request + if rf, ok := ret.Get(0).(func(*cloudwatchlogs.PutLogEventsInput) *request.Request); ok { + r0 = rf(_a0) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*request.Request) + } + } + + var r1 *cloudwatchlogs.PutLogEventsOutput + if rf, ok := ret.Get(1).(func(*cloudwatchlogs.PutLogEventsInput) *cloudwatchlogs.PutLogEventsOutput); ok { + r1 = rf(_a0) + } else { + if ret.Get(1) != nil { + r1 = ret.Get(1).(*cloudwatchlogs.PutLogEventsOutput) + } + } + + return r0, r1 +} + +// PutLogEventsWithContext provides a mock function with given fields: _a0, _a1, _a2 +func (_m *CloudWatchLogsAPI) PutLogEventsWithContext(_a0 context.Context, _a1 *cloudwatchlogs.PutLogEventsInput, _a2 ...request.Option) (*cloudwatchlogs.PutLogEventsOutput, error) { + _va := make([]interface{}, len(_a2)) + for _i := range _a2 { + _va[_i] = _a2[_i] + } + var _ca []interface{} + _ca = append(_ca, _a0, _a1) + _ca = append(_ca, _va...) + ret := _m.Called(_ca...) + + var r0 *cloudwatchlogs.PutLogEventsOutput + if rf, ok := ret.Get(0).(func(context.Context, *cloudwatchlogs.PutLogEventsInput, ...request.Option) *cloudwatchlogs.PutLogEventsOutput); ok { + r0 = rf(_a0, _a1, _a2...) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*cloudwatchlogs.PutLogEventsOutput) + } + } + + var r1 error + if rf, ok := ret.Get(1).(func(context.Context, *cloudwatchlogs.PutLogEventsInput, ...request.Option) error); ok { + r1 = rf(_a0, _a1, _a2...) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// PutMetricFilter provides a mock function with given fields: _a0 +func (_m *CloudWatchLogsAPI) PutMetricFilter(_a0 *cloudwatchlogs.PutMetricFilterInput) (*cloudwatchlogs.PutMetricFilterOutput, error) { + ret := _m.Called(_a0) + + var r0 *cloudwatchlogs.PutMetricFilterOutput + if rf, ok := ret.Get(0).(func(*cloudwatchlogs.PutMetricFilterInput) *cloudwatchlogs.PutMetricFilterOutput); ok { + r0 = rf(_a0) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*cloudwatchlogs.PutMetricFilterOutput) + } + } + + var r1 error + if rf, ok := ret.Get(1).(func(*cloudwatchlogs.PutMetricFilterInput) error); ok { + r1 = rf(_a0) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// PutMetricFilterRequest provides a mock function with given fields: _a0 +func (_m *CloudWatchLogsAPI) PutMetricFilterRequest(_a0 *cloudwatchlogs.PutMetricFilterInput) (*request.Request, *cloudwatchlogs.PutMetricFilterOutput) { + ret := _m.Called(_a0) + + var r0 *request.Request + if rf, ok := ret.Get(0).(func(*cloudwatchlogs.PutMetricFilterInput) *request.Request); ok { + r0 = rf(_a0) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*request.Request) + } + } + + var r1 *cloudwatchlogs.PutMetricFilterOutput + if rf, ok := ret.Get(1).(func(*cloudwatchlogs.PutMetricFilterInput) *cloudwatchlogs.PutMetricFilterOutput); ok { + r1 = rf(_a0) + } else { + if ret.Get(1) != nil { + r1 = ret.Get(1).(*cloudwatchlogs.PutMetricFilterOutput) + } + } + + return r0, r1 +} + +// PutMetricFilterWithContext provides a mock function with given fields: _a0, _a1, _a2 +func (_m *CloudWatchLogsAPI) PutMetricFilterWithContext(_a0 context.Context, _a1 *cloudwatchlogs.PutMetricFilterInput, _a2 ...request.Option) (*cloudwatchlogs.PutMetricFilterOutput, error) { + _va := make([]interface{}, len(_a2)) + for _i := range _a2 { + _va[_i] = _a2[_i] + } + var _ca []interface{} + _ca = append(_ca, _a0, _a1) + _ca = append(_ca, _va...) + ret := _m.Called(_ca...) + + var r0 *cloudwatchlogs.PutMetricFilterOutput + if rf, ok := ret.Get(0).(func(context.Context, *cloudwatchlogs.PutMetricFilterInput, ...request.Option) *cloudwatchlogs.PutMetricFilterOutput); ok { + r0 = rf(_a0, _a1, _a2...) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*cloudwatchlogs.PutMetricFilterOutput) + } + } + + var r1 error + if rf, ok := ret.Get(1).(func(context.Context, *cloudwatchlogs.PutMetricFilterInput, ...request.Option) error); ok { + r1 = rf(_a0, _a1, _a2...) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// PutQueryDefinition provides a mock function with given fields: _a0 +func (_m *CloudWatchLogsAPI) PutQueryDefinition(_a0 *cloudwatchlogs.PutQueryDefinitionInput) (*cloudwatchlogs.PutQueryDefinitionOutput, error) { + ret := _m.Called(_a0) + + var r0 *cloudwatchlogs.PutQueryDefinitionOutput + if rf, ok := ret.Get(0).(func(*cloudwatchlogs.PutQueryDefinitionInput) *cloudwatchlogs.PutQueryDefinitionOutput); ok { + r0 = rf(_a0) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*cloudwatchlogs.PutQueryDefinitionOutput) + } + } + + var r1 error + if rf, ok := ret.Get(1).(func(*cloudwatchlogs.PutQueryDefinitionInput) error); ok { + r1 = rf(_a0) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// PutQueryDefinitionRequest provides a mock function with given fields: _a0 +func (_m *CloudWatchLogsAPI) PutQueryDefinitionRequest(_a0 *cloudwatchlogs.PutQueryDefinitionInput) (*request.Request, *cloudwatchlogs.PutQueryDefinitionOutput) { + ret := _m.Called(_a0) + + var r0 *request.Request + if rf, ok := ret.Get(0).(func(*cloudwatchlogs.PutQueryDefinitionInput) *request.Request); ok { + r0 = rf(_a0) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*request.Request) + } + } + + var r1 *cloudwatchlogs.PutQueryDefinitionOutput + if rf, ok := ret.Get(1).(func(*cloudwatchlogs.PutQueryDefinitionInput) *cloudwatchlogs.PutQueryDefinitionOutput); ok { + r1 = rf(_a0) + } else { + if ret.Get(1) != nil { + r1 = ret.Get(1).(*cloudwatchlogs.PutQueryDefinitionOutput) + } + } + + return r0, r1 +} + +// PutQueryDefinitionWithContext provides a mock function with given fields: _a0, _a1, _a2 +func (_m *CloudWatchLogsAPI) PutQueryDefinitionWithContext(_a0 context.Context, _a1 *cloudwatchlogs.PutQueryDefinitionInput, _a2 ...request.Option) (*cloudwatchlogs.PutQueryDefinitionOutput, error) { + _va := make([]interface{}, len(_a2)) + for _i := range _a2 { + _va[_i] = _a2[_i] + } + var _ca []interface{} + _ca = append(_ca, _a0, _a1) + _ca = append(_ca, _va...) + ret := _m.Called(_ca...) + + var r0 *cloudwatchlogs.PutQueryDefinitionOutput + if rf, ok := ret.Get(0).(func(context.Context, *cloudwatchlogs.PutQueryDefinitionInput, ...request.Option) *cloudwatchlogs.PutQueryDefinitionOutput); ok { + r0 = rf(_a0, _a1, _a2...) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*cloudwatchlogs.PutQueryDefinitionOutput) + } + } + + var r1 error + if rf, ok := ret.Get(1).(func(context.Context, *cloudwatchlogs.PutQueryDefinitionInput, ...request.Option) error); ok { + r1 = rf(_a0, _a1, _a2...) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// PutResourcePolicy provides a mock function with given fields: _a0 +func (_m *CloudWatchLogsAPI) PutResourcePolicy(_a0 *cloudwatchlogs.PutResourcePolicyInput) (*cloudwatchlogs.PutResourcePolicyOutput, error) { + ret := _m.Called(_a0) + + var r0 *cloudwatchlogs.PutResourcePolicyOutput + if rf, ok := ret.Get(0).(func(*cloudwatchlogs.PutResourcePolicyInput) *cloudwatchlogs.PutResourcePolicyOutput); ok { + r0 = rf(_a0) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*cloudwatchlogs.PutResourcePolicyOutput) + } + } + + var r1 error + if rf, ok := ret.Get(1).(func(*cloudwatchlogs.PutResourcePolicyInput) error); ok { + r1 = rf(_a0) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// PutResourcePolicyRequest provides a mock function with given fields: _a0 +func (_m *CloudWatchLogsAPI) PutResourcePolicyRequest(_a0 *cloudwatchlogs.PutResourcePolicyInput) (*request.Request, *cloudwatchlogs.PutResourcePolicyOutput) { + ret := _m.Called(_a0) + + var r0 *request.Request + if rf, ok := ret.Get(0).(func(*cloudwatchlogs.PutResourcePolicyInput) *request.Request); ok { + r0 = rf(_a0) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*request.Request) + } + } + + var r1 *cloudwatchlogs.PutResourcePolicyOutput + if rf, ok := ret.Get(1).(func(*cloudwatchlogs.PutResourcePolicyInput) *cloudwatchlogs.PutResourcePolicyOutput); ok { + r1 = rf(_a0) + } else { + if ret.Get(1) != nil { + r1 = ret.Get(1).(*cloudwatchlogs.PutResourcePolicyOutput) + } + } + + return r0, r1 +} + +// PutResourcePolicyWithContext provides a mock function with given fields: _a0, _a1, _a2 +func (_m *CloudWatchLogsAPI) PutResourcePolicyWithContext(_a0 context.Context, _a1 *cloudwatchlogs.PutResourcePolicyInput, _a2 ...request.Option) (*cloudwatchlogs.PutResourcePolicyOutput, error) { + _va := make([]interface{}, len(_a2)) + for _i := range _a2 { + _va[_i] = _a2[_i] + } + var _ca []interface{} + _ca = append(_ca, _a0, _a1) + _ca = append(_ca, _va...) + ret := _m.Called(_ca...) + + var r0 *cloudwatchlogs.PutResourcePolicyOutput + if rf, ok := ret.Get(0).(func(context.Context, *cloudwatchlogs.PutResourcePolicyInput, ...request.Option) *cloudwatchlogs.PutResourcePolicyOutput); ok { + r0 = rf(_a0, _a1, _a2...) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*cloudwatchlogs.PutResourcePolicyOutput) + } + } + + var r1 error + if rf, ok := ret.Get(1).(func(context.Context, *cloudwatchlogs.PutResourcePolicyInput, ...request.Option) error); ok { + r1 = rf(_a0, _a1, _a2...) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// PutRetentionPolicy provides a mock function with given fields: _a0 +func (_m *CloudWatchLogsAPI) PutRetentionPolicy(_a0 *cloudwatchlogs.PutRetentionPolicyInput) (*cloudwatchlogs.PutRetentionPolicyOutput, error) { + ret := _m.Called(_a0) + + var r0 *cloudwatchlogs.PutRetentionPolicyOutput + if rf, ok := ret.Get(0).(func(*cloudwatchlogs.PutRetentionPolicyInput) *cloudwatchlogs.PutRetentionPolicyOutput); ok { + r0 = rf(_a0) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*cloudwatchlogs.PutRetentionPolicyOutput) + } + } + + var r1 error + if rf, ok := ret.Get(1).(func(*cloudwatchlogs.PutRetentionPolicyInput) error); ok { + r1 = rf(_a0) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// PutRetentionPolicyRequest provides a mock function with given fields: _a0 +func (_m *CloudWatchLogsAPI) PutRetentionPolicyRequest(_a0 *cloudwatchlogs.PutRetentionPolicyInput) (*request.Request, *cloudwatchlogs.PutRetentionPolicyOutput) { + ret := _m.Called(_a0) + + var r0 *request.Request + if rf, ok := ret.Get(0).(func(*cloudwatchlogs.PutRetentionPolicyInput) *request.Request); ok { + r0 = rf(_a0) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*request.Request) + } + } + + var r1 *cloudwatchlogs.PutRetentionPolicyOutput + if rf, ok := ret.Get(1).(func(*cloudwatchlogs.PutRetentionPolicyInput) *cloudwatchlogs.PutRetentionPolicyOutput); ok { + r1 = rf(_a0) + } else { + if ret.Get(1) != nil { + r1 = ret.Get(1).(*cloudwatchlogs.PutRetentionPolicyOutput) + } + } + + return r0, r1 +} + +// PutRetentionPolicyWithContext provides a mock function with given fields: _a0, _a1, _a2 +func (_m *CloudWatchLogsAPI) PutRetentionPolicyWithContext(_a0 context.Context, _a1 *cloudwatchlogs.PutRetentionPolicyInput, _a2 ...request.Option) (*cloudwatchlogs.PutRetentionPolicyOutput, error) { + _va := make([]interface{}, len(_a2)) + for _i := range _a2 { + _va[_i] = _a2[_i] + } + var _ca []interface{} + _ca = append(_ca, _a0, _a1) + _ca = append(_ca, _va...) + ret := _m.Called(_ca...) + + var r0 *cloudwatchlogs.PutRetentionPolicyOutput + if rf, ok := ret.Get(0).(func(context.Context, *cloudwatchlogs.PutRetentionPolicyInput, ...request.Option) *cloudwatchlogs.PutRetentionPolicyOutput); ok { + r0 = rf(_a0, _a1, _a2...) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*cloudwatchlogs.PutRetentionPolicyOutput) + } + } + + var r1 error + if rf, ok := ret.Get(1).(func(context.Context, *cloudwatchlogs.PutRetentionPolicyInput, ...request.Option) error); ok { + r1 = rf(_a0, _a1, _a2...) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// PutSubscriptionFilter provides a mock function with given fields: _a0 +func (_m *CloudWatchLogsAPI) PutSubscriptionFilter(_a0 *cloudwatchlogs.PutSubscriptionFilterInput) (*cloudwatchlogs.PutSubscriptionFilterOutput, error) { + ret := _m.Called(_a0) + + var r0 *cloudwatchlogs.PutSubscriptionFilterOutput + if rf, ok := ret.Get(0).(func(*cloudwatchlogs.PutSubscriptionFilterInput) *cloudwatchlogs.PutSubscriptionFilterOutput); ok { + r0 = rf(_a0) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*cloudwatchlogs.PutSubscriptionFilterOutput) + } + } + + var r1 error + if rf, ok := ret.Get(1).(func(*cloudwatchlogs.PutSubscriptionFilterInput) error); ok { + r1 = rf(_a0) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// PutSubscriptionFilterRequest provides a mock function with given fields: _a0 +func (_m *CloudWatchLogsAPI) PutSubscriptionFilterRequest(_a0 *cloudwatchlogs.PutSubscriptionFilterInput) (*request.Request, *cloudwatchlogs.PutSubscriptionFilterOutput) { + ret := _m.Called(_a0) + + var r0 *request.Request + if rf, ok := ret.Get(0).(func(*cloudwatchlogs.PutSubscriptionFilterInput) *request.Request); ok { + r0 = rf(_a0) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*request.Request) + } + } + + var r1 *cloudwatchlogs.PutSubscriptionFilterOutput + if rf, ok := ret.Get(1).(func(*cloudwatchlogs.PutSubscriptionFilterInput) *cloudwatchlogs.PutSubscriptionFilterOutput); ok { + r1 = rf(_a0) + } else { + if ret.Get(1) != nil { + r1 = ret.Get(1).(*cloudwatchlogs.PutSubscriptionFilterOutput) + } + } + + return r0, r1 +} + +// PutSubscriptionFilterWithContext provides a mock function with given fields: _a0, _a1, _a2 +func (_m *CloudWatchLogsAPI) PutSubscriptionFilterWithContext(_a0 context.Context, _a1 *cloudwatchlogs.PutSubscriptionFilterInput, _a2 ...request.Option) (*cloudwatchlogs.PutSubscriptionFilterOutput, error) { + _va := make([]interface{}, len(_a2)) + for _i := range _a2 { + _va[_i] = _a2[_i] + } + var _ca []interface{} + _ca = append(_ca, _a0, _a1) + _ca = append(_ca, _va...) + ret := _m.Called(_ca...) + + var r0 *cloudwatchlogs.PutSubscriptionFilterOutput + if rf, ok := ret.Get(0).(func(context.Context, *cloudwatchlogs.PutSubscriptionFilterInput, ...request.Option) *cloudwatchlogs.PutSubscriptionFilterOutput); ok { + r0 = rf(_a0, _a1, _a2...) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*cloudwatchlogs.PutSubscriptionFilterOutput) + } + } + + var r1 error + if rf, ok := ret.Get(1).(func(context.Context, *cloudwatchlogs.PutSubscriptionFilterInput, ...request.Option) error); ok { + r1 = rf(_a0, _a1, _a2...) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// StartQuery provides a mock function with given fields: _a0 +func (_m *CloudWatchLogsAPI) StartQuery(_a0 *cloudwatchlogs.StartQueryInput) (*cloudwatchlogs.StartQueryOutput, error) { + ret := _m.Called(_a0) + + var r0 *cloudwatchlogs.StartQueryOutput + if rf, ok := ret.Get(0).(func(*cloudwatchlogs.StartQueryInput) *cloudwatchlogs.StartQueryOutput); ok { + r0 = rf(_a0) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*cloudwatchlogs.StartQueryOutput) + } + } + + var r1 error + if rf, ok := ret.Get(1).(func(*cloudwatchlogs.StartQueryInput) error); ok { + r1 = rf(_a0) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// StartQueryRequest provides a mock function with given fields: _a0 +func (_m *CloudWatchLogsAPI) StartQueryRequest(_a0 *cloudwatchlogs.StartQueryInput) (*request.Request, *cloudwatchlogs.StartQueryOutput) { + ret := _m.Called(_a0) + + var r0 *request.Request + if rf, ok := ret.Get(0).(func(*cloudwatchlogs.StartQueryInput) *request.Request); ok { + r0 = rf(_a0) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*request.Request) + } + } + + var r1 *cloudwatchlogs.StartQueryOutput + if rf, ok := ret.Get(1).(func(*cloudwatchlogs.StartQueryInput) *cloudwatchlogs.StartQueryOutput); ok { + r1 = rf(_a0) + } else { + if ret.Get(1) != nil { + r1 = ret.Get(1).(*cloudwatchlogs.StartQueryOutput) + } + } + + return r0, r1 +} + +// StartQueryWithContext provides a mock function with given fields: _a0, _a1, _a2 +func (_m *CloudWatchLogsAPI) StartQueryWithContext(_a0 context.Context, _a1 *cloudwatchlogs.StartQueryInput, _a2 ...request.Option) (*cloudwatchlogs.StartQueryOutput, error) { + _va := make([]interface{}, len(_a2)) + for _i := range _a2 { + _va[_i] = _a2[_i] + } + var _ca []interface{} + _ca = append(_ca, _a0, _a1) + _ca = append(_ca, _va...) + ret := _m.Called(_ca...) + + var r0 *cloudwatchlogs.StartQueryOutput + if rf, ok := ret.Get(0).(func(context.Context, *cloudwatchlogs.StartQueryInput, ...request.Option) *cloudwatchlogs.StartQueryOutput); ok { + r0 = rf(_a0, _a1, _a2...) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*cloudwatchlogs.StartQueryOutput) + } + } + + var r1 error + if rf, ok := ret.Get(1).(func(context.Context, *cloudwatchlogs.StartQueryInput, ...request.Option) error); ok { + r1 = rf(_a0, _a1, _a2...) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// StopQuery provides a mock function with given fields: _a0 +func (_m *CloudWatchLogsAPI) StopQuery(_a0 *cloudwatchlogs.StopQueryInput) (*cloudwatchlogs.StopQueryOutput, error) { + ret := _m.Called(_a0) + + var r0 *cloudwatchlogs.StopQueryOutput + if rf, ok := ret.Get(0).(func(*cloudwatchlogs.StopQueryInput) *cloudwatchlogs.StopQueryOutput); ok { + r0 = rf(_a0) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*cloudwatchlogs.StopQueryOutput) + } + } + + var r1 error + if rf, ok := ret.Get(1).(func(*cloudwatchlogs.StopQueryInput) error); ok { + r1 = rf(_a0) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// StopQueryRequest provides a mock function with given fields: _a0 +func (_m *CloudWatchLogsAPI) StopQueryRequest(_a0 *cloudwatchlogs.StopQueryInput) (*request.Request, *cloudwatchlogs.StopQueryOutput) { + ret := _m.Called(_a0) + + var r0 *request.Request + if rf, ok := ret.Get(0).(func(*cloudwatchlogs.StopQueryInput) *request.Request); ok { + r0 = rf(_a0) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*request.Request) + } + } + + var r1 *cloudwatchlogs.StopQueryOutput + if rf, ok := ret.Get(1).(func(*cloudwatchlogs.StopQueryInput) *cloudwatchlogs.StopQueryOutput); ok { + r1 = rf(_a0) + } else { + if ret.Get(1) != nil { + r1 = ret.Get(1).(*cloudwatchlogs.StopQueryOutput) + } + } + + return r0, r1 +} + +// StopQueryWithContext provides a mock function with given fields: _a0, _a1, _a2 +func (_m *CloudWatchLogsAPI) StopQueryWithContext(_a0 context.Context, _a1 *cloudwatchlogs.StopQueryInput, _a2 ...request.Option) (*cloudwatchlogs.StopQueryOutput, error) { + _va := make([]interface{}, len(_a2)) + for _i := range _a2 { + _va[_i] = _a2[_i] + } + var _ca []interface{} + _ca = append(_ca, _a0, _a1) + _ca = append(_ca, _va...) + ret := _m.Called(_ca...) + + var r0 *cloudwatchlogs.StopQueryOutput + if rf, ok := ret.Get(0).(func(context.Context, *cloudwatchlogs.StopQueryInput, ...request.Option) *cloudwatchlogs.StopQueryOutput); ok { + r0 = rf(_a0, _a1, _a2...) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*cloudwatchlogs.StopQueryOutput) + } + } + + var r1 error + if rf, ok := ret.Get(1).(func(context.Context, *cloudwatchlogs.StopQueryInput, ...request.Option) error); ok { + r1 = rf(_a0, _a1, _a2...) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// TagLogGroup provides a mock function with given fields: _a0 +func (_m *CloudWatchLogsAPI) TagLogGroup(_a0 *cloudwatchlogs.TagLogGroupInput) (*cloudwatchlogs.TagLogGroupOutput, error) { + ret := _m.Called(_a0) + + var r0 *cloudwatchlogs.TagLogGroupOutput + if rf, ok := ret.Get(0).(func(*cloudwatchlogs.TagLogGroupInput) *cloudwatchlogs.TagLogGroupOutput); ok { + r0 = rf(_a0) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*cloudwatchlogs.TagLogGroupOutput) + } + } + + var r1 error + if rf, ok := ret.Get(1).(func(*cloudwatchlogs.TagLogGroupInput) error); ok { + r1 = rf(_a0) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// TagLogGroupRequest provides a mock function with given fields: _a0 +func (_m *CloudWatchLogsAPI) TagLogGroupRequest(_a0 *cloudwatchlogs.TagLogGroupInput) (*request.Request, *cloudwatchlogs.TagLogGroupOutput) { + ret := _m.Called(_a0) + + var r0 *request.Request + if rf, ok := ret.Get(0).(func(*cloudwatchlogs.TagLogGroupInput) *request.Request); ok { + r0 = rf(_a0) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*request.Request) + } + } + + var r1 *cloudwatchlogs.TagLogGroupOutput + if rf, ok := ret.Get(1).(func(*cloudwatchlogs.TagLogGroupInput) *cloudwatchlogs.TagLogGroupOutput); ok { + r1 = rf(_a0) + } else { + if ret.Get(1) != nil { + r1 = ret.Get(1).(*cloudwatchlogs.TagLogGroupOutput) + } + } + + return r0, r1 +} + +// TagLogGroupWithContext provides a mock function with given fields: _a0, _a1, _a2 +func (_m *CloudWatchLogsAPI) TagLogGroupWithContext(_a0 context.Context, _a1 *cloudwatchlogs.TagLogGroupInput, _a2 ...request.Option) (*cloudwatchlogs.TagLogGroupOutput, error) { + _va := make([]interface{}, len(_a2)) + for _i := range _a2 { + _va[_i] = _a2[_i] + } + var _ca []interface{} + _ca = append(_ca, _a0, _a1) + _ca = append(_ca, _va...) + ret := _m.Called(_ca...) + + var r0 *cloudwatchlogs.TagLogGroupOutput + if rf, ok := ret.Get(0).(func(context.Context, *cloudwatchlogs.TagLogGroupInput, ...request.Option) *cloudwatchlogs.TagLogGroupOutput); ok { + r0 = rf(_a0, _a1, _a2...) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*cloudwatchlogs.TagLogGroupOutput) + } + } + + var r1 error + if rf, ok := ret.Get(1).(func(context.Context, *cloudwatchlogs.TagLogGroupInput, ...request.Option) error); ok { + r1 = rf(_a0, _a1, _a2...) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// TestMetricFilter provides a mock function with given fields: _a0 +func (_m *CloudWatchLogsAPI) TestMetricFilter(_a0 *cloudwatchlogs.TestMetricFilterInput) (*cloudwatchlogs.TestMetricFilterOutput, error) { + ret := _m.Called(_a0) + + var r0 *cloudwatchlogs.TestMetricFilterOutput + if rf, ok := ret.Get(0).(func(*cloudwatchlogs.TestMetricFilterInput) *cloudwatchlogs.TestMetricFilterOutput); ok { + r0 = rf(_a0) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*cloudwatchlogs.TestMetricFilterOutput) + } + } + + var r1 error + if rf, ok := ret.Get(1).(func(*cloudwatchlogs.TestMetricFilterInput) error); ok { + r1 = rf(_a0) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// TestMetricFilterRequest provides a mock function with given fields: _a0 +func (_m *CloudWatchLogsAPI) TestMetricFilterRequest(_a0 *cloudwatchlogs.TestMetricFilterInput) (*request.Request, *cloudwatchlogs.TestMetricFilterOutput) { + ret := _m.Called(_a0) + + var r0 *request.Request + if rf, ok := ret.Get(0).(func(*cloudwatchlogs.TestMetricFilterInput) *request.Request); ok { + r0 = rf(_a0) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*request.Request) + } + } + + var r1 *cloudwatchlogs.TestMetricFilterOutput + if rf, ok := ret.Get(1).(func(*cloudwatchlogs.TestMetricFilterInput) *cloudwatchlogs.TestMetricFilterOutput); ok { + r1 = rf(_a0) + } else { + if ret.Get(1) != nil { + r1 = ret.Get(1).(*cloudwatchlogs.TestMetricFilterOutput) + } + } + + return r0, r1 +} + +// TestMetricFilterWithContext provides a mock function with given fields: _a0, _a1, _a2 +func (_m *CloudWatchLogsAPI) TestMetricFilterWithContext(_a0 context.Context, _a1 *cloudwatchlogs.TestMetricFilterInput, _a2 ...request.Option) (*cloudwatchlogs.TestMetricFilterOutput, error) { + _va := make([]interface{}, len(_a2)) + for _i := range _a2 { + _va[_i] = _a2[_i] + } + var _ca []interface{} + _ca = append(_ca, _a0, _a1) + _ca = append(_ca, _va...) + ret := _m.Called(_ca...) + + var r0 *cloudwatchlogs.TestMetricFilterOutput + if rf, ok := ret.Get(0).(func(context.Context, *cloudwatchlogs.TestMetricFilterInput, ...request.Option) *cloudwatchlogs.TestMetricFilterOutput); ok { + r0 = rf(_a0, _a1, _a2...) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*cloudwatchlogs.TestMetricFilterOutput) + } + } + + var r1 error + if rf, ok := ret.Get(1).(func(context.Context, *cloudwatchlogs.TestMetricFilterInput, ...request.Option) error); ok { + r1 = rf(_a0, _a1, _a2...) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// UntagLogGroup provides a mock function with given fields: _a0 +func (_m *CloudWatchLogsAPI) UntagLogGroup(_a0 *cloudwatchlogs.UntagLogGroupInput) (*cloudwatchlogs.UntagLogGroupOutput, error) { + ret := _m.Called(_a0) + + var r0 *cloudwatchlogs.UntagLogGroupOutput + if rf, ok := ret.Get(0).(func(*cloudwatchlogs.UntagLogGroupInput) *cloudwatchlogs.UntagLogGroupOutput); ok { + r0 = rf(_a0) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*cloudwatchlogs.UntagLogGroupOutput) + } + } + + var r1 error + if rf, ok := ret.Get(1).(func(*cloudwatchlogs.UntagLogGroupInput) error); ok { + r1 = rf(_a0) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// UntagLogGroupRequest provides a mock function with given fields: _a0 +func (_m *CloudWatchLogsAPI) UntagLogGroupRequest(_a0 *cloudwatchlogs.UntagLogGroupInput) (*request.Request, *cloudwatchlogs.UntagLogGroupOutput) { + ret := _m.Called(_a0) + + var r0 *request.Request + if rf, ok := ret.Get(0).(func(*cloudwatchlogs.UntagLogGroupInput) *request.Request); ok { + r0 = rf(_a0) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*request.Request) + } + } + + var r1 *cloudwatchlogs.UntagLogGroupOutput + if rf, ok := ret.Get(1).(func(*cloudwatchlogs.UntagLogGroupInput) *cloudwatchlogs.UntagLogGroupOutput); ok { + r1 = rf(_a0) + } else { + if ret.Get(1) != nil { + r1 = ret.Get(1).(*cloudwatchlogs.UntagLogGroupOutput) + } + } + + return r0, r1 +} + +// UntagLogGroupWithContext provides a mock function with given fields: _a0, _a1, _a2 +func (_m *CloudWatchLogsAPI) UntagLogGroupWithContext(_a0 context.Context, _a1 *cloudwatchlogs.UntagLogGroupInput, _a2 ...request.Option) (*cloudwatchlogs.UntagLogGroupOutput, error) { + _va := make([]interface{}, len(_a2)) + for _i := range _a2 { + _va[_i] = _a2[_i] + } + var _ca []interface{} + _ca = append(_ca, _a0, _a1) + _ca = append(_ca, _va...) + ret := _m.Called(_ca...) + + var r0 *cloudwatchlogs.UntagLogGroupOutput + if rf, ok := ret.Get(0).(func(context.Context, *cloudwatchlogs.UntagLogGroupInput, ...request.Option) *cloudwatchlogs.UntagLogGroupOutput); ok { + r0 = rf(_a0, _a1, _a2...) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*cloudwatchlogs.UntagLogGroupOutput) + } + } + + var r1 error + if rf, ok := ret.Get(1).(func(context.Context, *cloudwatchlogs.UntagLogGroupInput, ...request.Option) error); ok { + r1 = rf(_a0, _a1, _a2...) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} diff --git a/pkg/eks/mocks/mocks.go b/pkg/eks/mocks/mocks.go index 4532882243..ff50735d62 100644 --- a/pkg/eks/mocks/mocks.go +++ b/pkg/eks/mocks/mocks.go @@ -23,5 +23,6 @@ import ( //go:generate "${GOBIN}/mockery" --tags netgo --dir=${AWS_SDK_GO_DIR}/service/sts/stsiface --name=STSAPI --output=./ //go:generate "${GOBIN}/mockery" --tags netgo --dir=${AWS_SDK_GO_DIR}/service/iam/iamiface --name=IAMAPI --output=./ //go:generate "${GOBIN}/mockery" --tags netgo --dir=${AWS_SDK_GO_DIR}/service/cloudtrail/cloudtrailiface --name=CloudTrailAPI --output=./ +//go:generate "${GOBIN}/mockery" --tags netgo --dir=${AWS_SDK_GO_DIR}/service/cloudwatchlogs/cloudwatchlogsiface --name=CloudWatchLogsAPI --output=./ //go:generate "${GOBIN}/mockery" --tags netgo --dir=${AWS_SDK_GO_DIR}/service/ssm/ssmiface --name=SSMAPI --output=./ //go:generate "${GOBIN}/mockery" --tags netgo --dir=${AWS_SDK_GO_DIR}/aws/client --name=ConfigProvider --output=./ diff --git a/pkg/testutils/mockprovider/mock_provider.go b/pkg/testutils/mockprovider/mock_provider.go index 47f606f62c..09bdd9f8b7 100644 --- a/pkg/testutils/mockprovider/mock_provider.go +++ b/pkg/testutils/mockprovider/mock_provider.go @@ -8,6 +8,7 @@ import ( "github.com/aws/aws-sdk-go/service/autoscaling/autoscalingiface" "github.com/aws/aws-sdk-go/service/cloudformation/cloudformationiface" "github.com/aws/aws-sdk-go/service/cloudtrail/cloudtrailiface" + "github.com/aws/aws-sdk-go/service/cloudwatchlogs/cloudwatchlogsiface" "github.com/aws/aws-sdk-go/service/ec2/ec2iface" "github.com/aws/aws-sdk-go/service/eks/eksiface" "github.com/aws/aws-sdk-go/service/elb/elbiface" @@ -62,6 +63,7 @@ type MockProvider struct { ssm *mocks.SSMAPI iam *mocks.IAMAPI cloudtrail *mocks.CloudTrailAPI + cloudwatchlogs *mocks.CloudWatchLogsAPI configProvider *mocks.ConfigProvider } @@ -80,6 +82,7 @@ func NewMockProvider() *MockProvider { ssm: &mocks.SSMAPI{}, iam: &mocks.IAMAPI{}, cloudtrail: &mocks.CloudTrailAPI{}, + cloudwatchlogs: &mocks.CloudWatchLogsAPI{}, configProvider: &mocks.ConfigProvider{}, } } @@ -150,6 +153,14 @@ func (m MockProvider) MockCloudTrail() *mocks.CloudTrailAPI { return m.CloudTrail().(*mocks.CloudTrailAPI) } +// CloudWatchLogs returns a representation of the CloudWatchLogs API +func (m MockProvider) CloudWatchLogs() cloudwatchlogsiface.CloudWatchLogsAPI { return m.cloudwatchlogs } + +// MockCloudWatchLogs returns a mocked CloudWatchLogs API +func (m MockProvider) MockCloudWatchLogs() *mocks.CloudWatchLogsAPI { + return m.CloudWatchLogs().(*mocks.CloudWatchLogsAPI) +} + // Profile returns current profile setting func (m MockProvider) Profile() string { return ProviderConfig.Profile } From a37e218d7586b6f1d442760e76951a0ac9d721e5 Mon Sep 17 00:00:00 2001 From: cpu1 Date: Tue, 5 Oct 2021 18:20:14 +0530 Subject: [PATCH 053/124] Move package --- .../cloudwatch_logging/cloudwatch_logging_test.go | 3 ++- integration/tests/cluster_dns/cluster_dns_test.go | 3 ++- integration/tests/crud/creategetdelete_test.go | 5 +++-- integration/tests/managed/managed_nodegroup_test.go | 11 ++++++----- .../utilities/cluster/cluster.go | 4 ++-- 5 files changed, 15 insertions(+), 11 deletions(-) rename pkg/testutils/testutils.go => integration/utilities/cluster/cluster.go (80%) diff --git a/integration/tests/cloudwatch_logging/cloudwatch_logging_test.go b/integration/tests/cloudwatch_logging/cloudwatch_logging_test.go index 98f766353e..c9a34a887f 100644 --- a/integration/tests/cloudwatch_logging/cloudwatch_logging_test.go +++ b/integration/tests/cloudwatch_logging/cloudwatch_logging_test.go @@ -17,6 +17,7 @@ import ( . "github.com/onsi/gomega" "github.com/weaveworks/eksctl/integration/tests" + clusterutils "github.com/weaveworks/eksctl/integration/utilities/cluster" ) var params *tests.Params @@ -44,7 +45,7 @@ var _ = Describe("(Integration) [CloudWatch Logging test]", func() { "--verbose=4", ). WithoutArg("--region", params.Region). - WithStdin(testutils.ClusterConfigReaderFromFile(params.ClusterName, params.Region, "testdata/cloudwatch-cluster.yaml")) + WithStdin(clusterutils.ReaderFromFile(params.ClusterName, params.Region, "testdata/cloudwatch-cluster.yaml")) Expect(cmd).To(RunSuccessfullyWithOutputString(ContainSubstring("set log retention to 545 days for CloudWatch logging"))) }) diff --git a/integration/tests/cluster_dns/cluster_dns_test.go b/integration/tests/cluster_dns/cluster_dns_test.go index 962c456156..d86502035b 100644 --- a/integration/tests/cluster_dns/cluster_dns_test.go +++ b/integration/tests/cluster_dns/cluster_dns_test.go @@ -14,6 +14,7 @@ import ( "github.com/weaveworks/eksctl/integration/utilities/kube" "github.com/weaveworks/eksctl/integration/tests" + clusterutils "github.com/weaveworks/eksctl/integration/utilities/cluster" api "github.com/weaveworks/eksctl/pkg/apis/eksctl.io/v1alpha5" "github.com/weaveworks/eksctl/pkg/testutils" @@ -64,7 +65,7 @@ var _ = Describe("(Integration) [Cluster DNS test]", func() { "--verbose", "4", ). WithoutArg("--region", params.Region). - WithStdin(testutils.ClusterConfigReader(clusterConfig)) + WithStdin(clusterutils.Reader(clusterConfig)) Expect(cmd).To(RunSuccessfully()) }) diff --git a/integration/tests/crud/creategetdelete_test.go b/integration/tests/crud/creategetdelete_test.go index 47e9e17c27..4346239889 100644 --- a/integration/tests/crud/creategetdelete_test.go +++ b/integration/tests/crud/creategetdelete_test.go @@ -28,6 +28,7 @@ import ( . "github.com/weaveworks/eksctl/integration/matchers" . "github.com/weaveworks/eksctl/integration/runner" "github.com/weaveworks/eksctl/integration/tests" + clusterutils "github.com/weaveworks/eksctl/integration/utilities/cluster" "github.com/weaveworks/eksctl/integration/utilities/kube" api "github.com/weaveworks/eksctl/pkg/apis/eksctl.io/v1alpha5" "github.com/weaveworks/eksctl/pkg/eks" @@ -225,7 +226,7 @@ var _ = Describe("(Integration) Create, Get, Scale & Delete", func() { "--verbose", "4", ). WithoutArg("--region", params.Region). - WithStdin(testutils.ClusterConfigReaderFromFile(params.ClusterName, params.Region, "testdata/taints-max-pods.yaml")) + WithStdin(clusterutils.ReaderFromFile(params.ClusterName, params.Region, "testdata/taints-max-pods.yaml")) Expect(cmd).To(RunSuccessfully()) config, err := clientcmd.BuildConfigFromFlags("", params.KubeconfigPath) @@ -421,7 +422,7 @@ var _ = Describe("(Integration) Create, Get, Scale & Delete", func() { "--verbose", "4", ). WithoutArg("--region", params.Region). - WithStdin(testutils.ClusterConfigReader(clusterConfig)) + WithStdin(clusterutils.Reader(clusterConfig)) Expect(cmd).To(RunSuccessfully()) }) }) diff --git a/integration/tests/managed/managed_nodegroup_test.go b/integration/tests/managed/managed_nodegroup_test.go index 45747054ea..b37c9ad027 100644 --- a/integration/tests/managed/managed_nodegroup_test.go +++ b/integration/tests/managed/managed_nodegroup_test.go @@ -22,6 +22,7 @@ import ( . "github.com/weaveworks/eksctl/integration/matchers" . "github.com/weaveworks/eksctl/integration/runner" "github.com/weaveworks/eksctl/integration/tests" + clusterutils "github.com/weaveworks/eksctl/integration/utilities/cluster" "github.com/weaveworks/eksctl/integration/utilities/kube" api "github.com/weaveworks/eksctl/pkg/apis/eksctl.io/v1alpha5" "github.com/weaveworks/eksctl/pkg/testutils" @@ -100,7 +101,7 @@ var _ = Describe("(Integration) Create Managed Nodegroups", func() { "--verbose", "4", ). WithoutArg("--region", params.Region). - WithStdin(testutils.ClusterConfigReader(clusterConfig)) + WithStdin(clusterutils.Reader(clusterConfig)) Expect(cmd).To(RunSuccessfully()) }, @@ -217,7 +218,7 @@ var _ = Describe("(Integration) Create Managed Nodegroups", func() { "--verbose", "4", ). WithoutArg("--region", params.Region). - WithStdin(testutils.ClusterConfigReader(clusterConfig)) + WithStdin(clusterutils.Reader(clusterConfig)) Expect(cmd).To(RunSuccessfully()) @@ -533,7 +534,7 @@ var _ = Describe("(Integration) Create Managed Nodegroups", func() { "--verbose", "4", ). WithoutArg("--region", params.Region). - WithStdin(testutils.ClusterConfigReader(clusterConfig)) + WithStdin(clusterutils.Reader(clusterConfig)) Expect(cmd).To(RunSuccessfully()) config, err := clientcmd.BuildConfigFromFlags("", params.KubeconfigPath) @@ -579,7 +580,7 @@ var _ = Describe("(Integration) Create Managed Nodegroups", func() { "--verbose", "4", ). WithoutArg("--region", params.Region). - WithStdin(testutils.ClusterConfigReader(clusterConfig)) + WithStdin(clusterutils.Reader(clusterConfig)) Expect(cmd).To(RunSuccessfully()) clusterProvider, err := eks.New(&api.ProviderConfig{Region: params.Region}, clusterConfig) @@ -605,7 +606,7 @@ var _ = Describe("(Integration) Create Managed Nodegroups", func() { "--verbose", "4", ). WithoutArg("--region", params.Region). - WithStdin(testutils.ClusterConfigReader(clusterConfig)) + WithStdin(clusterutils.Reader(clusterConfig)) Expect(cmd).To(RunSuccessfullyWithOutputStringLines( ContainElement(ContainSubstring("unchanged fields for nodegroup update-config-ng: the following fields remain unchanged; they are not supported by `eksctl update nodegroup`: Spot")), diff --git a/pkg/testutils/testutils.go b/integration/utilities/cluster/cluster.go similarity index 80% rename from pkg/testutils/testutils.go rename to integration/utilities/cluster/cluster.go index 7f3c39a88a..17487d2137 100644 --- a/pkg/testutils/testutils.go +++ b/integration/utilities/cluster/cluster.go @@ -12,13 +12,13 @@ import ( "github.com/weaveworks/eksctl/pkg/eks" ) -func ClusterConfigReader(clusterConfig *v1alpha5.ClusterConfig) io.Reader { +func Reader(clusterConfig *v1alpha5.ClusterConfig) io.Reader { data, err := json.Marshal(clusterConfig) Expect(err).ToNot(HaveOccurred()) return bytes.NewReader(data) } -func ClusterConfigReaderFromFile(clusterName, region, filename string) io.Reader { +func ReaderFromFile(clusterName, region, filename string) io.Reader { data, err := os.ReadFile(filename) Expect(err).ToNot(HaveOccurred()) clusterConfig, err := eks.ParseConfig(data) From 4ea5266b1ea5f789e81e2ce3cf8c06fb2afa398e Mon Sep 17 00:00:00 2001 From: cpu1 Date: Mon, 18 Oct 2021 14:20:23 +0530 Subject: [PATCH 054/124] Improve integration test --- .../cloudwatch_logging/cloudwatch_logging_test.go | 14 ++++++++++++++ pkg/apis/eksctl.io/v1alpha5/assets/schema.json | 4 ++-- pkg/apis/eksctl.io/v1alpha5/cloudwatch.go | 2 +- pkg/apis/eksctl.io/v1alpha5/schema.go | 6 +++--- 4 files changed, 20 insertions(+), 6 deletions(-) diff --git a/integration/tests/cloudwatch_logging/cloudwatch_logging_test.go b/integration/tests/cloudwatch_logging/cloudwatch_logging_test.go index c9a34a887f..732a85af0d 100644 --- a/integration/tests/cloudwatch_logging/cloudwatch_logging_test.go +++ b/integration/tests/cloudwatch_logging/cloudwatch_logging_test.go @@ -4,8 +4,14 @@ package cloudwatch_logging import ( + "fmt" "testing" + "github.com/aws/aws-sdk-go/aws" + "github.com/aws/aws-sdk-go/service/cloudwatchlogs" + + . "github.com/weaveworks/eksctl/integration/matchers" + api "github.com/weaveworks/eksctl/pkg/apis/eksctl.io/v1alpha5" "github.com/pkg/errors" @@ -48,6 +54,14 @@ var _ = Describe("(Integration) [CloudWatch Logging test]", func() { WithStdin(clusterutils.ReaderFromFile(params.ClusterName, params.Region, "testdata/cloudwatch-cluster.yaml")) Expect(cmd).To(RunSuccessfullyWithOutputString(ContainSubstring("set log retention to 545 days for CloudWatch logging"))) + + cloudWatchLogs := cloudwatchlogs.New(NewSession(params.Region)) + logGroups, err := cloudWatchLogs.DescribeLogGroups(&cloudwatchlogs.DescribeLogGroupsInput{ + LogGroupNamePrefix: aws.String(fmt.Sprintf("/aws/eks/%s/cluster", params.ClusterName)), + }) + Expect(err).ToNot(HaveOccurred()) + Expect(logGroups.LogGroups).To(HaveLen(1)) + Expect(*logGroups.LogGroups[0].RetentionInDays).To(Equal(int64(545))) }) }) }) diff --git a/pkg/apis/eksctl.io/v1alpha5/assets/schema.json b/pkg/apis/eksctl.io/v1alpha5/assets/schema.json index 8f5b5215ff..e70b80cea8 100755 --- a/pkg/apis/eksctl.io/v1alpha5/assets/schema.json +++ b/pkg/apis/eksctl.io/v1alpha5/assets/schema.json @@ -128,8 +128,8 @@ }, "logRetentionInDays": { "type": "integer", - "description": "sets the number of days to retain the logs for (see [CloudWatch docs](https://docs.aws.amazon.com/AmazonCloudWatch/latest/logs/WhatIsCloudWatchLogs.html)) . Valid values are: 1, 3, 5, 7, 14, 30, 60, 90, 120, 150, 180, 365, 400, 545, 731, 1827, and 3653.", - "x-intellij-html-description": "sets the number of days to retain the logs for (see CloudWatch docs) . Valid values are: 1, 3, 5, 7, 14, 30, 60, 90, 120, 150, 180, 365, 400, 545, 731, 1827, and 3653." + "description": "sets the number of days to retain the logs for (see [CloudWatch docs](https://docs.aws.amazon.com/AmazonCloudWatchLogs/latest/APIReference/API_PutRetentionPolicy.html#API_PutRetentionPolicy_RequestSyntax)) . Valid values are: 1, 3, 5, 7, 14, 30, 60, 90, 120, 150, 180, 365, 400, 545, 731, 1827, and 3653.", + "x-intellij-html-description": "sets the number of days to retain the logs for (see CloudWatch docs) . Valid values are: 1, 3, 5, 7, 14, 30, 60, 90, 120, 150, 180, 365, 400, 545, 731, 1827, and 3653." } }, "preferredOrder": [ diff --git a/pkg/apis/eksctl.io/v1alpha5/cloudwatch.go b/pkg/apis/eksctl.io/v1alpha5/cloudwatch.go index 128eaaeb93..5c1c0c1b25 100644 --- a/pkg/apis/eksctl.io/v1alpha5/cloudwatch.go +++ b/pkg/apis/eksctl.io/v1alpha5/cloudwatch.go @@ -26,7 +26,7 @@ type ClusterCloudWatchLogging struct { // Valid entries are `CloudWatchLogging` constants //+optional EnableTypes []string `json:"enableTypes,omitempty"` - // LogRetentionInDays sets the number of days to retain the logs for (see [CloudWatch docs](https://docs.aws.amazon.com/AmazonCloudWatch/latest/logs/WhatIsCloudWatchLogs.html)) . + // LogRetentionInDays sets the number of days to retain the logs for (see [CloudWatch docs](https://docs.aws.amazon.com/AmazonCloudWatchLogs/latest/APIReference/API_PutRetentionPolicy.html#API_PutRetentionPolicy_RequestSyntax)) . // Valid values are: 1, 3, 5, 7, 14, 30, 60, 90, 120, 150, 180, 365, 400, 545, 731, // 1827, and 3653. //+optional diff --git a/pkg/apis/eksctl.io/v1alpha5/schema.go b/pkg/apis/eksctl.io/v1alpha5/schema.go index dec6b506fc..3c02a70a4a 100644 --- a/pkg/apis/eksctl.io/v1alpha5/schema.go +++ b/pkg/apis/eksctl.io/v1alpha5/schema.go @@ -1,6 +1,6 @@ // Code generated by go-bindata. DO NOT EDIT. // sources: -// assets/schema.json (88.349kB) +// assets/schema.json (88.451kB) package v1alpha5 @@ -69,7 +69,7 @@ func (fi bindataFileInfo) Sys() interface{} { return nil } -var _schemaJson = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\xec\x7d\xfd\x73\x1b\x37\xb2\xe0\xef\xfb\x57\xa0\x98\xad\xf7\xec\x57\x1c\xd1\xb2\x93\x6c\x92\xcd\xa9\x8e\x96\x14\x87\xe7\x48\xe2\x89\x72\x72\x17\xcb\xb5\x06\x67\x40\x12\xab\x21\x30\x0b\x60\x24\x31\xcf\xb9\xbf\xfd\x0a\x5f\xf3\x89\x19\xce\x97\x6c\x6d\x95\x7e\xb1\xa9\x99\x41\xa3\xd1\x68\x74\x37\x1a\xdd\x8d\xff\xfe\x0b\x00\xa3\xbf\x32\xb4\x1a\xfd\x00\x46\x5f\x4d\x02\xb4\xc2\x04\x0b\x4c\x09\x9f\x1c\x87\x31\x17\x88\x1d\x53\xb2\xc2\xeb\xd1\x58\x7e\x28\x76\x11\x92\x1f\xd2\xe5\x3f\x91\x2f\xf4\xb3\xbf\x72\x7f\x83\xb6\x50\x3e\xde\x08\x11\xfd\x30\x99\xfc\x93\x53\xe2\xe9\xa7\x07\x94\xad\x27\x01\x83\x2b\xe1\xbd\xf8\xdb\x44\x3f\xfb\x4a\xb7\xcb\x74\x35\xfa\x01\x48\x3c\x00\x18\x4d\x7f\x5f\xc4\x4b\x82\xc4\x19\x8c\x22\x4c\xd6\xc9\x0b\x00\x46\x30\x08\xd4\xd7\x30\x9c\x33\x1a\x21\x26\x30\xe2\x99\xf7\x95\xc3\xb0\x20\x17\x11\xf2\x47\xe6\xe3\x3f\xc7\x16\xaa\x63\x44\xea\x79\x80\xb8\xcf\x70\x24\x41\xa8\x91\xd1\x30\xe0\x80\x2b\x40\x40\x50\x30\xfd\x1d\x6c\x35\x8a\xfc\x00\xcc\x56\x40\x6c\x10\xb8\x41\x3b\x80\x39\x80\x04\x4c\x7f\x1f\x03\xb1\x81\x02\xc0\x90\x53\xb0\x44\x3e\xdd\x22\xae\xbe\x21\x70\x8b\x00\xd5\xdf\x1b\x68\x54\x6c\x10\xbb\xc3\x1c\x81\x98\xa3\x04\x90\xa0\x80\xa1\x15\x62\xf2\x87\xd8\x60\xdb\xf7\x41\x8a\xe1\xbd\x87\x89\x40\x61\x88\xff\xe9\x6d\xc4\x36\xf4\x1e\x3f\xc6\x01\x5a\xc1\x38\x14\x12\xbb\xff\xfe\x53\x4f\x85\x99\x88\x51\x6e\x92\x32\x93\x1e\x55\x4c\x35\xfc\x23\xf7\x77\x66\x22\xb9\x60\x92\x71\xc6\xd9\x77\x05\xd2\xf8\x90\x80\x25\x02\x74\x8b\x85\x40\x01\xc0\x65\x62\xe4\x9b\xef\xa1\x74\x03\x70\x09\xb4\x3f\x53\xc0\x23\x1f\x07\xac\x38\x0a\x37\x0b\xaf\xb1\xd8\xc4\xcb\x03\x9f\x6e\x3f\xdd\x21\x78\x8b\xee\x28\xbb\xe1\x9f\xd0\x0d\xf7\x45\xf8\x29\xba\x59\x7f\x8a\x05\x0e\xf9\x27\x1c\x49\x7a\xcf\xe6\xe7\x48\xb8\x7b\xc4\xc1\x1e\xaa\xa5\xad\x4a\x0b\x25\x52\x93\xcb\x50\x70\xc1\x02\x24\xf1\x7e\x9f\x83\x3b\xce\xcd\x4d\x71\x94\xe6\xcf\x0f\xe3\x3d\x8b\x79\x05\x43\x8e\xf2\x8c\x11\x04\x8a\xca\x09\x47\x30\xf4\xaf\x18\x33\x14\xe4\x31\x90\x5c\x5a\xee\xa5\x92\x7b\x84\x80\xfe\x66\x4e\x43\xec\xef\x9a\xcd\xc0\x8c\x84\x98\xa0\x13\xea\xc7\x5b\x44\x44\x2d\x77\xe9\x85\x07\x41\xa4\xc0\x83\xc0\xb4\x91\xcb\x42\xf7\xdb\x8a\xb9\xf6\x43\x73\xce\x74\x76\x84\xd3\xcb\x73\x5e\x1c\x25\x16\x68\x5b\x7c\x58\xc3\x0e\x39\xe0\x99\xef\x20\x63\x70\x57\x4b\x8d\x10\x73\x21\xc5\x87\x44\xc2\x8a\x91\xd9\xf4\x4c\x8f\x07\x4b\x19\xd3\x89\x2c\x2d\xc0\x3a\xe9\xa3\xf8\xa5\xe9\x5a\xc8\xb4\x8b\x10\xdb\x62\xce\x25\x4f\xbc\xa6\x31\x09\x20\x2b\x31\x50\x0b\x41\x34\xbd\x3c\xb7\xc8\x67\x00\x83\xa5\x81\xac\x06\xc1\x39\xf5\x31\x14\xa8\x15\x79\x5a\x01\x76\x0e\x94\x23\x76\x8b\x7d\x34\xf5\x7d\x1a\x13\x71\x49\x43\x34\xbd\x3c\xef\x42\x31\x01\xd7\x25\xee\xdb\xab\xca\x3b\x31\x63\x41\x85\xbb\x08\x7e\xb5\x41\x60\x8b\x04\x0c\xa0\x80\x8a\x08\x51\x14\xee\xb4\xc2\x42\xc0\xd7\xf6\x8e\x21\x8e\x64\xb0\x3b\x2c\x36\xc0\x87\x02\xad\x29\xc3\x7f\x40\x09\x05\x40\x12\x00\xca\xd6\x90\x98\x07\x07\xe0\x14\xfa\x1b\x20\xe0\x1a\xf8\x94\xc8\x66\x8a\x21\xa1\x52\x00\xf2\x63\x48\x00\x8d\xf4\x68\xc1\x2d\x0c\x63\x34\x06\x4b\x2a\x36\xf2\xa3\xbb\x0d\xf6\x37\x60\x47\x63\xa0\x64\x0d\x3a\x68\x35\xc9\xff\x5e\x83\x71\x28\xff\x22\xab\xdc\x22\xc6\x71\x4e\xda\x37\xe6\xb2\x3b\x14\x86\x6f\x09\xbd\x23\x73\x23\x00\x9a\x89\xf5\xdf\x4a\xcd\xea\xb8\x67\x45\x99\x11\x2a\x98\x48\x02\x6d\xb7\x94\xe4\xa4\x4e\xab\xe9\xdb\x0f\xad\xa3\x36\x56\xb2\xcd\x41\xd6\xbd\xab\xbb\x4e\x7f\x54\xbc\x1b\xed\x91\x8d\xb5\x53\x54\x94\x12\xad\xac\x84\x7a\x4b\x5d\x2e\x81\xd3\xb7\x0b\x00\xa5\xf9\x20\x79\x79\x85\xd7\x31\x53\x3c\xde\xd2\x82\xae\x83\x94\xb3\x54\xec\x76\x29\xa4\x71\xf0\x1b\x14\xfe\xa6\x89\x1d\x6b\x96\xe9\x2f\x74\xbd\xce\x6f\x77\x6a\x98\xb6\xd4\x91\x6d\xdd\x91\x5f\x0a\x38\x0c\x32\x0b\x3e\x25\x02\x62\xc2\x0d\xc1\x40\x04\x19\xdc\x22\x81\x18\x07\x0c\x85\x50\xda\xc9\x82\x82\x0c\xad\x9a\x4e\x4a\x6b\xc0\xf5\x73\x54\x26\x7c\xe5\x54\x21\x02\x97\x21\xba\xda\x45\x65\xe1\xd2\xcc\x9a\x1a\xe7\xdf\x22\x12\x6f\x73\x13\x61\xc9\x1d\xe1\xc2\xa7\xf2\x61\x1c\x60\xe1\x7a\x2c\x36\x88\x08\xec\x43\x41\x59\xf9\xb5\x24\x16\xa3\x61\x88\xd8\x19\x24\x70\x8d\x1c\x9f\xc8\x2d\x79\x10\x87\xae\x57\x30\x0c\xcb\x0f\xff\x6b\x94\x7b\xf2\x61\x00\x13\x51\x91\x54\x6a\x90\x50\x4f\x86\x9c\x40\x4d\x6c\xf0\x8c\x23\x04\xde\xa7\xd3\x25\xed\x5f\xfe\xe1\xd9\x24\xe6\x70\x8d\x26\xbe\x7c\x7e\x27\x9f\x7b\x86\x87\x3d\x03\x62\xf2\x95\x79\xa0\xb9\xc4\x43\xf7\x70\x1b\x85\x88\x3f\x7f\x7e\x00\x7e\x85\x21\x0e\x00\x22\x82\x49\x3b\x11\x32\xf4\x03\xf8\x78\x2d\xa9\x7e\x3d\xfa\x38\x56\x3f\x25\xad\xd3\x3f\x32\x14\xb6\x0f\x4b\x74\xb5\x2f\x12\x6a\x26\xcd\xc3\xd0\xfe\xfc\xaf\xeb\xd1\xc7\x96\x0a\x7e\x0f\x61\x7e\x84\x60\xc3\xd0\xea\x7f\x5c\x8f\x3a\x13\xe4\x7a\x74\x54\xa0\xee\x8f\x13\x78\xe4\xa6\xd2\x8f\x3e\x0d\xd0\xd1\x7f\xfc\x2b\xa6\xe2\xef\x30\xc2\xfa\xc7\x8f\x13\xf5\x74\x9c\x7f\x2b\x29\x58\xfb\x3e\x43\xd4\x9a\xef\x4a\x74\xae\xf9\x36\x21\x7d\x5d\xbf\x61\x58\xf3\xf6\xbf\x72\xef\x0e\xdc\x86\x46\x48\xd7\x97\x48\x48\xe4\x29\x99\x91\x13\xb8\x2b\x09\x03\xcb\xf8\x72\x6a\x8b\x4b\xae\xc8\xfa\x1c\x09\xe3\x65\x89\xb7\x4b\xc4\xe4\x5c\x07\x70\xc7\xb5\x2f\x45\xca\x39\xf5\x32\xa4\x6b\x0e\xa4\xb9\x50\xb1\x1c\x36\x42\x44\xfc\x87\xc9\x44\xfe\x75\x00\xef\xf8\x01\xdc\xc2\x3f\x28\x39\xf0\xe9\x76\x32\x55\x3f\xd3\x26\x13\x29\x23\xb9\x98\x48\x98\x93\xdf\x36\x50\xcc\x78\x4e\x1a\xf2\x03\xc9\x89\xcf\x9f\x03\xcb\x02\xca\xca\x33\x1c\x70\x38\x06\xaf\xc6\xe0\x9b\x31\xf8\xdb\x18\x1c\x7e\x3d\x06\xaf\x5e\x8c\xc1\xb7\x2f\xc6\xe0\xfb\x17\x63\x70\xf8\x52\xfe\xf3\x8d\xfc\xe7\xbb\x17\x63\xf0\xea\xdb\x6f\xc6\xe0\xeb\x17\x2f\xc6\xe0\x9b\xaf\x65\x83\x57\x87\xf2\xc5\xcb\xbf\x8d\x95\x19\xf9\xea\xdb\x6f\x5e\xb5\x5b\x0b\x5d\x28\x95\xae\x8f\xe1\x29\x54\xb1\x70\x3e\x07\xd9\x3a\xaa\xf9\xac\xfe\xaa\x67\xe8\x21\x2d\x00\xc4\xea\x35\xb5\xdd\xa7\x18\x39\xd5\xd6\x0e\x68\x0b\xde\x69\x0d\x68\x07\xf7\x5e\x1f\x93\xdd\x6b\x65\xa9\x77\x83\x49\xde\xf7\x15\xe1\x5f\x8d\xb9\xdd\xdc\x1b\x25\x2d\xcb\xa6\x36\x45\x85\x8f\x5b\x79\xc9\x1a\xea\x62\xb7\xc3\x28\x45\xbc\x85\x3f\xc3\x69\xc3\x8c\xb4\x63\xf2\x00\xd3\xc9\xed\x21\x0c\xa3\x0d\xfc\x26\x8b\xda\x07\x77\xff\xb7\x10\x87\x70\x89\x43\x2c\x76\xbf\x53\xd2\xd5\xc6\xea\x43\x02\xdf\x65\xb9\xd7\x10\xbd\x6c\xf0\xd7\x89\xfa\x45\x41\x74\xf3\x38\x8a\x28\x13\x4d\x8c\x99\xe7\xad\x24\xe5\xa2\xa5\x65\x90\x97\x64\x06\x2d\x29\xcc\xdc\x54\x5a\x41\xb6\x86\x02\xcd\x19\x5d\xe1\xb0\xf1\x34\xb9\x29\xf8\x53\x0e\x56\xaf\xc9\x5b\x63\xd1\x6c\xd6\xde\xe0\x7a\x17\xd1\x4f\xbf\xbc\xfb\x3f\xe0\xd7\x43\x70\x72\x3a\xbf\x3c\x3d\x9e\x5e\xcd\x2e\xce\xc1\xf9\xc5\xd5\xec\xf8\xf4\x00\x58\x35\x92\xfa\xe3\x27\xa9\x3f\x7e\xa2\xd9\x7e\x82\x39\x8f\x11\x9f\xbc\xfc\xfe\xdb\x57\xe0\x0d\x16\x00\xdd\x47\x94\x23\x9e\xdf\x3a\x2a\x25\xf5\x53\x18\xdf\x83\xdb\x43\xeb\x58\x41\x90\x85\x18\x31\x80\x05\x32\x1f\xd1\x15\x58\x63\x41\xa3\x76\x8e\x85\xc7\x39\x82\xaa\x59\x93\xef\x9a\x4e\xdc\x45\x91\x12\x85\x91\xef\x43\xf4\xa5\x42\xf4\x0e\x87\xa1\xfc\x44\x60\x12\x23\xa9\x24\x96\xea\x20\x2b\x00\x98\x80\x55\x2c\x62\x86\x0c\xce\x20\x0a\x21\xe1\x63\xc0\x50\x14\x42\x5f\x19\xe0\x1b\xa4\x28\x92\xef\x00\x2e\xe9\x6d\x3b\xff\xec\x17\x45\xd4\x39\x13\x18\x6e\x5b\x49\xbd\xd9\xf4\xac\xea\x8c\x49\xda\x12\x62\x37\x67\xf4\x16\x07\x88\xf5\x93\x10\xb3\x02\xb4\x5e\x32\x42\x29\xeb\xde\xda\x2d\x6f\x35\xec\x55\x6c\x37\xf1\x12\x31\x82\x04\xe2\xe7\x48\xc8\x65\x56\x32\x37\x6a\x86\xff\xb6\xa2\xb1\xb3\xa7\xad\xda\x23\x05\xe7\x34\x40\x6f\x18\x8d\xcb\xeb\xaa\x15\xe5\xcf\x0a\xd0\x86\x38\x0c\x52\x3a\x50\x42\x5c\x2b\xfc\x80\xd2\x4d\x89\x06\x54\xf8\x63\xb2\xf6\x48\xf2\xc5\x73\xb5\x0e\xde\x9b\x91\x81\xf4\x45\xd2\x08\xdd\x70\xcf\xbc\x56\xed\xf8\x10\xda\xd2\x81\xc9\xf5\xe8\xa8\x88\xb8\xd4\x91\x0a\xbf\x52\xfb\x32\x52\xd7\xa3\xa3\xf2\x20\xaa\x95\x6c\x62\x6a\xb6\x59\x92\x67\x48\xc0\x8a\xd3\xae\x61\x58\x62\x50\x5e\xf8\x89\x32\x80\xc9\x8a\xb2\x6d\x7a\x14\x61\xbd\x12\x40\xed\x73\x1d\xb3\xed\x62\x91\x76\xba\x71\x5f\xaf\x0d\x79\xa1\xc9\x24\x46\x0c\xdf\x42\x81\xcc\xec\x34\x9b\xca\x79\xbe\x4d\x1d\x01\x61\x18\xd2\xbb\x54\x85\x48\xa9\x0f\xc1\x2a\x0e\xc3\x9d\x67\x7a\x4e\x76\x3f\x98\x98\xd3\x19\x42\x15\xfb\x81\x0d\xe4\x80\xc6\x42\x9d\x07\x02\x49\x30\x29\x64\x00\xf4\x7d\xc4\xb9\xde\x6a\x5a\x10\xfa\x99\x0a\x20\xf9\x6d\x01\xcc\xb9\x01\x07\x98\x1b\x4f\x54\x00\x6e\x31\x04\xbf\xce\x8f\x01\x22\x41\x44\x31\x11\xed\x8c\x95\xc7\x3b\x0a\xe7\x9c\x72\xe4\x33\x24\xf8\x29\xf1\xd9\xce\x8e\xa1\xc1\xb4\x2e\x4a\xcd\x9c\xd0\x6f\x23\xbf\xd5\x8a\xff\x75\x7e\xdc\xd5\x1b\x50\xb3\x71\x75\xc9\xa1\x06\x0a\xad\x60\x4c\xd4\x9a\x04\x85\x31\x8f\x4b\x9b\xe1\xea\x65\xe4\x16\x6b\xb5\x6a\xb0\x66\xf7\x52\xbb\x03\x75\xef\x0d\x6b\xb9\xa1\xb0\x23\x29\x9b\xba\x83\xf8\x56\x20\xe0\x58\x8a\x2c\xb3\x6c\xc6\xc6\x36\xd4\xe6\x1f\x0a\xf4\x51\xaf\x21\x18\x98\xce\x67\x8d\xbd\x2a\x7d\x00\xa7\x7c\xe1\x29\xc9\xe8\x99\x73\x47\xcf\x98\x5d\x29\xf3\xe5\x18\x5c\x7d\xab\x6c\x62\xeb\x35\xc8\xcb\x8f\xf4\x50\x78\x94\x78\x13\x72\x1f\x18\xf0\x55\x76\x99\x5d\x16\x1f\x5c\xae\x9f\xd3\x64\xb5\x37\x38\x00\x32\x8c\x38\x55\xb2\xa4\xca\x8e\x5c\x52\x1a\x22\x58\xb1\xbe\xa3\x78\x19\x62\xbf\x2d\x80\x56\xeb\x3a\x8f\x64\x55\xdf\x83\x70\xa1\x3e\x1f\xb5\xd2\x19\x46\x58\x09\x56\xc4\x12\x19\x6a\xc5\x6e\x46\xe1\xb6\x3c\x7c\x6d\x09\xdc\x35\xc5\x72\xa3\xd2\x60\x72\xad\x60\xa0\xc1\xe9\x3d\xf2\x63\x09\xae\x59\xd0\x4b\x9d\x8a\x66\x34\x34\x3b\xb6\xe5\x0e\x44\x34\xd0\x61\x49\x1a\x6f\xa9\x88\xa6\xf3\x19\x3f\x00\x57\x1b\xcc\x81\xfa\x14\x73\x00\x83\x40\x7b\x2e\xe5\x0e\x2e\x35\xff\xc1\xe5\xeb\xe9\xb1\xda\x20\xc2\x58\x6c\x92\x00\x8e\x03\xa0\x4c\xea\x39\x0d\x40\x82\x36\x90\x78\xd7\x1f\x0a\xa0\x1b\x6e\xbd\xdc\x31\x47\x6c\x1d\xe3\x00\x4d\x22\x1a\x78\xc8\x02\xf1\x24\x3e\xfa\x28\xa0\x95\x3a\xff\x4c\x23\x6e\xe6\xd9\x6f\x33\xcc\xeb\xd1\x51\x99\x8a\xfb\xbd\x60\x05\x76\x99\x0f\x1a\x1e\xe6\x0c\xdd\x92\x14\x91\x94\x32\x18\x48\x22\x83\x64\x3c\x8a\xa8\x1f\x0d\x57\x9c\xbe\x5d\x00\xe3\x61\x03\x8b\x82\xb7\xd1\xb4\xf6\x8c\xbb\xaf\xe5\xa6\xa9\x1f\x62\x25\x13\xbb\x88\xcc\xf5\xe8\xc8\x81\x7b\xf5\x64\xe4\xa3\x59\xfa\xed\x71\x52\xa9\xb1\xc8\x41\x1d\x62\xcb\x63\xf0\x94\xeb\x41\x21\xaa\x0e\x28\x18\x92\x63\x34\xe7\x57\x46\xde\x99\x09\x9c\x4d\xcf\x80\xc1\x02\xd8\xc1\x7d\x78\x36\xc1\x70\x6b\x20\x59\x40\x93\xaf\x14\x21\x3d\xa9\x9e\x3d\x73\xc2\xab\xec\x9b\x76\xd3\xda\x12\xbf\xcc\x3c\xb6\x40\xe9\x7a\x74\xe4\x1a\xd7\xde\xd9\xed\x11\x82\x98\x81\xf0\x99\x16\x28\x0c\x43\x60\xad\x5e\x6f\x09\xa5\x3c\x54\x7f\x60\xc4\x0d\x45\x95\x80\x34\x26\x8f\x9e\x6d\x29\x1e\x53\xf4\x80\x45\xaf\x5e\x92\xcf\xa6\x67\x56\xc4\xbd\xe3\x88\xbd\x51\x22\x4e\xcb\xdb\x7f\xd8\x38\xb2\x7f\x18\xd4\x30\xe2\x1d\x24\xfa\x90\x63\x6c\x26\xb6\xbb\x8c\xe9\x7a\x74\x54\x41\xbf\x6a\xc6\xba\x8d\xfc\x4b\xc4\x69\xcc\x7c\x74\x9c\x04\x1a\xb8\x83\xc2\x8b\xc6\x59\xed\xbe\x5c\x85\xc7\x99\xec\x89\x24\x9e\x6f\x07\x08\x92\x23\x30\xd1\xb7\x2c\xd6\x0b\x4a\x6e\x39\xd3\x28\x87\x64\x99\xe9\x27\xca\xad\xdb\xce\xb1\xfc\xb0\x9d\xa7\x31\x9c\x82\xc5\xc8\x49\x54\xb9\xde\x2f\x66\x27\xc7\x7d\x28\xa8\xf7\xe4\xe9\x18\x24\x3c\x10\x99\xcd\x23\x80\x1c\xdc\xa1\x30\x94\xff\xcf\x2e\x17\xd3\x44\xef\xe8\x73\x7c\x70\x7c\x3e\x03\x51\x18\xaf\x31\x69\xe7\x91\x1f\xa8\xcf\x8e\x66\x7b\x41\xc8\x35\x17\x5e\xfb\x6d\x92\x02\xbc\x16\x96\x8b\x6b\x5a\x6b\xd4\x6e\xc3\xa5\x35\xe0\xde\x43\x8a\x20\x39\x59\x50\x08\x86\x97\xb1\x40\x26\x5a\xd9\x2f\xf8\x0a\x1a\x26\x59\xec\x81\x56\xb1\xbb\x50\x6e\xd7\x26\x29\x4b\x84\x50\x01\xf3\xf9\x6e\xf5\x14\x78\x90\x78\xf8\xbd\x51\xd8\x21\x5c\xa2\xf0\x71\xa3\xd8\x35\x7b\x43\xb6\xe3\x11\xf4\x9b\x37\x6e\xb5\x88\x8b\x81\xd7\x69\x77\x65\xf2\x8e\xdd\x8c\x31\xe0\xe2\xc8\xba\xb9\xef\x10\xf0\x21\xd1\xe9\x7a\x89\x4d\x77\xa1\x88\x2f\xd9\x57\xc9\xb3\xa2\xf5\xd7\x72\xf5\xf4\xee\xae\x62\x79\x15\xcc\xf0\x26\x0b\xed\x8b\x66\x77\xa5\xe9\x8f\xf9\x01\x0e\x9b\xf5\x55\xd9\x8b\x93\xef\x9f\xb2\xc1\x9a\x64\xcb\xf5\xf7\xf7\x64\xd2\xae\x94\x77\xa3\x30\x5d\xa8\x17\x4f\xb4\x06\xee\x1c\x6a\xa7\x93\x45\xab\xe5\xdc\x4e\xcd\x2f\x96\x12\xa7\xdd\xd1\x03\xd2\xb5\x47\x8f\x4e\xd2\xc8\x79\x3a\xdf\xaf\xab\x6a\x8f\xcc\x23\xe4\xe3\x15\xf6\xf5\x9c\xab\x64\x6c\x4c\xb8\x40\x30\xb0\x48\xab\xe0\xad\x44\xf6\x7a\x6b\x44\x10\x53\x9b\xaf\xa4\x45\xbb\x03\xf1\x21\x3a\xac\xa4\xc6\x05\x09\x7b\x6d\xae\x34\x76\x3b\x80\x57\x80\x92\x70\x97\xac\xf4\x82\x3b\x41\xa3\xc2\x37\x34\x0e\x03\xb0\x44\xc9\x7e\x54\x4e\x1f\x8d\x85\xfe\x1b\x93\xf5\xc4\xea\x5e\x13\x32\xd3\x87\x8f\x3e\x33\x6a\x6e\x4f\x87\x80\x22\x6e\x18\x4f\x55\xa5\x62\x17\x1a\x86\x13\xfe\xa3\x4a\xe6\x94\x1b\x7e\x89\x50\xb2\x1b\xeb\x25\x05\x5a\x01\x6b\x60\xa3\x0e\x96\x91\xd8\xd1\x18\x75\x1d\xdd\xd6\x65\xf5\xd5\xa6\xe7\x55\xa5\xfc\xe5\x15\xe7\x1e\xa5\x50\xe6\x53\x97\xa8\x74\x09\x8c\x22\x07\x0e\xb9\x85\xd4\x39\x97\x85\xd9\x4e\xf3\x6a\x21\x09\x7a\xa5\x0f\xb6\x87\xdf\xc8\x0e\x5e\x14\x17\x7a\xa5\x35\xcc\x5a\xfa\x4d\x5b\x31\x99\x05\x3e\xe0\x84\x68\xd6\xc8\x5a\x71\x55\x2b\xb1\x61\x05\x94\xbd\xf0\x5c\x04\x2f\x6e\xea\x6b\xaa\x4e\x64\x19\x16\xad\xdb\x45\xfe\x3f\x0e\x97\x40\xde\x83\xc8\x96\x58\x30\x69\xf8\x24\x3c\x8a\xd7\x84\x32\xed\xcd\xfd\xa8\xdd\xb9\x2d\x13\xd9\xea\x61\xea\x1c\x2c\x0d\x38\x49\xbe\x7a\x00\x97\x40\xdd\xa8\x0d\x7b\x14\x1d\x47\x4d\x06\x57\x68\xea\x36\x7d\x34\x63\x74\xc7\x4f\x39\x1b\x7f\x5b\x00\x0d\x08\x6c\x28\x37\x86\x01\xe6\x9d\x90\x6e\x02\xef\xf1\x5b\x00\xea\xa0\x59\xee\x7e\xe0\xda\x8c\x46\xfb\x1c\x1d\x07\x10\xad\xa8\xd3\x19\xee\x60\x45\x0e\xea\x46\x6d\x13\xcc\x18\x86\x44\xa4\x19\xac\x87\x07\x87\x7f\xb3\xb9\xa6\x87\x07\x87\xdf\x65\x7e\x7f\x9f\xfe\x7e\xf9\xe2\x7a\xf4\x11\x3c\x33\x88\x3e\xb7\x4f\x0f\x5b\x27\xa7\xba\xb0\xc8\x66\x53\x4a\x74\x6a\x92\x2d\x25\x86\xf5\xaf\xbf\xaf\x7d\xfd\xf2\x45\xee\x75\x76\x44\x85\x0f\x0f\x0b\x69\x9d\x55\x13\x26\x61\x36\x89\xff\x96\x03\x2b\xe6\x72\xcb\xd1\x38\x9e\x7d\x5f\x7e\x56\xe8\x43\x3f\x3b\xac\x08\x23\x6f\xa5\x8b\x2b\x94\x91\x83\xf5\x8a\xcb\xf9\x21\x7d\x91\x49\xbe\xbe\xde\x26\x86\x99\x68\xce\xf6\x41\x41\x8d\x80\xb9\xd4\xf9\xf9\xf4\xaa\x89\xad\xb4\x86\x02\xdd\xc1\x3e\xee\x8b\x8a\xb5\xf9\x33\x5e\x6f\xc2\xdd\x54\x47\x18\x86\x48\x2e\x41\x6b\xf4\x21\x0e\x20\xd8\xa8\xf7\x00\xda\x0f\xc0\xf9\xf4\x0a\x18\x6c\xd4\x12\x5d\x60\xb2\x76\xb4\xe3\xea\x71\xf6\xeb\xc2\xd2\x3e\xc1\xdc\x76\x18\xe8\x9f\x5c\x7e\x3d\xec\x52\x2f\x8c\x2e\xbf\x30\x5b\x8c\x33\x0b\x53\x0f\xb8\x06\x54\xfd\xd0\xb3\xa0\x0c\x0d\xf2\xb0\x6a\xa8\x91\x91\x09\x1a\x8b\x26\x52\xa1\x40\x83\xe2\x22\x77\x00\x02\xc0\xce\xce\x10\xab\xdf\xb2\xee\x20\x8b\x56\x12\xd5\xcf\x47\xf5\xee\xe3\x91\x4c\x13\xd7\x02\xd4\xd5\xfd\xda\x84\x59\x36\xdb\x2e\x17\xeb\x45\x3a\x55\xae\x0e\x7d\xec\x0b\xb0\xd5\x74\xd8\x41\x94\xb1\x18\x70\xab\x94\x44\xb7\x93\x00\x68\xe8\xa6\xe6\x62\xdb\xb3\x9b\x1a\x40\xae\xc9\xfc\x75\x7e\xdc\xe8\x1c\x26\x16\x74\x1a\x86\xd4\x87\x02\xcd\xe6\xb7\xdf\xf6\xf1\xfb\x4d\x73\xb0\x7e\xfd\x16\xc8\x0d\x19\xe2\x42\x6f\xb0\xe7\xb7\xdf\x82\xe3\xd9\xc9\x25\x58\x86\xd4\xbf\xd1\x4e\xda\xc9\x37\xdf\x02\x39\x43\xf8\x3e\x71\xe9\x48\xbc\x5b\xf9\x84\x86\xea\xd4\xc9\x95\x9f\xbf\xfc\xa3\x5f\x1d\xf4\x5c\xd3\x7b\x29\x54\xba\xd6\x3f\x8b\x90\x49\xd7\x52\x99\x1c\x69\xda\xc5\x7c\x96\xc4\x1e\xde\x46\xbe\x47\x74\xea\x80\xaa\x4c\x92\x64\xd8\xe8\xcf\x3d\x41\x3d\xb1\x41\xd9\x78\x72\x18\x61\x4f\x87\xff\x7a\x49\x7e\xc6\x00\x69\x5e\xc3\x20\x62\x53\xbb\x4a\x03\xae\x8e\x3c\x42\xf7\x82\x41\xc9\x3b\x5f\xee\x24\x4e\x45\x70\x25\x92\x47\x33\xb2\x3d\xe6\x90\xd3\x3e\x06\xe8\x60\x7d\x00\xa0\x7e\x23\xbf\xb6\x42\xc2\x48\x06\x20\x01\x90\x1d\x80\x81\xb7\xa1\x65\xc1\xd3\x64\x52\x1e\x0a\x07\x27\xcd\x5b\xd4\x3e\xcd\x1e\x97\xa9\x64\x92\xc5\x06\x32\x9d\x51\xb2\x40\x7e\xcc\xb0\xd8\xa9\xcc\x92\xcb\xd8\x91\x00\xdf\x56\xaa\x49\xab\xd5\x87\xa1\xb4\x8a\x82\x00\x70\x03\x1f\xa8\xb4\x08\xc0\xe2\xd0\x9c\x5e\x92\x00\xac\x18\xdd\x2a\x91\x62\x0c\x94\xc4\xfa\x2d\x34\x92\xdf\x2a\x0f\xb6\xc2\x5a\xa7\x4a\xe5\x3f\x31\x11\xd8\x26\xf7\x2a\x26\xd9\xd4\x44\x1d\xf5\x49\xb7\xdb\x98\x60\x3f\x77\xe4\x95\x0b\x0c\x53\xbd\xe4\xda\x19\xa0\xba\x3c\x20\xf0\xd5\x4e\x02\x2c\x91\xb5\xb4\x02\x70\xb7\x41\x04\xc4\xd2\x6e\x33\x7b\xe7\x64\x37\x9d\xc7\x8e\xb7\xb3\x4e\x9f\x88\xd8\x84\x88\x0d\x42\xf7\x08\x6c\x58\x42\x21\xb3\xa9\xaa\xb1\xb7\x74\xaa\xc9\x97\x95\x72\x3a\x5f\x30\xd5\xd2\x9a\x0d\xe4\x8c\x65\x44\xb5\xb1\x78\x6e\xbe\xe3\x52\x6a\x27\x09\x26\xad\x98\xb0\x57\x47\x4e\x22\xf2\xac\xa4\xe9\xb1\x23\x7d\x06\x6f\xa0\x3e\xb6\xd5\x9c\x37\x97\x8c\x97\x13\x63\xcf\x95\x68\x4d\xb9\x55\x72\xde\x12\x89\x3b\x84\x88\x83\x5d\x15\x9b\xb6\xa2\xcd\xc3\x60\xe0\x26\x9a\x5b\x50\xf7\x20\x9f\xd6\x3a\xc8\xd3\x35\x4d\x83\x9c\x3c\x58\xbc\x69\xad\xee\x6a\x40\xb9\x07\x54\xda\x37\x81\xbd\xeb\x72\xe1\x52\xc5\x05\x5c\x6e\xd0\x4e\x7b\x31\xa7\xbf\x1b\xda\x93\x5b\x44\x30\x22\x3e\x32\xe1\xe8\xca\x15\x6c\x52\xa3\x3f\x3c\x9b\xd8\x24\xe9\x09\x43\x4a\xfa\x78\x18\x6e\x3d\x48\x02\xef\x36\xf2\x27\xcf\xb3\x01\xb2\xef\x8d\x74\xba\xc7\xda\xa7\xfc\xeb\xfc\x98\x57\xda\x7e\x31\x47\x9e\xfd\x52\x82\xf2\x54\x6d\x79\xcf\x8f\xb9\xa0\x5b\x2f\x77\x30\xf6\xbc\x9d\x5a\xd8\x3b\xc2\x8c\x39\x58\x3b\xb8\xeb\xd1\x51\x96\x16\x3a\xeb\x3f\x1d\xee\x5e\xab\xb2\xc5\x10\xaf\x47\x47\x0e\xe2\xc9\x1e\x3b\x57\xfd\xca\x97\x66\x57\x7b\x8e\x4a\x21\xe3\xe0\x3b\xb7\xd1\xda\x60\xc5\xb5\xb3\xa1\xc6\x35\xbb\xc6\x82\x86\xaa\xdb\xcf\xd4\xea\xa0\x01\x37\xde\xeb\x90\x2e\x61\x68\xaf\x43\x50\xc5\x6f\xc2\x10\xf8\x1b\x1c\x06\x1d\x77\xe0\x4d\x20\xe6\xb6\xe2\x85\xd2\x49\x03\x17\xc8\x1f\xe6\x34\xcd\x26\x70\x45\x1a\xc9\x76\xeb\xb7\x0a\x86\xdb\xe2\x18\x34\x6d\x73\x36\x3d\x53\x51\x3a\xff\xc9\xc1\xf4\xf2\x5c\x6a\x6e\x13\xc9\xca\x62\xa2\x93\x1a\x29\x11\xd4\xa2\xd6\x6e\x58\x6d\x61\x57\xd8\x06\x21\xf2\x05\xed\x59\x5b\x27\xcf\x42\x0b\x03\x73\x08\xb3\x4b\x6b\x38\x1d\xaa\x68\x8d\x6f\x8d\x33\x90\x62\x31\xa4\x50\x1d\xaf\xd9\x92\x9d\x3d\xc8\xd9\xaf\x27\x37\x71\x9d\x31\x54\x2d\xd8\xe7\x4a\x9a\xf9\x31\x63\x88\x88\x42\xf4\x41\xaf\x05\xd1\x02\x6c\x1b\x53\xe2\x33\xdb\xe2\x16\x57\x13\x00\x67\x98\x3f\xa0\xc0\xa8\x4c\xa0\x2a\x0d\xa8\x60\x67\x7b\xe9\x8c\x9a\x4e\xb9\xf5\x31\x13\xaa\xae\xaf\x21\x94\x20\x9b\x9f\x13\x8c\x95\xb4\xb4\x4e\x01\xeb\x79\xb3\x3b\x3b\x55\x46\xcb\x94\xce\x6a\x47\xf2\x47\x82\xb2\x73\x3a\x1f\xd5\x41\xfc\xbb\xcc\x81\x79\x1a\x5a\x60\x0e\xcd\x5b\x91\xbc\x05\xa4\xaa\xc3\xf6\x56\xf6\x51\xf1\xd4\xd4\xa5\x49\x9c\x92\xb7\xde\x58\x2a\x9e\xab\xf2\x5c\x50\x65\x3f\x1b\x44\xcb\x3c\x6e\x38\x4d\x48\x3b\x91\x03\x1b\xb2\x90\x48\xba\x44\xfc\xb9\x85\x6b\x33\xc1\xda\xb1\x93\x1a\x4b\x25\x51\x33\x8d\x2c\x16\x9d\x3d\xd3\xd8\x6c\xf9\xf2\xa9\x4b\x39\x1a\x66\x8a\x19\x28\xcc\x40\xc2\x3d\x19\xbd\x5f\xd0\x56\xed\x04\xd4\x00\x3d\x34\x8c\xad\x6a\x92\x36\xd5\x90\x16\x09\x38\xed\x8c\xd3\x42\x76\x40\x4a\x34\x86\xdf\x43\x64\x54\xa5\x75\x0d\xba\xc0\x7b\xd8\x4e\x4d\x97\x77\x57\xa3\x29\x59\xdc\x61\x7c\xdf\xa8\xbc\x4a\xe8\x50\x57\x15\x66\x69\x18\xdf\xff\x14\xe6\xe5\xa7\x23\x4c\x91\x80\x4c\x54\x21\x8c\xa4\xea\xd5\x6c\xa8\x50\x4f\x7e\x45\x90\x73\x75\x46\xa0\x30\x90\x4f\x54\x85\xcd\x25\xa5\x82\x0b\x06\x23\x55\xf8\xcb\x78\x52\x39\x42\x49\x81\xd4\x55\x18\xdf\xfb\xc1\x01\xa6\x2a\x45\x7d\xa2\x34\x74\x36\xc5\x8d\x12\xa5\xc0\x57\x65\x44\xf7\xc5\x42\x3e\x26\xc4\x9d\xcb\x7d\x8d\x45\x52\x6e\xb3\x9f\x15\xcc\x50\x44\x39\x16\x94\xed\x92\x08\x43\x13\x7c\x7b\x00\x8e\xf5\xad\x79\x08\x8b\x0d\x62\xe0\x8d\x3a\xe2\x04\x54\xfd\x0a\xe1\xb2\xbd\x69\xdc\xa7\xaf\x8e\x82\x20\x4b\xa8\x71\x91\xd7\x07\x91\x04\xa6\xdc\x24\xd4\x75\x60\x33\x95\x5c\xf5\x01\x41\xae\xd4\x39\x54\x05\x5f\x33\x64\x50\xda\x7a\xa5\x87\x79\x11\x71\x70\x45\x69\x78\x83\x05\x78\x66\x6a\xcc\x3e\x6f\x2e\x2e\x1e\x1a\x8f\x92\x4c\xf9\xa9\x20\x2f\x1a\xdc\xfe\xe9\x56\xe0\xad\x6f\xfa\x84\x85\x45\xa9\xbc\xb6\x90\x2b\xb7\x5c\xba\x70\x2b\x16\x65\x63\x82\x0e\xd4\x4b\xcd\x8d\x9a\x6f\x70\xa3\x64\xd9\x04\x68\xd9\x93\x54\x23\xa3\xed\xc7\x75\x02\x40\x3b\xb6\x2c\x83\x08\xaa\xd2\xc8\x24\x07\x41\xf0\xba\xd0\xa9\x14\x4a\xb9\xf2\x32\xb6\x74\xf5\xe9\x49\x3b\x41\x30\x54\x9f\x4e\xb9\x28\x09\x08\xf3\xa6\x6b\x0d\x89\x2e\xec\xd7\xad\x68\x94\x84\xb8\x29\xdc\x7e\x46\xe1\x16\x58\x40\x00\xab\xc3\x90\x7f\xc6\xc4\x57\x4b\x4f\x1d\x29\xc2\xa4\x04\xb7\x19\xa9\x29\x92\x35\x18\x01\x1f\x02\x21\x27\x75\xa5\xc0\x68\x46\xd9\x4b\xf9\x65\x2b\xaa\x9a\x4b\x73\x2c\x66\x94\x80\x1d\x8d\xd9\x03\xb0\x5b\x9b\x8e\x3a\x2a\x1d\x96\x1f\x7d\xca\x95\xe3\x9a\x45\xfd\xd9\x95\x91\x22\x84\x14\x66\x46\xe6\x4b\xab\x23\xad\xe6\x47\x02\x10\x62\x72\x23\xdf\x63\xe1\xd2\x19\x07\xe0\xfd\x1b\x5d\xd9\x5c\x55\xff\xf9\xf0\x6c\xa2\xcb\x67\x7a\xff\x8a\xb1\x7f\xc3\x05\xcc\x95\x2c\x1b\x52\x7b\xf5\x46\x3c\x73\x1e\x54\xc6\xf9\x7a\x74\x94\x1d\x57\x1a\x21\x94\x91\xda\x17\x51\xa3\x30\xc9\x55\xde\xf2\xae\x59\x2f\xca\x46\xef\xbe\x5e\x5e\x16\xd9\x78\xc0\x25\x52\x86\xdd\x71\x55\x28\x6a\x7c\x71\x2e\xb7\x96\x4d\x6b\xa6\x39\xa7\x02\xfd\xa0\xb3\x6f\x94\xeb\xcf\x14\x5c\x55\x32\x97\x86\x81\x36\x5a\x81\xc8\xdd\xdd\xf3\x90\x5c\xff\x59\x06\x92\x63\xfc\x52\xa1\xff\xbd\xfe\x21\x65\xcf\x35\x76\x0d\x19\xeb\x6f\xe0\xb8\x7e\x8a\x03\xff\x7a\xf4\xf1\x07\x5d\x2e\xca\x56\x43\x4b\xea\x46\x0d\x1a\x65\x2f\xfb\xca\xc5\xb0\x37\xeb\xd5\x1d\xae\x2e\x81\x0d\x11\x76\xee\x9e\x04\x4a\xd0\xc5\xaa\xba\xe4\x6f\x85\xc1\x34\x3b\x39\xae\xbe\xee\xe1\xcf\x52\x27\x55\xe9\xb6\x25\x7a\xe4\xd9\x3f\x09\x6f\x40\xf6\x44\x3f\x09\xa4\x52\x9f\xa5\xf5\xf6\x6a\xef\x48\x59\x86\x74\x39\xd9\x42\x4c\xd2\xe0\x81\x97\x7f\xf3\x24\x59\x3d\xdb\xef\xc1\x0e\x6e\xc3\x16\x9b\xac\x76\x23\x28\xd7\xd2\x1b\x04\x5f\x15\xed\x50\x41\x9a\x4c\x20\x42\xb2\x6c\xf3\x95\x73\x1a\x6c\xd8\x5a\x6f\xc8\x2c\x59\x76\x99\x8d\xd1\xff\x5a\x5c\x9c\x4f\xfe\xef\xf4\xec\x97\xa4\x34\x0e\x1f\x03\x1e\xfb\x1b\x00\x39\x50\x81\x0a\x8e\x6b\xc1\x28\x73\x5f\xd6\xdb\x74\x5e\x1e\x0e\x81\x9a\x6d\xdc\x4c\x5a\xd1\xc4\x77\xfa\xcd\x2b\x2f\x95\x8d\xe2\x29\xf3\x37\x58\x20\x5f\xc4\xac\x8f\xd8\x3b\x9e\xbf\x03\x59\x50\xf6\x80\xeb\xf4\xf8\xa5\xb6\xef\x89\x94\xed\xbb\x08\xa5\xd7\xde\x15\x24\xe4\xfd\x77\xdf\xfe\xe3\xdb\xaf\xaf\x47\x1f\xd5\x6d\x98\xdb\x20\xfd\xcd\xb6\xea\x77\x2b\x19\xd9\x13\x9f\xac\x38\xd5\x88\xe5\x93\x82\x72\x77\x45\x4a\x5c\x6b\x5e\x4b\xf4\x73\xaf\x9b\x88\x5d\xdd\x69\x31\x0d\x48\x75\x55\x7a\x28\x3b\xd8\x7f\xbd\xcc\x3a\xaa\x3e\xab\x6e\x74\x03\xa5\x2e\xf7\x82\x8a\x97\x2b\xbe\x99\xbf\xe3\x07\x60\x26\x54\x21\xaf\xa5\x3a\x03\x92\x1a\xff\x45\xc6\x57\x4c\x28\xf1\xde\xcc\xdf\xe5\x09\xdf\x32\x78\xf7\x01\xba\x77\x92\x69\x8b\xb6\xb4\x57\x5d\xa2\x3c\xa2\x1a\x1c\xb8\xda\x20\x10\x13\x2c\x6c\x30\xb1\x32\x70\xdf\xe0\xd7\x3d\x48\xb0\x0f\xb2\x73\x74\xb7\xc7\xf3\x77\x0f\xc2\x05\x1a\xf0\x10\x13\xaa\x21\x75\xb4\x32\x8a\x68\xd8\xe9\x2c\xae\x83\x71\xb5\x0c\x1c\x64\x6f\xa0\x35\x41\x4e\xd8\xd8\x03\x37\x6b\x55\xb7\xd4\x2a\xf5\xb0\x72\x9a\xa0\xea\x2e\xa8\x06\x0a\xc1\x38\xc2\x67\xf3\xdb\xaf\x8f\x67\x27\x97\x7d\x14\xc2\xec\xe4\x12\x30\x48\xd6\xc9\xe1\x1a\x62\x08\x7c\xb4\x65\x4a\xe6\x1f\x95\xa4\x05\x90\x73\xbc\x26\x28\x68\x27\xdc\x9d\xb0\xb5\xd0\x4d\x3a\x30\xc2\xb6\xd0\x4d\x47\xbe\x2a\xd2\x65\x10\x26\x49\x6f\x28\x37\xfb\xa6\x34\x18\xb4\x35\x93\x34\x81\x95\x63\x92\x5f\x60\x4c\xfc\xcd\x15\xda\x46\x61\x3e\x87\xb2\x62\x13\x85\x83\xe6\x5b\xa8\xbd\x19\x34\x75\x8c\xa3\x11\x03\xc2\x60\x06\x66\x27\xad\x78\xc3\xd1\xdc\x2d\x09\x7b\x57\x57\x28\xf6\x64\x20\x82\x93\x8c\x20\xce\xe6\x8f\x84\x15\xdf\x5f\x5d\x9c\x5c\xd8\xdb\x34\xc1\x5f\x4d\xeb\x31\xf8\xeb\x2f\xaa\xb2\x75\xaf\xc1\x3f\x10\x4a\x1d\x17\x51\x3e\xc2\xf8\xb6\xea\xf6\xdb\xba\xa5\x94\x63\xe1\xd2\xc5\x73\x03\xc7\xb6\xc2\x2d\xee\x5d\x8f\x6f\x07\xde\xeb\xf8\x6d\x30\x3d\x9b\x65\x2e\xa4\xd7\x31\xdd\x70\x8b\xd3\x8b\x15\xc6\xe0\x23\x8c\x05\xf5\x38\xdf\x7e\x34\xbf\x3f\x8e\xe5\x56\xe0\x23\x17\x50\x60\xbf\x9d\x01\x6c\xbb\x2f\x5f\xf0\x5a\xee\xfa\x7a\x74\x94\x41\x52\x6e\xde\x6c\x5e\xbc\x45\xa8\x50\x5b\x43\x3e\x4e\x1e\x51\x66\x9e\x6a\x34\xad\x91\xeb\x5c\x75\x70\x8b\x7f\x82\x5b\x5c\x5d\xda\xaf\xbb\x87\x45\x57\xd8\xfe\x05\x93\xf8\xfe\x65\xb9\x72\xc9\xbb\x65\x4c\x44\xfc\xf2\xc5\x8b\xaf\x6d\x85\x13\xfd\xe4\xf0\xbb\xf4\xc9\x6b\x2a\x44\x88\x18\xf5\x6f\x50\x72\xab\xff\x6f\x98\x04\xf4\x8e\x2f\x54\x2a\xe7\xcb\x17\x87\xdf\x1f\x53\xa6\x2a\x55\xab\x2b\xa5\x2b\xbf\xfa\x29\x0e\xc3\x7d\x5f\xbd\xf8\xba\x08\x6b\xd8\x62\x0b\x59\x82\x34\x2a\x81\x92\xd2\xa8\xa6\xa0\x4a\x4a\xb6\x9a\x8f\xb2\x94\xac\xf9\xac\x9e\xb8\x6d\x1a\xe6\xe8\xdd\xbc\x61\x61\x0a\x1a\xd6\x7f\xc9\x12\xb6\xc9\x5e\xae\xf2\x7b\x00\x32\x7c\xe9\x7e\x23\x09\x5d\x7c\x93\xa5\x6e\xf1\x5d\x3d\x49\xf7\x7e\x9d\xa3\xe3\x9e\xaf\x0b\xc4\xdb\xbf\x03\x85\x7c\xbd\x88\x79\x84\x48\x30\x67\xd4\x47\x9c\x3f\xf0\xdd\xdd\xb5\xd2\x19\x21\xf0\x9e\xa1\x10\xdd\x42\x22\x54\xec\x68\x40\x7d\x5e\x7f\x85\xc6\xf4\xb7\x85\xaa\x68\xfa\x93\x0d\x91\x71\x5c\x3e\x71\xc7\xbd\xa4\x2a\xbc\x17\x47\x01\x14\x48\x97\x66\x56\x97\x4f\x7c\xe5\xaf\x48\xfa\x9e\xe7\x3e\xf0\x18\x0d\x43\x4c\xd6\xfa\x99\xc7\x35\xa5\x22\x4b\xa9\x3e\x59\xec\x8f\x76\x50\xd7\xa3\xa3\xd2\x1c\x54\x27\xc3\x7f\xde\x9b\xdf\x6b\x4d\x3f\xbc\xc5\x42\xdf\x3b\xaa\x63\xe2\x6c\x29\xdc\xe9\xef\xa9\x8e\x97\x4a\x92\xfb\x30\x54\xb9\x5d\x7f\x50\x82\x3c\x78\x07\x19\xf2\xb4\x4e\xd5\x2f\xda\xcd\xaa\xee\xb6\xa4\xd1\x9b\x74\x64\x6e\x22\x2d\x61\x5b\x4d\xed\x65\x56\xca\x34\x3a\x3e\x4c\x0c\xb1\x4a\x01\x55\xed\x4d\x48\x22\x87\x57\x94\x81\x6c\xfb\x0e\x69\xa4\xcd\xa1\x3a\x07\x1e\x20\x2e\x2d\xc7\x63\x18\x41\x1f\x8b\x4a\x4b\xc5\x7a\x4b\xdc\x30\x74\x16\xf6\xec\xec\x64\x71\x7b\xd8\x27\xf1\xdf\xd8\xb1\x3c\xad\x28\x62\x4c\xf8\xa4\x3e\xa2\x2d\x52\x69\xc2\x78\x55\x97\x2f\x81\xa0\x37\x88\xb4\x23\xdb\x90\x5d\xa5\xda\x32\x35\xdb\x2b\x68\x34\xa7\x81\x04\xd4\x87\x48\x26\x91\x5a\x5d\xcb\x71\x76\xb2\x48\x07\xa0\xbc\x03\xc4\x94\x2d\xcc\x6e\x89\x23\x1a\xb4\x23\xce\x10\x5d\x34\x21\x0a\x5a\xf2\x8b\x48\xe0\x2d\xfe\x03\x55\x6e\xa2\xdb\xdc\x8c\xf3\xfe\xf4\xf5\x42\x39\x00\xb6\xe6\x5a\xbc\xbd\x2a\xee\xf4\xf8\x65\x59\x05\xa0\x25\xf7\xa8\xc5\xab\xc3\xdd\x50\x16\x9d\xc6\x3a\xa9\x21\x16\xd7\xa3\xa3\xe2\x00\x6b\x8a\xa9\xac\xe0\xa9\xbe\xc4\xb7\x0f\x65\x75\x15\x05\xe3\x83\x85\xf7\x78\x1b\x6f\x75\xfe\x3e\x0a\x32\x5e\xcc\xd3\x9f\xa6\x9e\xbd\x31\xd8\x66\xff\xf8\x90\xa9\xac\x3d\x53\xf8\x41\xdd\xa2\x84\xb9\xa9\x11\xd1\x8a\x9c\x0f\x85\x83\x9b\x6c\x0a\xc4\x09\x12\x10\x87\x28\x38\xa3\x04\x0b\xaa\x14\x69\x0f\x22\xea\x79\x50\x4e\xcd\xc0\x00\x06\xdb\x14\x72\x1b\x5a\xec\x01\xe5\x1c\x12\x86\xdb\x96\x2a\x6d\x36\x3d\xab\x00\x65\x7c\xb2\x0d\xaa\xf7\xd7\xb6\x9f\xab\x62\x50\x7d\x20\x38\x0e\xfe\x6a\x46\x56\x3a\x2e\x6c\xa6\xa7\x6d\x48\x88\x54\xa8\x4e\x97\x74\x47\x4d\xbd\x1f\x6e\xed\xd8\xaf\xf6\x07\x6d\xec\x6d\xff\xe5\xcc\xc9\x94\x0c\x10\xd8\x1b\x4a\xf2\x87\x55\x1d\xa9\x5a\x09\xce\x49\x8c\x2f\x9f\x14\xd5\xe0\xca\xa9\x0a\xaf\x35\xa8\xe6\xf4\x82\xa7\xbb\xe1\x44\x90\xb4\xb4\x42\xd1\x4b\x6a\xcc\x1f\x9b\x8a\x99\xdc\xf0\xdf\x75\x92\xba\x74\xe5\xa4\xce\x16\xde\xcf\x69\xc0\xe7\x88\x49\xb9\xd5\xc9\x70\xdd\xc2\xfb\x05\xfe\xa3\x63\x5b\x4c\x3a\xb7\xed\x7a\x51\x17\xbd\x45\x8c\xe1\x00\x25\x41\xdb\xc7\x74\xbb\x85\xa4\xcf\x01\xc4\x85\x01\x99\x94\x30\xff\x4f\x9e\x46\xd4\x47\x2a\x5d\x44\x7d\xde\x6a\xba\x13\xa0\x8e\x1a\xe6\x55\xf0\x9d\x03\x4e\x52\x88\x1b\xc6\xdf\x27\x9f\x37\x3f\xd5\x4d\xb3\x94\x75\x85\x2b\x4c\x4c\x6a\x9c\xb6\x19\xd2\x1b\x49\x78\x04\xef\xda\x9e\xdd\xf5\xec\xca\x4d\x13\x56\x9a\xff\x2f\x27\xcc\xf5\x4d\xc6\x48\x62\xbd\xa2\x0c\x15\xa6\xd6\xca\xe1\x64\x73\xd5\x25\x54\xb6\x63\x17\x15\xb4\x53\x85\xf2\xce\x93\x8d\xcb\x00\x66\xdd\x7b\x5b\x7d\x2f\xdd\x0e\xd5\xd6\xf5\x31\x9f\x7b\x26\x3d\xda\x5b\x51\xe6\x29\x0e\x86\xa1\x97\x88\x3c\x5d\xfa\xa9\x9b\xb0\x35\x78\x35\xaa\xc0\xd3\x08\x99\xeb\xd1\x51\x79\x8c\xaa\xe0\x4f\x0d\x92\x19\xfd\xa6\x36\x80\x55\xe9\x0d\x21\x82\x1c\xfd\xda\xfb\x7c\x52\x25\xc5\x9f\xcd\x92\x43\x3d\x1b\x01\xf5\x36\xd9\x2f\xa1\x40\x7d\xa0\x95\x4c\x2b\x82\xb6\x85\xed\x1c\x69\xae\xa6\x50\xc3\x9c\xcf\xc4\x20\x5f\xbc\xa9\xaa\xec\x15\xd1\x92\x6c\xec\xb2\xbf\x83\x40\x42\xea\xc8\x70\xcd\x80\x34\x63\x08\xce\x37\x6d\x69\xb3\xf8\xb9\x7e\x88\x69\x79\x6c\xce\x37\xb6\xee\x9c\x36\x32\x30\xef\x3a\xe4\xa6\x40\xdd\x83\xfc\xc2\x35\x47\xb4\x6b\xb5\xec\x22\xed\x52\xad\x74\x1f\x2c\x27\x01\x1e\x55\x95\x8e\x69\x14\x85\xd8\x94\xd7\x90\x2b\x3d\x75\x30\x83\x37\x69\xd1\x4b\x5a\x8a\xa8\xe4\xe0\x59\x52\xde\xf2\xf9\x18\x14\xc0\x48\xe9\x70\x6e\xd9\x20\xa9\xd5\x51\x03\xcb\x42\x6a\x45\xfd\x47\x8d\x7b\x83\x2d\x8e\x80\xae\x8a\xcb\xad\xea\x35\x25\x82\xe0\x0a\xe6\xaa\x46\x76\x5f\x1e\x1a\x29\x95\xc9\x11\x45\xe1\xce\x8e\xb9\x9b\xa4\xd8\x0b\xcc\x49\x17\x7d\x84\x54\x0a\x65\x6b\x42\x86\x77\xd9\xa6\x0d\x05\xe3\x86\xde\x29\xe5\xa5\x9a\x82\x04\x54\xcb\xa8\xd5\x46\x00\x9d\xc3\xbd\xa5\x61\xbc\x45\xa7\xc4\x67\xbb\x48\xec\xf7\x58\xd6\xc0\x98\x5d\xcc\x2b\xbd\xeb\xb5\x7b\x32\xdd\xfc\xed\x96\xbf\x45\xbb\xd9\x49\x97\xdd\x99\x86\xd0\xd5\x35\xa6\x5b\x37\xd9\x52\xd6\xcd\xe9\x1a\xaf\xe1\x72\x27\x5a\xfa\x50\x2a\x5a\xa5\xeb\xf7\xbb\x17\x35\x38\x5f\x6d\x18\x8d\xd7\x9b\x28\xae\xb4\x44\x1a\x10\xbe\x81\x4f\xab\x43\x98\xcc\x3a\x52\xd1\x31\x98\x83\x37\xe6\x6a\x94\x79\xcc\x22\xca\x11\x58\x2c\x4e\xc6\xfa\x8b\x57\xd5\x5f\x98\xed\x99\x09\xb6\xd6\xb6\x9e\xcd\xda\xdf\xe0\xf5\x06\x88\x64\xe8\x85\x08\x1c\x4c\x0f\x0d\x58\x95\xb3\x23\xcd\x46\x14\x00\xc9\x9c\x49\xcf\xdc\xb7\x9f\x1c\xd3\x30\x00\x3f\x9f\x98\xc7\xc2\x3e\x4e\xe9\x0a\x92\x53\x12\xf9\xd9\xb0\x81\x33\xeb\xa8\x10\x2f\x53\x45\xac\x7c\xa3\x57\x4d\x1a\x75\xa4\x5f\xb6\x27\x4c\x0f\x4b\x3d\xb9\x49\x9a\x6d\xc5\xfd\x72\xab\x94\xca\xb9\x2f\x45\xf9\xcb\x86\x84\xcf\xa8\xb7\x75\xf4\xaa\x49\x6c\xcc\x3a\x2a\x85\xc4\x14\x5b\x4a\xed\x47\x0f\x8b\x8f\xb8\x5f\x7e\x24\x1e\xe4\x7a\xa4\x34\x66\xad\xca\xf1\x5c\x1b\xa3\xe0\x30\x72\xab\xdd\xff\x55\x07\x0b\x35\xc7\xd3\x0e\x07\x9c\xc3\x9f\xe7\x16\xab\x85\x5d\x46\xd9\x17\x5c\xeb\x28\x28\x5a\xaf\x85\x03\x96\x3c\x09\x47\xd5\x1b\xbf\x6a\x0f\xe6\x9e\xe0\xa1\xaa\x73\x53\xb7\x28\x75\xeb\xa5\x1a\x95\x5b\xad\x0a\xdd\x3a\xb6\x4e\x0d\xec\xf3\x56\x35\x71\x69\x56\xc6\x17\x54\x1f\xaa\x3b\x1d\x87\xee\x23\xd1\xba\x13\xa5\xcc\xbb\xa5\x3b\xb6\xa3\xfa\x94\xb0\xf2\xb4\xa5\xb8\x67\x2f\xdb\xc0\x55\xd6\x5f\xf5\x81\x40\xb5\x1f\xc5\xbc\xe8\x17\xb1\xcf\x50\xc4\x10\x47\x44\x5f\xec\x72\xfa\x76\xe1\x65\x6b\xf2\xeb\xbd\x81\x8a\x9d\x56\x2a\x46\xda\x79\x52\xae\xcb\x6d\x45\x14\x49\x21\x8f\x91\x4e\x10\x0c\x94\x98\xbf\x53\xae\x7f\xc6\x32\x04\xde\x1f\xa3\xf1\x40\x08\xa8\xfe\x93\xc0\x6a\x24\x18\xf6\xf9\x31\x0d\xe5\xfc\xe7\xbd\x50\x15\x91\xd5\x6b\x06\x49\x1c\x42\xb9\xaa\x9b\x07\x58\x67\x1b\x75\xb9\x72\x43\xa3\xf9\xa0\x3e\x83\x8e\x3a\x24\x3b\x32\x07\xc6\x83\x30\xa3\xaa\x96\xb4\xd4\xd7\x87\xdb\x1d\xae\xde\x6f\x8c\x55\x9d\xaf\xf7\x7e\xee\xfa\xf5\xe1\x02\x1c\xd3\xe9\xf4\x20\xf7\xcc\x98\xfc\x84\x59\x0a\xe1\x21\x8d\xae\xd0\xac\x19\xc6\xa0\x61\x8c\x4d\x50\xbf\x1e\x1d\x39\x28\x57\xae\xc0\xf1\x94\x77\xf0\x94\x77\xf0\x94\x77\xf0\x94\x77\xf0\x94\x77\xf0\xf8\xf3\x0e\xea\x2c\x1a\xd0\xda\xbf\x5a\x86\xd6\xda\x9a\xd8\xb3\xb3\x79\x4a\x8b\x78\x4a\x8b\x78\x4a\x8b\x68\x38\xab\x4f\x69\x11\x8d\xc8\xd4\x33\x2d\xc2\x0f\x21\xe7\xd8\xff\x85\xc2\xe0\x35\x0c\xe5\x36\x9e\x9d\xc3\xed\x17\xe4\xb6\xa9\xb9\x00\x12\x01\x55\x87\x7a\x69\x90\xe2\xa6\xbc\x64\xac\x0a\x53\xeb\xfd\x44\xfb\x33\xaa\xd6\xc0\x2b\x68\xa6\x22\x6f\x4e\xce\x2b\x0f\x60\x1a\xd8\x9d\xef\x8f\xb5\x8d\x0c\x83\x80\x21\x5e\x7d\x43\x96\xbd\x27\x4a\xf7\xe9\x05\x84\x7b\xa6\xc9\xf3\xb4\xb2\xee\xc9\xf9\x02\x84\x94\xde\xe4\xfd\x6e\xfb\xe9\xb1\x37\x74\xa6\xba\xf7\xeb\xd1\x51\x7e\x04\x2a\x4e\xc6\x89\x91\x9b\x88\x56\xd3\x5f\xc6\x44\xe0\x5e\xd7\x0d\x65\xef\x2a\x60\x1a\x1a\x78\x76\x7c\x39\x7b\x9e\x0d\xb4\x4c\xfa\xe3\xb6\xf2\x2b\xc9\xfb\x22\xdb\xdd\x89\xd0\xb6\x1f\x37\x0d\xa2\xf8\x98\xa1\x00\x97\x0f\x86\x5b\x8c\x3e\x73\x18\xf9\xfe\xea\x15\x78\x47\x42\x29\x38\x51\xd0\x2d\x25\x64\x19\x33\x2e\xe0\x32\x44\x5e\x84\x98\xda\x2b\x13\x1f\x79\xc9\x09\xb8\x17\x5b\xf0\xde\x96\x06\x48\x3b\x05\xc6\xe0\x56\x6d\x1e\x28\x09\x77\x8a\x06\x57\x9e\xc4\x3f\x3d\x37\xef\x7a\xb8\xda\x2f\xaf\xa4\xc3\x50\xae\x47\x47\x59\x12\xea\xbd\xeb\xbe\xc1\x39\xa7\xf6\x29\xdd\xec\x29\xdd\xec\x29\xdd\xec\x29\xdd\xac\x82\xb2\x4f\xe9\x66\x4f\xe9\x66\x55\xa7\xc2\x4f\xe9\x66\xff\xa6\xe9\x66\xfc\x04\x73\xed\x18\x70\xb8\xa2\xf6\xb1\x86\x13\x86\xb3\xbb\x9b\x78\x89\x42\x24\x4e\xd5\x7d\xac\x2d\x02\xe7\x0a\xb5\x5a\x1b\x6c\x4e\xf0\x1f\x08\x7c\x34\xdd\x7d\x4c\xea\xe3\xe6\x3c\xff\xf8\x0f\x4c\xd6\x9e\xd8\x20\xcf\x7c\x37\x69\x27\xd3\x2b\x0e\x14\xca\x60\x93\xfd\x86\x44\x4a\x3b\x61\xcd\x2b\xeb\x87\x4e\x8b\xd4\xfe\xdb\x26\xc2\x3d\xa5\x7a\x3d\xa5\x7a\x3d\xa5\x7a\x3d\xa5\x7a\x3d\xa5\x7a\xfd\x1b\xa7\x7a\x3d\x50\x02\xd4\x53\xbe\xd0\x53\xbe\xd0\x53\xbe\x50\x53\xea\x3f\x6a\xdc\x3b\xe7\x0b\xb9\x57\xbc\xfe\xf6\x37\xa9\x3e\xf6\x64\x4d\x3c\x82\x84\x1f\x01\xd9\x1a\x09\x35\x07\xd3\xcb\xf3\xc7\x70\xce\xa4\x31\x32\xf6\xcb\xb0\xa7\x4c\x8d\x40\x3b\xc9\xf4\x94\x17\x55\x67\xc2\xd4\xc0\x78\xca\x8b\x7a\xca\x8b\x7a\xca\x8b\x7a\xca\x8b\x7a\xca\x8b\x7a\xca\x8b\x02\x4f\x79\x51\xe0\x29\x2f\x2a\x43\xb6\x2f\x92\x17\x95\x77\xe9\xe7\x27\xb9\x1c\x73\x9a\x79\x9f\x09\x0f\xc9\x3e\xad\x8a\xd8\xaa\x31\xb2\xcb\x1b\x8b\x2a\x53\x33\xd7\x51\x12\xe6\x54\x7f\xfa\x90\x6d\x53\x8c\xea\x31\xaf\x86\xb8\x77\x27\x7f\x8b\x65\x1a\x83\x09\xc4\x06\x0a\x75\x1f\x4c\xb2\xc7\x56\x77\x53\x96\x77\x35\xcd\xee\xe4\xe9\xde\x8f\xea\xa6\x94\x48\xf2\xda\x1d\x5b\x58\x99\x28\xa2\x79\x6b\x1a\x6c\x31\x49\xc3\xa1\xbb\x18\xc4\x36\x20\x70\xf0\xe3\xa1\xe4\x5a\x1a\x48\x76\xe0\x7d\x76\x8d\x24\x41\x88\xce\x6b\x14\xb3\x5f\x7a\x94\xe7\xfe\x9e\x7c\x95\xe9\xc4\xa3\x2b\xcf\x42\x6a\xb7\xef\xcf\xa1\x56\x7b\x47\x62\x27\x64\xae\x47\x47\xce\xe1\x16\x4e\x9d\x5a\x69\x60\xe7\x7c\xbb\xa6\x71\xc0\xb5\xa4\xbc\xca\x39\x3e\x2f\x05\x8d\x2e\xa1\xb4\xd4\x5c\x5b\xc1\x66\xcb\xa8\x53\x17\xee\x15\x34\x9b\x9e\x35\x59\x38\x50\x08\xe8\x6f\xe6\x2a\x16\xfb\xc1\x7d\x0b\xce\x15\x97\xda\x37\xea\xde\xed\xe9\xe5\x79\x9f\xf3\xe4\x4b\x3a\x08\x88\xbe\x41\x05\x12\xc6\x1c\xb1\x2d\xe6\xd2\xe4\xe6\xaf\x69\x4c\x02\xb8\xf7\x32\x3d\x27\xc8\x3b\x2c\x36\xd3\x20\xa0\x64\x6e\xef\xc0\x6c\x1d\x40\x91\x6f\xde\x71\xc9\x95\x38\xa5\x7e\x0e\x6b\xe6\xa6\x8e\xe6\x2d\x68\x59\x4b\xa3\x01\xd7\xbd\x0a\x3d\x9b\x9e\x65\xb5\x1a\x5d\x01\x98\xae\xc1\x96\x8b\x7c\x3f\xbc\xca\x15\x5d\xc5\x07\xd5\xcb\x3b\x5c\xce\xc8\x9a\x21\x5e\x19\x2d\x5b\xab\x0d\x61\x14\x9d\xa1\xf2\x21\x4a\x97\x78\xb8\x55\x1c\x86\xf6\x68\x43\x50\x30\x35\x90\x5b\x9d\x00\xd6\x83\xaa\x1b\xc1\x9c\xa1\x5b\x8c\xee\x1e\x6e\x20\xc0\xf6\x30\xdc\x80\x12\x90\xee\x81\xc5\x82\x2e\x7c\x18\xee\xb7\x73\x9a\x0c\x2a\xb9\x63\x57\xc7\xeb\xda\xd8\x75\x9b\x38\xd2\xf6\xa8\xb6\x31\x54\xe7\xd0\x7c\xc4\x84\xbe\xd1\x6c\x90\xb1\x49\xa5\x6a\xf6\xdb\xca\xf8\x0c\x02\xc0\x90\x4f\x59\xa0\x88\x7d\x49\x63\x81\xc0\x37\xaf\x00\x26\x80\x4a\xa9\xa7\x0e\x9e\x68\x78\xab\x2f\x60\x3f\x39\x5f\xbc\x38\x04\xfe\x06\x86\x21\x22\x6b\x74\x00\xce\x28\x43\x00\x93\x34\x25\xda\x38\x6a\x56\x52\x2c\x81\xf7\x1b\xc4\x50\x6a\xc7\xc9\x91\x98\xba\x04\xec\x00\x53\x15\x73\x39\xc9\x29\xf8\x09\xf4\xb7\x68\x12\x10\xfe\xe2\x70\xc2\x24\x2a\xdf\xbc\x9a\x7c\xc5\x91\xf0\xe2\xc8\x83\x1e\x86\x5b\x8f\xd1\x10\x75\x8b\xf9\xfc\x9c\x03\x2f\x9b\x8d\x43\x8d\xfd\x7a\x74\x24\x89\x5a\x1d\xa3\xa4\x52\xd4\x7f\x83\xc2\xdf\x2b\xa7\x9c\xcd\xd1\x72\xaf\x6c\x6c\xca\x65\x04\xdd\x81\xd3\xd7\x0b\x70\xbc\x98\x81\x67\xa7\x21\xe4\x02\xfb\xe0\x75\x48\xfd\x1b\xb0\x10\x92\x7c\x89\xad\xaa\xfe\x86\x6b\x04\x66\x44\x20\xb6\x82\x3e\x7a\x0e\x02\x86\x6f\x3b\x2e\xb4\xc1\x3a\x77\x53\x68\xd5\x4d\x7b\xa0\x7b\x81\x18\x81\x61\x4d\xd2\x4f\x13\x0a\xc3\xc0\x58\xc6\x16\x9e\x17\x10\x0e\x22\x46\xff\x89\x7c\x91\xdc\x0c\xae\x24\x8c\xce\xf3\x4d\x58\xbb\x15\x2d\x7b\x74\xe3\x1c\xfd\x8a\x57\x06\x95\xd6\x52\x0d\x6f\xe1\x1a\xbd\x8e\x71\x18\xf4\x13\x7f\x2a\x2c\x59\xe3\xab\xf4\xcb\xe9\xf1\x65\xca\x17\x29\x2f\x5c\xa2\x35\xe6\x82\xed\x9e\x1b\x05\x74\x00\xae\x36\x98\x03\xcc\x41\xcc\xd1\x2a\x0e\x15\x80\xa5\x44\x07\x93\xf5\x58\xfd\x65\x2e\xba\x1f\x03\x08\x8e\x67\x2a\x37\x41\x0a\x0f\xb9\xd1\x27\x08\x69\xe1\x12\xc5\x7c\x03\xd4\x48\xd4\x9f\xa7\xc7\x97\xed\xe6\xe2\x91\xe1\xee\x9c\xa8\xfb\x4b\x58\x69\xd0\x97\x67\xb8\x95\xad\x9d\xe3\x01\xb7\xd2\xaf\x58\x67\x15\x6a\xd4\x61\xd3\x55\x1b\x49\x05\xe1\x58\xe0\xe9\x82\x60\x18\x3b\x8d\xcd\x22\x99\xdc\xe2\xfa\x21\x8c\x74\x69\x21\x27\xab\xb5\xab\x65\x9e\x07\x52\x61\x8e\xef\x89\x60\xae\xba\x3d\x38\x57\xf9\xa9\x44\x81\x2a\x43\xde\x37\xce\xfc\x4b\x64\x12\x30\x87\x88\x58\xb3\x40\x01\x33\x50\x55\xcc\x5a\x5d\x82\x48\x36\x93\x18\xf9\x2f\x27\x31\x47\x6c\xad\x52\x44\x2c\x2c\xcf\xc2\x32\x89\x6e\x6a\xd5\xa9\xd2\xcf\xdd\x52\xdb\x4a\x51\x6c\x83\xa2\x77\x3d\x3a\x72\x11\x21\x09\x6a\xab\x43\xbc\x59\x64\xdb\xe7\xbb\x57\xc5\xd9\xfd\x16\xde\xcf\x19\xae\x66\x17\x9d\xb4\x52\x39\x30\x4a\x40\x80\xb6\x90\x04\x20\x52\x50\x9c\x7d\x50\x72\xa2\xbe\x79\x0d\x39\x6a\x9a\xbc\x57\xd1\xa1\xfb\xc8\xdc\x76\x30\x47\xcc\x47\x44\xc0\x35\x9a\x2e\xe9\x2d\xea\xd1\x5f\x8e\xc5\x2e\xd5\xfd\xe9\xef\x5f\x78\x87\x2f\x5e\x7c\x68\xc5\x9c\x35\x2d\xd3\x31\x1d\xbe\x70\x8f\x4a\xf2\xd6\x34\x0c\xa9\xaf\x8c\xe1\x85\x60\x50\xa0\x75\x27\x17\x91\x84\x64\xc5\xd1\x9c\xd2\x72\xc0\x7e\x07\x6a\x1c\x7a\x2f\xbb\x11\xc3\xd1\x30\xa5\xc5\xcb\xae\x0a\xb1\xaa\x5e\x5e\xc2\xdf\xfb\xf8\xb1\x25\x3b\xd5\x52\x77\xff\x24\x8e\xeb\x24\xf7\x80\x6a\xcf\xed\x30\x7e\x9f\x17\x5b\x49\x18\xb2\x7c\x9c\x26\xf3\x4e\x9a\x57\x26\xab\xeb\xac\x14\x5f\x5c\xe8\xe5\x7a\x74\x94\x47\xa7\xa6\x7e\xd8\xe2\x4d\x33\xaf\x96\x72\x45\xce\x4e\xbe\x5c\x24\x9c\xc6\x00\x71\x90\x4e\x1d\xb0\x67\xd6\x3a\x44\x8d\xf7\x0b\x14\xec\xd4\x81\x53\x38\xdc\x61\xb1\xf9\x85\xfa\x30\xec\xb5\x99\x50\xe8\x00\x58\xc0\x01\x48\xc6\x0f\x35\x22\xd9\x48\x65\x70\x4e\x85\xbd\x35\xdf\x84\xae\x94\xaa\x33\xb6\x33\x03\x1e\x1e\x81\x54\x48\x09\x16\xbb\x73\x84\x25\x29\x17\x1b\xc8\xfa\xe5\xb1\x9a\xa1\xa8\x2a\x7f\xf9\xc1\x70\x05\x1b\xc0\x2d\x25\x6b\x65\x8c\xa6\xb8\xea\x84\xd1\x6e\x99\x13\xc3\x77\x58\x45\xab\x56\x32\x3d\x5d\xc5\x6e\x12\x3b\x79\x78\x10\xd9\xe9\x53\x22\x18\x0d\x79\x69\x45\xd5\x04\xf2\x37\x39\x44\x6d\x0a\xb3\x42\xf8\x2d\x7e\x6e\xe6\xd2\x0f\x69\x2f\x47\xf6\x6c\x05\xa4\xc6\xba\x93\xfb\x64\x39\x7d\x6a\x9a\x17\x8b\x9f\x0b\xb2\x3d\x62\xf4\x16\x07\x28\x30\xdb\xe9\x60\x0c\xa8\xd8\x20\x76\x87\x39\x02\x58\xc8\xa7\x78\x4d\x28\x43\xc1\x01\xb8\x20\xe1\x0e\x50\x82\x00\x5d\x81\x79\xbc\x0c\xb1\xff\x16\xed\xe6\x50\x6c\xc6\xe9\x9f\x2a\xe0\x3b\xf9\xeb\x1c\x6e\x91\x75\x20\x26\x11\xb0\xed\x72\xaa\x1e\xf1\x30\xdc\xde\x30\xb5\x91\x59\xf0\x52\x02\x74\xfb\x9d\x5b\xc9\xb5\xfb\x5e\x8e\x9b\x12\x41\x4d\xee\x44\xcc\x31\x59\x83\xc5\xe2\xec\xc3\xb3\x09\x96\x7c\x19\xc4\x2a\x52\xe6\x2b\xce\x37\x9e\xf6\x95\xb4\x73\x29\x57\xf4\x9b\xd1\xfd\x15\xdd\x5c\x8f\x8e\xaa\x70\xab\xf6\xe8\x46\x96\xbe\x3d\x82\x5b\xf5\x1c\x81\x1b\xa4\x10\x5d\x22\xa9\x48\xd3\xa4\x04\x8d\x8a\xc4\xec\x06\xed\xfc\x0d\xc4\xe4\x00\x64\x19\x4a\x89\x0f\xbd\x6c\x6f\x61\x18\xa3\x2c\x9f\xb4\x22\xdc\x03\xa2\x51\x4f\xba\x06\x27\xd8\x0d\xc9\x47\x24\x93\x63\xa2\xd2\x34\x1e\x09\x29\x1f\x12\xa5\x7a\xb2\x4a\x71\xd0\x83\xac\x57\x1b\x04\x22\x28\x36\x16\x53\x89\x63\xd4\x8b\x45\x8c\xe8\x4b\x86\x62\x54\xb3\xb2\x0e\xaf\x47\xff\x6f\x72\xc0\xf9\x66\x82\x83\x7f\x30\x0e\x0f\xa2\x78\x79\x3d\xca\x0a\x40\xd9\x41\xbf\x49\xf9\xbc\x03\xd2\x51\xc7\xa5\x41\xe9\xc7\xfb\x07\xe6\xde\x3c\xab\x7c\xa4\x45\x36\xe0\x74\xf6\xc0\x99\xb4\x5d\x0d\x26\xa5\xf9\x2b\xb9\xd2\x29\x40\x2b\x45\xc3\x7e\x0a\x38\x75\xd7\x80\x7b\x57\x69\x6f\x2a\x9b\x34\xcd\x79\xcc\xab\x6e\x15\x29\xd8\x27\xca\xa2\x0d\x74\xb7\x4d\xa6\xaf\x8d\x6a\x12\x80\xb8\x5a\x21\xbf\x61\x7a\xfa\xcd\x77\xfc\x00\xd3\x4f\x30\xc2\x9f\x7c\xca\xd0\xa7\xdb\xc3\x03\xd5\xcf\xa9\x86\xe1\xe4\xd2\x9b\xbd\xca\xd0\xd9\x4c\xad\x81\xc6\x0d\x5b\x71\xe3\x4d\x9e\xbb\x74\x4f\xe3\x12\x45\x06\x61\x98\x6c\xb1\x7f\xf0\x36\x5e\x22\x46\x90\x8a\x2e\x55\xd3\xd3\x94\x31\xea\xa1\xb8\x19\xe0\x9d\x3b\xa7\xac\x92\x0f\xb6\xf0\xfe\x1d\x31\x21\xfe\x61\xaf\xac\x24\x8e\x44\x52\x67\x28\x53\x5b\xc8\x24\xc7\x6e\xa0\x30\x86\xa7\x4f\xb7\x08\xc4\x69\x9f\xe0\x6e\x83\x88\x4e\x22\x93\x86\x56\x26\xd6\x16\x3c\xb3\x75\x08\x02\x00\xb9\x81\xd9\xce\x0e\xfc\x6c\x48\x39\xb9\x39\x4f\xdc\xd4\x7d\xf7\xa8\xc9\x1c\x25\x68\x3e\x32\x52\x67\x11\xeb\x28\x03\x0a\xdc\xde\x64\xaa\x06\xdb\xc0\xab\x88\x65\xb7\x4b\x32\x19\x7c\x97\x48\xdc\x2e\xb0\x73\xb2\xe3\x62\x76\x72\x3c\x0b\x10\x11\x58\xec\xe6\x7a\xf7\xc9\x1a\x5e\x8c\x90\x3d\x37\xe2\x3c\x46\xec\xdd\xe5\x2f\xf9\xb3\x53\x8c\x88\x98\x9d\xb4\x38\x37\xb4\x2d\x3a\x28\x0f\xed\xc0\x38\x0e\x21\xae\xdc\xb3\xee\x6f\xde\xa3\xbc\x56\x42\x81\x0e\x8d\xbb\x96\xd6\xb1\x93\xa3\x46\xfd\xb8\x0b\x1f\x7d\xe9\xba\x07\x7b\x11\x8c\x39\x62\x72\x1e\x3a\x73\x90\x05\xd0\x92\x87\x5a\x89\xb0\x76\xeb\xae\x72\x74\xd5\x58\x57\x2c\xa8\xaa\x85\x52\xcd\x8b\xc5\xa9\x1f\xd0\x14\x57\x86\x72\x84\x7c\x15\x88\x4c\x80\x94\x60\xd6\x71\xc6\xb2\x85\x7a\x4f\xdf\x2e\x00\x8c\xc5\xe6\x0f\xd2\xe1\xe8\xa8\x65\x07\x79\x99\x1a\x21\x06\xf3\x25\xf6\xaa\x1d\xa4\x09\x19\x7e\x0a\xe3\xfb\x29\x2b\xaf\x92\xcf\x57\x30\x21\x3d\xbc\xf1\x75\x8a\x1e\x08\x31\x41\x00\xb2\xb5\xca\x18\xb2\xde\x61\x04\x24\xaa\x20\x80\x68\x4b\x09\x38\x39\x9d\x5f\x9e\x1e\x4f\xaf\x4e\x4f\x5a\x19\x0c\xbd\x3b\x73\xae\xc1\x94\x9a\x3f\xa3\x70\x6b\xe7\xe1\xdf\x84\xaa\x12\x65\x60\x71\x7e\x78\xba\x56\x76\xe7\xa4\xac\x04\x86\x85\xfd\xfc\x0c\x12\xbc\x42\xbc\xba\xac\x75\x13\xf7\xf0\xb1\x02\xa9\x7c\xd4\x2a\x8a\x4d\x4d\xf4\xd6\x42\xb6\x1e\x98\x37\x58\x80\x4b\x14\x51\x40\x89\x3e\x95\x0d\xc3\xae\xb4\x19\xa4\x43\x27\x75\x54\x7a\x71\x0f\x4f\x9b\xec\x53\xc1\x90\x48\xdc\x20\x14\x01\xc1\xa0\x7f\x23\x05\x90\x44\xf2\x3f\x39\xe0\x3b\xe2\x4b\x21\xa4\x22\xd6\xfe\xae\x5d\x4e\x98\x03\x29\x74\x6f\x61\x88\x88\x90\x2d\x4d\xaa\xad\x34\xf8\x3c\x6f\x8d\x85\x27\x5b\x79\x02\xae\xd5\x98\xf5\x23\x42\x05\xe2\x1e\x43\x2b\x80\x89\xa6\x40\x47\x6a\x3e\x16\x9c\x2b\x2d\x2a\x1e\xc1\xea\x50\xa2\x06\x93\x72\xac\x0f\x13\x41\x02\x4b\x6e\x56\x98\xaa\x6b\x6d\xf9\x42\xe1\xa2\xaf\xe5\x2b\x2e\x28\x74\xb0\x3e\x00\xab\x1e\xf4\x7d\x80\xee\x2b\x8c\x48\x18\x5c\x90\xea\x2b\xb6\x1a\x9d\xd2\x11\x2e\x58\xec\x0b\x8d\x91\xa0\x40\x02\xf5\x54\x45\xf5\x2d\x0d\x74\xfd\x24\x5d\x8d\x58\xa1\x1a\xa0\x28\xa4\x3b\xe5\x73\x85\x3c\xf3\x6d\x47\x4a\x3d\x70\xef\xcd\x42\xe7\xee\xb0\xd8\xc8\x29\xe8\x4b\x46\xeb\x0a\x1c\x44\x1b\x34\x02\xd8\xd1\x16\xad\xd2\x08\x25\xb1\xe8\x5c\x96\x2e\xca\xb9\x98\xd2\xa9\xdc\x13\x53\xa9\x99\xea\x1f\xc4\xf6\x34\x07\xe4\x92\x9a\xf9\x7d\xb6\xad\x49\xcc\x50\x08\x45\x7a\x72\x40\x2d\xa5\xd5\x8d\x19\x89\x88\x4c\x83\x14\x92\x85\x2b\x05\x29\x43\x11\xe5\x58\x50\xb6\x93\x22\x4e\x8a\xc0\xe6\x3e\x80\xcf\x8f\x59\xce\xda\x9d\x3b\xca\x9d\xd6\x5c\x1d\x4a\xe3\xa8\x55\xbe\x6a\x2b\x9e\x4c\xc1\x0f\x32\xe7\x69\x25\xd4\x72\x15\xd4\x24\xb5\xa8\xf1\x3c\x35\x83\x96\xa7\xad\x2e\x52\x62\x54\x41\xbb\xfd\xc4\x29\x09\x22\x8a\x89\x58\xe8\xeb\x18\x3a\x5a\xc0\xe3\xfc\x5b\x67\xd5\x1b\x1b\x27\x5f\x26\x49\x8a\x56\x1a\xeb\x5c\x7e\x19\xd2\x35\x1f\xe5\x1e\x7e\x18\xc0\xf0\x4e\xc9\x9d\x89\x4a\x43\x86\x28\xf6\x92\x0a\xe3\x9c\xdc\xc6\x5c\x80\x25\x02\xb6\x0e\xbe\xb4\x91\x6d\xf5\x50\x9b\xad\xa1\xcb\x2c\x21\x22\x98\x82\x69\xea\x4f\xe5\x07\x6e\xaf\x6e\xcc\x0c\xd7\x3e\x92\x83\x6c\x7d\x67\xe3\x67\x18\x43\xb6\x54\x52\x7e\x30\x35\xf7\x22\x66\xc6\x57\xf3\x95\x1c\x72\xe1\x8e\x44\xa7\xea\x44\xfd\xaf\x5b\xb0\xb9\x65\x4a\xcd\x2b\xd9\xb7\x02\x50\xa5\xe3\xec\x6c\xb9\xd8\x6e\x75\x7c\xbb\xc2\xad\x31\x1a\x5a\x49\x34\x54\x2e\x67\x53\xb3\xc4\x07\x91\x7a\xd9\x5b\x90\xca\x2e\xe5\x7d\xa3\x6f\x73\xc7\x52\x73\xe8\x05\xa9\xa8\x12\xf7\x9b\x88\x43\x1a\x8b\x28\x16\x3d\xe3\x20\x2e\x14\x10\x10\x60\xa6\xca\x07\xed\x92\x2d\xb4\xbd\xf9\x2f\x90\xbf\x24\x4a\x40\x98\x1b\xcd\x39\x78\xb6\x56\xd5\xd2\x04\x4a\xde\x99\xfd\x78\xbb\x83\x95\x07\xed\x3b\xc3\xa4\x07\x93\x1f\xff\x15\x63\xff\x86\x0b\xc8\x84\x27\x95\xbe\x27\x8d\xb5\x8a\x98\x27\x86\x74\x79\xb6\x1e\x44\xa5\x2b\x35\x8c\xff\x2d\x3b\x05\x0b\xd9\xab\x45\xf6\x00\x1c\xeb\x20\x35\x08\x96\x0c\x12\x7f\x33\x06\x72\x3b\xa8\xae\xde\x52\x1b\xf8\x0d\xe4\x9b\x8c\x01\xdb\x4e\xa4\x0e\xd9\xaf\x93\x36\x3a\x40\xa1\x07\x65\x54\x9c\x1e\x65\xe0\xdd\xe5\x2f\xa0\x1a\xdb\x56\x83\xee\x02\xd2\x24\x1f\xf2\x72\x91\x3b\x18\x45\x5e\x80\x6e\x87\x28\x4e\x67\x88\xe5\x62\xad\xb1\x73\x15\x0f\x6d\xcb\xeb\xcb\x60\xd4\x5d\x37\x10\xa4\x2b\x20\x5d\x54\xd4\x28\x54\x7b\xd9\x5b\xd6\x46\x86\x41\x90\xf5\x1a\xa5\xa6\x72\x27\xe3\xfd\xa1\x50\xc9\xc9\xce\x4b\x14\xd1\x26\x82\x53\xaf\x80\x9e\xc1\x63\x6b\x2c\xcc\x52\x02\x31\x09\x10\xb3\xd5\x22\x0d\xde\x05\xf1\x8f\xa5\xa2\xbd\xc3\x61\xa8\x03\x54\xe5\x92\x93\xbb\x96\xff\x50\xce\x3a\x14\x8c\xb5\x4f\x63\x0b\x55\xdb\x8e\x1b\xe2\xe1\xb0\x82\xdb\xe8\xef\xfb\x30\x73\x5b\x3b\x5b\x88\xfb\xfa\x0a\x15\x0c\x83\xb7\xc5\xcd\xee\xe6\x8c\xb0\xf2\x37\x90\xac\x11\xef\xe3\xdd\xeb\xd6\x8b\x73\xd0\xab\x30\xbe\x1f\x20\x1a\x31\x55\x83\xd9\x99\x53\x6e\x9f\xba\x69\xbb\x63\x72\xd2\xc8\x38\xf5\x8a\x4d\xfa\x30\xd0\xc3\x60\xe1\xa4\x5b\x04\xc5\xe6\xcb\x9d\x5d\x5c\xa2\x10\x0a\x7c\xab\x83\x26\xf5\x1d\xaa\x26\xd1\xa2\xe0\x19\xd0\x14\x30\x2f\x2e\x22\x9e\xfa\x18\xd4\xe0\xcd\x45\x5b\x92\x6f\x56\x98\x04\xd9\x70\xa6\x9c\xfb\x5d\x95\x19\x37\xf4\x79\x7f\xad\x2a\x11\x7a\x7c\xc7\x05\xda\x5e\x8f\xc6\xe0\x7a\xb4\x84\x1c\x5d\x8f\x3e\x74\x9d\xbb\x2f\x3a\x1c\xbd\x11\xca\x0c\xc9\xc6\x81\xea\xff\xe5\xd0\xf4\xaf\x0f\xfb\x99\x42\x1b\xc7\x8b\xc5\xcf\xfd\x63\x7c\xe7\x99\x70\x58\x6b\x74\x9b\x70\x57\x7b\xd4\x29\x47\x12\x8b\x0d\x22\x02\xfb\xf2\x75\x47\xea\xf7\xeb\xc9\x49\x88\x98\xf5\x11\xa4\x57\x66\xe2\x25\x12\xd2\x30\x32\xb8\x95\xf8\x40\xcd\xb9\x09\xb4\xc9\xe9\xdd\xdc\x62\x6f\x2d\x45\x1e\xaa\xeb\x6a\xbb\x6d\x8d\xc5\xff\x4c\xeb\x23\xfe\x40\xd9\x7a\x22\x7b\xac\xb0\xe3\x0a\x41\x02\x3d\x35\x96\x04\xf1\xe0\x0a\xab\x53\x27\x1d\x2d\x57\xc9\x7b\xe3\x92\xbd\x54\x12\xdd\x2e\x1d\x58\xa4\x6c\xc9\x38\xa8\x5d\xeb\x43\x5b\xc0\x7b\x7d\xc6\xb0\x28\x1e\x93\x3b\xa0\xb5\x74\x7c\x18\x4f\xf5\xfe\x5e\x73\x76\xed\x02\xf9\x0c\x09\x6e\xaa\x1d\x37\x2a\x6e\x71\x83\x76\xd3\xcb\xf3\xe6\xd1\x69\xe6\xfb\x87\x8a\x4f\x76\xe2\x32\xbc\xff\xe6\xed\xd9\x02\xa0\x84\x4a\x49\x5c\xcb\x40\xfe\x9b\x2a\xe8\xb9\xb9\xfa\x0d\x85\xe1\x5b\x42\xef\xda\x15\x07\x1c\xa4\x84\x9c\xaa\x9b\x94\x2b\x8f\x54\xae\xf3\x76\x00\x16\x08\x81\xf7\xe9\x03\x30\xfd\x6d\x01\x02\xea\xf3\xfa\x72\x23\xe8\x86\xdb\xcb\x68\x33\xa5\x3c\xca\xe0\x55\xa5\x91\x76\x4e\x8b\xe6\x68\x37\x2b\x3d\xd2\x06\xd5\xeb\xd1\x91\x83\x14\x3f\x4e\xe0\x51\x75\xb5\xfc\x9a\x73\x52\x78\xc7\xb3\x95\xad\x8f\x75\x26\xea\xe0\xd3\xaa\x13\xf7\x54\x06\xe0\x1d\xf7\x42\x0a\x03\xcf\x54\x34\x60\x9e\x9f\xf4\x69\xa6\x5a\x22\x04\x2c\x46\x5d\x67\xba\xb6\x9f\x41\xe6\xbc\xcd\x98\x7a\xf0\xc1\xde\x81\x5c\x8f\x8e\xca\x14\xeb\xcc\x10\x03\x15\x50\x54\xe4\xca\x96\xf1\x4b\x68\x67\x26\x39\xf7\x2e\x3f\xc7\x9d\xaa\xff\x75\x99\xce\x1a\xfc\x06\xaa\x49\x78\x3d\x3a\x2a\x0d\xb4\xf3\xd4\xa0\x25\x3f\x5e\xcc\x1e\x7e\x89\xa2\x25\xf7\x7c\x8e\xcb\x0b\x53\xb2\xa2\x7d\xa9\x8b\xfe\x15\x66\x2e\x53\xee\xfb\x26\xd9\x85\x79\x1c\xaf\xf9\xa4\xdc\xd6\x96\x6b\xd4\x7f\x79\x51\x52\xa6\x77\xc0\x95\x59\x35\x94\xda\x4a\xe5\x3d\x50\x97\xd2\xd9\x4d\xa4\xee\xb3\xbe\xfa\x4c\xb3\xbe\xaa\x9b\xf5\x55\xcd\xac\x17\xa4\xd8\x32\xa4\x6b\xb5\x32\x74\xa5\x3d\x9e\xa4\x77\x63\xb2\x4e\x01\xed\x08\xdc\x62\xdf\x8b\xec\xd5\x32\x98\xac\x87\x9c\xf7\x8a\xc1\x94\xe7\x7d\x28\xe4\xed\xcc\x97\x09\xd5\x7d\xe6\x07\xac\x81\x99\x2f\x4c\x59\x53\x90\xd2\x4c\x7a\xee\xfb\xc6\x8b\x3c\xdb\x4a\x92\x72\x39\xd1\x5e\x58\x2d\x2c\x45\x2c\x28\xc3\x30\x54\x2b\xea\x60\x1b\x74\x99\xef\x96\xe3\x68\xb5\xce\xdb\x61\x7f\x3d\x3a\x2a\x11\xa9\xf3\x54\x7f\xe9\xc2\x9d\xed\x26\x62\x90\x4e\x86\x3a\x92\x6f\x57\xef\xb2\xda\xde\xad\x58\x78\x15\xa6\x51\x9d\x5a\xae\x13\xde\x83\x6c\x29\xd5\xd1\xbc\xaa\x80\x23\xe5\x9d\x4f\xb7\x5b\x4a\xd2\x82\xd9\x6d\x6a\x57\xee\x87\x94\xdb\x2a\xa6\x8b\xe7\xd3\x1d\x82\xb7\xe8\x8e\xb2\x1b\xfe\x49\xdf\xcd\xfd\x29\xba\x59\x7f\x8a\x05\x0e\xf9\x27\x1c\x11\x24\x0e\x66\xf3\xf3\xfc\x05\x2c\x15\x3e\xaa\x12\x0f\x13\x30\x9b\x03\x18\x04\x0c\x71\x55\x4a\xe8\x78\x76\x72\x09\x08\x15\xed\xe2\xbb\xf6\x80\xc9\x8d\x6b\x4f\x56\x75\xf5\x18\x72\x50\xf2\xf7\x82\x66\x1a\x95\x4f\x08\xf6\x5d\xbc\x70\x95\xa6\x15\x67\xd7\x81\xfb\xac\xa0\x94\x97\x03\x49\x10\x22\x0e\x62\xb2\x85\x8c\x6f\x60\xa8\x2e\xbf\x5c\x52\xb1\x01\x5b\x18\xbd\xd7\xa8\x7f\xd0\xff\xa9\xd3\xca\xf7\x1f\x0a\x1d\x37\xa5\x71\xff\x9e\xfe\x62\x17\xfc\x9f\x7f\xf9\xf3\x2f\xff\x3f\x00\x00\xff\xff\x2a\x17\xcc\xa5\x1d\x59\x01\x00") +var _schemaJson = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\xec\x7d\x6d\x73\x1b\x37\xd2\xe0\xf7\xfd\x15\x28\x66\xeb\x59\x7b\x8b\x23\x5a\x76\x92\x4d\xb2\x39\xd5\xd1\x92\xec\xf0\x1c\xc9\x3c\x51\x4e\xee\x62\xb9\x62\x70\x06\x24\xb1\x1a\x02\xb3\x00\x46\x12\xf3\x38\xf7\xdb\xaf\xf0\x36\xaf\x98\xe1\xbc\xc9\xd6\x56\xe9\x8b\x4d\xcd\x0c\x1a\x8d\x46\xa3\xbb\xd1\xe8\x6e\xfc\xf7\x5f\x00\x18\xfd\x95\xa1\xd5\xe8\x07\x30\xfa\x6a\x12\xa0\x15\x26\x58\x60\x4a\xf8\xe4\x38\x8c\xb9\x40\xec\x98\x92\x15\x5e\x8f\xc6\xf2\x43\xb1\x8b\x90\xfc\x90\x2e\xff\x85\x7c\xa1\x9f\xfd\x95\xfb\x1b\xb4\x85\xf2\xf1\x46\x88\xe8\x87\xc9\xe4\x5f\x9c\x12\x4f\x3f\x3d\xa0\x6c\x3d\x09\x18\x5c\x09\xef\xd9\x3f\x26\xfa\xd9\x57\xba\x5d\xa6\xab\xd1\x0f\x40\xe2\x01\xc0\x68\xfa\xdb\x22\x5e\x12\x24\xce\x60\x14\x61\xb2\x4e\x5e\x00\x30\x82\x41\xa0\xbe\x86\xe1\x9c\xd1\x08\x31\x81\x11\xcf\xbc\xaf\x1c\x86\x05\xb9\x88\x90\x3f\x32\x1f\xff\x39\xb6\x50\x1d\x23\x52\xcf\x03\xc4\x7d\x86\x23\x09\x42\x8d\x8c\x86\x01\x07\x5c\x01\x02\x82\x82\xe9\x6f\x60\xab\x51\xe4\x07\x60\xb6\x02\x62\x83\xc0\x35\xda\x01\xcc\x01\x24\x60\xfa\xdb\x18\x88\x0d\x14\x00\x86\x9c\x82\x25\xf2\xe9\x16\x71\xf5\x0d\x81\x5b\x04\xa8\xfe\xde\x40\xa3\x62\x83\xd8\x2d\xe6\x08\xc4\x1c\x25\x80\x04\x05\x0c\xad\x10\x93\x3f\xc4\x06\xdb\xbe\x0f\x52\x0c\xef\x3c\x4c\x04\x0a\x43\xfc\x2f\x6f\x23\xb6\xa1\xf7\xf0\x31\x0e\xd0\x0a\xc6\xa1\x90\xd8\xfd\xf7\x9f\x7a\x2a\xcc\x44\x8c\x72\x93\x94\x99\xf4\xa8\x62\xaa\xe1\x1f\xb9\xbf\x33\x13\xc9\x05\x93\x8c\x33\xce\xbe\x2b\x90\xc6\x87\x04\x2c\x11\xa0\x5b\x2c\x04\x0a\x00\x2e\x13\x23\xdf\x7c\x0f\xa5\x1b\x80\x4b\xa0\xfd\x99\x02\x1e\xf9\x38\x60\xc5\x51\xb8\x59\x78\x8d\xc5\x26\x5e\x1e\xf8\x74\xfb\xe9\x16\xc1\x1b\x74\x4b\xd9\x35\xff\x84\xae\xb9\x2f\xc2\x4f\xd1\xf5\xfa\x53\x2c\x70\xc8\x3f\xe1\x48\xd2\x7b\x36\x3f\x47\xc2\xdd\x23\x0e\xf6\x50\x2d\x6d\x55\x5a\x28\x91\x9a\x5c\x86\x82\xb7\x2c\x40\x12\xef\xf7\x39\xb8\xe3\xdc\xdc\x14\x47\x69\xfe\xfc\x30\xde\xb3\x98\x57\x30\xe4\x28\xcf\x18\x41\xa0\xa8\x9c\x70\x04\x43\xff\x8e\x31\x43\x41\x1e\x03\xc9\xa5\xe5\x5e\x2a\xb9\x47\x08\xe8\x6f\xe6\x34\xc4\xfe\xae\xd9\x0c\xcc\x48\x88\x09\x3a\xa1\x7e\xbc\x45\x44\xd4\x72\x97\x5e\x78\x10\x44\x0a\x3c\x08\x4c\x1b\xb9\x2c\x74\xbf\xad\x98\x6b\x3f\x34\xe7\x4c\x67\x47\x38\xbd\x38\xe7\xc5\x51\x62\x81\xb6\xc5\x87\x35\xec\x90\x03\x9e\xf9\x0e\x32\x06\x77\xb5\xd4\x08\x31\x17\x52\x7c\x48\x24\xac\x18\x99\x4d\xcf\xf4\x78\xb0\x94\x31\x9d\xc8\xd2\x02\xac\x93\x3e\x8a\x5f\x9a\xae\x85\x4c\xbb\x08\xb1\x2d\xe6\x5c\xf2\xc4\x4b\x1a\x93\x00\xb2\x12\x03\xb5\x10\x44\xd3\x8b\x73\x8b\x7c\x06\x30\x58\x1a\xc8\x6a\x10\x9c\x53\x1f\x43\x81\x5a\x91\xa7\x15\x60\xe7\x40\x39\x62\x37\xd8\x47\x53\xdf\xa7\x31\x11\x17\x34\x44\xd3\x8b\xf3\x2e\x14\x13\x70\x5d\xe2\xbe\xbd\xaa\xbc\x13\x33\x16\x54\xb8\x8b\xe0\x97\x1b\x04\xb6\x48\xc0\x00\x0a\xa8\x88\x10\x45\xe1\x4e\x2b\x2c\x04\x7c\x6d\xef\x18\xe2\x48\x06\xbb\xc5\x62\x03\x7c\x28\xd0\x9a\x32\xfc\x07\x94\x50\x00\x24\x01\xa0\x6c\x0d\x89\x79\x70\x00\x4e\xa1\xbf\x01\x02\xae\x81\x4f\x89\x6c\xa6\x18\x12\x2a\x05\x20\x3f\x86\x04\xd0\x48\x8f\x16\xdc\xc0\x30\x46\x63\xb0\xa4\x62\x23\x3f\xba\xdd\x60\x7f\x03\x76\x34\x06\x4a\xd6\xa0\x83\x56\x93\xfc\x9f\x35\x18\x87\xf2\x2f\xb2\xca\x0d\x62\x1c\xe7\xa4\x7d\x63\x2e\xbb\x45\x61\xf8\x86\xd0\x5b\x32\x37\x02\xa0\x99\x58\xff\xb5\xd4\xac\x8e\x7b\x56\x94\x19\xa1\x82\x89\x24\xd0\x76\x4b\x49\x4e\xea\xb4\x9a\xbe\xfd\xd0\x3a\x6a\x63\x25\xdb\x1c\x64\xdd\xbb\xba\xeb\xf4\x47\xc5\xbb\xd1\x1e\xd9\x58\x3b\x45\x45\x29\xd1\xca\x4a\xa8\xb7\xd4\xe5\x12\x38\x7d\xb3\x00\x50\x9a\x0f\x92\x97\x57\x78\x1d\x33\xc5\xe3\x2d\x2d\xe8\x3a\x48\x39\x4b\xc5\x6e\x97\x42\x1a\x07\xbf\x42\xe1\x6f\x9a\xd8\xb1\x66\x99\xfe\x4c\xd7\xeb\xfc\x76\xa7\x86\x69\x4b\x1d\xd9\xd6\x1d\xf9\xa5\x80\xc3\x20\xb3\xe0\x53\x22\x20\x26\xdc\x10\x0c\x44\x90\xc1\x2d\x12\x88\x71\xc0\x50\x08\xa5\x9d\x2c\x28\xc8\xd0\xaa\xe9\xa4\xb4\x06\x5c\x3f\x47\x65\xc2\x57\x4e\x15\x22\x70\x19\xa2\xcb\x5d\x54\x16\x2e\xcd\xac\xa9\x71\xfe\x2d\x22\xf1\x36\x37\x11\x96\xdc\x11\x2e\x7c\x2a\x1f\xc6\x01\x16\xae\xc7\x62\x83\x88\xc0\x3e\x14\x94\x95\x5f\x4b\x62\x31\x1a\x86\x88\x9d\x41\x02\xd7\xc8\xf1\x89\xdc\x92\x07\x71\xe8\x7a\x05\xc3\xb0\xfc\xf0\xef\xa3\xdc\x93\x0f\x03\x98\x88\x8a\xa4\x52\x83\x84\x7a\x32\xe4\x04\x6a\x62\x83\x27\x1c\x21\xf0\x3e\x9d\x2e\x69\xff\xf2\x0f\x4f\x26\x31\x87\x6b\x34\xf1\xe5\xf3\x5b\xf9\xdc\x33\x3c\xec\x19\x10\x93\xaf\xcc\x03\xcd\x25\x1e\xba\x83\xdb\x28\x44\xfc\xe9\xd3\x03\xf0\x0b\x0c\x71\x00\x10\x11\x4c\xda\x89\x90\xa1\x1f\xc0\xc7\x2b\x49\xf5\xab\xd1\xc7\xb1\xfa\x29\x69\x9d\xfe\x91\xa1\xb0\x7d\x58\xa2\xab\x7d\x91\x50\x33\x69\x1e\x86\xf6\xe7\xdf\xaf\x46\x1f\x5b\x2a\xf8\x3d\x84\xf9\x11\x82\x0d\x43\xab\xff\x71\x35\xea\x4c\x90\xab\xd1\x51\x81\xba\x3f\x4e\xe0\x91\x9b\x4a\x3f\xfa\x34\x40\x47\xff\xf5\xef\x98\x8a\x7f\xc2\x08\xeb\x1f\x3f\x4e\xd4\xd3\x71\xfe\xad\xa4\x60\xed\xfb\x0c\x51\x6b\xbe\x2b\xd1\xb9\xe6\xdb\x84\xf4\x75\xfd\x86\x61\xcd\xdb\xbf\xe7\xde\x1d\xb8\x0d\x8d\x90\xae\x2f\x90\x90\xc8\x53\x32\x23\x27\x70\x57\x12\x06\x96\xf1\xe5\xd4\x16\x97\x5c\x91\xf5\x39\x12\xc6\xcb\x12\x6f\x97\x88\xc9\xb9\x0e\xe0\x8e\x6b\x5f\x8a\x94\x73\xea\x65\x48\xd7\x1c\x48\x73\xa1\x62\x39\x6c\x84\x88\xf8\x0f\x93\x89\xfc\xeb\x00\xde\xf2\x03\xb8\x85\x7f\x50\x72\xe0\xd3\xed\x64\xaa\x7e\xe6\x04\x1e\x9f\x48\x39\xc9\xc5\x64\x3a\x9f\x5d\x48\xb5\x80\x88\x8f\xe4\x1f\xbf\xcf\x63\x91\x0c\x4e\xeb\xf7\x03\xc9\x97\x5f\xb9\xdf\xfd\x7e\x81\xfe\x1d\x23\x2e\x16\x3b\x22\xe0\xdd\xd3\xa7\xc0\x72\x8d\x32\x0c\x0d\xd3\x1c\x8e\xc1\x8b\x31\xf8\x66\x0c\xfe\x31\x06\x87\x5f\x8f\xc1\x8b\x67\x63\xf0\xed\xb3\x31\xf8\xfe\xd9\x18\x1c\x3e\x97\xff\x7c\x23\xff\xf9\xee\xd9\x18\xbc\xf8\xf6\x9b\x31\xf8\xfa\xd9\xb3\x31\xf8\xe6\x6b\xd9\xe0\xc5\xa1\x7c\xf1\xfc\x1f\x63\x65\x79\xbe\xf8\xf6\x9b\x17\xed\x96\x4f\x17\xe2\xa6\x4b\xea\x41\x10\xb5\x62\x79\x7e\x0e\x4a\x77\x34\x26\xb2\x5a\xb2\x7e\xd9\x0c\x69\x67\x20\x56\x6f\x0f\xd8\xdd\x90\x91\x86\x6d\xad\x8d\xb6\xe0\x9d\x36\x87\x76\xa3\xef\xf5\x64\xd9\x1d\x5d\x96\x7a\xd7\x98\xe4\x3d\x6c\x11\xfe\xc5\x18\xf5\xcd\x7d\x5e\xd2\x7e\x6d\x6a\xb9\x54\x78\xd2\x95\x2f\xae\xa1\xc6\x77\xbb\xa5\x52\xc4\x5b\x78\x4d\x9c\x96\xd2\x48\xbb\x3f\x0f\x30\x9d\xdc\x1c\xc2\x30\xda\xc0\x6f\xb2\xa8\x7d\x70\xf7\x7f\x03\x71\x08\x97\x38\xc4\x62\xf7\x1b\x25\x5d\x2d\xb9\x3e\x24\xf0\x5d\xfb\x83\x1a\xa2\x97\xb7\x15\x75\x0a\x65\x51\x50\x10\x3c\x8e\x22\xca\x44\x13\x93\xe9\x69\x2b\xe1\xba\x68\x69\x7f\xe4\x25\x99\x41\x4b\x0a\x33\x37\x95\x56\x90\xad\xa1\x40\x73\x46\x57\x38\x6c\x3c\x4d\x6e\x0a\xbe\xca\xc1\xea\x35\x79\x6b\x2c\x9a\xcd\xda\x6b\x5c\xef\x88\x7a\xf5\xf3\xbb\xff\x03\x7e\x39\x04\x27\xa7\xf3\x8b\xd3\xe3\xe9\xe5\xec\xed\x39\x38\x7f\x7b\x39\x3b\x3e\x3d\x00\x56\xf3\xa4\x5e\xff\x49\xea\xf5\x9f\x68\xb6\x9f\x60\xce\x63\xc4\x27\xcf\xbf\xff\xf6\x05\x78\x8d\x05\x40\x77\x11\xe5\x88\xe7\x37\xa8\x4a\xaf\xbd\x0a\xe3\x3b\x70\x73\x68\xdd\x37\x08\xb2\x10\x23\x06\xb0\x40\xe6\x23\xba\x02\x6b\x2c\x68\xd4\xce\x7d\xf1\x30\x47\x50\x35\x6b\xf2\x5d\xd3\x89\x7b\x5b\xa4\x44\x61\xe4\xfb\x10\x7d\xae\x10\xbd\xc5\x61\x28\x3f\x11\x98\xc4\x48\x2a\x89\xa5\x3a\x2e\x0b\x00\x26\x60\x15\x8b\x98\x21\x83\x33\x88\x42\x48\xf8\x18\x30\x14\x85\xd0\x57\x66\xfe\x06\x29\x8a\xe4\x3b\x80\x4b\x7a\xd3\xce\x0b\xfc\x45\x11\x75\xce\x04\x86\xdb\x56\x52\x6f\x36\x3d\xab\x3a\xc9\x92\xb6\x84\xd8\xcd\x19\xbd\xc1\x01\x62\xfd\x24\xc4\xac\x00\xad\x97\x8c\x50\xca\xba\xb7\x76\xcb\x5b\x0d\x7b\x15\xdb\x75\xbc\x44\x8c\x20\x81\xf8\x39\x12\x72\x99\x95\xcc\x8d\x9a\xe1\xbf\xa9\x68\xec\xec\x69\xab\x76\x62\xc1\x39\x0d\xd0\x6b\x46\xe3\xf2\xba\x6a\x45\xf9\xb3\x02\xb4\x21\x8e\x9c\x94\x0e\x94\x10\xd7\x0a\x3f\xa0\x74\x53\xa2\x01\x15\xfe\x98\xac\x3d\x92\x7c\xf1\x54\xad\x83\xf7\x66\x64\x20\x7d\x91\x34\x42\xd7\xdc\x33\xaf\x55\x3b\x3e\x84\xb6\x74\x60\x72\x35\x3a\x2a\x22\x2e\x75\xa4\xc2\xaf\xd4\xbe\x8c\xd4\xd5\xe8\xa8\x3c\x88\x6a\x25\x9b\x98\x9a\x6d\x96\xe4\x19\x12\xb0\xe2\x4c\x6d\x18\x96\x18\x94\x17\x5e\x51\x06\x30\x59\x51\xb6\x4d\x0f\x3c\xac\xef\x03\xa8\xdd\xb4\x63\xb6\x5d\x2c\xd2\x4e\x37\xee\xeb\xb5\x21\x2f\x34\x99\xc4\x88\xe1\x1b\x28\x90\x99\x9d\x66\x53\x39\xcf\xb7\xa9\x23\x20\x0c\x43\x7a\x9b\xaa\x10\x29\xf5\x21\x58\xc5\x61\xb8\xf3\x4c\xcf\xc9\xee\x07\x13\x73\x06\x44\xa8\x62\x3f\xb0\x81\x1c\xd0\x58\xa8\x53\x47\x20\x09\x26\x85\x0c\x80\xbe\x8f\x38\xd7\x5b\x4d\x0b\x42\x3f\x53\x61\x2a\xbf\x2e\x80\x39\x9d\xe0\x00\x73\xe3\xef\x0a\xc0\x0d\x86\xe0\x97\xf9\x31\x40\x24\x88\x28\x26\xa2\x9d\xb1\xf2\x70\x47\xe1\x9c\x53\x8e\x7c\x86\x04\x3f\x25\x3e\xdb\xd9\x31\x34\x98\xd6\x45\xa9\x99\x13\xfa\x4d\xe4\xb7\x5a\xf1\xbf\xcc\x8f\xbb\x7a\x03\x6a\x36\xae\x2e\x39\xd4\x40\xa1\x15\x8c\x89\x5a\x93\xa0\x30\xe6\x71\x69\x33\x5c\xbd\x8c\xdc\x62\xad\x56\x0d\xd6\xec\x5e\x6a\x77\xa0\xee\xbd\x61\x2d\x37\x14\x76\x24\x65\x53\x77\x10\xdf\x0a\x04\x1c\x4b\x91\x65\x96\xcd\xd8\xd8\x86\xda\xfc\x43\x81\x3e\x50\x36\x04\x03\xd3\xf9\xac\xb1\x57\xa5\x0f\xe0\x94\x2f\x3c\x25\x19\x3d\x73\xba\xe9\x19\xb3\x2b\x65\xbe\x1c\x83\xab\x6f\x95\x4d\x6c\xbd\x06\x79\xf9\x91\x1e\x3d\x8f\x12\x6f\x42\xee\x03\x03\xbe\xca\x2e\xb3\xcb\xe2\x83\xcb\xf5\x73\x9a\xac\xf6\x06\xc7\x4c\x86\x11\xa7\x4a\x96\x54\xd9\x91\x4b\x4a\x43\x04\x2b\xd6\x77\x14\x2f\x43\xec\xb7\x05\xd0\x6a\x5d\xe7\x91\xac\xea\x7b\x10\x2e\xd4\xa7\xb0\x56\x3a\xc3\x08\x2b\xc1\x8a\x58\x22\x43\xad\xd8\xcd\x28\xdc\x96\x47\xbc\x2d\x81\xbb\xa6\x58\x6e\x54\x1a\x4c\xae\x15\x0c\x34\x38\xbd\x43\x7e\x2c\xc1\x35\x0b\xad\xa9\x53\xd1\x8c\x86\x66\xc7\xb6\xdc\x81\x88\x06\x3a\xf8\x49\xe3\x2d\x15\xd1\x74\x3e\xe3\x07\xe0\x72\x83\x39\x50\x9f\x62\x0e\x60\x10\x68\xcf\xa5\xdc\xc1\xa5\xe6\x3f\xb8\x78\x39\x3d\x56\x1b\x44\x18\x8b\x4d\x12\x26\x72\x00\x94\x49\x3d\xa7\x01\x48\xd0\x06\x12\xef\xfa\xa3\x07\x74\x9d\x38\xc5\x63\x8e\xd8\x3a\xc6\x01\x9a\x44\x34\xf0\x90\x05\xe2\x49\x7c\x94\x37\xbc\x9d\x7d\xf5\x99\x46\xdc\xec\x30\xa0\xcd\x30\xaf\x46\x47\x65\x2a\xee\xf7\x82\x15\xd8\x65\x3e\x68\x10\x9a\x33\x40\x4c\x52\x44\x52\xca\x60\x20\x89\x0c\x92\xf1\x28\xa2\x7e\x34\x5c\x71\xfa\x66\x01\x8c\x87\x0d\x2c\x0a\xde\x46\xd3\xda\x33\xee\xbe\x96\x9b\xa6\x7e\x88\x95\x4c\xec\x22\x32\x57\xa3\x23\x07\xee\xd5\x93\x91\x8f\x99\xe9\xb7\xc7\x49\xa5\xc6\x22\x07\x75\x88\x2d\x8f\xc1\x53\xae\x07\x85\xa8\x3a\xa0\x60\x48\x8e\xd1\x1c\x79\x19\x79\x67\x26\x70\x36\x3d\x03\x06\x0b\x60\x07\xf7\xe1\xc9\x04\xc3\xad\x81\x64\x01\x4d\xbe\x52\x84\xf4\xa4\x7a\xf6\xcc\x39\xb2\xb2\x6f\xda\x4d\x6b\x4b\xfc\x32\xf3\xd8\x02\xa5\xab\xd1\x91\x6b\x5c\x7b\x67\xb7\x47\xa0\x63\x06\xc2\x67\x5a\xa0\x30\x0c\x81\xb5\x7a\xbd\x25\x94\xf2\x50\xfd\x81\x11\x37\x14\x55\x02\xd2\x98\x3c\x7a\xb6\xa5\x78\x4c\xd1\x03\x16\xbd\x7a\x49\x3e\x9b\x9e\x59\x11\xf7\x8e\x23\xf6\x5a\x89\x38\x2d\x6f\x7f\xb7\xd1\x6a\xbf\x1b\xd4\x30\xe2\x1d\x24\xfa\x90\x63\x6c\x26\xb6\xbb\x8c\xe9\x6a\x74\x54\x41\xbf\x6a\xc6\xba\x89\xfc\x0b\xc4\x69\xcc\x7c\x74\x9c\x84\x33\xb8\x43\xcf\x8b\xc6\x59\xed\xbe\x5c\x05\xe1\x99\x1c\x8d\x24\x6a\x70\x07\x08\x92\x23\x30\x31\xbe\x2c\xd6\x0b\x4a\x6e\x39\xd3\x58\x8a\x64\x99\xe9\x27\xca\xad\xdb\xce\xb1\x7c\xbf\x9d\xa7\x91\xa2\x82\xc5\xc8\x49\x54\xb9\xde\xdf\xce\x4e\x8e\xfb\x50\x50\xef\xc9\xd3\x31\x48\x78\x20\x32\x9b\x47\x00\x39\xb8\x45\x61\x28\xff\x9f\x5d\x2c\xa6\x89\xde\xd1\x47\xff\xe0\xf8\x7c\x06\xa2\x30\x5e\x63\xd2\xce\x23\x3f\x50\x9f\x1d\xcd\xf6\x82\x90\x6b\x2e\xbc\xf6\xdb\x24\x05\x78\x2d\x2c\x17\xd7\xb4\xd6\xa8\xdd\x86\x4b\x6b\xc0\xbd\x87\x14\x41\x72\xb2\xa0\x10\x0c\x2f\x63\x81\x4c\x4c\xb4\x5f\xf0\x15\x34\x4c\xe5\xd8\x03\xad\x62\x77\xa1\xdc\xae\x4d\x12\xa3\x08\xa1\x02\xe6\xb3\xea\xea\x29\x70\x2f\x51\xf7\x7b\x63\xbd\x43\xb8\x44\xe1\xc3\x46\xb1\x6b\x8e\x88\x6c\xc7\x23\xe8\x37\x6f\xdc\x6a\x11\x17\xc3\xbb\xd3\xee\xca\xe4\x1d\xbb\x19\x63\xc0\xc5\x91\x75\x73\xdf\x22\xe0\x43\xa2\x93\x02\x13\x9b\xee\xad\x22\xbe\x64\x5f\x25\xcf\x8a\xd6\x5f\xcb\xd5\xd3\xbb\xbb\x8a\xe5\x55\x30\xc3\x9b\x2c\xb4\x2f\x9a\x43\x96\x26\x59\xe6\x07\x38\x6c\x6e\x59\x65\x2f\x4e\xbe\x7f\xcc\x39\x6b\x92\x93\xd7\xdf\xdf\x93\x49\xee\x52\xde\x8d\xc2\x74\xa1\x5e\x3c\xd1\x1a\xb8\x73\xa8\x9d\x4e\x16\xad\x96\x73\x3b\x35\xbf\x58\xe2\x9d\x76\x47\x0f\x48\xd7\x1e\x3d\x3a\x49\x23\xe7\xe9\x7c\xbf\xae\xaa\x3d\x32\x8f\x90\x8f\x57\xd8\xd7\x73\xae\x52\xbe\x31\xe1\x02\xc1\xc0\x22\xad\x82\xb7\x12\xd9\xeb\xad\x11\x41\x4c\x6d\xbe\x92\x16\xed\x0e\xc4\x87\xe8\xb0\x92\x1a\x6f\x49\xd8\x6b\x73\xa5\xb1\xdb\x01\xbc\x02\x94\x84\xbb\x64\xa5\x17\xdc\x09\x1a\x15\xbe\xa1\x71\x18\x80\x25\x4a\xf6\xa3\x72\xfa\x68\x2c\xf4\xdf\x98\xac\x27\x56\xf7\x9a\x90\x99\x3e\x7c\xf4\x99\x51\x73\x7b\x3a\x04\x14\x71\xc3\x78\xaa\x2a\x15\xbb\xd0\x30\x9c\xf0\x1f\x54\xca\xa8\xdc\xf0\x4b\x84\x92\xdd\x58\x2f\x29\xd0\x0a\x58\x03\x1b\x75\xb0\xbc\xc7\x8e\xc6\xa8\xeb\xe8\xb6\x2e\x77\xb0\x36\x09\xb0\x2a\xb1\x30\xaf\x38\xf7\x28\x85\x32\x9f\xba\x44\xa5\x4b\x60\x14\x39\x70\xc8\x2d\xa4\xce\xec\x2c\xcc\x76\x9a\xbd\x0b\x49\xd0\x2b\x49\xb1\x3d\xfc\x46\x76\xf0\xa2\xb8\xd0\x2b\xad\x61\xd6\xd2\x6f\xda\x8a\xc9\x2c\xf0\x01\x27\x44\xb3\x46\xd6\x8a\xab\x5a\x89\x0d\xeb\xac\xec\x85\xe7\x22\x78\x71\x53\x5f\x53\xdb\x22\xcb\xb0\x68\xdd\x2e\xf2\xff\x61\xb8\x04\xf2\x1e\x44\xb6\xc4\x82\x49\xc3\x27\xe1\x51\xbc\x26\x94\x69\x6f\xee\x47\xed\xce\x6d\x99\x2e\x57\x0f\x53\x67\x7a\x69\xc0\x49\x8a\xd7\x3d\xb8\x04\xea\x46\x6d\xd8\xa3\xe8\x38\x6a\x32\xb8\x42\x53\xb7\xe9\xa3\x19\xa3\x3b\x7e\xca\xd9\xf8\xeb\x02\x68\x40\x60\x43\xb9\x31\x0c\x30\xef\x84\x74\x13\x78\x0f\xdf\x02\x50\x07\xcd\x72\xf7\x03\xd7\x66\x34\xda\xe7\xe8\x38\x80\x68\x45\x9d\xce\x70\x07\x2b\xa5\x50\x37\x6a\x9b\x60\xc6\x30\x24\x22\xcd\x93\x3d\x3c\x38\xfc\x87\xcd\x68\x3d\x3c\x38\xfc\x2e\xf3\xfb\xfb\xf4\xf7\xf3\x67\x57\xa3\x8f\xe0\x89\x41\xf4\xa9\x7d\x7a\xd8\x3a\x05\xd6\x85\x45\x36\x67\x53\xa2\x53\x93\xd2\x29\x31\xac\x7f\xfd\x7d\xed\xeb\xe7\xcf\x72\xaf\xb3\x23\x2a\x7c\x78\x58\x48\x1e\xad\x9a\x30\x09\xb3\x49\xfc\xb7\x1c\x58\x31\x63\x5c\x8e\xc6\xf1\xec\xfb\xf2\xb3\x42\x1f\xfa\xd9\x61\x45\x18\x79\x2b\x5d\x5c\xa1\x8c\x1c\xac\x57\x5c\xce\xf7\xe9\x8b\x4c\xaa\x02\xe8\x6d\x62\x98\x89\xe6\x6c\x1f\x14\xd4\x08\x98\x4b\x9d\x9f\x4f\x2f\x9b\xd8\x4a\x6b\x28\xd0\x2d\xec\xe3\xbe\xa8\x58\x9b\x3f\xe1\xf5\x26\xdc\x4d\x75\x84\x61\x88\xe4\x12\xb4\x46\x1f\xe2\x00\x82\x8d\x7a\x0f\xa0\xfd\x00\x9c\x4f\x2f\x81\xc1\x46\x2d\xd1\x05\x26\x6b\x47\x3b\xae\x1e\x67\xbf\x2e\x2c\xed\x13\xcc\x6d\x87\x81\xfe\xc9\xe5\xd7\xc3\x2e\xf5\xc2\xe8\xf2\x0b\xb3\xc5\x38\xb3\x30\xf5\x80\x6b\x40\xd5\x0f\x3d\x0b\xca\xd0\x20\x0f\xab\x86\x1a\x19\x99\xa0\xb1\x68\x22\x15\x0a\x34\x28\x2e\x72\x07\x20\x00\xec\xec\x0c\xb1\xfa\x2d\xeb\x0e\xb2\x68\x25\x51\xfd\x7c\x54\xef\x3e\x1e\xc9\x34\x71\x2d\x40\x5d\x43\xb0\x4d\x98\x65\xb3\xed\x72\xb1\x2a\xa5\x53\xe5\xea\xd0\xc7\xbe\x00\x5b\x4d\x87\x1d\x44\x19\x8b\x01\xb7\x4a\x49\x74\x3b\x09\x80\x86\x6e\x2a\x3b\xb6\x3d\xbb\xa9\x01\xe4\x9a\xcc\x5f\xe6\xc7\x8d\xce\x61\x62\x41\xa7\x61\x48\x7d\x28\xd0\x6c\x7e\xf3\x6d\x1f\xbf\xdf\x34\x07\xeb\x97\x6f\x01\xd3\xc9\xf8\x7a\x83\x3d\xbf\xf9\x16\x1c\xcf\x4e\x2e\xc0\x32\xa4\xfe\xb5\x76\xd2\x4e\xbe\xf9\x16\xc8\x19\xc2\x77\x89\x4b\x47\xe2\xdd\xca\x27\x34\x54\xa7\x4e\xae\xfc\xfc\x45\x26\xfd\xea\xa0\xe7\x9a\xde\x4b\xa1\xd2\xb5\xfe\x59\x84\x4c\xba\x96\xca\xe4\x48\xd3\x2e\xe6\xb3\x24\xf6\xf0\x26\xf2\x3d\xa2\x53\x07\x54\xfd\x93\x24\xc3\x46\x7f\xee\x09\xea\x89\x0d\xca\xc6\x93\xc3\x08\x7b\x3a\xfc\xd7\x4b\xf2\x33\x06\x48\xf3\x1a\x06\x11\x9b\xda\x55\x1a\x70\x75\xe4\x11\xba\x13\x0c\x4a\xde\xf9\x72\x27\x71\x2a\x82\x2b\x91\x3c\x9a\x91\xed\x31\x87\x9c\xf6\x31\x40\x07\xeb\x03\x00\xf5\x1b\xf9\xb5\x15\x12\x46\x32\x00\x09\x80\xec\x00\x0c\xbc\x0d\x2d\x0b\x9e\x26\x93\x72\x5f\x38\x38\x69\xde\xa2\xc2\x6a\xf6\xb8\x4c\x25\x93\x2c\x36\x90\xe9\x8c\x92\x05\xf2\x63\x86\xc5\x4e\x65\x96\x5c\xc4\x8e\x04\xf8\xb6\x52\x4d\x5a\xad\x3e\x0c\xa5\x55\x14\x04\x80\x1b\xf8\x40\xa5\x45\x00\x16\x87\xe6\xf4\x92\x04\x60\xc5\xe8\x56\x89\x14\x63\xa0\x24\xd6\x6f\xa1\x91\xfc\x56\x79\xb0\x15\xd6\x3a\x55\x2a\xff\x89\x89\xc0\x36\xb9\x57\x31\xc9\xa6\x26\xea\xa8\x4f\xba\xdd\xc6\x04\xfb\xb9\x23\xaf\x5c\x60\x98\xea\x25\xd7\xce\x00\xd5\x45\x08\x81\xaf\x76\x12\x60\x89\xac\xa5\x15\x80\xdb\x0d\x22\x20\x96\x76\x9b\xd9\x3b\x27\xbb\xe9\x3c\x76\xbc\x9d\x75\xfa\x48\xc4\x26\x44\x6c\x10\xba\x47\x60\xc3\x12\x0a\x99\x4d\x55\x8d\xbd\xa5\x53\x4d\xbe\xac\x94\xd3\xf9\x82\xa9\x96\xd6\x6c\x20\x67\x2c\x23\xaa\x8d\xc5\x73\xfd\x1d\x97\x52\x3b\x49\x30\x69\xc5\x84\xbd\x3a\x72\x12\x91\x67\x25\x4d\x8f\x1d\xe9\x13\x78\x0d\xf5\xb1\xad\xe6\xbc\xb9\x64\xbc\x9c\x18\x7b\xaa\x44\x6b\xca\xad\x92\xf3\x96\x48\xdc\x22\x44\x1c\xec\xaa\xd8\xb4\x15\x6d\xee\x07\x03\x37\xd1\xdc\x82\xba\x07\xf9\xb4\xd6\x41\x9e\xae\x9c\x1a\xe4\xe4\xc1\xe2\x75\x6b\x75\x57\x03\xca\x3d\xa0\xd2\xbe\x09\xec\x5d\x97\x0b\x97\x2a\x2e\xe0\x72\x8d\x76\xda\x8b\x39\xfd\xcd\xd0\x9e\xdc\x20\x82\x11\xf1\x91\x09\x47\x57\xae\x60\x93\x1a\xfd\xe1\xc9\xc4\x26\x49\x4f\x18\x52\xd2\xc7\xc3\x70\xeb\x41\x12\x78\x37\x91\x3f\x79\x9a\x0d\x90\x7d\x6f\xa4\xd3\x1d\xd6\x3e\xe5\x5f\xe6\xc7\xbc\xd2\xf6\x8b\x39\xf2\xec\x97\x12\x94\xa7\x2a\xd8\x7b\x7e\xcc\x05\xdd\x7a\xb9\x83\xb1\xa7\xed\xd4\xc2\xde\x11\x66\xcc\xc1\xda\xc1\x5d\x8d\x8e\xb2\xb4\xd0\x59\xff\xe9\x70\xf7\x5a\x95\x2d\x86\x78\x35\x3a\x72\x10\x4f\xf6\xd8\xb9\xea\x57\xbe\x00\xbc\xda\x73\x54\x0a\x19\x07\xdf\xb9\x8d\xd6\x06\x2b\xae\x9d\x0d\x35\xae\xd9\x35\x16\x34\x54\xdd\x7e\xa6\x56\x07\x0d\xb8\xf1\x5e\x87\x74\x09\x43\x7b\xe9\x82\x2a\x7e\x13\x86\xc0\xdf\xe0\x30\xe8\xb8\x03\x6f\x02\x31\xb7\x15\x2f\x94\x4e\x1a\xb8\x0c\xff\x30\xa7\x69\x36\x81\x2b\xd2\x48\xb6\x5b\xbf\x55\x30\xdc\x16\xc7\xa0\x69\x9b\xb3\xe9\x99\x8a\xd2\xf9\x1b\x07\xd3\x8b\x73\xa9\xb9\x4d\x24\x2b\x8b\x89\x4e\x6a\xa4\x44\x50\x8b\x5a\xbb\x61\xb5\x85\x5d\x61\x1b\x84\xc8\x17\xb4\x67\x6d\x9d\x3c\x0b\x2d\x0c\xcc\x21\xcc\x2e\xad\xe1\x74\xa8\xa2\x35\xbe\x35\xce\x40\x8a\xc5\x90\x42\x75\xbc\x66\x0b\x83\xf6\x20\x67\xbf\x9e\xdc\xc4\x75\xc6\x50\xb5\x60\x9f\x4b\x69\xe6\xc7\x8c\x21\x22\x0a\xd1\x07\xbd\x16\x44\x0b\xb0\x6d\x4c\x89\xcf\x6c\x8b\x5b\x5c\x4d\x00\x9c\x61\xfe\x80\x02\xa3\x32\x81\xaa\x34\xa0\x82\x9d\xed\xd5\x36\x6a\x3a\xe5\xd6\xc7\x4c\xa8\xba\x24\x87\x50\x82\x6c\x7e\x4e\x30\x56\xd2\xd2\x3a\x05\xac\xe7\xcd\xee\xec\x54\x19\x2d\x53\x3a\xab\x1d\xc9\x1f\x08\xca\xce\xe9\x7c\x50\x07\xf1\xef\x32\x07\xe6\x69\x68\x81\x39\x34\x6f\x45\xf2\x16\x90\xaa\x0e\xdb\x5b\xd9\x47\xc5\x53\x53\x97\x26\x71\x4a\xde\x7a\x63\xa9\x78\xae\xca\x73\x41\x95\xfd\x6c\x10\x2d\xf3\xb8\xe1\x34\x21\xed\x44\x0e\x6c\xc8\x42\x22\xe9\x12\xf1\xe7\x16\xae\xcd\x04\x6b\xc7\x4e\x6a\x2c\x95\x44\xcd\x34\xb2\x58\x74\xf6\x4c\x63\xb3\xe5\xcb\xa7\x2e\xe5\x68\x98\x29\x66\xa0\x30\x03\x09\xf7\x64\xf4\x7e\x41\x5b\xb5\x13\x50\x03\xf4\xd0\x30\xb6\xaa\x49\xda\x54\x43\x5a\x24\xe0\xb4\x33\x4e\x0b\xd9\x01\x29\xd1\x18\x7e\x0f\x91\x51\x95\xd6\x35\xe8\x02\xef\x61\x3b\x35\x5d\xde\x5d\x8d\xa6\x64\x71\x87\xf1\x5d\xa3\xf2\x2a\xa1\x43\x5d\x55\x98\xa5\x61\x7c\xf7\x2a\xcc\xcb\x4f\x47\x98\x22\x01\x99\xa8\x42\x18\x49\xd5\xab\xd9\x50\xa1\x9e\xfc\x8a\x20\xe7\xea\x8c\x40\x61\x20\x9f\xa8\x0a\x9b\x4b\x4a\x05\x17\x0c\x46\xaa\xf0\x97\xf1\xa4\x72\x84\x92\x02\xa9\xab\x30\xbe\xf3\x83\x03\x4c\x55\x8a\xfa\x44\x69\xe8\x6c\x8a\x1b\x25\x4a\x81\xaf\xca\x88\xee\x8b\x85\x7c\x48\x88\x3b\x97\xfb\x1a\x8b\xa4\xdc\x66\x3f\x2b\x98\xa1\x88\x72\x2c\x28\xdb\x25\x11\x86\x26\xf8\xf6\x00\x1c\xeb\xbb\xf9\x10\x16\x1b\xc4\xc0\x6b\x75\xc4\x09\xa8\xfa\x15\xc2\x65\x7b\xd3\xb8\x4f\x5f\x1d\x05\x41\x96\x50\xe3\x22\xaf\x0f\x22\x09\x4c\xb9\x49\xa8\xeb\xc0\x66\x2a\xb9\xea\x03\x82\x5c\xa9\x73\xa8\x0a\xbe\x66\xc8\xa0\xb4\xf5\x4a\x0f\xf3\x6d\xc4\xc1\x25\xa5\xe1\x35\x16\xe0\x89\xa9\x31\xfb\xb4\xb9\xb8\xb8\x6f\x3c\x4a\x32\xe5\x55\x41\x5e\x34\xb8\x63\xd4\xad\xc0\x5b\xdf\x27\x0a\x0b\x8b\x52\x79\x6d\x21\x57\x6e\xb9\x74\xe1\x56\x2c\xca\xc6\x04\x1d\xa8\x97\x9a\x7b\x3b\x5f\xe3\x46\xc9\xb2\x09\xd0\xb2\x27\xa9\x46\x46\xdb\x8f\xeb\x04\x80\x76\x6c\x59\x06\x11\x54\xa5\x91\x49\x0e\x82\xe0\x65\xa1\x53\x29\x94\x72\xe5\x65\x6c\xe9\xea\xd3\x93\x76\x82\x60\xa8\x3e\x9d\x72\x51\x12\x10\xe6\x4d\xd7\x1a\x12\xbd\xb5\x5f\xb7\xa2\x51\x12\xe2\xa6\x70\xfb\x09\x85\x5b\x60\x01\x01\xac\x0e\x43\xfe\x15\x13\x5f\x2d\x3d\x75\xa4\x08\x93\x12\xdc\x66\xa4\xa6\x48\xd6\x60\x04\xbc\x0f\x84\x9c\xd4\x95\x02\xa3\x19\x65\x2f\xe4\x97\xad\xa8\x6a\xae\xe6\xb1\x98\x51\x02\x76\x34\x66\xf7\xc0\x6e\x6d\x3a\xea\xa8\x74\x58\x7e\xf4\x29\x57\x8e\x6b\x16\xf5\x67\x57\x46\x8a\x10\x52\x98\x19\x99\x2f\xad\x8e\xb4\x9a\x1f\x09\x40\x88\xc9\xb5\x7c\x8f\x85\x4b\x67\x1c\x80\xf7\xaf\x75\x65\x73\x55\xfd\xe7\xc3\x93\x89\x2e\x9f\xe9\xfd\x3b\xc6\xfe\x35\x17\x30\x57\xb2\x6c\x48\xed\xd5\x1b\xf1\xcc\x79\x50\x19\xe7\xab\xd1\x51\x76\x5c\x69\x84\x50\x46\x6a\xbf\x8d\x1a\x85\x49\xae\xf2\x96\x77\xcd\x7a\x51\x36\x7a\xf7\xf5\xf2\xbc\xc8\xc6\x03\x2e\x91\x32\xec\x8e\xab\x42\x51\xe3\x8b\x73\xb9\xb5\x6c\x5a\x33\xcd\x39\x15\xe8\x07\x9d\x7d\xa3\x5c\x7f\xa6\xe0\xaa\x92\xb9\x34\x0c\xb4\xd1\x0a\x44\xee\xee\x9e\xfb\xe4\xfa\xcf\x32\x90\x1c\xe3\x97\x0a\xfd\xef\xf5\x0f\x29\x7b\xae\xb1\x6b\xc8\x58\x7f\x03\xc7\xf5\x53\x1c\xf8\x57\xa3\x8f\x3f\xe8\x72\x51\xb6\x1a\x5a\x52\x37\x6a\xd0\x28\x7b\xd9\x57\x2e\x86\xbd\x59\xaf\xee\x70\x75\x09\x6c\x88\xb0\x73\xf7\x24\x50\x82\xde\xae\xaa\x4b\xfe\x56\x18\x4c\xb3\x93\xe3\xea\xeb\x1e\xfe\x2c\x75\x52\x95\x6e\x5b\xa2\x47\x9e\xfd\x93\xf0\x06\x64\x4f\xf4\x93\x40\x2a\xf5\x59\x5a\x6f\xaf\xf6\x8e\x94\x65\x48\x97\x93\x2d\xc4\x24\x0d\x1e\x78\xfe\x0f\x4f\x92\xd5\xb3\xfd\x1e\xec\xe0\x36\x6c\xb1\xc9\x6a\x37\x82\x72\x2d\xbd\x41\xf0\x55\xd1\x0e\x15\xa4\xc9\x04\x22\x24\xcb\x36\x5f\x39\xa7\xc1\x86\xad\xf5\x86\xcc\x92\x65\x97\xd9\x18\xfd\xaf\xc5\xdb\xf3\xc9\xff\x9d\x9e\xfd\x9c\x94\xc6\xe1\x63\xc0\x63\x7f\x03\x20\x07\x2a\x50\xc1\x71\x2d\x18\x65\xee\x2b\x81\x9b\xce\xcb\xfd\x21\x50\xb3\x8d\x9b\x49\x2b\x9a\xf8\x4e\xbf\x79\xe5\xd5\xb5\x51\x3c\x65\xfe\x06\x0b\xe4\x8b\x98\xf5\x11\x7b\xc7\xf3\x77\x20\x0b\xca\x1e\x70\x9d\x1e\x3f\xd7\xf6\x3d\x91\xb2\x7d\x17\xa1\xf4\xda\xbb\x82\x84\xbc\xfb\xee\xdb\xdf\xbf\xfd\xfa\x6a\xf4\x51\xdd\xb9\xb9\x0d\xd2\xdf\x6c\xab\x7e\xb7\x92\x91\x3d\xf1\xc9\x8a\x53\x8d\x58\x3e\x29\x28\x77\x23\xa5\xc4\xb5\xe6\xb5\x44\x3f\xf7\xba\x89\xd8\xd5\x9d\x16\xd3\x80\x54\x57\xa5\x87\xb2\x83\xfd\xd7\xcb\xac\xa3\xea\xb3\xea\x46\xf7\x5c\xea\x72\x2f\xa8\x78\x1f\xe3\xeb\xf9\x3b\x7e\x00\x66\x42\x15\xf2\x5a\xaa\x33\x20\xa9\xf1\x9f\x65\x7c\xc5\x84\x12\xef\xf5\xfc\x5d\x9e\xf0\x2d\x83\x77\xef\xa1\x7b\x27\x99\xb6\x68\x4b\x7b\xd5\x25\xca\x23\xaa\xc1\x81\xcb\x0d\x02\x31\xc1\xc2\x06\x13\x2b\x03\xf7\x35\x7e\xd9\x83\x04\xfb\x20\x3b\x47\x77\x73\x3c\x7f\x77\x2f\x5c\xa0\x01\x0f\x31\xa1\x1a\x52\x47\x2b\xa3\x88\x86\x9d\xce\xe2\x3a\x18\x57\xcb\xc0\x41\xf6\x06\x5a\x13\xe4\x84\x8d\x3d\x70\xb3\x56\x75\x4b\xad\x52\x0f\x2b\xa7\x09\xaa\xee\x82\x6a\xa0\x10\x8c\x23\x7c\x36\xbf\xf9\xfa\x78\x76\x72\xd1\x47\x21\xcc\x4e\x2e\x00\x83\x64\x9d\x1c\xae\x21\x86\xc0\x47\x5b\xa6\x64\xfe\x51\x49\x5a\x00\x39\xc7\x6b\x82\x82\x76\xc2\xdd\x09\x5b\x0b\xdd\xa4\x03\x23\x6c\x0b\xdd\x74\xe4\xab\x22\x5d\x06\x61\x92\xf4\x1e\x74\xb3\x6f\x4a\x83\x41\x5b\x33\x49\x13\x58\x39\x26\xf9\x19\xc6\xc4\xdf\x5c\xa2\x6d\x14\xe6\x73\x28\x2b\x36\x51\x38\x68\xbe\x85\xda\x9b\x41\x53\xc7\x38\x1a\x31\x20\x0c\x66\x60\x76\xd2\x8a\x37\x1c\xcd\xdd\x92\xb0\x77\x75\x85\x62\x4f\x06\x22\x38\xc9\x08\xe2\x6c\xfe\x48\x58\xf1\xfd\xe5\xdb\x93\xb7\xf6\x36\x4d\xf0\x57\xd3\x7a\x0c\xfe\xfa\xb3\xaa\x6c\xdd\x6b\xf0\xf7\x84\x52\xc7\x45\x94\x8f\x30\xbe\xa9\xba\xfd\xb6\x6e\x29\xe5\x58\xb8\x74\xf1\xdc\xc0\xb1\xad\x70\x8b\x7b\xd7\xe3\xdb\x81\xf7\x3a\x7e\x1b\x4c\xcf\x66\x99\x6b\xef\x75\x4c\x37\xdc\xe2\xf4\x62\x85\x31\xf8\x08\x63\x41\x3d\xce\xb7\x1f\xcd\xef\x8f\x63\xb9\x15\xf8\xc8\x05\x14\xd8\x6f\x67\x00\xdb\xee\xcb\x17\xbc\x96\xbb\xbe\x1a\x1d\x65\x90\x94\x9b\x37\x9b\x17\x6f\x11\x2a\xd4\xd6\x90\x8f\x93\x47\x94\x99\xa7\x1a\x4d\x6b\xe4\x3a\x57\x1d\xdc\xe2\x57\x70\x8b\xab\x4b\xfb\x75\xf7\xb0\xe8\x0a\xdb\x3f\x63\x12\xdf\x3d\x2f\x57\x2e\x79\xb7\x8c\x89\x88\x9f\x3f\x7b\xf6\xb5\xad\x70\xa2\x9f\x1c\x7e\x97\x3e\x79\x49\x85\x08\x11\xa3\xfe\x35\x12\xf6\xd9\xaf\x98\x04\xf4\x96\x2f\x54\x2a\xe7\xf3\x67\x87\xdf\x1f\x53\xa6\x2a\x55\xab\x2b\xa5\x2b\xbf\x7a\x15\x87\xe1\xbe\xaf\x9e\x7d\x5d\x84\x35\x6c\xb1\x85\x2c\x41\x1a\x95\x40\x49\x69\x54\x53\x50\x25\x25\x5b\xcd\x47\x59\x4a\xd6\x7c\x56\x4f\xdc\x36\x0d\x73\xf4\x6e\xde\xb0\x30\x05\x0d\xeb\xbf\x64\x09\xdb\x64\x2f\x57\xf9\x3d\x00\x19\xbe\x74\xbf\x91\x84\x2e\xbe\xc9\x52\xb7\xf8\xae\x9e\xa4\x7b\xbf\xce\xd1\x71\xcf\xd7\x05\xe2\xed\xdf\x81\x42\xbe\x5e\xc4\x3c\x42\x24\x98\x33\xea\x23\xce\xef\xf9\xee\xee\x5a\xe9\x8c\x10\x78\xcf\x50\x88\x6e\x20\x11\x2a\x76\x34\xa0\x3e\xaf\xbf\x42\x63\xfa\xeb\x42\x55\x34\x7d\x65\x43\x64\x1c\x97\x4f\xdc\x72\x2f\xa9\x0a\xef\xc5\x51\x00\x05\xd2\xa5\x99\xd5\xe5\x13\x5f\xf9\x2b\x92\xbe\xe7\xb9\x0f\x3c\x46\xc3\x10\x93\xb5\x7e\xe6\x71\x4d\xa9\xc8\x52\xaa\x4f\x16\xfb\x83\x1d\xd4\xd5\xe8\xa8\x34\x07\xd5\xc9\xf0\x9f\xf7\xe6\xf7\x5a\xd3\x0f\x6f\xb1\xd0\xf7\x8e\xea\x98\x38\x5b\x0a\x77\xfa\x5b\xaa\xe3\xa5\x92\xe4\x3e\x0c\x55\x6e\xd7\x1f\x94\x20\x0f\xde\x42\x86\x3c\xad\x53\xf5\x8b\x76\xb3\xaa\xbb\x2d\x69\xf4\x26\x1d\x99\x9b\x48\x4b\xd8\x56\x53\x7b\x99\x95\x32\x8d\x8e\x0f\x13\x43\xac\x52\x40\x55\x7b\x13\x92\xc8\xe1\x15\x65\x20\xdb\xbe\x43\x1a\x69\x73\xa8\xce\x81\x07\x88\x4b\xcb\xf1\x18\x46\xd0\xc7\xa2\xd2\x52\xb1\xde\x12\x37\x0c\x9d\x85\x3d\x3b\x3b\x59\xdc\x1c\xf6\x49\xfc\x37\x76\x2c\x4f\x2b\x8a\x18\x13\x3e\xa9\x8f\x68\x8b\x54\x9a\x30\x5e\xd5\xe5\x73\x20\xe8\x35\x22\xed\xc8\x36\x64\x57\xa9\xb6\x4c\xcd\xf6\x0a\x1a\xcd\x69\x20\x01\xf5\x21\x92\x49\xa4\x56\xd7\x72\x9c\x9d\x2c\xd2\x01\x28\xef\x00\x31\x65\x0b\xb3\x5b\xe2\x88\x06\xed\x88\x33\x44\x17\x4d\x88\x82\x96\xfc\x6d\x24\xf0\x16\xff\x81\x2a\x37\xd1\x6d\x6e\xc6\x79\x7f\xfa\x72\xa1\x1c\x00\x5b\x73\x2d\xde\x5e\x15\x77\x7a\xfc\xbc\xac\x02\xd0\x92\x7b\xd4\xe2\xd5\xe1\x6e\x28\x8b\x4e\x63\x9d\xd4\x10\x8b\xab\xd1\x51\x71\x80\x35\xc5\x54\x56\xf0\x54\x5f\xe2\xdb\x87\xb2\xba\x8a\x82\xf1\xc1\xc2\x3b\xbc\x8d\xb7\x3a\x7f\x1f\x05\x19\x2f\xe6\xe9\xab\xa9\x67\x6f\x0c\xb6\xd9\x3f\x3e\x64\x2a\x6b\xcf\x14\x7e\x50\xb7\x28\x61\x6e\x6a\x44\xb4\x22\xe7\x7d\xe1\xe0\x26\x9b\x02\x71\x82\x04\xc4\x21\x0a\xce\x28\xc1\x82\x2a\x45\xda\x83\x88\x7a\x1e\x94\x53\x33\x30\x80\xc1\x36\x85\xdc\x86\x16\x7b\x40\x39\x87\x84\xe1\xb6\xa5\x4a\x9b\x4d\xcf\x2a\x40\x19\x9f\x6c\x83\xea\xfd\xb5\xed\xe7\xaa\x18\x54\x1f\x08\x8e\x83\xbf\x9a\x91\x95\x8e\x0b\x9b\xe9\x69\x1b\x12\x22\x15\xaa\xd3\x25\xdd\x51\x53\xef\x87\x5b\x3b\xf6\xcb\xfd\x41\x1b\x7b\xdb\x7f\x39\x73\x32\x25\x03\x04\xf6\x86\x92\xfc\x61\x55\x47\xaa\x56\x82\x73\x12\xe3\xcb\x27\x45\x35\xb8\x72\xaa\xc2\x6b\x0d\xaa\x39\xbd\xe0\xe9\x6e\x38\x11\x24\x2d\xad\x50\xf4\x92\x1a\xf3\xc7\xa6\x62\x26\x37\xfc\x77\x9d\xa4\x2e\x5d\x39\xa9\xb3\x85\x77\x73\x1a\xf0\x39\x62\x52\x6e\x75\x32\x5c\xb7\xf0\x6e\x81\xff\xe8\xd8\x16\x93\xce\x6d\xbb\x5e\xd4\x45\x6f\x10\x63\x38\x40\x49\xd0\xf6\x31\xdd\x6e\x21\xe9\x73\x00\xf1\xd6\x80\x4c\x4a\x98\xff\x8d\xa7\x11\xf5\x91\x4a\x17\x51\x9f\xb7\x9a\xee\x04\xa8\xa3\x86\x79\x15\x7c\xe7\x80\x93\x14\xe2\x86\xf1\xf7\xc9\xe7\xcd\x4f\x75\xd3\x2c\x65\x5d\xe1\x0a\x13\x93\x1a\xa7\x6d\x86\xf4\x46\x12\x1e\xc1\xdb\xb6\x67\x77\x3d\xbb\x72\xd3\x84\x95\xe6\xff\xcb\x09\x73\x7d\x93\x31\x92\x58\xaf\x28\x43\x85\xa9\xb5\x72\x38\xd9\x5c\x75\x09\x95\xed\xd8\x45\x05\xed\x54\xa1\xbc\xf3\x64\xe3\x32\x80\x59\xf7\xde\x56\xdf\x4b\xb7\x43\xb5\x75\x7d\xcc\xe7\x9e\x49\x8f\xf6\x56\x94\x79\x8a\x83\x61\xe8\x25\x22\x4f\x97\x7e\xea\x26\x6c\x0d\x5e\x8d\x2a\xf0\x34\x42\xe6\x6a\x74\x54\x1e\xa3\x2a\xf8\x53\x83\x64\x46\xbf\xa9\x0d\x60\x55\x7a\x43\x88\x20\x47\xbf\xf4\x3e\x9f\x54\x49\xf1\x67\xb3\xe4\x50\xcf\x46\x40\xbd\x49\xf6\x4b\x28\x50\x1f\x68\x25\xd3\x8a\xa0\x6d\x61\x3b\x47\x9a\xab\x29\xd4\x30\xe7\x33\x31\xc8\x17\xaf\xab\x2a\x7b\x45\xb4\x24\x1b\xbb\xec\xef\x20\x90\x90\x3a\x32\x5c\x33\x20\xcd\x18\x82\xf3\x4d\x5b\xda\x2c\x7e\xaa\x1f\x62\x5a\x1e\x9b\xf3\x8d\xad\x3b\xa7\x8d\x0c\xcc\xbb\x0e\xb9\x29\x50\xf7\x20\xbf\x70\xcd\x11\xed\x5a\x2d\xbb\x48\xbb\x54\x2b\xdd\x07\xcb\x49\x80\x07\x55\xa5\x63\x1a\x45\x21\x36\xe5\x35\xe4\x4a\x4f\x1d\xcc\xe0\x75\x5a\xf4\x92\x96\x22\x2a\x39\x78\x92\x94\xb7\x7c\x3a\x06\x05\x30\x52\x3a\x9c\x5b\x36\x48\x6a\x75\xd4\xc0\xb2\x90\x5a\x51\xff\x41\xe3\xde\x60\x8b\x23\xa0\xab\xe2\x72\xab\x7a\x4d\x89\x20\xb8\x84\xb9\xaa\x91\xdd\x97\x87\x46\x4a\x65\x72\x44\x51\xb8\xb3\x63\xee\x26\x29\xf6\x02\x73\xd2\x45\x1f\x21\x95\x42\xd9\x9a\x90\xe1\x5d\xb6\x69\x43\xc1\xb8\xa1\xb7\x4a\x79\xa9\xa6\x20\x01\xd5\x32\x6a\xb5\x11\x40\xe7\x70\x6f\x68\x18\x6f\xd1\x29\xf1\xd9\x2e\x12\xfb\x3d\x96\x35\x30\x66\x6f\xe7\x95\xde\xf5\xda\x3d\x99\x6e\xfe\x66\xcb\xdf\xa0\xdd\xec\xa4\xcb\xee\x4c\x43\xe8\xea\x1a\xd3\xad\x9b\x6c\x29\xeb\xe6\x74\x8d\xd7\x70\xb9\x13\x2d\x7d\x28\x15\xad\xd2\xf5\xfb\xdd\xb3\x1a\x9c\x2f\x37\x8c\xc6\xeb\x4d\x14\x57\x5a\x22\x0d\x08\xdf\xc0\xa7\xd5\x21\x4c\x66\x1d\xa9\xe8\x18\xcc\xc1\x6b\x73\x35\xca\x3c\x66\x11\xe5\x08\x2c\x16\x27\x63\xfd\xc5\x8b\xea\x2f\xcc\xf6\xcc\x04\x5b\x6b\x5b\xcf\x66\xed\x6f\xf0\x7a\x03\x44\x32\xf4\x42\x04\x0e\xa6\x87\x06\xac\xca\xd9\x91\x66\x23\x0a\x80\x64\xce\xa4\x67\xee\xdb\x4f\x8e\x69\x18\x80\x9f\x4e\xcc\x63\x61\x1f\xa7\x74\x05\xc9\x29\x89\xfc\x6c\xd8\xc0\x99\x75\x54\x88\x97\xa9\x22\x56\xbe\xd1\x8b\x26\x8d\x3a\xd2\x2f\xdb\x13\xa6\x87\xa5\x9e\xdc\x24\xcd\xb6\xe2\x7e\xb9\x55\x4a\xe5\xdc\x97\xa2\xfc\x65\x43\xc2\x67\xd4\xdb\x3a\x7a\xd1\x24\x36\x66\x1d\x95\x42\x62\x8a\x2d\xa5\xf6\xa3\x87\xc5\x47\xdc\x2f\x3f\x12\xf7\x72\x3d\x52\x1a\xb3\x56\xe5\x78\xae\x8d\x51\x70\x18\xb9\xd5\xee\xff\xaa\x83\x85\x9a\xe3\x69\x87\x03\xce\xe1\xcf\x73\x8b\xd5\xc2\x2e\xa3\xec\x0b\xae\x75\x14\x14\xad\xd7\xc2\x01\x4b\x9e\x84\xa3\xea\x8d\x5f\xb5\x07\x73\x4f\xf0\x50\xd5\xb9\xa9\x5b\x94\xba\xf5\x52\x8d\xca\xad\x56\x85\x6e\x1d\x5b\xa7\x06\xf6\x79\xab\x9a\xb8\x34\x2b\xe3\x0b\xaa\x0f\xd5\x9d\x8e\x43\xf7\x91\x68\xdd\x89\x52\xe6\xdd\xd2\x1d\xdb\x51\x7d\x4a\x58\x79\xda\x52\xdc\xb3\x97\x6d\xe0\x2a\xeb\xaf\xfa\x40\xa0\xda\x8f\x62\x5e\xf4\x8b\xd8\x67\x28\x62\x88\x23\xa2\x2f\x76\x39\x7d\xb3\xf0\xb2\x35\xf9\xf5\xde\x40\xc5\x4e\x2b\x15\x23\xed\x3c\x29\xd7\xe5\xb6\x22\x8a\xa4\x90\xc7\x48\x27\x08\x06\x4a\xcc\xdf\x2a\xd7\x3f\x63\x19\x02\xef\x8f\xd1\xb8\x27\x04\x54\xff\x49\x60\x35\x12\x0c\xfb\xfc\x98\x86\x72\xfe\xf3\x5e\xa8\x8a\xc8\xea\x35\x83\x24\x0e\xa1\x5c\xd5\xcd\x03\xac\xb3\x8d\xba\x5c\xb9\xa1\xd1\xbc\x57\x9f\x41\x47\x1d\x92\x1d\x99\x03\xe3\x41\x98\x51\x55\x4b\x5a\xea\xeb\xc3\xed\x0e\x57\xef\x37\xc6\xaa\xce\xd7\x7b\x3f\x77\xfd\xfa\x70\x01\x8e\xe9\x74\x7a\x90\x7b\x66\x4c\x7e\xc2\x2c\x85\xf0\x90\x46\x57\x68\xd6\x0c\x63\xd0\x30\xc6\x26\xa8\x5f\x8d\x8e\x1c\x94\x2b\x57\xe0\x78\xcc\x3b\x78\xcc\x3b\x78\xcc\x3b\x78\xcc\x3b\x78\xcc\x3b\x78\xf8\x79\x07\x75\x16\x0d\x68\xed\x5f\x2d\x43\x6b\x6d\x4d\xec\xd9\xd9\x3c\xa6\x45\x3c\xa6\x45\x3c\xa6\x45\x34\x9c\xd5\xc7\xb4\x88\x46\x64\xea\x99\x16\xe1\x87\x90\x73\xec\xff\x4c\x61\xf0\x12\x86\x72\x1b\xcf\xce\xe1\xf6\x0b\x72\xdb\xd4\x5c\x00\x89\x80\xaa\x43\xbd\x34\x48\x71\x53\x5e\x32\x56\x85\xa9\xf5\x7e\xa2\xfd\x19\x55\x6b\xe0\x15\x34\x53\x91\x37\x27\xe7\x95\x07\x30\x0d\xec\xce\xf7\xc7\xda\x46\x86\x41\xc0\x10\xaf\xbe\x21\xcb\xde\x13\xa5\xfb\xf4\x02\xc2\x3d\xd3\xe4\x69\x5a\x59\xf7\xe4\x7c\x01\x42\x4a\xaf\xf3\x7e\xb7\xfd\xf4\xd8\x1b\x3a\x53\xdd\xfb\xd5\xe8\x28\x3f\x02\x15\x27\xe3\xc4\xc8\x4d\x44\xab\xe9\x2f\x62\x22\x70\xaf\xeb\x86\xb2\x77\x15\x30\x0d\x0d\x3c\x39\xbe\x98\x3d\xcd\x06\x5a\x26\xfd\x71\x5b\xf9\x95\xe4\x7d\x91\xed\xee\x44\x68\xdb\x8f\x9b\x06\x51\x7c\xcc\x50\x80\xcb\x07\xc3\x2d\x46\x9f\x39\x8c\x7c\x7f\xf9\x02\xbc\x23\xa1\x14\x9c\x28\xe8\x96\x12\xb2\x8c\x19\x17\x70\x19\x22\x2f\x42\x4c\xed\x95\x89\x8f\xbc\xe4\x04\xdc\x8b\x2d\x78\x6f\x4b\x03\xa4\x9d\x02\x63\x70\xa3\x36\x0f\x94\x84\x3b\x45\x83\x4b\x4f\xe2\x9f\x9e\x9b\x77\x3d\x5c\xed\x97\x57\xd2\x61\x28\x57\xa3\xa3\x2c\x09\xf5\xde\x75\xdf\xe0\x9c\x53\xfb\x98\x6e\xf6\x98\x6e\xf6\x98\x6e\xf6\x98\x6e\x56\x41\xd9\xc7\x74\xb3\xc7\x74\xb3\xaa\x53\xe1\xc7\x74\xb3\xff\xd0\x74\x33\x7e\x82\xb9\x76\x0c\x38\x5c\x51\xfb\x58\xc3\x09\xc3\xd9\xdd\x75\xbc\x44\x21\x12\xa7\xea\x3e\xd6\x16\x81\x73\x85\x5a\xad\x0d\x36\x27\xf8\x0f\x04\x3e\x9a\xee\x3e\x26\xf5\x71\x73\x9e\x7f\xfc\x07\x26\x6b\x4f\x6c\x90\x67\xbe\x9b\xb4\x93\xe9\x15\x07\x0a\x65\xb0\xc9\x7e\x43\x22\xa5\x9d\xb0\xe6\x95\xf5\x43\xa7\x45\x6a\xff\x63\x13\xe1\x1e\x53\xbd\x1e\x53\xbd\x1e\x53\xbd\x1e\x53\xbd\x1e\x53\xbd\xfe\x83\x53\xbd\xee\x29\x01\xea\x31\x5f\xe8\x31\x5f\xe8\x31\x5f\xa8\x29\xf5\x1f\x34\xee\x9d\xf3\x85\xdc\x2b\x5e\x7f\xfb\xab\x54\x1f\x7b\xb2\x26\x1e\x40\xc2\x8f\x80\x6c\x8d\x84\x9a\x83\xe9\xc5\xf9\x43\x38\x67\xd2\x18\x19\xfb\x65\xd8\x53\xa6\x46\xa0\x9d\x64\x7a\xcc\x8b\xaa\x33\x61\x6a\x60\x3c\xe6\x45\x3d\xe6\x45\x3d\xe6\x45\x3d\xe6\x45\x3d\xe6\x45\x3d\xe6\x45\x81\xc7\xbc\x28\xf0\x98\x17\x95\x21\xdb\x17\xc9\x8b\xca\xbb\xf4\xf3\x93\x5c\x8e\x39\xcd\xbc\xcf\x84\x87\x64\x9f\x56\x45\x6c\xd5\x18\xd9\xe5\x8d\x45\x95\xa9\x99\xeb\x28\x09\x73\xaa\x3f\x7d\xc8\xb6\x29\x46\xf5\x98\x57\x43\xdc\xbb\x93\xbf\xc5\x32\x8d\xc1\x04\x62\x03\x85\xba\x0f\x26\xd9\x63\xab\xbb\x29\xcb\xbb\x9a\x66\x77\xf2\x74\xef\x47\x75\x53\x4a\x24\x79\xe9\x8e\x2d\xac\x4c\x14\xd1\xbc\x35\x0d\xb6\x98\xa4\xe1\xd0\x5d\x0c\x62\x1b\x10\x38\xf8\xf1\x50\x72\x2d\x0d\x24\x3b\xf0\x3e\xbb\x46\x92\x20\x44\xe7\x35\x8a\xd9\x2f\x3d\xca\x73\x7f\x4f\xbe\xca\x74\xe2\xd1\x95\x67\x21\xb5\xdb\xf7\xe7\x50\xab\xbd\x23\xb1\x13\x32\x57\xa3\x23\xe7\x70\x0b\xa7\x4e\xad\x34\xb0\x73\xbe\x5d\xd3\x38\xe0\x5a\x52\x5e\xe5\x1c\x9f\x97\x82\x46\x97\x50\x5a\x6a\xae\xad\x60\xb3\x65\xd4\xa9\x0b\xf7\x0a\x9a\x4d\xcf\x9a\x2c\x1c\x28\x04\xf4\x37\x73\x15\x8b\x7d\xef\xbe\x05\xe7\x8a\x4b\xed\x1b\x75\xef\xf6\xf4\xe2\xbc\xcf\x79\xf2\x05\x1d\x04\x44\xdf\xa0\x02\x09\x63\x8e\xd8\x16\x73\x69\x72\xf3\x97\x34\x26\x01\xdc\x7b\x99\x9e\x13\xe4\x2d\x16\x9b\x69\x10\x50\x32\xb7\x77\x60\xb6\x0e\xa0\xc8\x37\xef\xb8\xe4\x4a\x9c\x52\x3f\x87\x35\x73\x53\x47\xf3\x16\xb4\xac\xa5\xd1\x80\xeb\x5e\x85\x9e\x4d\xcf\xb2\x5a\x8d\xae\x00\x4c\xd7\x60\xcb\x45\xbe\x1f\x5e\xe5\x8a\xae\xe2\x83\xea\xe5\x1d\x2e\x67\x64\xcd\x10\xaf\x8c\x96\xad\xd5\x86\x30\x8a\xce\x50\xf9\x10\xa5\x4b\x3c\xdc\x2a\x0e\x43\x7b\xb4\x21\x28\x98\x1a\xc8\xad\x4e\x00\xeb\x41\xd5\x8d\x60\xce\xd0\x0d\x46\xb7\xf7\x37\x10\x60\x7b\x18\x6e\x40\x09\x48\xf7\xc0\x62\x41\x17\x3e\x0c\xf7\xdb\x39\x4d\x06\x95\xdc\xb1\xab\xe3\x75\x6d\xec\xba\x4d\x1c\x69\x7b\x54\xdb\x18\xaa\x73\x68\x3e\x62\x42\xdf\x68\x36\xc8\xd8\xa4\x52\x35\xfb\x6d\x65\x7c\x06\x01\x60\xc8\xa7\x2c\x50\xc4\xbe\xa0\xb1\x40\xe0\x9b\x17\x00\x13\x40\xa5\xd4\x53\x07\x4f\x34\xbc\xd1\x17\xb0\x9f\x9c\x2f\x9e\x1d\x02\x7f\x03\xc3\x10\x91\x35\x3a\x00\x67\x94\x21\x80\x49\x9a\x12\x6d\x1c\x35\x2b\x29\x96\xc0\xfb\x0d\x62\x28\xb5\xe3\xe4\x48\x4c\x5d\x02\x76\x80\xa9\x8a\xb9\x9c\xe4\x14\xfc\x04\xfa\x5b\x34\x09\x08\x7f\x76\x38\x61\x12\x95\x6f\x5e\x4c\xbe\xe2\x48\x78\x71\xe4\x41\x0f\xc3\xad\xc7\x68\x88\xba\xc5\x7c\x7e\xce\x81\x97\xcd\xc6\xa1\xc6\x7e\x35\x3a\x92\x44\xad\x8e\x51\x52\x29\xea\xbf\x42\xe1\xef\x95\x53\xce\xe6\x68\xb9\x57\x36\x36\xe5\x32\x82\x6e\xc1\xe9\xcb\x05\x38\x5e\xcc\xc0\x93\xd3\x10\x72\x81\x7d\xf0\x32\xa4\xfe\x35\x58\x08\x49\xbe\xc4\x56\x55\x7f\xc3\x35\x02\x33\x22\x10\x5b\x41\x1f\x3d\x05\x01\xc3\x37\x1d\x17\xda\x60\x9d\xbb\x29\xb4\xea\xa6\x3d\xd0\x9d\x40\x8c\xc0\xb0\x26\xe9\xa7\x09\x85\x61\x60\x2c\x63\x0b\xcf\x0b\x08\x07\x11\xa3\xff\x42\xbe\x48\x6e\x06\x57\x12\x46\xe7\xf9\x26\xac\xdd\x8a\x96\x3d\xba\x71\x8e\x7e\xc5\x2b\x83\x4a\x6b\xa9\x86\xb7\x70\x8d\x5e\xc6\x38\x0c\xfa\x89\x3f\x15\x96\xac\xf1\x55\xfa\xe5\xf4\xf8\x22\xe5\x8b\x94\x17\x2e\xd0\x1a\x73\xc1\x76\x4f\x8d\x02\x3a\x00\x97\x1b\xcc\x01\xe6\x20\xe6\x68\x15\x87\x0a\xc0\x52\xa2\x83\xc9\x7a\xac\xfe\x32\x17\xdd\x8f\x01\x04\xc7\x33\x95\x9b\x20\x85\x87\xdc\xe8\x13\x84\xb4\x70\x89\x62\xbe\x01\x6a\x24\xea\xcf\xd3\xe3\x8b\x76\x73\xf1\xc0\x70\x77\x4e\xd4\xdd\x05\xac\x34\xe8\xcb\x33\xdc\xca\xd6\xce\xf1\x80\x5b\xe9\x57\xac\xb3\x0a\x35\xea\xb0\xe9\xaa\x8d\xa4\x82\x70\x2c\xf0\x74\x41\x30\x8c\x9d\xc6\x66\x91\x4c\x6e\x71\x7d\x1f\x46\xba\xb4\x90\x93\xd5\xda\xd5\x32\xcf\x03\xa9\x30\xc7\xf7\x44\x30\x57\xdd\x1e\x9c\xab\xfc\x54\xa2\x40\x95\x21\xef\x1b\x67\xfe\x05\x32\x09\x98\x43\x44\xac\x59\xa0\x80\x19\xa8\x2a\x66\xad\x2e\x41\x24\x9b\x49\x8c\xfc\xe7\x93\x98\x23\xb6\x56\x29\x22\x16\x96\x67\x61\x99\x44\x37\xb5\xea\x54\xe9\xe7\x6e\xa9\x6d\xa5\x28\xb6\x41\xd1\xbb\x1a\x1d\xb9\x88\x90\x04\xb5\xd5\x21\xde\x2c\xb2\xed\xf3\xdd\xab\xe2\xec\x7e\x0b\xef\xe6\x0c\x57\xb3\x8b\x4e\x5a\xa9\x1c\x18\x25\x20\x40\x5b\x48\x02\x10\x29\x28\xce\x3e\x28\x39\x51\xdf\xbc\x84\x1c\x35\x4d\xde\xab\xe8\xd0\x7d\x64\x6e\x3b\x98\x23\xe6\x23\x22\xe0\x1a\x4d\x97\xf4\x06\xf5\xe8\x2f\xc7\x62\x17\xea\xfe\xf4\xf7\xcf\xbc\xc3\x67\xcf\x3e\xb4\x62\xce\x9a\x96\xe9\x98\x0e\x9f\xb9\x47\x25\x79\x6b\x1a\x86\xd4\x57\xc6\xf0\x42\x30\x28\xd0\xba\x93\x8b\x48\x42\xb2\xe2\x68\x4e\x69\x39\x60\xbf\x03\x35\x0e\xbd\xe7\xdd\x88\xe1\x68\x98\xd2\xe2\x79\x57\x85\x58\x55\x2f\x2f\xe1\xef\x7d\xfc\xd8\x92\x9d\x6a\xa9\xbb\x7f\x12\xc7\x75\x92\x7b\x40\xb5\xe7\x76\x18\xbf\xcf\x8b\xad\x24\x0c\x59\x3e\x4e\x93\x79\x27\xcd\x2b\x93\xd5\x75\x56\x8a\x2f\x2e\xf4\x72\x35\x3a\xca\xa3\x53\x53\x3f\x6c\xf1\xba\x99\x57\x4b\xb9\x22\x67\x27\x5f\x2e\x12\x4e\x63\x80\x38\x48\xa7\x0e\xd8\x33\x6b\x1d\xa2\xc6\xfb\x05\x0a\x76\xea\xc0\x29\x1c\x6e\xb1\xd8\xfc\x4c\x7d\x18\xf6\xda\x4c\x28\x74\x00\x2c\xe0\x00\x24\xe3\x87\x1a\x91\x6c\xa4\x32\x38\xa7\xc2\xde\x9a\x6f\x42\x57\x4a\xd5\x19\xdb\x99\x01\xf7\x8f\x40\x2a\xa4\x04\x8b\xdd\x39\xc2\x92\x94\x8b\x0d\x64\xfd\xf2\x58\xcd\x50\x54\x95\xbf\xfc\x60\xb8\x82\x0d\xe0\x96\x92\xb5\x32\x46\x53\x5c\x75\xc2\x68\xb7\xcc\x89\xe1\x3b\xac\xa2\x55\x2b\x99\x9e\xae\x62\x37\x89\x9d\x3c\x3c\x88\xec\xf4\x29\x11\x8c\x86\xbc\xb4\xa2\x6a\x02\xf9\x9b\x1c\xa2\x36\x85\x59\x21\xfc\x16\x3f\x35\x73\xe9\x87\xb4\x97\x23\x7b\xb6\x02\x52\x63\xdd\xca\x7d\xb2\x9c\x3e\x35\xcd\x8b\xc5\x4f\x05\xd9\x1e\x31\x7a\x83\x03\x14\x98\xed\x74\x30\x06\x54\x6c\x10\xbb\xc5\x1c\x01\x2c\xe4\x53\xbc\x26\x94\xa1\xe0\x00\xbc\x25\xe1\x0e\x50\x82\x00\x5d\x81\x79\xbc\x0c\xb1\xff\x06\xed\xe6\x50\x6c\xc6\xe9\x9f\x2a\xe0\x3b\xf9\xeb\x1c\x6e\x91\x75\x20\x26\x11\xb0\xed\x72\xaa\x1e\xf0\x30\xdc\xde\x30\xb5\x91\x59\xf0\x52\x02\x74\xfb\x9d\x5b\xc9\xb5\xfb\x5e\x8e\x9b\x12\x41\x4d\xee\x44\xcc\x31\x59\x83\xc5\xe2\xec\xc3\x93\x09\x96\x7c\x19\xc4\x2a\x52\xe6\x2b\xce\x37\x9e\xf6\x95\xb4\x73\x29\x57\xf4\x9b\xd1\xfd\x15\xdd\x5c\x8d\x8e\xaa\x70\xab\xf6\xe8\x46\x96\xbe\x3d\x82\x5b\xf5\x1c\x81\x6b\xa4\x10\x5d\x22\xa9\x48\xd3\xa4\x04\x8d\x8a\xc4\xec\x1a\xed\xfc\x0d\xc4\xe4\x00\x64\x19\x4a\x89\x0f\xbd\x6c\x6f\x60\x18\xa3\x2c\x9f\xb4\x22\xdc\x3d\xa2\x51\x4f\xba\x06\x27\xd8\x0d\xc9\x47\x24\x93\x63\xa2\xd2\x34\x1e\x08\x29\xef\x13\xa5\x7a\xb2\x4a\x71\xd0\x83\xac\x97\x1b\x04\x22\x28\x36\x16\x53\x89\x63\xd4\x8b\x45\x8c\xe8\x4b\x86\x62\x54\xb3\xb2\x0e\xaf\x46\xff\x6f\x72\xc0\xf9\x66\x82\x83\xdf\x19\x87\x07\x51\xbc\xbc\x1a\x65\x05\xa0\xec\xa0\xdf\xa4\x7c\xde\x01\xe9\xa8\xe3\xd2\xa0\xf4\xe3\xfd\x03\x73\x6f\x9e\x55\x3e\xd2\x22\x1b\x70\x3a\xbb\xe7\x4c\xda\xae\x06\x93\xd2\xfc\x95\x5c\xe9\x14\xa0\x95\xa2\x61\x3f\x05\x9c\xba\x6b\xc0\xbd\xab\xb4\x37\x95\x4d\x9a\xe6\x3c\xe6\x55\xb7\x8a\x14\xec\x13\x65\xd1\x06\xba\xdb\x26\xd3\xd7\x46\x35\x09\x40\x5c\xad\x90\xdf\x30\x3d\xfd\xfa\x3b\x7e\x80\xe9\x27\x18\xe1\x4f\x3e\x65\xe8\xd3\xcd\xe1\x81\xea\xe7\x54\xc3\x70\x72\xe9\xf5\x5e\x65\xe8\x6c\xa6\xd6\x40\xe3\x86\xad\xb8\xf1\x3a\xcf\x5d\xba\xa7\x71\x89\x22\x83\x30\x4c\xb6\xd8\x3f\x78\x13\x2f\x11\x23\x48\x45\x97\xaa\xe9\x69\xca\x18\xf5\x50\xdc\x0c\xf0\xce\x9d\x53\x56\xc9\x07\x5b\x78\xf7\x8e\x98\x10\xff\xb0\x57\x56\x12\x47\x22\xa9\x33\x94\xa9\x2d\x64\x92\x63\x37\x50\x18\xc3\xd3\xa7\x5b\x04\xe2\xb4\x4f\x70\xbb\x41\x44\x27\x91\x49\x43\x2b\x13\x6b\x0b\x9e\xd8\x3a\x04\x01\x80\xdc\xc0\x6c\x67\x07\x7e\x36\xa4\x9c\xdc\x9c\x27\x6e\xea\xbe\x7b\xd0\x64\x8e\x12\x34\x1f\x18\xa9\xb3\x88\x75\x94\x01\x05\x6e\x6f\x32\x55\x83\x6d\xe0\x55\xc4\xb2\xdb\x25\x99\x0c\xbe\x4b\x24\x6e\x17\xd8\x39\xd9\xf1\x76\x76\x72\x3c\x0b\x10\x11\x58\xec\xe6\x7a\xf7\xc9\x1a\x5e\x8c\x90\x3d\x37\xe2\x3c\x46\xec\xdd\xc5\xcf\xf9\xb3\x53\x8c\x88\x98\x9d\xb4\x38\x37\xb4\x2d\x3a\x28\x0f\xed\xc0\x38\x0e\x21\xae\xdc\xb3\xee\x6f\xde\xa3\xbc\x56\x42\x81\x0e\x8d\xbb\x96\xd6\xb1\x93\xa3\x46\xfd\xb0\x0b\x1f\x7d\xe9\xba\x07\x7b\x11\x8c\x39\x62\x72\x1e\x3a\x73\x90\x05\xd0\x92\x87\x5a\x89\xb0\x76\xeb\xae\x72\x74\xd5\x58\x57\x2c\xa8\xaa\x85\x52\xcd\x8b\xc5\xa9\x1f\xd0\x14\x57\x86\x72\x84\x7c\x15\x88\x4c\x80\x94\x60\xd6\x71\xc6\xb2\x85\x7a\x4f\xdf\x2c\x00\x8c\xc5\xe6\x0f\xd2\xe1\xe8\xa8\x65\x07\x79\x99\x1a\x21\x06\xf3\x25\xf6\xaa\x1d\xa4\x09\x19\x5e\x85\xf1\xdd\x94\x95\x57\xc9\xe7\x2b\x98\x90\x1e\xde\xf8\x3a\x45\x0f\x84\x98\x20\x00\xd9\x5a\x65\x0c\x59\xef\x30\x02\x12\x55\x10\x40\xb4\xa5\x04\x9c\x9c\xce\x2f\x4e\x8f\xa7\x97\xa7\x27\xad\x0c\x86\xde\x9d\x39\xd7\x60\x4a\xcd\x9f\x50\xb8\xb5\xf3\xf0\x1f\x42\x55\x89\x32\xb0\x38\xdf\x3f\x5d\x2b\xbb\x73\x52\x56\x02\xc3\xc2\x7e\x7e\x06\x09\x5e\x21\x5e\x5d\xd6\xba\x89\x7b\xf8\x58\x81\x54\x3e\x6a\x15\xc5\xa6\x26\x7a\x6b\x21\x5b\x0f\xcc\x6b\x2c\xc0\x05\x8a\x28\xa0\x44\x9f\xca\x86\x61\x57\xda\x0c\xd2\xa1\x93\x3a\x2a\xbd\xb8\x87\xa7\x4d\xf6\xa9\x60\x48\x24\xae\x11\x8a\x80\x60\xd0\xbf\x96\x02\x48\x22\xf9\x37\x0e\xf8\x8e\xf8\x52\x08\xa9\x88\xb5\x7f\x6a\x97\x13\xe6\x40\x0a\xdd\x1b\x18\x22\x22\x64\x4b\x93\x6a\x2b\x0d\x3e\xcf\x5b\x63\xe1\xc9\x56\x9e\x80\x6b\x35\x66\xfd\x88\x50\x81\xb8\xc7\xd0\x0a\x60\xa2\x29\xd0\x91\x9a\x0f\x05\xe7\x4a\x8b\x8a\x47\xb0\x3a\x94\xa8\xc1\xa4\x1c\xeb\xc3\x44\x90\xc0\x92\x9b\x15\xa6\xea\x5a\x5b\xbe\x50\xb8\xe8\x6b\xf9\x8a\x0b\x0a\x1d\xac\x0f\xc0\xaa\x07\x7d\xef\xa1\xfb\x0a\x23\x12\x06\x6f\x49\xf5\x15\x5b\x8d\x4e\xe9\x08\x17\x2c\xf6\x85\xc6\x48\x50\x20\x81\x7a\xaa\xa2\xfa\x96\x06\xba\x7e\x92\xae\x46\xac\x50\x0d\x50\x14\xd2\x9d\xf2\xb9\x42\x9e\xf9\xb6\x23\xa5\xee\xb9\xf7\x66\xa1\x73\xb7\x58\x6c\xe4\x14\xf4\x25\xa3\x75\x05\x0e\xa2\x0d\x1a\x01\xec\x68\x8b\x56\x69\x84\x92\x58\x74\x2e\x4b\x17\xe5\x5c\x4c\xe9\x54\xee\x89\xa9\xd4\x4c\xf5\x0f\x62\x7b\x9a\x03\x72\x49\xcd\xfc\x3e\xdb\xd6\x24\x66\x28\x84\x22\x3d\x39\xa0\x96\xd2\xea\xc6\x8c\x44\x44\xa6\x41\x0a\xc9\xc2\x95\x82\x94\xa1\x88\x72\x2c\x28\xdb\x49\x11\x27\x45\x60\x73\x1f\xc0\xe7\xc7\x2c\x67\xed\xce\x1d\xe5\x4e\x6b\xae\x0e\xa5\x71\xd4\x2a\x5f\xb5\x15\x4f\xa6\xe0\x07\x99\xf3\xb4\x12\x6a\xb9\x0a\x6a\x92\x5a\xd4\x78\x9e\x9a\x41\xcb\xd3\x56\x17\x29\x31\xaa\xa0\xdd\x7e\xe2\x94\x04\x11\xc5\x44\x2c\xf4\x75\x0c\x1d\x2d\xe0\x71\xfe\xad\xb3\xea\x8d\x8d\x93\x2f\x93\x24\x45\x2b\x8d\x75\x2e\xbf\x0c\xe9\x9a\x8f\x72\x0f\x3f\x0c\x60\x78\xa7\xe4\xce\x44\xa5\x21\x43\x14\x7b\x49\x85\x71\x4e\x6e\x63\x2e\xc0\x12\x01\x5b\x07\x5f\xda\xc8\xb6\x7a\xa8\xcd\xd6\xd0\x65\x96\x10\x11\x4c\xc1\x34\xf5\xa7\xf2\x03\xb7\x57\x37\x66\x86\x6b\x1f\xc9\x41\xb6\xbe\xb3\xf1\x33\x8c\x21\x5b\x2a\x29\x3f\x98\x9a\x7b\x11\x33\xe3\xab\xf9\x4a\x0e\xb9\x70\x47\xa2\x53\x75\xa2\xfe\xd7\x2d\xd8\xdc\x32\xa5\xe6\x95\xec\x5b\x01\xa8\xd2\x71\x76\xb6\x5c\x6c\xb7\x3a\xbe\x5d\xe1\xd6\x18\x0d\xad\x24\x1a\x2a\x97\xb3\xa9\x59\xe2\x83\x48\xbd\xec\x2d\x48\x65\x97\xf2\xbe\xd1\xb7\xb9\x63\xa9\x39\xf4\x82\x54\x54\x89\xfb\x4d\xc4\x21\x8d\x45\x14\x8b\x9e\x71\x10\x6f\x15\x10\x10\x60\xa6\xca\x07\xed\x92\x2d\xb4\xbd\xf9\x2f\x90\xbf\x24\x4a\x40\x98\x1b\xcd\x39\x78\xb2\x56\xd5\xd2\x04\x4a\xde\x99\xfd\x78\xbb\x83\x95\x7b\xed\x3b\xc3\xa4\x07\x93\x1f\xff\x1d\x63\xff\x9a\x0b\xc8\x84\x27\x95\xbe\x27\x8d\xb5\x8a\x98\x27\x86\x74\x79\xb6\x1e\x44\xa5\x2b\x35\x8c\xff\x2d\x3b\x05\x0b\xd9\xab\x45\xf6\x00\x1c\xeb\x20\x35\x08\x96\x0c\x12\x7f\x33\x06\x72\x3b\xa8\xae\xde\x52\x1b\xf8\x0d\xe4\x9b\x8c\x01\xdb\x4e\xa4\x0e\xd9\xaf\x93\x36\x3a\x40\xa1\x07\x65\x54\x9c\x1e\x65\xe0\xdd\xc5\xcf\xa0\x1a\xdb\x56\x83\xee\x02\xd2\x24\x1f\xf2\x72\x91\x3b\x18\x45\x5e\x80\x6e\x86\x28\x4e\x67\x88\xe5\x62\xad\xb1\x73\x15\x0f\x6d\xcb\xeb\xcb\x60\xd4\x5d\x37\x10\xa4\x2b\x20\x5d\x54\xd4\x28\x54\x7b\xd9\x5b\xd6\x46\x86\x41\x90\xf5\x1a\xa5\xa6\x72\x27\xe3\xfd\xbe\x50\xc9\xc9\xce\x0b\x14\xd1\x26\x82\x53\xaf\x80\x9e\xc1\x63\x6b\x2c\xcc\x52\x02\x31\x09\x10\xb3\xd5\x22\x0d\xde\x05\xf1\x8f\xa5\xa2\xbd\xc5\x61\xa8\x03\x54\xe5\x92\x93\xbb\x96\xff\x52\xce\x3a\x14\x8c\xb5\x4f\x63\x0b\x55\xdb\x8e\x1b\xe2\xe1\xb0\x82\xdb\xe8\x9f\xfb\x30\x73\x5b\x3b\x5b\x88\xfb\xfa\x0a\x15\x0c\x83\xb7\xc5\xcd\xee\xe6\x8c\xb0\xf2\x37\x90\xac\x11\xef\xe3\xdd\xeb\xd6\x8b\x73\xd0\xab\x30\xbe\x1b\x20\x1a\x31\x55\x83\xd9\x99\x53\x6e\x9f\xba\x69\xbb\x65\x72\xd2\xc8\x38\xf5\x8a\x4d\xfa\x30\xd0\xfd\x60\xe1\xa4\x5b\x04\xc5\xe6\xcb\x9d\x5d\x5c\xa0\x10\x0a\x7c\xa3\x83\x26\xf5\x1d\xaa\x26\xd1\xa2\xe0\x19\xd0\x14\x30\x2f\xde\x46\x3c\xf5\x31\xa8\xc1\x9b\x8b\xb6\x24\xdf\xac\x30\x09\xb2\xe1\x4c\x39\xf7\xbb\x2a\x33\x6e\xe8\xf3\xfe\x4a\x55\x22\xf4\xf8\x8e\x0b\xb4\xbd\x1a\x8d\xc1\xd5\x68\x09\x39\xba\x1a\x7d\xe8\x3a\x77\x5f\x74\x38\x7a\x23\x94\x19\x92\x8d\x03\xd5\xff\xcb\xa1\xe9\x5f\x1f\xf6\x33\x85\x36\x8e\x17\x8b\x9f\xfa\xc7\xf8\xce\x33\xe1\xb0\xd6\xe8\x36\xe1\xae\xf6\xa8\x53\x8e\x24\x16\x1b\x44\x04\xf6\xe5\xeb\x8e\xd4\xef\xd7\x93\x93\x10\x31\xeb\x23\x48\x2f\xcd\xc4\x4b\x24\xa4\x61\x64\x70\x2b\xf1\x81\x9a\x73\x13\x68\x93\xd3\xbb\xb9\xc5\xde\x5a\x8a\xdc\x57\xd7\xd5\x76\xdb\x1a\x8b\xff\x99\xd6\x47\xfc\x81\xb2\xf5\x44\xf6\x58\x61\xc7\x15\x82\x04\x7a\x6a\x2c\x09\xe2\xde\x15\x56\xa7\x4e\x3a\x5a\xae\x92\xf7\xc6\x25\x7b\xa9\x24\xba\x5d\x3a\xb0\x48\xd9\x92\x71\x50\xbb\xd6\x87\xb6\x80\xf7\xfa\x8c\x61\x51\x3c\x26\x77\x40\x6b\xe9\x78\x3f\x9e\xea\xfd\xbd\xe6\xec\xda\x05\xf2\x19\x12\xdc\x54\x3b\x6e\x54\xdc\xe2\x1a\xed\xa6\x17\xe7\xcd\xa3\xd3\xcc\xf7\xf7\x15\x9f\xec\xc4\x65\x78\xff\xcd\x9b\xb3\x05\x40\x09\x95\x92\xb8\x96\x81\xfc\x37\x55\xd0\x73\x73\xf5\x2b\x0a\xc3\x37\x84\xde\xb6\x2b\x0e\x38\x48\x09\x39\x55\x37\x29\x57\x1e\xa9\x5c\xe7\xed\x00\x2c\x10\x02\xef\xd3\x07\x60\xfa\xeb\x02\x04\xd4\xe7\xf5\xe5\x46\xd0\x35\xb7\x97\xd1\x66\x4a\x79\x94\xc1\xab\x4a\x23\xed\x9c\x16\xcd\xd1\x6e\x56\x7a\xa4\x0d\xaa\x57\xa3\x23\x07\x29\x7e\x9c\xc0\xa3\xea\x6a\xf9\x35\xe7\xa4\xf0\x96\x67\x2b\x5b\x1f\xeb\x4c\xd4\xc1\xa7\x55\x27\xee\xa9\x0c\xc0\x5b\xee\x85\x14\x06\x9e\xa9\x68\xc0\x3c\x3f\xe9\xd3\x4c\xb5\x44\x08\x58\x8c\xba\xce\x74\x6d\x3f\x83\xcc\x79\x9b\x31\xf5\xe0\x83\xbd\x03\xb9\x1a\x1d\x95\x29\xd6\x99\x21\x06\x2a\xa0\xa8\xc8\x95\x2d\xe3\x97\xd0\xce\x4c\x72\xee\x5d\x7e\x8e\x3b\x55\xff\xeb\x32\x9d\x35\xf8\x0d\x54\x93\xf0\x6a\x74\x54\x1a\x68\xe7\xa9\x41\x4b\x7e\xbc\x98\xdd\xff\x12\x45\x4b\xee\xf9\x1c\x97\x17\xa6\x64\x45\xfb\x52\x17\xfd\x2b\xcc\x5c\xa6\xdc\xf7\x75\xb2\x0b\xf3\x38\x5e\xf3\x49\xb9\xad\x2d\xd7\xa8\xff\xf2\xa2\xa4\x4c\xef\x80\x2b\xb3\x6a\x28\xb5\x95\xca\x7b\xa0\x2e\xa5\xb3\x9b\x48\xdd\x67\x7d\xf5\x99\x66\x7d\x55\x37\xeb\xab\x9a\x59\x2f\x48\xb1\x65\x48\xd7\x6a\x65\xe8\x4a\x7b\x3c\x49\xef\xc6\x64\x9d\x02\xda\x11\xb8\xc5\xbe\x17\xd9\xab\x65\x30\x59\x0f\x39\xef\x15\x83\x29\xcf\xfb\x50\xc8\xdb\x99\x2f\x13\xaa\xfb\xcc\x0f\x58\x03\x33\x5f\x98\xb2\xa6\x20\xa5\x99\xf4\xdc\xf7\x8d\x17\x79\xb6\x95\x24\xe5\x72\xa2\xbd\xb0\x5a\x58\x8a\x58\x50\x86\x61\xa8\x56\xd4\xc1\x36\xe8\x32\xdf\x2d\xc7\xd1\x6a\x9d\xb7\xc3\xfe\x6a\x74\x54\x22\x52\xe7\xa9\xfe\xd2\x85\x3b\xdb\x4d\xc4\x20\x9d\x0c\x75\x24\xdf\xae\xde\x65\xb5\xbd\x5b\xb1\xf0\x2a\x4c\xa3\x3a\xb5\x5c\x27\xbc\x07\xd9\x52\xaa\xa3\x79\x55\x01\x47\xca\x3b\x9f\x6e\xb7\x94\xa4\x05\xb3\xdb\xd4\xae\xdc\x0f\x29\xb7\x55\x4c\x17\xcf\xa7\x5b\x04\x6f\xd0\x2d\x65\xd7\xfc\x93\xbe\x9b\xfb\x53\x74\xbd\xfe\x14\x0b\x1c\xf2\x4f\x38\x22\x48\x1c\xcc\xe6\xe7\xf9\x0b\x58\x2a\x7c\x54\x25\x1e\x26\x60\x36\x07\x30\x08\x18\xe2\xaa\x94\xd0\xf1\xec\xe4\x02\x10\x2a\xda\xc5\x77\xed\x01\x93\x1b\xd7\x9e\xac\xea\xea\x31\xe4\xa0\xe4\xef\x05\xcd\x34\x2a\x9f\x10\xec\xbb\x78\xe1\x32\x4d\x2b\xce\xae\x03\xf7\x59\x41\x29\x2f\x07\x92\x20\x44\x1c\xc4\x64\x0b\x19\xdf\xc0\x50\x5d\x7e\xb9\xa4\x62\x03\xb6\x30\x7a\xaf\x51\xff\xa0\xff\x53\xa7\x95\xef\x3f\x14\x3a\x6e\x4a\xe3\xfe\x3d\xfd\xc5\x2e\xf8\x3f\xff\xf2\xe7\x5f\xfe\x7f\x00\x00\x00\xff\xff\x6a\x03\x6e\x04\x83\x59\x01\x00") func schemaJsonBytes() ([]byte, error) { return bindataRead( @@ -85,7 +85,7 @@ func schemaJson() (*asset, error) { } info := bindataFileInfo{name: "schema.json", size: 0, mode: os.FileMode(0), modTime: time.Unix(0, 0)} - a := &asset{bytes: bytes, info: info, digest: [32]uint8{0x7b, 0xec, 0xac, 0xa, 0x8e, 0x25, 0x3b, 0x1, 0x19, 0x5f, 0x34, 0x5a, 0x9c, 0xc6, 0x85, 0x5f, 0xe8, 0x92, 0xa4, 0x32, 0x70, 0xaa, 0x45, 0x3e, 0x7b, 0xc4, 0x60, 0x90, 0x63, 0x92, 0xfb, 0x80}} + a := &asset{bytes: bytes, info: info, digest: [32]uint8{0x6f, 0xa9, 0xeb, 0x66, 0x3, 0x7c, 0x9e, 0x0, 0x36, 0xdc, 0xee, 0x21, 0xa5, 0xad, 0xc0, 0x96, 0x2f, 0xfb, 0x70, 0x7, 0x13, 0x63, 0xb1, 0xa4, 0x2a, 0xe3, 0x6f, 0x95, 0xeb, 0x96, 0xd6, 0xb0}} return a, nil } From d37d8c82ca28d27d34d5359d2697441390d8d9a4 Mon Sep 17 00:00:00 2001 From: cpu1 Date: Wed, 3 Nov 2021 14:58:34 +0530 Subject: [PATCH 055/124] Improve validation tests --- pkg/apis/eksctl.io/v1alpha5/validation_test.go | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/pkg/apis/eksctl.io/v1alpha5/validation_test.go b/pkg/apis/eksctl.io/v1alpha5/validation_test.go index f35ff2dc88..968f92c25f 100644 --- a/pkg/apis/eksctl.io/v1alpha5/validation_test.go +++ b/pkg/apis/eksctl.io/v1alpha5/validation_test.go @@ -469,9 +469,7 @@ var _ = Describe("ClusterConfig validation", func() { It("should handle known types", func() { cfg.CloudWatch.ClusterLogging.EnableTypes = []string{"api"} - - err = api.ValidateClusterConfig(cfg) - Expect(err).ToNot(HaveOccurred()) + Expect(api.ValidateClusterConfig(cfg)).To(Succeed()) }) It("should handle unknown types", func() { @@ -479,6 +477,7 @@ var _ = Describe("ClusterConfig validation", func() { err = api.ValidateClusterConfig(cfg) Expect(err).To(HaveOccurred()) + Expect(err).To(MatchError(ContainSubstring(`log type "anything" (cloudWatch.clusterLogging.enableTypes[0]) is unknown`))) }) }) From 843d4ab720eee9afca826f93003f1af7aeea3909 Mon Sep 17 00:00:00 2001 From: cpu1 Date: Wed, 3 Nov 2021 15:03:02 +0530 Subject: [PATCH 056/124] Add example for setting logRetentionInDays --- examples/11-cloudwatch-cluster-logging.yaml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/examples/11-cloudwatch-cluster-logging.yaml b/examples/11-cloudwatch-cluster-logging.yaml index 78e07f0f2a..b2747ac9d2 100644 --- a/examples/11-cloudwatch-cluster-logging.yaml +++ b/examples/11-cloudwatch-cluster-logging.yaml @@ -18,3 +18,7 @@ cloudWatch: enableTypes: ["audit", "authenticator", "controllerManager"] # all supported types: "api", "audit", "authenticator", "controllerManager", "scheduler" # supported special values: "*" and "all" + + # Sets the number of days to retain the logs for (see [CloudWatch docs](https://docs.aws.amazon.com/AmazonCloudWatchLogs/latest/APIReference/API_PutRetentionPolicy.html#API_PutRetentionPolicy_RequestSyntax)). + # By default, log data is stored in CloudWatch Logs indefinitely. + logRetentionInDays: 60 From d4c7db47a2a7d3acc2458934ce54b37715f05bde Mon Sep 17 00:00:00 2001 From: cpu1 Date: Wed, 3 Nov 2021 21:03:58 +0530 Subject: [PATCH 057/124] Fix Windows integration test --- integration/tests/windows/windows_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/integration/tests/windows/windows_test.go b/integration/tests/windows/windows_test.go index dbb5c7cbe0..35ca04152d 100644 --- a/integration/tests/windows/windows_test.go +++ b/integration/tests/windows/windows_test.go @@ -54,7 +54,7 @@ var _ = Describe("(Integration) [Windows Nodegroups]", func() { }, { NodeGroupBase: &api.NodeGroupBase{ - Name: "windows", + Name: "windows20h2", AMIFamily: api.NodeImageFamilyWindowsServer20H2CoreContainer, }, }, From d29c6be884af6d73f45b78a1218155588f304f27 Mon Sep 17 00:00:00 2001 From: Jake Klein Date: Thu, 4 Nov 2021 09:46:41 +0000 Subject: [PATCH 058/124] fix panic in cloudwatch validation (#4409) --- pkg/apis/eksctl.io/v1alpha5/validation.go | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/pkg/apis/eksctl.io/v1alpha5/validation.go b/pkg/apis/eksctl.io/v1alpha5/validation.go index 42444e1fea..44e573a85f 100644 --- a/pkg/apis/eksctl.io/v1alpha5/validation.go +++ b/pkg/apis/eksctl.io/v1alpha5/validation.go @@ -152,7 +152,9 @@ func ValidateClusterConfig(cfg *ClusterConfig) error { func validateCloudWatchLogging(clusterConfig *ClusterConfig) error { if !clusterConfig.HasClusterCloudWatchLogging() { - if clusterConfig.CloudWatch.ClusterLogging.LogRetentionInDays != 0 { + if clusterConfig.CloudWatch != nil && + clusterConfig.CloudWatch.ClusterLogging != nil && + clusterConfig.CloudWatch.ClusterLogging.LogRetentionInDays != 0 { return errors.New("cannot set cloudWatch.clusterLogging.logRetentionInDays without enabling log types") } return nil From 46357fa75dafebc1111833e6cc2cf807efee0670 Mon Sep 17 00:00:00 2001 From: Jake Klein Date: Thu, 4 Nov 2021 10:02:08 +0000 Subject: [PATCH 059/124] bump gjson (#4410) --- go.mod | 6 +++--- go.sum | 12 ++++++------ 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/go.mod b/go.mod index 94655d5e75..d4935c3b49 100644 --- a/go.mod +++ b/go.mod @@ -276,9 +276,9 @@ require ( github.com/subosito/gotenv v1.2.0 // indirect github.com/tdakkota/asciicheck v0.0.0-20200416200610-e657995f937b // indirect github.com/tetafro/godot v1.4.8 // indirect - github.com/tidwall/gjson v1.8.1 - github.com/tidwall/match v1.0.3 // indirect - github.com/tidwall/pretty v1.1.0 // indirect + github.com/tidwall/gjson v1.11.0 + github.com/tidwall/match v1.1.1 // indirect + github.com/tidwall/pretty v1.2.0 // indirect github.com/tidwall/sjson v1.1.7 github.com/timakin/bodyclose v0.0.0-20200424151742-cb6215831a94 // indirect github.com/tj/assert v0.0.3 diff --git a/go.sum b/go.sum index 1349a3c0aa..7f3f920169 100644 --- a/go.sum +++ b/go.sum @@ -299,8 +299,6 @@ github.com/aws/aws-sdk-go v1.36.0/go.mod h1:hcU610XS61/+aQV88ixoOzUoG7v3b31pl2zK github.com/aws/aws-sdk-go v1.36.30/go.mod h1:hcU610XS61/+aQV88ixoOzUoG7v3b31pl2zKMmprdro= github.com/aws/aws-sdk-go v1.37.0/go.mod h1:hcU610XS61/+aQV88ixoOzUoG7v3b31pl2zKMmprdro= github.com/aws/aws-sdk-go v1.40.34/go.mod h1:585smgzpB/KqRA+K3y/NL/oYRqQvpNJYvLm+LY1U59Q= -github.com/aws/aws-sdk-go v1.40.38 h1:kl3iIW0h/JEBFjSBcAxDsiRbKMPz4aI5FJIHMCAQ+J0= -github.com/aws/aws-sdk-go v1.40.38/go.mod h1:585smgzpB/KqRA+K3y/NL/oYRqQvpNJYvLm+LY1U59Q= github.com/aws/aws-sdk-go v1.41.13 h1:wGgr6jkHdGExF33phfOqijFq7ZF+h7a6FXvJc77GpTc= github.com/aws/aws-sdk-go v1.41.13/go.mod h1:585smgzpB/KqRA+K3y/NL/oYRqQvpNJYvLm+LY1U59Q= github.com/aws/aws-sdk-go-v2 v0.18.0/go.mod h1:JWVYvqSMppoMJC0x5wdwiImzgXTI9FuZwxzkQq9wy+g= @@ -1687,13 +1685,15 @@ github.com/tetafro/godot v1.4.8 h1:rhuUH+tBrx24yVAr6Ox3/UxcsiUPPJcGhinfLdbdew0= github.com/tetafro/godot v1.4.8/go.mod h1:LR3CJpxDVGlYOWn3ZZg1PgNZdTUvzsZWu8xaEohUpn8= github.com/thecodeteam/goscaleio v0.1.0/go.mod h1:68sdkZAsK8bvEwBlbQnlLS+xU+hvLYM/iQ8KXej1AwM= github.com/tidwall/gjson v1.8.0/go.mod h1:5/xDoumyyDNerp2U36lyolv46b3uF/9Bu6OfyQ9GImk= -github.com/tidwall/gjson v1.8.1 h1:8j5EE9Hrh3l9Od1OIEDAb7IpezNA20UdRngNAj5N0WU= -github.com/tidwall/gjson v1.8.1/go.mod h1:5/xDoumyyDNerp2U36lyolv46b3uF/9Bu6OfyQ9GImk= -github.com/tidwall/match v1.0.3 h1:FQUVvBImDutD8wJLN6c5eMzWtjgONK9MwIBCOrUJKeE= +github.com/tidwall/gjson v1.11.0 h1:C16pk7tQNiH6VlCrtIXL1w8GaOsi1X3W8KDkE1BuYd4= +github.com/tidwall/gjson v1.11.0/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk= github.com/tidwall/match v1.0.3/go.mod h1:eRSPERbgtNPcGhD8UCthc6PmLEQXEWd3PRB5JTxsfmM= +github.com/tidwall/match v1.1.1 h1:+Ho715JplO36QYgwN9PGYNhgZvoUSc9X2c80KVTi+GA= +github.com/tidwall/match v1.1.1/go.mod h1:eRSPERbgtNPcGhD8UCthc6PmLEQXEWd3PRB5JTxsfmM= github.com/tidwall/pretty v1.0.0/go.mod h1:XNkn88O1ChpSDQmQeStsy+sBenx6DDtFZJxhVysOjyk= -github.com/tidwall/pretty v1.1.0 h1:K3hMW5epkdAVwibsQEfR/7Zj0Qgt4DxtNumTq/VloO8= github.com/tidwall/pretty v1.1.0/go.mod h1:XNkn88O1ChpSDQmQeStsy+sBenx6DDtFZJxhVysOjyk= +github.com/tidwall/pretty v1.2.0 h1:RWIZEg2iJ8/g6fDDYzMpobmaoGh5OLl4AXtGUGPcqCs= +github.com/tidwall/pretty v1.2.0/go.mod h1:ITEVvHYasfjBbM0u2Pg8T2nJnzm8xPwvNhhsoaGGjNU= github.com/tidwall/sjson v1.1.7 h1:sgVPwu/yygHJ2m1pJDLgGM/h+1F5odx5Q9ljG3imRm8= github.com/tidwall/sjson v1.1.7/go.mod h1:w/yG+ezBeTdUxiKs5NcPicO9diP38nk96QBAbIIGeFs= github.com/timakin/bodyclose v0.0.0-20200424151742-cb6215831a94 h1:ig99OeTyDwQWhPe2iw9lwfQVF1KB3Q4fpP3X7/2VBG8= From 7565de70d46cd0930929b834527e5a1368ecb46e Mon Sep 17 00:00:00 2001 From: Gergely Brautigam <182850+Skarlso@users.noreply.github.com> Date: Thu, 4 Nov 2021 12:06:12 +0100 Subject: [PATCH 060/124] Fix wait for managed nodegroups #3889 (#4401) * Fix wait for managed nodegroups #3889 * Refactored the long parameter list --- pkg/actions/addon/update.go | 14 ++-- pkg/actions/addon/update_test.go | 51 +++++++------- pkg/actions/irsa/tasks.go | 13 ++-- pkg/actions/irsa/update_test.go | 15 ++-- pkg/actions/nodegroup/upgrade.go | 9 ++- pkg/cfn/manager/api.go | 46 +++++++------ pkg/cfn/manager/api_test.go | 76 ++++++++++++++++++++- pkg/cfn/manager/cluster.go | 8 ++- pkg/cfn/manager/compat.go | 8 ++- pkg/cfn/manager/fakes/fake_stack_manager.go | 46 ++++++------- pkg/cfn/manager/interface.go | 15 +++- pkg/ctl/upgrade/nodegroup.go | 12 ++-- pkg/managed/service.go | 25 ++++--- 13 files changed, 222 insertions(+), 116 deletions(-) diff --git a/pkg/actions/addon/update.go b/pkg/actions/addon/update.go index 34b3a0fabd..7834e226c2 100644 --- a/pkg/actions/addon/update.go +++ b/pkg/actions/addon/update.go @@ -3,13 +3,13 @@ package addon import ( "fmt" - "github.com/google/uuid" - "github.com/weaveworks/eksctl/pkg/cfn/manager" - "github.com/aws/aws-sdk-go/aws" "github.com/aws/aws-sdk-go/service/eks" + "github.com/google/uuid" "github.com/kris-nova/logger" + api "github.com/weaveworks/eksctl/pkg/apis/eksctl.io/v1alpha5" + "github.com/weaveworks/eksctl/pkg/cfn/manager" ) func (a *Manager) Update(addon *api.Addon, wait bool) error { @@ -101,7 +101,13 @@ func (a *Manager) updateWithNewPolicies(addon *api.Addon) (string, error) { return "", err } var templateBody manager.TemplateBody = createNewTemplate - err = a.stackManager.UpdateStack(stackName, fmt.Sprintf("updating-policy-%s", uuid.NewString()), "updating policies", templateBody, nil) + err = a.stackManager.UpdateStack(manager.UpdateStackOptions{ + StackName: stackName, + ChangeSetName: fmt.Sprintf("updating-policy-%s", uuid.NewString()), + Description: "updating policies", + TemplateData: templateBody, + Wait: true, + }) if err != nil { return "", err } diff --git a/pkg/actions/addon/update_test.go b/pkg/actions/addon/update_test.go index 197da67fd4..8662b4c868 100644 --- a/pkg/actions/addon/update_test.go +++ b/pkg/actions/addon/update_test.go @@ -4,23 +4,19 @@ import ( "fmt" "time" - "github.com/aws/aws-sdk-go/service/cloudformation" - - iamoidc "github.com/weaveworks/eksctl/pkg/iam/oidc" - - "github.com/weaveworks/eksctl/pkg/cfn/manager" - - "github.com/weaveworks/eksctl/pkg/cfn/builder" - - "github.com/weaveworks/eksctl/pkg/cfn/manager/fakes" - "github.com/aws/aws-sdk-go/aws" + "github.com/aws/aws-sdk-go/service/cloudformation" awseks "github.com/aws/aws-sdk-go/service/eks" . "github.com/onsi/ginkgo" . "github.com/onsi/gomega" "github.com/stretchr/testify/mock" + "github.com/weaveworks/eksctl/pkg/actions/addon" api "github.com/weaveworks/eksctl/pkg/apis/eksctl.io/v1alpha5" + "github.com/weaveworks/eksctl/pkg/cfn/builder" + "github.com/weaveworks/eksctl/pkg/cfn/manager" + "github.com/weaveworks/eksctl/pkg/cfn/manager/fakes" + iamoidc "github.com/weaveworks/eksctl/pkg/iam/oidc" "github.com/weaveworks/eksctl/pkg/testutils/mockprovider" ) @@ -287,13 +283,14 @@ var _ = Describe("Update", func() { Expect(err).NotTo(HaveOccurred()) Expect(fakeStackManager.UpdateStackCallCount()).To(Equal(1)) - stackName, changeSetName, description, templateData, _ := fakeStackManager.UpdateStackArgsForCall(0) - Expect(stackName).To(Equal("eksctl-my-cluster-addon-vpc-cni")) - Expect(changeSetName).To(ContainSubstring("updating-policy")) - Expect(description).To(Equal("updating policies")) + options := fakeStackManager.UpdateStackArgsForCall(0) + Expect(options.StackName).To(Equal("eksctl-my-cluster-addon-vpc-cni")) + Expect(options.ChangeSetName).To(ContainSubstring("updating-policy")) + Expect(options.Description).To(Equal("updating policies")) + Expect(options.Wait).To(BeTrue()) Expect(err).NotTo(HaveOccurred()) - Expect(string(templateData.(manager.TemplateBody))).To(ContainSubstring("arn-1")) - Expect(string(templateData.(manager.TemplateBody))).To(ContainSubstring(":sub\":\"system:serviceaccount:kube-system:aws-node")) + Expect(string(options.TemplateData.(manager.TemplateBody))).To(ContainSubstring("arn-1")) + Expect(string(options.TemplateData.(manager.TemplateBody))).To(ContainSubstring(":sub\":\"system:serviceaccount:kube-system:aws-node")) Expect(*updateAddonInput.ClusterName).To(Equal("my-cluster")) Expect(*updateAddonInput.AddonName).To(Equal("vpc-cni")) @@ -357,12 +354,13 @@ var _ = Describe("Update", func() { Expect(err).NotTo(HaveOccurred()) Expect(fakeStackManager.UpdateStackCallCount()).To(Equal(1)) - stackName, changeSetName, description, templateData, _ := fakeStackManager.UpdateStackArgsForCall(0) - Expect(stackName).To(Equal("eksctl-my-cluster-addon-vpc-cni")) - Expect(changeSetName).To(ContainSubstring("updating-policy")) - Expect(description).To(Equal("updating policies")) + options := fakeStackManager.UpdateStackArgsForCall(0) + Expect(options.StackName).To(Equal("eksctl-my-cluster-addon-vpc-cni")) + Expect(options.ChangeSetName).To(ContainSubstring("updating-policy")) + Expect(options.Description).To(Equal("updating policies")) + Expect(options.Wait).To(BeTrue()) Expect(err).NotTo(HaveOccurred()) - Expect(string(templateData.(manager.TemplateBody))).To(ContainSubstring("policy-bar")) + Expect(string(options.TemplateData.(manager.TemplateBody))).To(ContainSubstring("policy-bar")) Expect(*updateAddonInput.ClusterName).To(Equal("my-cluster")) Expect(*updateAddonInput.AddonName).To(Equal("vpc-cni")) @@ -428,12 +426,13 @@ var _ = Describe("Update", func() { Expect(err).NotTo(HaveOccurred()) Expect(fakeStackManager.UpdateStackCallCount()).To(Equal(1)) - stackName, changeSetName, description, templateData, _ := fakeStackManager.UpdateStackArgsForCall(0) - Expect(stackName).To(Equal("eksctl-my-cluster-addon-vpc-cni")) - Expect(changeSetName).To(ContainSubstring("updating-policy")) - Expect(description).To(Equal("updating policies")) + options := fakeStackManager.UpdateStackArgsForCall(0) + Expect(options.StackName).To(Equal("eksctl-my-cluster-addon-vpc-cni")) + Expect(options.ChangeSetName).To(ContainSubstring("updating-policy")) + Expect(options.Description).To(Equal("updating policies")) + Expect(options.Wait).To(BeTrue()) Expect(err).NotTo(HaveOccurred()) - Expect(string(templateData.(manager.TemplateBody))).To(ContainSubstring("autoscaling:SetDesiredCapacity")) + Expect(string(options.TemplateData.(manager.TemplateBody))).To(ContainSubstring("autoscaling:SetDesiredCapacity")) Expect(*updateAddonInput.ClusterName).To(Equal("my-cluster")) Expect(*updateAddonInput.AddonName).To(Equal("vpc-cni")) diff --git a/pkg/actions/irsa/tasks.go b/pkg/actions/irsa/tasks.go index 79a389ea10..c4af6f0478 100644 --- a/pkg/actions/irsa/tasks.go +++ b/pkg/actions/irsa/tasks.go @@ -4,12 +4,11 @@ import ( "fmt" "github.com/google/uuid" - iamoidc "github.com/weaveworks/eksctl/pkg/iam/oidc" - - "github.com/weaveworks/eksctl/pkg/cfn/builder" api "github.com/weaveworks/eksctl/pkg/apis/eksctl.io/v1alpha5" + "github.com/weaveworks/eksctl/pkg/cfn/builder" "github.com/weaveworks/eksctl/pkg/cfn/manager" + iamoidc "github.com/weaveworks/eksctl/pkg/iam/oidc" "github.com/weaveworks/eksctl/pkg/utils/tasks" ) @@ -59,5 +58,11 @@ func (t *updateIAMServiceAccountTask) Do(errorCh chan error) error { }() desc := fmt.Sprintf("updating policies for IAMServiceAccount %s/%s", t.sa.Namespace, t.sa.Name) - return t.stackManager.UpdateStack(stackName, fmt.Sprintf("updating-policy-%s", uuid.NewString()), desc, t.templateData, nil) + return t.stackManager.UpdateStack(manager.UpdateStackOptions{ + StackName: stackName, + ChangeSetName: fmt.Sprintf("updating-policy-%s", uuid.NewString()), + Description: desc, + TemplateData: t.templateData, + Wait: true, + }) } diff --git a/pkg/actions/irsa/update_test.go b/pkg/actions/irsa/update_test.go index bc9774512f..cbec2f442d 100644 --- a/pkg/actions/irsa/update_test.go +++ b/pkg/actions/irsa/update_test.go @@ -5,10 +5,10 @@ import ( "github.com/aws/aws-sdk-go/service/cloudformation" . "github.com/onsi/ginkgo" . "github.com/onsi/gomega" - "github.com/weaveworks/eksctl/pkg/cfn/manager" "github.com/weaveworks/eksctl/pkg/actions/irsa" api "github.com/weaveworks/eksctl/pkg/apis/eksctl.io/v1alpha5" + "github.com/weaveworks/eksctl/pkg/cfn/manager" "github.com/weaveworks/eksctl/pkg/cfn/manager/fakes" iamoidc "github.com/weaveworks/eksctl/pkg/iam/oidc" ) @@ -57,13 +57,14 @@ var _ = Describe("Update", func() { Expect(fakeStackManager.ListStacksMatchingArgsForCall(0)).To(Equal("eksctl-.*-addon-iamserviceaccount")) Expect(fakeStackManager.UpdateStackCallCount()).To(Equal(1)) fakeStackManager.UpdateStackArgsForCall(0) - stackName, changeSetName, description, templateData, _ := fakeStackManager.UpdateStackArgsForCall(0) - Expect(stackName).To(Equal("eksctl-my-cluster-addon-iamserviceaccount-default-test-sa")) - Expect(changeSetName).To(ContainSubstring("updating-policy")) - Expect(description).To(Equal("updating policies for IAMServiceAccount default/test-sa")) + options := fakeStackManager.UpdateStackArgsForCall(0) + Expect(options.StackName).To(Equal("eksctl-my-cluster-addon-iamserviceaccount-default-test-sa")) + Expect(options.ChangeSetName).To(ContainSubstring("updating-policy")) + Expect(options.Description).To(Equal("updating policies for IAMServiceAccount default/test-sa")) + Expect(options.Wait).To(BeTrue()) Expect(err).NotTo(HaveOccurred()) - Expect(string(templateData.(manager.TemplateBody))).To(ContainSubstring("arn-123")) - Expect(string(templateData.(manager.TemplateBody))).To(ContainSubstring(":sub\":\"system:serviceaccount:default:test-sa")) + Expect(string(options.TemplateData.(manager.TemplateBody))).To(ContainSubstring("arn-123")) + Expect(string(options.TemplateData.(manager.TemplateBody))).To(ContainSubstring(":sub\":\"system:serviceaccount:default:test-sa")) }) When("in plan mode", func() { diff --git a/pkg/actions/nodegroup/upgrade.go b/pkg/actions/nodegroup/upgrade.go index 083587c69e..d83f9b9409 100644 --- a/pkg/actions/nodegroup/upgrade.go +++ b/pkg/actions/nodegroup/upgrade.go @@ -4,19 +4,18 @@ import ( "fmt" "github.com/aws/aws-sdk-go/aws" - - "github.com/pkg/errors" - "github.com/aws/aws-sdk-go/aws/request" "github.com/aws/aws-sdk-go/service/eks" "github.com/blang/semver" "github.com/kris-nova/logger" + "github.com/pkg/errors" + "github.com/weaveworks/eksctl/pkg/cfn/manager" "github.com/weaveworks/eksctl/pkg/managed" "github.com/weaveworks/eksctl/pkg/utils/waiters" ) -func (m *Manager) Upgrade(options managed.UpgradeOptions, wait bool) error { +func (m *Manager) Upgrade(options managed.UpgradeOptions) error { stackCollection := manager.NewStackCollection(m.ctl.Provider, m.cfg) hasStacks, err := m.hasStacks(options.NodegroupName) if err != nil { @@ -38,7 +37,7 @@ func (m *Manager) Upgrade(options managed.UpgradeOptions, wait bool) error { return err } - if wait { + if options.Wait { return m.waitForUpgrade(options) } diff --git a/pkg/cfn/manager/api.go b/pkg/cfn/manager/api.go index 14a40f8ba4..f25a723354 100644 --- a/pkg/cfn/manager/api.go +++ b/pkg/cfn/manager/api.go @@ -6,25 +6,22 @@ import ( "regexp" "time" + "github.com/aws/aws-sdk-go/aws" "github.com/aws/aws-sdk-go/service/autoscaling/autoscalingiface" - "github.com/aws/aws-sdk-go/service/cloudtrail/cloudtrailiface" - "github.com/weaveworks/eksctl/pkg/cfn/waiter" - + "github.com/aws/aws-sdk-go/service/cloudformation" "github.com/aws/aws-sdk-go/service/cloudformation/cloudformationiface" + "github.com/aws/aws-sdk-go/service/cloudtrail" + "github.com/aws/aws-sdk-go/service/cloudtrail/cloudtrailiface" "github.com/aws/aws-sdk-go/service/ec2/ec2iface" "github.com/aws/aws-sdk-go/service/eks/eksiface" "github.com/aws/aws-sdk-go/service/iam/iamiface" - - "github.com/weaveworks/eksctl/pkg/version" - - "github.com/aws/aws-sdk-go/aws" - "github.com/aws/aws-sdk-go/service/cloudformation" - "github.com/aws/aws-sdk-go/service/cloudtrail" "github.com/kris-nova/logger" "github.com/pkg/errors" api "github.com/weaveworks/eksctl/pkg/apis/eksctl.io/v1alpha5" "github.com/weaveworks/eksctl/pkg/cfn/builder" + "github.com/weaveworks/eksctl/pkg/cfn/waiter" + "github.com/weaveworks/eksctl/pkg/version" ) const ( @@ -242,33 +239,36 @@ func (c *StackCollection) createStackRequest(stackName string, resourceSet build } // UpdateStack will update a CloudFormation stack by creating and executing a ChangeSet -func (c *StackCollection) UpdateStack(stackName, changeSetName, description string, templateData TemplateData, parameters map[string]string) error { - logger.Info(description) - i := &Stack{StackName: &stackName} +func (c *StackCollection) UpdateStack(options UpdateStackOptions) error { + logger.Info(options.Description) + i := &Stack{StackName: &options.StackName} // Read existing tags s, err := c.DescribeStack(i) if err != nil { return err } - if err := c.doCreateChangeSetRequest(stackName, changeSetName, description, templateData, parameters, s.Capabilities, s.Tags); err != nil { + if err := c.doCreateChangeSetRequest(options.StackName, options.ChangeSetName, options.Description, options.TemplateData, options.Parameters, s.Capabilities, s.Tags); err != nil { return err } - if err := c.doWaitUntilChangeSetIsCreated(i, changeSetName); err != nil { + if err := c.doWaitUntilChangeSetIsCreated(i, options.ChangeSetName); err != nil { if _, ok := err.(*noChangeError); ok { return nil } return err } - changeSet, err := c.DescribeStackChangeSet(i, changeSetName) + changeSet, err := c.DescribeStackChangeSet(i, options.ChangeSetName) if err != nil { return err } logger.Debug("changes = %#v", changeSet.Changes) - if err := c.doExecuteChangeSet(stackName, changeSetName); err != nil { - logger.Warning("error executing Cloudformation changeSet %s in stack %s. Check the Cloudformation console for further details", changeSetName, stackName) + if err := c.doExecuteChangeSet(options.StackName, options.ChangeSetName); err != nil { + logger.Warning("error executing Cloudformation changeSet %s in stack %s. Check the Cloudformation console for further details", options.ChangeSetName, options.StackName) return err } - return c.doWaitUntilStackIsUpdated(i) + if options.Wait { + return c.doWaitUntilStackIsUpdated(i) + } + return nil } // DescribeStack describes a cloudformation stack. @@ -307,9 +307,15 @@ func (c *StackCollection) GetManagedNodeGroupTemplate(nodeGroupName string) (str } // UpdateNodeGroupStack updates the nodegroup stack with the specified template -func (c *StackCollection) UpdateNodeGroupStack(nodeGroupName, template string) error { +func (c *StackCollection) UpdateNodeGroupStack(nodeGroupName, template string, wait bool) error { stackName := c.makeNodeGroupStackName(nodeGroupName) - return c.UpdateStack(stackName, c.MakeChangeSetName("update-nodegroup"), "updating nodegroup stack", TemplateBody(template), nil) + return c.UpdateStack(UpdateStackOptions{ + StackName: stackName, + ChangeSetName: c.MakeChangeSetName("update-nodegroup"), + Description: "updating nodegroup stack", + TemplateData: TemplateBody(template), + Wait: wait, + }) } // ListStacksMatching gets all of CloudFormation stacks with names matching nameRegex. diff --git a/pkg/cfn/manager/api_test.go b/pkg/cfn/manager/api_test.go index 22be024bc6..ea00f184fe 100644 --- a/pkg/cfn/manager/api_test.go +++ b/pkg/cfn/manager/api_test.go @@ -46,7 +46,13 @@ var _ = Describe("StackCollection", func() { p.MockCloudFormation().On("DescribeChangeSet", mock.Anything).Return(describeChangeSetNoChange, nil) sm := NewStackCollection(p, api.NewClusterConfig()) - err := sm.UpdateStack(stackName, changeSetName, "description", TemplateBody(""), nil) + err := sm.UpdateStack(UpdateStackOptions{ + StackName: stackName, + ChangeSetName: changeSetName, + Description: "description", + TemplateData: TemplateBody(""), + Wait: true, + }) Expect(err).ToNot(HaveOccurred()) }) }) @@ -105,7 +111,13 @@ var _ = Describe("StackCollection", func() { spec.Metadata.Name = clusterName spec.Metadata.Tags = map[string]string{"meta": "data"} sm := NewStackCollection(p, spec) - err := sm.UpdateStack(stackName, changeSetName, "description", TemplateBody(""), nil) + err := sm.UpdateStack(UpdateStackOptions{ + StackName: stackName, + ChangeSetName: changeSetName, + Description: "description", + TemplateData: TemplateBody(""), + Wait: true, + }) Expect(err).ToNot(HaveOccurred()) // Second is CreateChangeSet() call which we are interested in @@ -118,4 +130,64 @@ var _ = Describe("StackCollection", func() { // Metadata tag Expect(createChangeSetInput.Tags).To(ContainElement(&cfn.Tag{Key: aws.String("meta"), Value: aws.String("data")})) }) + When("wait is set to false", func() { + It("will skip the last wait sequence", func() { + clusterName := "cluster" + stackName := "eksctl-stack" + changeSetName := "eksctl-changeset" + describeInput := &cfn.DescribeStacksInput{StackName: &stackName} + existingTag := &cfn.Tag{ + Key: aws.String("existing"), + Value: aws.String("tag"), + } + describeOutput := &cfn.DescribeStacksOutput{Stacks: []*cfn.Stack{{ + StackName: &stackName, + StackStatus: aws.String(cfn.StackStatusCreateComplete), + Tags: []*cfn.Tag{existingTag}, + }}} + describeChangeSetCreateCompleteOutput := &cfn.DescribeChangeSetOutput{ + StackName: &stackName, + ChangeSetName: &changeSetName, + Status: aws.String(cfn.ChangeSetStatusCreateComplete), + } + executeChangeSetInput := &cfn.ExecuteChangeSetInput{ + ChangeSetName: &changeSetName, + StackName: &stackName, + } + + p := mockprovider.NewMockProvider() + p.MockCloudFormation().On("DescribeStacks", describeInput).Return(describeOutput, nil) + p.MockCloudFormation().On("CreateChangeSet", mock.Anything).Return(nil, nil) + req := awstesting.NewClient(nil).NewRequest(&request.Operation{Name: "Operation"}, nil, describeChangeSetCreateCompleteOutput) + p.MockCloudFormation().On("DescribeChangeSetRequest", mock.Anything).Return(req, describeChangeSetCreateCompleteOutput) + p.MockCloudFormation().On("DescribeChangeSet", mock.Anything).Return(describeChangeSetCreateCompleteOutput, nil) + p.MockCloudFormation().On("ExecuteChangeSet", executeChangeSetInput).Return(nil, nil) + // For the future, this is the call we do not expect to happen, and this is the difference compared to the + // above test case. + // p.MockCloudFormation().On("DescribeStacksRequest", mock.Anything).Return(req, describeStacksUpdateCompleteOutput) + + spec := api.NewClusterConfig() + spec.Metadata.Name = clusterName + spec.Metadata.Tags = map[string]string{"meta": "data"} + sm := NewStackCollection(p, spec) + err := sm.UpdateStack(UpdateStackOptions{ + StackName: stackName, + ChangeSetName: changeSetName, + Description: "description", + TemplateData: TemplateBody(""), + Wait: false, + }) + Expect(err).ToNot(HaveOccurred()) + + // Second is CreateChangeSet() call which we are interested in + args := p.MockCloudFormation().Calls[1].Arguments.Get(0) + createChangeSetInput := args.(*cfn.CreateChangeSetInput) + // Existing tag + Expect(createChangeSetInput.Tags).To(ContainElement(existingTag)) + // Auto-populated tag + Expect(createChangeSetInput.Tags).To(ContainElement(&cfn.Tag{Key: aws.String(api.ClusterNameTag), Value: &clusterName})) + // Metadata tag + Expect(createChangeSetInput.Tags).To(ContainElement(&cfn.Tag{Key: aws.String("meta"), Value: aws.String("data")})) + }) + }) }) diff --git a/pkg/cfn/manager/cluster.go b/pkg/cfn/manager/cluster.go index ad3b3b392b..03e52e66ac 100644 --- a/pkg/cfn/manager/cluster.go +++ b/pkg/cfn/manager/cluster.go @@ -192,7 +192,13 @@ func (c *StackCollection) AppendNewClusterStackResource(plan, supportsManagedNod logger.Info("(plan) %s", describeUpdate) return true, nil } - return true, c.UpdateStack(name, c.MakeChangeSetName("update-cluster"), describeUpdate, TemplateBody(currentTemplate), nil) + return true, c.UpdateStack(UpdateStackOptions{ + StackName: name, + ChangeSetName: c.MakeChangeSetName("update-cluster"), + Description: describeUpdate, + TemplateData: TemplateBody(currentTemplate), + Wait: true, + }) } func (c *StackCollection) importServiceRoleARN(resources gjson.Result) error { diff --git a/pkg/cfn/manager/compat.go b/pkg/cfn/manager/compat.go index b6c79fd3ee..978c0e197d 100644 --- a/pkg/cfn/manager/compat.go +++ b/pkg/cfn/manager/compat.go @@ -129,7 +129,13 @@ func (c *StackCollection) EnsureMapPublicIPOnLaunchEnabled() error { } } description := fmt.Sprintf("update public subnets %q with property MapPublicIpOnLaunch enabled", publicSubnetsNames) - if err := c.UpdateStack(stackName, c.MakeChangeSetName("update-subnets"), description, TemplateBody(currentTemplate), nil); err != nil { + if err := c.UpdateStack(UpdateStackOptions{ + StackName: stackName, + ChangeSetName: c.MakeChangeSetName("update-subnets"), + Description: description, + TemplateData: TemplateBody(currentTemplate), + Wait: true, + }); err != nil { return errors.Wrap(err, "unable to update subnets") } return nil diff --git a/pkg/cfn/manager/fakes/fake_stack_manager.go b/pkg/cfn/manager/fakes/fake_stack_manager.go index 7a82774855..b8a13a7889 100644 --- a/pkg/cfn/manager/fakes/fake_stack_manager.go +++ b/pkg/cfn/manager/fakes/fake_stack_manager.go @@ -695,11 +695,12 @@ type FakeStackManager struct { stackStatusIsNotTransitionalReturnsOnCall map[int]struct { result1 bool } - UpdateNodeGroupStackStub func(string, string) error + UpdateNodeGroupStackStub func(string, string, bool) error updateNodeGroupStackMutex sync.RWMutex updateNodeGroupStackArgsForCall []struct { arg1 string arg2 string + arg3 bool } updateNodeGroupStackReturns struct { result1 error @@ -707,14 +708,10 @@ type FakeStackManager struct { updateNodeGroupStackReturnsOnCall map[int]struct { result1 error } - UpdateStackStub func(string, string, string, manager.TemplateData, map[string]string) error + UpdateStackStub func(manager.UpdateStackOptions) error updateStackMutex sync.RWMutex updateStackArgsForCall []struct { - arg1 string - arg2 string - arg3 string - arg4 manager.TemplateData - arg5 map[string]string + arg1 manager.UpdateStackOptions } updateStackReturns struct { result1 error @@ -4047,19 +4044,20 @@ func (fake *FakeStackManager) StackStatusIsNotTransitionalReturnsOnCall(i int, r }{result1} } -func (fake *FakeStackManager) UpdateNodeGroupStack(arg1 string, arg2 string) error { +func (fake *FakeStackManager) UpdateNodeGroupStack(arg1 string, arg2 string, arg3 bool) error { fake.updateNodeGroupStackMutex.Lock() ret, specificReturn := fake.updateNodeGroupStackReturnsOnCall[len(fake.updateNodeGroupStackArgsForCall)] fake.updateNodeGroupStackArgsForCall = append(fake.updateNodeGroupStackArgsForCall, struct { arg1 string arg2 string - }{arg1, arg2}) + arg3 bool + }{arg1, arg2, arg3}) stub := fake.UpdateNodeGroupStackStub fakeReturns := fake.updateNodeGroupStackReturns - fake.recordInvocation("UpdateNodeGroupStack", []interface{}{arg1, arg2}) + fake.recordInvocation("UpdateNodeGroupStack", []interface{}{arg1, arg2, arg3}) fake.updateNodeGroupStackMutex.Unlock() if stub != nil { - return stub(arg1, arg2) + return stub(arg1, arg2, arg3) } if specificReturn { return ret.result1 @@ -4073,17 +4071,17 @@ func (fake *FakeStackManager) UpdateNodeGroupStackCallCount() int { return len(fake.updateNodeGroupStackArgsForCall) } -func (fake *FakeStackManager) UpdateNodeGroupStackCalls(stub func(string, string) error) { +func (fake *FakeStackManager) UpdateNodeGroupStackCalls(stub func(string, string, bool) error) { fake.updateNodeGroupStackMutex.Lock() defer fake.updateNodeGroupStackMutex.Unlock() fake.UpdateNodeGroupStackStub = stub } -func (fake *FakeStackManager) UpdateNodeGroupStackArgsForCall(i int) (string, string) { +func (fake *FakeStackManager) UpdateNodeGroupStackArgsForCall(i int) (string, string, bool) { fake.updateNodeGroupStackMutex.RLock() defer fake.updateNodeGroupStackMutex.RUnlock() argsForCall := fake.updateNodeGroupStackArgsForCall[i] - return argsForCall.arg1, argsForCall.arg2 + return argsForCall.arg1, argsForCall.arg2, argsForCall.arg3 } func (fake *FakeStackManager) UpdateNodeGroupStackReturns(result1 error) { @@ -4109,22 +4107,18 @@ func (fake *FakeStackManager) UpdateNodeGroupStackReturnsOnCall(i int, result1 e }{result1} } -func (fake *FakeStackManager) UpdateStack(arg1 string, arg2 string, arg3 string, arg4 manager.TemplateData, arg5 map[string]string) error { +func (fake *FakeStackManager) UpdateStack(arg1 manager.UpdateStackOptions) error { fake.updateStackMutex.Lock() ret, specificReturn := fake.updateStackReturnsOnCall[len(fake.updateStackArgsForCall)] fake.updateStackArgsForCall = append(fake.updateStackArgsForCall, struct { - arg1 string - arg2 string - arg3 string - arg4 manager.TemplateData - arg5 map[string]string - }{arg1, arg2, arg3, arg4, arg5}) + arg1 manager.UpdateStackOptions + }{arg1}) stub := fake.UpdateStackStub fakeReturns := fake.updateStackReturns - fake.recordInvocation("UpdateStack", []interface{}{arg1, arg2, arg3, arg4, arg5}) + fake.recordInvocation("UpdateStack", []interface{}{arg1}) fake.updateStackMutex.Unlock() if stub != nil { - return stub(arg1, arg2, arg3, arg4, arg5) + return stub(arg1) } if specificReturn { return ret.result1 @@ -4138,17 +4132,17 @@ func (fake *FakeStackManager) UpdateStackCallCount() int { return len(fake.updateStackArgsForCall) } -func (fake *FakeStackManager) UpdateStackCalls(stub func(string, string, string, manager.TemplateData, map[string]string) error) { +func (fake *FakeStackManager) UpdateStackCalls(stub func(manager.UpdateStackOptions) error) { fake.updateStackMutex.Lock() defer fake.updateStackMutex.Unlock() fake.UpdateStackStub = stub } -func (fake *FakeStackManager) UpdateStackArgsForCall(i int) (string, string, string, manager.TemplateData, map[string]string) { +func (fake *FakeStackManager) UpdateStackArgsForCall(i int) manager.UpdateStackOptions { fake.updateStackMutex.RLock() defer fake.updateStackMutex.RUnlock() argsForCall := fake.updateStackArgsForCall[i] - return argsForCall.arg1, argsForCall.arg2, argsForCall.arg3, argsForCall.arg4, argsForCall.arg5 + return argsForCall.arg1 } func (fake *FakeStackManager) UpdateStackReturns(result1 error) { diff --git a/pkg/cfn/manager/interface.go b/pkg/cfn/manager/interface.go index ed6485f0e8..a58af13cf2 100644 --- a/pkg/cfn/manager/interface.go +++ b/pkg/cfn/manager/interface.go @@ -4,6 +4,7 @@ import ( "github.com/aws/aws-sdk-go/service/cloudformation" "github.com/aws/aws-sdk-go/service/cloudtrail" "github.com/aws/aws-sdk-go/service/eks/eksiface" + "github.com/weaveworks/eksctl/pkg/apis/eksctl.io/v1alpha5" "github.com/weaveworks/eksctl/pkg/cfn/builder" iamoidc "github.com/weaveworks/eksctl/pkg/iam/oidc" @@ -12,6 +13,16 @@ import ( "github.com/weaveworks/eksctl/pkg/vpc" ) +// UpdateStackOptions contains options for updating a stack. +type UpdateStackOptions struct { + StackName string + ChangeSetName string + Description string + TemplateData TemplateData + Parameters map[string]string + Wait bool +} + //go:generate go run github.com/maxbrunsfeld/counterfeiter/v6 -generate //counterfeiter:generate -o fakes/fake_stack_manager.go . StackManager type StackManager interface { @@ -25,10 +36,10 @@ type StackManager interface { DoWaitUntilStackIsCreated(i *Stack) error DoCreateStackRequest(i *Stack, templateData TemplateData, tags, parameters map[string]string, withIAM bool, withNamedIAM bool) error CreateStack(name string, stack builder.ResourceSet, tags, parameters map[string]string, errs chan error) error - UpdateStack(stackName, changeSetName, description string, templateData TemplateData, parameters map[string]string) error + UpdateStack(options UpdateStackOptions) error DescribeStack(i *Stack) (*Stack, error) GetManagedNodeGroupTemplate(nodeGroupName string) (string, error) - UpdateNodeGroupStack(nodeGroupName, template string) error + UpdateNodeGroupStack(nodeGroupName, template string, wait bool) error ListStacksMatching(nameRegex string, statusFilters ...string) ([]*Stack, error) ListClusterStackNames() ([]string, error) ListStacks(statusFilters ...string) ([]*Stack, error) diff --git a/pkg/ctl/upgrade/nodegroup.go b/pkg/ctl/upgrade/nodegroup.go index 22d170ee85..ffbf47ec71 100644 --- a/pkg/ctl/upgrade/nodegroup.go +++ b/pkg/ctl/upgrade/nodegroup.go @@ -3,14 +3,13 @@ package upgrade import ( "time" - "github.com/weaveworks/eksctl/pkg/actions/nodegroup" - "github.com/spf13/cobra" "github.com/spf13/pflag" - "github.com/weaveworks/eksctl/pkg/managed" + "github.com/weaveworks/eksctl/pkg/actions/nodegroup" api "github.com/weaveworks/eksctl/pkg/apis/eksctl.io/v1alpha5" "github.com/weaveworks/eksctl/pkg/ctl/cmdutils" + "github.com/weaveworks/eksctl/pkg/managed" ) const upgradeNodegroupTimeout = 45 * time.Minute @@ -33,15 +32,12 @@ func upgradeNodeGroupCmd(cmd *cmdutils.Cmd) { fs.StringVar(&options.KubernetesVersion, "kubernetes-version", "", "Kubernetes version") fs.BoolVar(&options.ForceUpgrade, "force-upgrade", false, "Force the update if the existing node group's pods are unable to be drained due to a pod disruption budget issue") fs.StringVar(&options.ReleaseVersion, "release-version", "", "AMI version of the EKS optimized AMI to use") + fs.BoolVar(&options.Wait, "wait", true, "nodegroup upgrade to complete") }) cmd.FlagSetGroup.InFlagSet("General", func(fs *pflag.FlagSet) { cmdutils.AddClusterFlag(fs, cmd.ClusterConfig.Metadata) - cmdutils.AddRegionFlag(fs, &cmd.ProviderConfig) - cmd.Wait = true - cmdutils.AddWaitFlag(fs, &cmd.Wait, "nodegroup upgrade to complete") - // found with experimentation cmdutils.AddTimeoutFlagWithValue(fs, &cmd.ProviderConfig.WaitTimeout, upgradeNodegroupTimeout) }) @@ -82,6 +78,6 @@ func upgradeNodeGroup(cmd *cmdutils.Cmd, options managed.UpgradeOptions) error { return err } - return nodegroup.New(cfg, ctl, clientSet).Upgrade(options, cmd.Wait) + return nodegroup.New(cfg, ctl, clientSet).Upgrade(options) } diff --git a/pkg/managed/service.go b/pkg/managed/service.go index 983dfba82b..be19fec7ad 100644 --- a/pkg/managed/service.go +++ b/pkg/managed/service.go @@ -19,17 +19,19 @@ import ( "github.com/pkg/errors" "github.com/tidwall/gjson" "github.com/tidwall/sjson" - "github.com/weaveworks/eksctl/pkg/version" "github.com/weaveworks/goformation/v4/cloudformation" - "github.com/weaveworks/eksctl/pkg/ami" - api "github.com/weaveworks/eksctl/pkg/apis/eksctl.io/v1alpha5" - "github.com/weaveworks/eksctl/pkg/cfn/builder" - "github.com/weaveworks/eksctl/pkg/cfn/manager" + "github.com/weaveworks/eksctl/pkg/version" + "github.com/weaveworks/goformation/v4" gfnec2 "github.com/weaveworks/goformation/v4/cloudformation/ec2" gfneks "github.com/weaveworks/goformation/v4/cloudformation/eks" gfnt "github.com/weaveworks/goformation/v4/cloudformation/types" + + "github.com/weaveworks/eksctl/pkg/ami" + api "github.com/weaveworks/eksctl/pkg/apis/eksctl.io/v1alpha5" + "github.com/weaveworks/eksctl/pkg/cfn/builder" + "github.com/weaveworks/eksctl/pkg/cfn/manager" ) // A Service provides methods for managing managed nodegroups @@ -60,6 +62,8 @@ type UpgradeOptions struct { ForceUpgrade bool // ReleaseVersion AMI version of the EKS optimized AMI to use ReleaseVersion string + // Wait for the upgrade to finish + Wait bool } // TODO use goformation types @@ -135,7 +139,7 @@ func (m *Service) UpdateLabels(nodeGroupName string, labelsToAdd map[string]stri return err } - return m.stackCollection.UpdateNodeGroupStack(nodeGroupName, template) + return m.stackCollection.UpdateNodeGroupStack(nodeGroupName, template, true) } // GetLabels fetches the labels for a nodegroup @@ -185,12 +189,12 @@ func (m *Service) UpgradeNodeGroup(options UpgradeOptions) error { return errors.New("unexpected error: failed to find nodegroup resource in nodegroup stack") } - updateStack := func(stack *cloudformation.Template) error { + updateStack := func(stack *cloudformation.Template, wait bool) error { bytes, err := stack.JSON() if err != nil { return err } - if err := m.stackCollection.UpdateNodeGroupStack(options.NodegroupName, string(bytes)); err != nil { + if err := m.stackCollection.UpdateNodeGroupStack(options.NodegroupName, string(bytes), true); err != nil { return errors.Wrap(err, "error updating nodegroup stack") } return nil @@ -202,7 +206,8 @@ func (m *Service) UpgradeNodeGroup(options UpgradeOptions) error { } if requiresUpdate { logger.Info("updating nodegroup stack to a newer format before upgrading nodegroup version") - if err := updateStack(stack); err != nil { + // always wait for the main stack update + if err := updateStack(stack, true); err != nil { return err } } @@ -268,7 +273,7 @@ func (m *Service) UpgradeNodeGroup(options UpgradeOptions) error { ngResource.ForceUpdateEnabled = gfnt.NewBoolean(options.ForceUpgrade) logger.Info("upgrading nodegroup version") - if err := updateStack(stack); err != nil { + if err := updateStack(stack, options.Wait); err != nil { return err } logger.Info("nodegroup successfully upgraded") From fbce9194e7f0dd9ac18d528f1f75877ea5abddb0 Mon Sep 17 00:00:00 2001 From: Gergely Brautigam <182850+Skarlso@users.noreply.github.com> Date: Thu, 4 Nov 2021 12:46:48 +0100 Subject: [PATCH 061/124] Unpin and fix containerd integration test (#4411) --- integration/tests/crud/creategetdelete_test.go | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/integration/tests/crud/creategetdelete_test.go b/integration/tests/crud/creategetdelete_test.go index 4346239889..7ae879e277 100644 --- a/integration/tests/crud/creategetdelete_test.go +++ b/integration/tests/crud/creategetdelete_test.go @@ -385,7 +385,7 @@ var _ = Describe("(Integration) Create, Get, Scale & Delete", func() { }) }) - PContext("and creating a nodegroup with containerd runtime", func() { + Context("and creating a nodegroup with containerd runtime", func() { var ( nodegroupName string ) @@ -404,6 +404,7 @@ var _ = Describe("(Integration) Create, Get, Scale & Delete", func() { }) It("should create the nodegroup without problems", func() { clusterConfig := makeClusterConfig() + clusterConfig.Metadata.Name = params.ClusterName clusterConfig.NodeGroups = []*api.NodeGroup{ { NodeGroupBase: &api.NodeGroupBase{ From 9a3e8e7b943362d09d212f3c9edab7ce58dbbb13 Mon Sep 17 00:00:00 2001 From: Weaveworks Bot Date: Thu, 4 Nov 2021 08:34:27 -0400 Subject: [PATCH 062/124] Update aws-node (#4408) Co-authored-by: Jake Klein --- pkg/addons/default/assets/aws-node.yaml | 1 - 1 file changed, 1 deletion(-) diff --git a/pkg/addons/default/assets/aws-node.yaml b/pkg/addons/default/assets/aws-node.yaml index 3e08ab2322..7fae3facb1 100644 --- a/pkg/addons/default/assets/aws-node.yaml +++ b/pkg/addons/default/assets/aws-node.yaml @@ -262,4 +262,3 @@ "maxUnavailable": "10%" "type": "RollingUpdate" ... - From 15eae56fb74aeb47c5ea393f5027fdc50ce7ff70 Mon Sep 17 00:00:00 2001 From: Jake Klein Date: Thu, 4 Nov 2021 15:20:06 +0000 Subject: [PATCH 063/124] pend failing windows test (#4413) --- integration/tests/windows/windows_test.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/integration/tests/windows/windows_test.go b/integration/tests/windows/windows_test.go index 35ca04152d..3fda1ee603 100644 --- a/integration/tests/windows/windows_test.go +++ b/integration/tests/windows/windows_test.go @@ -97,8 +97,8 @@ var _ = Describe("(Integration) [Windows Nodegroups]", func() { createCluster(withOIDC) runWindowsPod() }, - Entry("when withOIDC is disabled", false), - Entry("when withOIDC is enabled", true), + PEntry("when withOIDC is disabled", false), + PEntry("when withOIDC is enabled", true), ) }) From 87a25437a2391cfcd440ba5919e0629d09334ecd Mon Sep 17 00:00:00 2001 From: Adam Malcontenti-Wilson Date: Fri, 5 Nov 2021 02:52:18 +1100 Subject: [PATCH 064/124] Update to kops v1.21.2 (#4380) --- go.mod | 36 +++----- go.sum | 283 ++++++++++++++++++++++++++++++++++++++++++++------------- 2 files changed, 236 insertions(+), 83 deletions(-) diff --git a/go.mod b/go.mod index d4935c3b49..8bcbf286e0 100644 --- a/go.mod +++ b/go.mod @@ -43,8 +43,6 @@ require ( github.com/aws/amazon-ec2-instance-selector/v2 v2.0.3-0.20210303155736-3e43512d88f8 github.com/aws/aws-sdk-go v1.41.13 github.com/awslabs/goformation/v4 v4.15.5 // indirect - github.com/bazelbuild/bazel-gazelle v0.19.1 // indirect - github.com/bazelbuild/buildtools v0.0.0-20190917191645-69366ca98f89 // indirect github.com/benjamintf1/unmarshalledmatchers v0.0.0-20190408201839-bb1c1f34eaea github.com/beorn7/perks v1.0.1 // indirect github.com/bgentry/speakeasy v0.1.0 // indirect @@ -63,7 +61,6 @@ require ( github.com/cespare/xxhash/v2 v2.1.1 // indirect github.com/charithe/durationcheck v0.0.8 // indirect github.com/chavacava/garif v0.0.0-20210405164556-e8a0a408d6af // indirect - github.com/client9/misspell v0.3.4 // indirect github.com/cloudflare/cfssl v1.6.1 github.com/coreos/go-semver v0.3.0 // indirect github.com/cpuguy83/go-md2man/v2 v2.0.0 // indirect @@ -71,7 +68,7 @@ require ( github.com/dave/jennifer v1.4.1 github.com/davecgh/go-spew v1.1.1 // indirect github.com/denis-tingajkin/go-header v0.4.2 // indirect - github.com/denverdino/aliyungo v0.0.0-20191128015008-acd8035bbb1d // indirect + github.com/denverdino/aliyungo v0.0.0-20210425065611-55bee4942cba // indirect github.com/dghubble/go-twitter v0.0.0-20210609183100-2fdbf421508e // indirect github.com/dghubble/oauth1 v0.7.0 // indirect github.com/dghubble/sling v1.3.0 // indirect @@ -93,13 +90,12 @@ require ( github.com/fzipp/gocyclo v0.3.1 // indirect github.com/ghodss/yaml v1.0.0 // indirect github.com/github-release/github-release v0.10.0 - github.com/go-bindata/go-bindata v3.1.2+incompatible // indirect github.com/go-critic/go-critic v0.5.6 // indirect github.com/go-errors/errors v1.0.1 // indirect github.com/go-git/gcfg v1.5.0 // indirect github.com/go-git/go-billy/v5 v5.1.0 // indirect github.com/go-git/go-git/v5 v5.3.0 // indirect - github.com/go-ini/ini v1.51.0 // indirect + github.com/go-ini/ini v1.62.0 // indirect github.com/go-logr/logr v0.4.0 // indirect github.com/go-openapi/jsonpointer v0.19.3 // indirect github.com/go-openapi/jsonreference v0.19.3 // indirect @@ -113,7 +109,6 @@ require ( github.com/go-toolsmith/strparse v1.0.0 // indirect github.com/go-toolsmith/typep v1.0.2 // indirect github.com/go-xmlfmt/xmlfmt v0.0.0-20191208150333-d5b6f63a941b // indirect - github.com/gobuffalo/flect v0.2.0 // indirect github.com/gobwas/glob v0.2.3 github.com/gofrs/flock v0.8.1 github.com/gogo/protobuf v1.3.2 // indirect @@ -138,14 +133,14 @@ require ( github.com/google/go-github/v32 v32.1.0 // indirect github.com/google/go-github/v35 v35.3.0 // indirect github.com/google/go-querystring v1.0.0 // indirect - github.com/google/gofuzz v1.1.0 // indirect + github.com/google/gofuzz v1.2.0 // indirect github.com/google/rpmpack v0.0.0-20210410105602-e20c988a6f5a // indirect github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 // indirect github.com/google/uuid v1.3.0 github.com/google/wire v0.5.0 // indirect github.com/googleapis/gax-go/v2 v2.1.0 // indirect - github.com/googleapis/gnostic v0.4.1 // indirect - github.com/gophercloud/gophercloud v0.11.1-0.20200518183226-7aec46f32c19 // indirect + github.com/googleapis/gnostic v0.5.4 // indirect + github.com/gophercloud/gophercloud v0.18.0 // indirect github.com/gordonklaus/ineffassign v0.0.0-20210225214923-2e10b2664254 // indirect github.com/goreleaser/chglog v0.1.2 // indirect github.com/goreleaser/fileglob v1.2.0 // indirect @@ -164,13 +159,13 @@ require ( github.com/hashicorp/go-cleanhttp v0.5.1 // indirect github.com/hashicorp/go-multierror v1.1.1 // indirect github.com/hashicorp/go-retryablehttp v0.6.8 // indirect - github.com/hashicorp/go-rootcerts v1.0.1 // indirect + github.com/hashicorp/go-rootcerts v1.0.2 // indirect github.com/hashicorp/go-sockaddr v1.0.2 // indirect github.com/hashicorp/go-version v1.3.0 github.com/hashicorp/golang-lru v0.5.4 // indirect github.com/hashicorp/hcl v1.0.0 // indirect - github.com/hashicorp/vault/api v1.0.4 // indirect - github.com/hashicorp/vault/sdk v0.1.13 // indirect + github.com/hashicorp/vault/api v1.1.0 // indirect + github.com/hashicorp/vault/sdk v0.1.14-0.20200519221838-e0cfd64bc267 // indirect github.com/huandu/xstrings v1.3.2 // indirect github.com/imdario/mergo v0.3.12 // indirect github.com/inconshreveable/mousetrap v1.0.0 // indirect @@ -237,7 +232,7 @@ require ( github.com/phayes/checkstyle v0.0.0-20170904204023-bfd46e6a821d // indirect github.com/pierrec/lz4 v2.0.5+incompatible // indirect github.com/pkg/errors v0.9.1 - github.com/pkg/sftp v1.10.1 // indirect + github.com/pkg/sftp v1.13.0 // indirect github.com/pmezard/go-difflib v1.0.0 // indirect github.com/polyfloyd/go-errorlint v0.0.0-20210510181950-ab96adb96fea // indirect github.com/prometheus/client_golang v1.10.0 // indirect @@ -269,7 +264,7 @@ require ( github.com/spf13/jwalterweatherman v1.1.0 // indirect github.com/spf13/pflag v1.0.5 github.com/spf13/viper v1.8.1 // indirect - github.com/spotinst/spotinst-sdk-go v1.58.0 // indirect + github.com/spotinst/spotinst-sdk-go v1.85.0 // indirect github.com/ssgreg/nlreturn/v2 v2.1.0 // indirect github.com/stretchr/objx v0.2.0 // indirect github.com/stretchr/testify v1.7.0 @@ -301,7 +296,7 @@ require ( github.com/xanzy/ssh-agent v0.3.0 // indirect github.com/xeipuuv/gojsonpointer v0.0.0-20190905194746-02993c407bfb // indirect github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415 // indirect - github.com/xeipuuv/gojsonschema v0.0.0-20181112162635-ac52e6811b56 // indirect + github.com/xeipuuv/gojsonschema v1.2.0 // indirect github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2 // indirect github.com/xlab/treeprint v0.0.0-20181112141820-a009c3971eca // indirect github.com/yeya24/promlinter v0.1.0 // indirect @@ -333,7 +328,7 @@ require ( gopkg.in/gcfg.v1 v1.2.3 // indirect gopkg.in/inf.v0 v0.9.1 // indirect gopkg.in/ini.v1 v1.62.0 // indirect - gopkg.in/square/go-jose.v2 v2.3.1 // indirect + gopkg.in/square/go-jose.v2 v2.5.1 // indirect gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 // indirect gopkg.in/warnings.v0 v0.1.2 // indirect gopkg.in/yaml.v2 v2.4.0 @@ -348,20 +343,19 @@ require ( k8s.io/code-generator v0.21.2 k8s.io/component-base v0.21.2 // indirect k8s.io/csi-translation-lib v0.21.2 // indirect - k8s.io/gengo v0.0.0-20201214224949-b6c5ce23f027 // indirect + k8s.io/gengo v0.0.0-20210203185629-de9496dff47b // indirect k8s.io/klog/v2 v2.8.0 // indirect - k8s.io/kops v1.19.0 + k8s.io/kops v1.21.2 k8s.io/kube-openapi v0.0.0-20210305001622-591a79e4bda7 // indirect k8s.io/kubelet v0.21.2 k8s.io/legacy-cloud-providers v0.21.2 k8s.io/sample-controller v0.16.8 // indirect - k8s.io/utils v0.0.0-20201110183641-67b214c5f920 // indirect + k8s.io/utils v0.0.0-20210305010621-2afb4311ab10 // indirect mvdan.cc/gofumpt v0.1.1 // indirect mvdan.cc/interfacer v0.0.0-20180901003855-c20040233aed // indirect mvdan.cc/lint v0.0.0-20170908181259-adc824a0674b // indirect mvdan.cc/unparam v0.0.0-20210104141923-aac4ce9116a7 // indirect sigs.k8s.io/aws-iam-authenticator v0.5.2 - sigs.k8s.io/controller-tools v0.2.8 // indirect sigs.k8s.io/kustomize/api v0.8.8 // indirect sigs.k8s.io/kustomize/kyaml v0.10.17 // indirect sigs.k8s.io/mdtoc v1.0.1 diff --git a/go.sum b/go.sum index 7f3f920169..6d46eca2e6 100644 --- a/go.sum +++ b/go.sum @@ -1,5 +1,6 @@ 4d63.com/gochecknoglobals v0.0.0-20201008074935-acfc0b28355a h1:wFEQiK85fRsEVF0CRrPAos5LoAryUsIX1kPW/WrIqFw= 4d63.com/gochecknoglobals v0.0.0-20201008074935-acfc0b28355a/go.mod h1:wfdC5ZjKSPr7CybKEcgJhUOgeAQW1+7WcyK8OvUilfo= +bazil.org/fuse v0.0.0-20160811212531-371fbbdaa898/go.mod h1:Xbm+BRKSBEpa4q4hTSxohYNQpsxXPbPry4JJWOB3LB8= bazil.org/fuse v0.0.0-20180421153158-65cc252bf669/go.mod h1:Xbm+BRKSBEpa4q4hTSxohYNQpsxXPbPry4JJWOB3LB8= bitbucket.org/bertimus9/systemstat v0.0.0-20180207000608-0eeff89b0690/go.mod h1:Ulb78X89vxKYgdL24HMTiXYHlyHEvruOj1ZPlqeNEZM= bitbucket.org/creachadair/shell v0.0.6/go.mod h1:8Qqi/cYk7vPnsOePHroKXDJYmb5x7ENhtiFtfZq8K+M= @@ -96,21 +97,26 @@ github.com/Azure/azure-amqp-common-go/v3 v3.1.1/go.mod h1:YsDaPfaO9Ub2XeSKdIy2Df github.com/Azure/azure-pipeline-go v0.2.1/go.mod h1:UGSo8XybXnIGZ3epmeBw7Jdz+HiUVpqIlpz/HKHylF4= github.com/Azure/azure-pipeline-go v0.2.3 h1:7U9HBg1JFK3jHl5qmo4CTZKFTVgMwdFHMVtCdfBE21U= github.com/Azure/azure-pipeline-go v0.2.3/go.mod h1:x841ezTBIMG6O3lAcl8ATHnsOPVl2bqk7S3ta6S6u4k= +github.com/Azure/azure-sdk-for-go v16.2.1+incompatible/go.mod h1:9XXNKU+eRnpl9moKnB4QOLf1HestfXbmab5FXxiDBjc= github.com/Azure/azure-sdk-for-go v29.0.0+incompatible/go.mod h1:9XXNKU+eRnpl9moKnB4QOLf1HestfXbmab5FXxiDBjc= github.com/Azure/azure-sdk-for-go v30.1.0+incompatible/go.mod h1:9XXNKU+eRnpl9moKnB4QOLf1HestfXbmab5FXxiDBjc= github.com/Azure/azure-sdk-for-go v43.0.0+incompatible/go.mod h1:9XXNKU+eRnpl9moKnB4QOLf1HestfXbmab5FXxiDBjc= +github.com/Azure/azure-sdk-for-go v46.3.0+incompatible/go.mod h1:9XXNKU+eRnpl9moKnB4QOLf1HestfXbmab5FXxiDBjc= github.com/Azure/azure-sdk-for-go v51.1.0+incompatible/go.mod h1:9XXNKU+eRnpl9moKnB4QOLf1HestfXbmab5FXxiDBjc= +github.com/Azure/azure-sdk-for-go v53.4.0+incompatible/go.mod h1:9XXNKU+eRnpl9moKnB4QOLf1HestfXbmab5FXxiDBjc= github.com/Azure/azure-sdk-for-go v57.0.0+incompatible h1:isVki3PbIFrwKvKdVP1byxo73/pt+Nn174YxW1k4PNw= github.com/Azure/azure-sdk-for-go v57.0.0+incompatible/go.mod h1:9XXNKU+eRnpl9moKnB4QOLf1HestfXbmab5FXxiDBjc= github.com/Azure/azure-service-bus-go v0.9.1/go.mod h1:yzBx6/BUGfjfeqbRZny9AQIbIe3AcV9WZbAdpkoXOa0= github.com/Azure/azure-service-bus-go v0.10.16/go.mod h1:MlkLwGGf1ewcx5jZadn0gUEty+tTg0RaElr6bPf+QhI= github.com/Azure/azure-storage-blob-go v0.8.0/go.mod h1:lPI3aLPpuLTeUwh1sViKXFxwl2B6teiRqI0deQUvsw0= +github.com/Azure/azure-storage-blob-go v0.13.0/go.mod h1:pA9kNqtjUeQF2zOSu4s//nUdBD+e64lEuc4sVnuOfNs= github.com/Azure/azure-storage-blob-go v0.14.0 h1:1BCg74AmVdYwO3dlKwtFU1V0wU2PZdREkXvAmZJRUlM= github.com/Azure/azure-storage-blob-go v0.14.0/go.mod h1:SMqIBi+SuiQH32bvyjngEewEeXoPfKMgWlBDaYf6fck= github.com/Azure/go-amqp v0.13.0/go.mod h1:qj+o8xPCz9tMSbQ83Vp8boHahuRDl5mkNHyt1xlxUTs= github.com/Azure/go-amqp v0.13.11/go.mod h1:D5ZrjQqB1dyp1A+G73xeL/kNn7D5qHJIIsNNps7YNmk= github.com/Azure/go-amqp v0.13.12/go.mod h1:D5ZrjQqB1dyp1A+G73xeL/kNn7D5qHJIIsNNps7YNmk= github.com/Azure/go-ansiterm v0.0.0-20170929234023-d6e3b3328b78/go.mod h1:LmzpDX56iTiv29bbRTIsUNlaFfuhWRQBWjQdVyAevI8= +github.com/Azure/go-autorest v10.8.1+incompatible/go.mod h1:r+4oMnoxhatjLLJ6zxSWATqVooLgysK6ZNox3g/xq24= github.com/Azure/go-autorest v12.0.0+incompatible/go.mod h1:r+4oMnoxhatjLLJ6zxSWATqVooLgysK6ZNox3g/xq24= github.com/Azure/go-autorest v14.2.0+incompatible h1:V5VMDjClD3GiElqLWO7mz2MxNAK/vTfRHdAubSIPRgs= github.com/Azure/go-autorest v14.2.0+incompatible/go.mod h1:r+4oMnoxhatjLLJ6zxSWATqVooLgysK6ZNox3g/xq24= @@ -118,6 +124,7 @@ github.com/Azure/go-autorest/autorest v0.9.0/go.mod h1:xyHB1BMZT0cuDHU7I0+g046+B github.com/Azure/go-autorest/autorest v0.9.6/go.mod h1:/FALq9T/kS7b5J5qsQ+RSTUdAmGFqi0vUdVNNx8q630= github.com/Azure/go-autorest/autorest v0.11.3/go.mod h1:JFgpikqFJ/MleTTxwepExTKnFUKKszPS8UavbQYUMuw= github.com/Azure/go-autorest/autorest v0.11.4/go.mod h1:JFgpikqFJ/MleTTxwepExTKnFUKKszPS8UavbQYUMuw= +github.com/Azure/go-autorest/autorest v0.11.6/go.mod h1:V6p3pKZx1KKkJubbxnDWrzNhEIfOy/pTGasLqzHIPHs= github.com/Azure/go-autorest/autorest v0.11.12/go.mod h1:eipySxLmqSyC5s5k1CLupqet0PSENBEDP93LQ9a8QYw= github.com/Azure/go-autorest/autorest v0.11.17/go.mod h1:eipySxLmqSyC5s5k1CLupqet0PSENBEDP93LQ9a8QYw= github.com/Azure/go-autorest/autorest v0.11.18/go.mod h1:dSiJPy22c3u0OtOKDNttNgqpNFY/GeWa7GH/Pz56QRA= @@ -126,12 +133,15 @@ github.com/Azure/go-autorest/autorest v0.11.20/go.mod h1:o3tqFY+QR40VOlk+pV4d77m github.com/Azure/go-autorest/autorest/adal v0.5.0/go.mod h1:8Z9fGy2MpX0PvDjB1pEgQTmVqjGhiHBW7RJJEciWzS0= github.com/Azure/go-autorest/autorest/adal v0.8.2/go.mod h1:ZjhuQClTqx435SRJ2iMlOxPYt3d2C/T/7TiQCVZSn3Q= github.com/Azure/go-autorest/autorest/adal v0.9.0/go.mod h1:/c022QCutn2P7uY+/oQWWNcK9YU+MH96NgK+jErpbcg= +github.com/Azure/go-autorest/autorest/adal v0.9.2/go.mod h1:/3SMAM86bP6wC9Ev35peQDUeqFZBMH07vvUOmg4z/fE= +github.com/Azure/go-autorest/autorest/adal v0.9.4/go.mod h1:/3SMAM86bP6wC9Ev35peQDUeqFZBMH07vvUOmg4z/fE= github.com/Azure/go-autorest/autorest/adal v0.9.5/go.mod h1:B7KF7jKIeC9Mct5spmyCB/A8CG/sEz1vwIRGv/bbw7A= github.com/Azure/go-autorest/autorest/adal v0.9.11/go.mod h1:nBKAnTomx8gDtl+3ZCJv2v0KACFHWTB2drffI1B68Pk= github.com/Azure/go-autorest/autorest/adal v0.9.13/go.mod h1:W/MM4U6nLxnIskrw4UwWzlHfGjwUS50aOsc/I3yuU8M= github.com/Azure/go-autorest/autorest/adal v0.9.14/go.mod h1:W/MM4U6nLxnIskrw4UwWzlHfGjwUS50aOsc/I3yuU8M= github.com/Azure/go-autorest/autorest/adal v0.9.15 h1:X+p2GF0GWyOiSmqohIaEeuNFNDY4I4EOlVuUQvFdWMk= github.com/Azure/go-autorest/autorest/adal v0.9.15/go.mod h1:tGMin8I49Yij6AQ+rvV+Xa/zwxYQB5hmsd6DkfAx2+A= +github.com/Azure/go-autorest/autorest/azure/auth v0.5.7/go.mod h1:AkzUsqkrdmNhfP2i54HqINVQopw0CLDnvHpJ88Zz1eI= github.com/Azure/go-autorest/autorest/azure/auth v0.5.8 h1:TzPg6B6fTZ0G1zBf3T54aI7p3cAT6u//TOXGPmFMOXg= github.com/Azure/go-autorest/autorest/azure/auth v0.5.8/go.mod h1:kxyKZTSfKh8OVFWPAgOgQ/frrJgeYQJPyR5fLFmXko4= github.com/Azure/go-autorest/autorest/azure/cli v0.4.2/go.mod h1:7qkJkT+j6b+hIpzMOwPChJhTqS8VbsqqgULzMNRugoM= @@ -151,6 +161,7 @@ github.com/Azure/go-autorest/autorest/to v0.2.0/go.mod h1:GunWKJp1AEqgMaGLV+iocm github.com/Azure/go-autorest/autorest/to v0.4.0 h1:oXVqrxakqqV1UZdSazDOPOLvOIz+XA683u8EctwboHk= github.com/Azure/go-autorest/autorest/to v0.4.0/go.mod h1:fE8iZBn7LQR7zH/9XU2NcPR4o9jEImooCeWJcYV/zLE= github.com/Azure/go-autorest/autorest/validation v0.1.0/go.mod h1:Ha3z/SqBeaalWQvokg3NZAlQTalVMtOIAs1aGK7G6u8= +github.com/Azure/go-autorest/autorest/validation v0.3.0/go.mod h1:yhLgjC0Wda5DYXl6JAsWyUe4KVNffhoDhG0zVzUMo3E= github.com/Azure/go-autorest/autorest/validation v0.3.1 h1:AgyqjAd94fwNAoTjl/WQXg4VvFeRFpO+UhNyRXqF1ac= github.com/Azure/go-autorest/autorest/validation v0.3.1/go.mod h1:yhLgjC0Wda5DYXl6JAsWyUe4KVNffhoDhG0zVzUMo3E= github.com/Azure/go-autorest/logger v0.1.0/go.mod h1:oExouG+K6PryycPJfVSxi/koC6LSNgds39diKLz7Vrc= @@ -164,6 +175,8 @@ github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03 github.com/BurntSushi/toml v0.4.1 h1:GaI7EiDXDRfa8VshkTj7Fym7ha+y8/XxIgD2okUIjLw= github.com/BurntSushi/toml v0.4.1/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ= github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= +github.com/DATA-DOG/go-sqlmock v1.5.0/go.mod h1:f/Ixk793poVmq4qj/V1dPUg2JEAKC73Q5eFN3EC/SaM= +github.com/DataDog/datadog-go v3.2.0+incompatible/go.mod h1:LButxg5PwREeZtORoXG3tL4fMGNddJ+vMq1mwgfaqoQ= github.com/DisgoOrg/disgohook v1.4.3 h1:JtZiV0jAku9NZRYD6wVH7tWY1617rh4tRqn4ihTUJRc= github.com/DisgoOrg/disgohook v1.4.3/go.mod h1:aHNyBHq1pBbdWrkCq3ZCSBeavUoGWZAAT4+609EcrvU= github.com/DisgoOrg/log v1.1.0 h1:a6hLfVSDuTFJc5AKQ8FDYQ5TASnwk3tciUyXThm1CR4= @@ -182,10 +195,11 @@ github.com/JeffAshton/win_pdh v0.0.0-20161109143554-76bb4ee9f0ab/go.mod h1:3VYc5 github.com/Knetic/govaluate v3.0.1-0.20171022003610-9aa49832a739+incompatible/go.mod h1:r7JcOSlj0wfOMncg0iLm8Leh48TZaKVeNIfJntJ2wa0= github.com/MakeNowJust/heredoc v0.0.0-20170808103936-bb23615498cd h1:sjQovDkwrZp8u+gxLtPgKGjk5hCxuy2hrRejBTA9xFU= github.com/MakeNowJust/heredoc v0.0.0-20170808103936-bb23615498cd/go.mod h1:64YHyfSL2R96J44Nlwm39UHepQbyR5q10x7iYa1ks2E= +github.com/MakeNowJust/heredoc/v2 v2.0.1 h1:rlCHh70XXXv7toz95ajQWOWQnN4WNLt0TdpZYIR/J6A= +github.com/MakeNowJust/heredoc/v2 v2.0.1/go.mod h1:6/2Abh5s+hc3g9nbWLe9ObDIOhaRrqsyY9MWy+4JdRM= github.com/Masterminds/goutils v1.1.0/go.mod h1:8cTjp+g8YejhMuvIA5y2vz3BpJxksy863GQaJW2MFNU= github.com/Masterminds/goutils v1.1.1 h1:5nUrii3FMTL5diU80unEVvNevw1nH4+ZV4DSLVJLSYI= github.com/Masterminds/goutils v1.1.1/go.mod h1:8cTjp+g8YejhMuvIA5y2vz3BpJxksy863GQaJW2MFNU= -github.com/Masterminds/semver v1.3.1/go.mod h1:MB6lktGJrhw8PrUyiEoblNEGEQ+RzHPF078ddwwvV3Y= github.com/Masterminds/semver v1.4.2/go.mod h1:MB6lktGJrhw8PrUyiEoblNEGEQ+RzHPF078ddwwvV3Y= github.com/Masterminds/semver v1.5.0 h1:H65muMkzWKEuNDnfl9d70GUjFniHKHRbFPGBuZ3QEww= github.com/Masterminds/semver v1.5.0/go.mod h1:MB6lktGJrhw8PrUyiEoblNEGEQ+RzHPF078ddwwvV3Y= @@ -194,14 +208,19 @@ github.com/Masterminds/semver/v3 v3.1.0/go.mod h1:VPu/7SZ7ePZ3QOrcuXROw5FAcLl4a0 github.com/Masterminds/semver/v3 v3.1.1 h1:hLg3sBzpNErnxhQtUy/mmLR2I9foDujNK030IGemrRc= github.com/Masterminds/semver/v3 v3.1.1/go.mod h1:VPu/7SZ7ePZ3QOrcuXROw5FAcLl4a0cBrbBpGY/8hQs= github.com/Masterminds/sprig v2.15.0+incompatible/go.mod h1:y6hNFY5UBTIWBxnzTeuNhlNS5hqE0NB0E6fgfo2Br3o= -github.com/Masterminds/sprig v2.17.1+incompatible/go.mod h1:y6hNFY5UBTIWBxnzTeuNhlNS5hqE0NB0E6fgfo2Br3o= github.com/Masterminds/sprig v2.22.0+incompatible h1:z4yfnGrZ7netVz+0EDJ0Wi+5VZCSYp4Z0m2dk6cEM60= github.com/Masterminds/sprig v2.22.0+incompatible/go.mod h1:y6hNFY5UBTIWBxnzTeuNhlNS5hqE0NB0E6fgfo2Br3o= +github.com/Masterminds/sprig/v3 v3.2.0/go.mod h1:tWhwTbUTndesPNeF0C900vKoq283u6zp4APT9vaF3SI= +github.com/Masterminds/sprig/v3 v3.2.2/go.mod h1:UoaO7Yp8KlPnJIYWTFkMaqPUYKTfGFPhxNuwnnxkKlk= +github.com/Masterminds/squirrel v1.5.0/go.mod h1:NNaOrjSoIDfDA40n7sr2tPNZRfjzjA400rg+riTZj10= +github.com/Masterminds/vcs v1.13.1/go.mod h1:N09YCmOQr6RLxC6UNHzuVwAdodYbbnycGHSmwVJjcKA= +github.com/MichaelTJones/walk v0.0.0-20161122175330-4748e29d5718/go.mod h1:VVwKsx9Dc8rNG55BWqogoJzGubjKnRoXdUvpGbWqeCc= github.com/Microsoft/go-winio v0.4.14/go.mod h1:qXqCSQ3Xa7+6tgxaGTIe4Kpcdsi+P8jBhyzoq1bpyYA= github.com/Microsoft/go-winio v0.4.15-0.20190919025122-fc70bd9a86b5/go.mod h1:tTuCMEN+UleMWgg9dVx4Hu52b1bJo+59jBh3ajtinzw= github.com/Microsoft/go-winio v0.4.15/go.mod h1:tTuCMEN+UleMWgg9dVx4Hu52b1bJo+59jBh3ajtinzw= github.com/Microsoft/go-winio v0.4.16 h1:FtSW/jqD+l4ba5iPBj9CODVtgfYAD8w2wS923g/cFDk= github.com/Microsoft/go-winio v0.4.16/go.mod h1:XB6nPKklQyQ7GC9LdcBEcBl8PF76WugXOPRXwdLnMv0= +github.com/Microsoft/hcsshim v0.8.7/go.mod h1:OHd7sQqRFrYd3RmSgbgji+ctCwkbq2wbEYNSzOYtcBQ= github.com/Microsoft/hcsshim v0.8.10-0.20200715222032-5eafd1556990/go.mod h1:ay/0dTb7NsG8QMDfsRfLHgZo/6xAJShLe1+ePPflihk= github.com/NYTimes/gziphandler v0.0.0-20170623195520-56545f4a5d46/go.mod h1:3wb06e3pkSAbeQ52E9H9iFoQsEEwGN64994WTCIhntQ= github.com/NYTimes/gziphandler v1.1.1/go.mod h1:n/CVRwUEOgIxrgPvAQhUUr9oeUtvrhMomdKFjzJNB0c= @@ -222,9 +241,11 @@ github.com/PuerkitoBio/purell v1.1.1/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbt github.com/PuerkitoBio/urlesc v0.0.0-20160726150825-5bd2802263f2/go.mod h1:uGdkoq3SwY9Y+13GIhn11/XLaGBb4BfwItxLd5jeuXE= github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578 h1:d+Bc7a5rLufV/sSk/8dngufqelfh6jnri85riMAaF/M= github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578/go.mod h1:uGdkoq3SwY9Y+13GIhn11/XLaGBb4BfwItxLd5jeuXE= +github.com/Shopify/logrus-bugsnag v0.0.0-20171204204709-577dee27f20d/go.mod h1:HI8ITrYtUY+O+ZhtlqUnD8+KwNPOyugEhfP9fdUIaEQ= github.com/Shopify/sarama v1.19.0/go.mod h1:FVkBWblsNy7DGZRfXLU0O9RCGt5g3g3yEuWXgklEdEo= github.com/Shopify/toxiproxy v2.1.4+incompatible/go.mod h1:OXgGpZ6Cli1/URJOF1DMxUHB2q5Ap20/P/eIdh4G0pI= github.com/StackExchange/wmi v1.2.1/go.mod h1:rcmrprowKIVzvc+NUiLncP2uuArMWLCbu9SBzvHz7e8= +github.com/Venafi/vcert/v4 v4.13.1/go.mod h1:Z3sJFoAurFNXPpoSUSHq46aIeHLiGQEMDhprfxlpofQ= github.com/VividCortex/gohistogram v1.0.0/go.mod h1:Pf5mBqqDxYaXu3hDrrU+w6nw50o/4+TcAqDqk/vUH7g= github.com/afex/hystrix-go v0.0.0-20180502004556-fa1af6a1f4f5/go.mod h1:SkGFH1ia65gfNATL8TAiHDNxPzPdmEL5uirI2Uyuz6c= github.com/agext/levenshtein v1.2.1/go.mod h1:JEDfjyjHDjOF/1e4FlBE/PkbqA9OfWu2ki2W0IB5558= @@ -242,7 +263,7 @@ github.com/alecthomas/units v0.0.0-20190717042225-c3de453c63f4/go.mod h1:ybxpYRF github.com/alecthomas/units v0.0.0-20190924025748-f65c72e2690d/go.mod h1:rBZYJk541a8SKzHPHnH3zbiI+7dagKZ0cgpgrD7Fyho= github.com/alexkohler/prealloc v1.0.0 h1:Hbq0/3fJPQhNkN0dR95AVrr6R7tou91y0uHG5pOcUuw= github.com/alexkohler/prealloc v1.0.0/go.mod h1:VetnK3dIgFBBKmg0YnD9F9x6Icjd+9cvfHR56wJVlKE= -github.com/aliyun/alibaba-cloud-sdk-go v1.61.264/go.mod h1:pUKYbK5JQ+1Dfxk80P0qxGqe5dkxDoabbZS7zOcouyA= +github.com/aliyun/alibaba-cloud-sdk-go v1.61.1059/go.mod h1:pUKYbK5JQ+1Dfxk80P0qxGqe5dkxDoabbZS7zOcouyA= github.com/andreyvit/diff v0.0.0-20170406064948-c7f18ee00883/go.mod h1:rCTlJbsFo29Kk6CurOXKm700vrz8f0KW0JNfpkRJY/8= github.com/andybalholm/brotli v1.0.0/go.mod h1:loMXtMfwqflxFJPmdbJO0a3KNoPuLBgiu3qAvBg8x/Y= github.com/anmitsu/go-shlex v0.0.0-20161002113705-648efa622239 h1:kFOfPq6dUM1hTo4JG6LR5AXSUEsOjtdm0kw0FtQtMJA= @@ -262,15 +283,18 @@ github.com/aphistic/golf v0.0.0-20180712155816-02c07f170c5a/go.mod h1:3NqKYiepwy github.com/aphistic/sweet v0.2.0/go.mod h1:fWDlIh/isSE9n6EPsRmC0det+whmX6dJid3stzu0Xys= github.com/apparentlymart/go-dump v0.0.0-20180507223929-23540a00eaa3/go.mod h1:oL81AME2rN47vu18xqj1S1jPIPuN7afo62yKTNn3XMM= github.com/apparentlymart/go-textseg v1.0.0/go.mod h1:z96Txxhf3xSFMPmb5X/1W05FF/Nj9VFpLOpjS5yuumk= +github.com/apparentlymart/go-textseg/v13 v13.0.0/go.mod h1:ZK2fH7c4NqDTLtiYLvIkEghdlcqw7yxLeM89kiTRPUo= github.com/armon/circbuf v0.0.0-20150827004946-bbbad097214e/go.mod h1:3U/XgcO3hCbHZ8TKRvWD2dDTCfh9M9ya+I9JpbB7O8o= github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6/go.mod h1:grANhF5doyWs3UAsr3K4I6qtAmlQcZDesFNEHPZAzj8= github.com/armon/go-metrics v0.0.0-20180917152333-f0300d1749da/go.mod h1:Q73ZrmVTwzkszR9V5SSuryQ31EELlFMUz1kKyl939pY= +github.com/armon/go-metrics v0.3.0/go.mod h1:zXjbSimjXTd7vOpY8B0/2LpvNvDoXBuplAD+gJD3GYs= github.com/armon/go-radix v0.0.0-20180808171621-7fddfc383310/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8= github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5 h1:0CwZNZbxp69SHPdPJAN/hZIm0C4OItdklCFmMRWYpio= github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5/go.mod h1:wHh0iHkYZB8zMSxRWpUBQtwG5a7fFgvEO+odwuTv2gs= github.com/aryann/difflib v0.0.0-20170710044230-e206f873d14a/go.mod h1:DAHtR1m6lCRdSC2Tm3DSWRPvIPr6xNKyeHdqDQSQT+A= github.com/asaskevich/govalidator v0.0.0-20180720115003-f9ffefc3facf/go.mod h1:lB+ZfQJz7igIIfQNfa7Ml4HSf2uFQQRzpGGRXenZAgY= github.com/asaskevich/govalidator v0.0.0-20190424111038-f61b66f89f4a/go.mod h1:lB+ZfQJz7igIIfQNfa7Ml4HSf2uFQQRzpGGRXenZAgY= +github.com/asaskevich/govalidator v0.0.0-20200428143746-21a406dcc535/go.mod h1:oGkLhpf+kjZl6xBf758TQhh5XrAeiJv/7FRz/2spLIg= github.com/ashanbrown/forbidigo v1.2.0 h1:RMlEFupPCxQ1IogYOQUnIQwGEUGK8g5vAPMRyJoSxbc= github.com/ashanbrown/forbidigo v1.2.0/go.mod h1:vVW7PEdqEFqapJe95xHkTfB1+XvZXBFg8t0sG2FIxmI= github.com/ashanbrown/makezero v0.0.0-20210520155254-b6261585ddde h1:YOsoVXsZQPA9aOTy1g0lAJv5VzZUvwQuZqug8XPeqfM= @@ -278,11 +302,12 @@ github.com/ashanbrown/makezero v0.0.0-20210520155254-b6261585ddde/go.mod h1:oG9D github.com/atc0005/go-teams-notify/v2 v2.6.0 h1:YegKDWbjlatR0fP2yHsQYXzTcUGNJXhm1/OiCgbyysc= github.com/atc0005/go-teams-notify/v2 v2.6.0/go.mod h1:xo6GejLDHn3tWBA181F8LrllIL0xC1uRsRxq7YNXaaY= github.com/auth0/go-jwt-middleware v0.0.0-20170425171159-5493cabe49f7/go.mod h1:LWMyo4iOLWXHGdBki7NIht1kHru/0wM179h+d3g8ATM= -github.com/aws/amazon-ec2-instance-selector/v2 v2.0.1/go.mod h1:juzWzDAyOHbufrohZ77l2VW+CEgtXIm2SzrTVMmfJy8= +github.com/aws/amazon-ec2-instance-selector/v2 v2.0.2/go.mod h1:qot+32DWumAuTogNcselkYbAXK4UUbQz3OhM97PIff8= github.com/aws/amazon-ec2-instance-selector/v2 v2.0.3-0.20210303155736-3e43512d88f8 h1:qR505xKnVxbA/jNh61AoQRnbWlL0b5a58ZgU79AX+VM= github.com/aws/amazon-ec2-instance-selector/v2 v2.0.3-0.20210303155736-3e43512d88f8/go.mod h1:L7sFBlPt6UhH1KrAwvPinQzyVddTu4CGNd19gp6k1xg= github.com/aws/aws-lambda-go v1.13.3/go.mod h1:4UKl9IzQMoD+QF79YdCuzCwp8VbmG4VAQwij/eHl5CU= github.com/aws/aws-sdk-go v1.6.10/go.mod h1:ZRmQr0FajVIyZ4ZzBYKG5P3ZqPz9IHG41ZoMu1ADI3k= +github.com/aws/aws-sdk-go v1.15.11/go.mod h1:mFuSZ37Z9YOHbQEwBWztmVzqXrEkub65tZoCYDt7FT0= github.com/aws/aws-sdk-go v1.15.27/go.mod h1:mFuSZ37Z9YOHbQEwBWztmVzqXrEkub65tZoCYDt7FT0= github.com/aws/aws-sdk-go v1.19.18/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpiN924inxo= github.com/aws/aws-sdk-go v1.19.45/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpiN924inxo= @@ -294,10 +319,11 @@ github.com/aws/aws-sdk-go v1.27.0/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpiN github.com/aws/aws-sdk-go v1.28.2/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpiN924inxo= github.com/aws/aws-sdk-go v1.30.0/go.mod h1:5zCpMtNQVjRREroY7sYe8lOMRSxkhG6MZveU8YkpAk0= github.com/aws/aws-sdk-go v1.31.12/go.mod h1:5zCpMtNQVjRREroY7sYe8lOMRSxkhG6MZveU8YkpAk0= +github.com/aws/aws-sdk-go v1.34.30/go.mod h1:H7NKnBqNVzoTJpGfLrQkkD+ytBA93eiDYi/+8rV9s48= github.com/aws/aws-sdk-go v1.35.24/go.mod h1:tlPOdRjfxPBpNIwqDj61rmsnA85v9jc0Ps9+muhnW+k= -github.com/aws/aws-sdk-go v1.36.0/go.mod h1:hcU610XS61/+aQV88ixoOzUoG7v3b31pl2zKMmprdro= github.com/aws/aws-sdk-go v1.36.30/go.mod h1:hcU610XS61/+aQV88ixoOzUoG7v3b31pl2zKMmprdro= github.com/aws/aws-sdk-go v1.37.0/go.mod h1:hcU610XS61/+aQV88ixoOzUoG7v3b31pl2zKMmprdro= +github.com/aws/aws-sdk-go v1.38.29/go.mod h1:hcU610XS61/+aQV88ixoOzUoG7v3b31pl2zKMmprdro= github.com/aws/aws-sdk-go v1.40.34/go.mod h1:585smgzpB/KqRA+K3y/NL/oYRqQvpNJYvLm+LY1U59Q= github.com/aws/aws-sdk-go v1.41.13 h1:wGgr6jkHdGExF33phfOqijFq7ZF+h7a6FXvJc77GpTc= github.com/aws/aws-sdk-go v1.41.13/go.mod h1:585smgzpB/KqRA+K3y/NL/oYRqQvpNJYvLm+LY1U59Q= @@ -327,17 +353,11 @@ github.com/aws/smithy-go v1.8.0/go.mod h1:SObp3lf9smib00L/v3U2eAKG8FyQ7iLrJnQiAm github.com/awslabs/goformation/v4 v4.15.5 h1:q3lm7oj4yqqJ76ZcaFThUACT3MQLD6yBcJRKuZ6g87w= github.com/awslabs/goformation/v4 v4.15.5/go.mod h1:wB5lKZf1J0MYH1Lt4B9w3opqz0uIjP7MMCAcib3QkwA= github.com/aybabtme/rgbterm v0.0.0-20170906152045-cc83f3b3ce59/go.mod h1:q/89r3U2H7sSsE2t6Kca0lfwTK8JdoNGS/yzM/4iH5I= -github.com/bazelbuild/bazel-gazelle v0.19.1 h1:TSCGVqpHStCj1MTszuDfZt6Z2Ca8ekq2oWiqcHKVEAE= -github.com/bazelbuild/bazel-gazelle v0.19.1/go.mod h1:rPwzNHUqEzngx1iVBfO/2X2npKaT3tqPqqHW6rVsn/A= -github.com/bazelbuild/buildtools v0.0.0-20190731111112-f720930ceb60/go.mod h1:5JP0TXzWDHXv8qvxRC4InIazwdyDseBDbzESUMKk1yU= -github.com/bazelbuild/buildtools v0.0.0-20190917191645-69366ca98f89 h1:3B/ZE1a6eEJ/4Jf/M6RM2KBouN8yKCUcMmXzSyWqa3g= -github.com/bazelbuild/buildtools v0.0.0-20190917191645-69366ca98f89/go.mod h1:5JP0TXzWDHXv8qvxRC4InIazwdyDseBDbzESUMKk1yU= -github.com/bazelbuild/rules_go v0.0.0-20190719190356-6dae44dc5cab h1:wzbawlkLtl2ze9w/312NHZ84c7kpUCtlkD8HgFY27sw= -github.com/bazelbuild/rules_go v0.0.0-20190719190356-6dae44dc5cab/go.mod h1:MC23Dc/wkXEyk3Wpq6lCqz0ZAYOZDw2DR5y3N1q2i7M= github.com/benbjohnson/clock v1.1.0 h1:Q92kusRqC1XV2MjkWETPvjJVqKetz1OzxZB7mHJLju8= github.com/benbjohnson/clock v1.1.0/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA= github.com/benjamintf1/unmarshalledmatchers v0.0.0-20190408201839-bb1c1f34eaea h1:NhnqtoeNnEBu36bfeP2CZq/d5bJxzJBtChscvM7v5Cg= github.com/benjamintf1/unmarshalledmatchers v0.0.0-20190408201839-bb1c1f34eaea/go.mod h1:jfBxQAPihPj5l6sipcapjHruLizHrt3RKuppDE97K+g= +github.com/beorn7/perks v0.0.0-20160804104726-4c0e84591b9a/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8= github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= @@ -345,6 +365,7 @@ github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6r github.com/bgentry/speakeasy v0.1.0 h1:ByYyxL9InA1OWqxJqqp2A5pYHUrCiAL6K3J+LKSsQkY= github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs= github.com/bifurcation/mint v0.0.0-20180715133206-93c51c6ce115/go.mod h1:zVt7zX3K/aDCk9Tj+VM7YymsX66ERvzCJzw8rFCX2JU= +github.com/bitly/go-simplejson v0.5.0/go.mod h1:cXHtHw4XUPsvGaxgjIAn8PhEWG9NfngEKAMDJEczWVA= github.com/bketelsen/crypt v0.0.3-0.20200106085610-5cbc8cc4026c/go.mod h1:MKsuJmJgSg28kpZDP6UIiPt0e0Oz0kqKNGyRaWEPv84= github.com/bketelsen/crypt v0.0.4/go.mod h1:aI6NrJ0pMGgvZKL1iVgXLnfIFJtfV+bKCoqOes/6LfM= github.com/bkielbasa/cyclop v1.2.0 h1:7Jmnh0yL2DjKfw28p86YTd/B4lRGcNuu12sKE35sM7A= @@ -357,9 +378,14 @@ github.com/blang/semver v3.5.1+incompatible h1:cQNTCjp13qL8KC3Nbxr/y2Bqb63oX6wdn github.com/blang/semver v3.5.1+incompatible/go.mod h1:kRBLl5iJ+tD4TcOOxsy/0fnwebNt5EWlYSAyrTnjyyk= github.com/blang/semver/v4 v4.0.0 h1:1PFHFE6yCCTv8C1TeyNNarDzntLi7wMI5i/pzqYIsAM= github.com/blang/semver/v4 v4.0.0/go.mod h1:IbckMUScFkM3pff0VJDNKRiT6TG/YpiHIM2yvyW5YoQ= +github.com/bmizerany/assert v0.0.0-20160611221934-b7ed37b82869/go.mod h1:Ekp36dRnpXw/yCqJaO+ZrUyxD+3VXMFFr56k5XYrpB4= github.com/boltdb/bolt v1.3.1/go.mod h1:clJnj/oiGkjum5o1McbSZDSLxVThjynRyGBgiAx27Ps= github.com/bombsimon/wsl/v3 v3.3.0 h1:Mka/+kRLoQJq7g2rggtgQsjuI/K5Efd87WX96EWFxjM= github.com/bombsimon/wsl/v3 v3.3.0/go.mod h1:st10JtZYLE4D5sC7b8xV4zTKZwAQjCH/Hy2Pm1FNZIc= +github.com/bshuster-repo/logrus-logstash-hook v0.4.1/go.mod h1:zsTqEiSzDgAa/8GZR7E1qaXrhYNDKBYy5/dWPTIflbk= +github.com/bugsnag/bugsnag-go v0.0.0-20141110184014-b1d153021fcd/go.mod h1:2oa8nejYd4cQ/b0hMIopN0lCRxU0bueqREvZLWFrtK8= +github.com/bugsnag/osext v0.0.0-20130617224835-0dd3f918b21b/go.mod h1:obH5gd0BsqsP2LwDJ9aOkm/6J86V6lyAXCoQWGw3K50= +github.com/bugsnag/panicwrap v0.0.0-20151223152923-e2c28503fcd0/go.mod h1:D/8v3kj0zr8ZAKg1AQ6crr+5VwKN5eIywRkfhyM/+dE= github.com/bxcodec/faker v2.0.1+incompatible h1:P0KUpUw5w6WJXwrPfv35oc91i4d8nf40Nwln+M/+faA= github.com/bxcodec/faker v2.0.1+incompatible/go.mod h1:BNzfpVdTwnFJ6GtfYTcQu6l6rHShT+veBxNCnjCx5XM= github.com/caarlos0/ctrlc v1.0.0 h1:2DtF8GSIcajgffDFJzyG15vO+1PuBWOMUdFut7NnXhw= @@ -392,7 +418,6 @@ github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghf github.com/cespare/xxhash/v2 v2.1.1 h1:6MnRN8NT7+YBpUIWxHtefFZOKTAPgGjpQSxqLNn0+qY= github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= github.com/chai2010/gettext-go v0.0.0-20160711120539-c6fed771bfd5/go.mod h1:/iP1qXHoty45bqomnu2LM+VVyAEdWN+vtSHGlQgyxbw= -github.com/chai2010/gettext-go v0.0.0-20170215093142-bf70f2a70fb1/go.mod h1:/iP1qXHoty45bqomnu2LM+VVyAEdWN+vtSHGlQgyxbw= github.com/charithe/durationcheck v0.0.8 h1:cnZrThioNW9gSV5JsRIXmkyHUbcDH7Y9hkzFDVc9/j0= github.com/charithe/durationcheck v0.0.8/go.mod h1:SSbRIBVfMjCi/kEB6K65XEA83D6prSM8ap1UCpNKtgg= github.com/chavacava/garif v0.0.0-20210405164556-e8a0a408d6af h1:spmv8nSH9h5oCQf40jt/ufBCt9j0/58u4G+rkeMqXGI= @@ -406,12 +431,14 @@ github.com/cilium/ebpf v0.0.0-20200110133405-4032b1d8aae3/go.mod h1:MA5e5Lr8slmE github.com/cilium/ebpf v0.0.0-20200507155900-a9f01edf17e3/go.mod h1:XT+cAw5wfvsodedcijoh1l9cf7v1x9FlFB/3VmF/O8s= github.com/cilium/ebpf v0.0.0-20200601085316-9f1617e5c574/go.mod h1:XT+cAw5wfvsodedcijoh1l9cf7v1x9FlFB/3VmF/O8s= github.com/cilium/ebpf v0.0.0-20200702112145-1c8d4c9ef775/go.mod h1:7cR51M8ViRLIdUjrmSXlK9pkrsDlLHbO8jiB8X8JnOc= +github.com/circonus-labs/circonus-gometrics v2.3.1+incompatible/go.mod h1:nmEj6Dob7S7YxXgwXpfOuvO54S+tGdZdw9fuRZt25Ag= +github.com/circonus-labs/circonusllhist v0.1.3/go.mod h1:kMXHVDlOchFAehlya5ePtbp5jckzBHf4XRpQvBOLI+I= github.com/clbanning/x2j v0.0.0-20191024224557-825249438eec/go.mod h1:jMjuTZXRI4dUb/I5gc9Hdhagfvm9+RyrPryS/auMzxE= -github.com/client9/misspell v0.3.4 h1:ta993UF76GwbvJcIo3Y68y/M3WxlpEHPWIGDkJYwzJI= github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= github.com/cloudflare/backoff v0.0.0-20161212185259-647f3cdfc87a/go.mod h1:rzgs2ZOiguV6/NpiDgADjRLPNyZlApIWxKpkT+X8SdY= github.com/cloudflare/cfssl v1.6.1 h1:aIOUjpeuDJOpWjVJFP2ByplF53OgqG8I1S40Ggdlk3g= github.com/cloudflare/cfssl v1.6.1/go.mod h1:ENhCj4Z17+bY2XikpxVmTHDg/C2IsG2Q0ZBeXpAqhCk= +github.com/cloudflare/cloudflare-go v0.13.2/go.mod h1:27kfc1apuifUmJhp069y0+hwlKDg4bd8LWlu7oKeZvM= github.com/cloudflare/redoctober v0.0.0-20201013214028-99c99a8e7544/go.mod h1:6Se34jNoqrd8bTxrmJB2Bg2aoZ2CdSXonils9NsiNgo= github.com/clusterhq/flocker-go v0.0.0-20160920122132-2b8b7259d313/go.mod h1:P1wt9Z3DP8O6W3rvwCt0REIlshg1InHImaLW0t3ObY0= github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= @@ -431,12 +458,17 @@ github.com/cockroachdb/logtags v0.0.0-20190617123548-eb05cc24525f/go.mod h1:i/u9 github.com/codahale/hdrhistogram v0.0.0-20161010025455-3a0bb77429bd/go.mod h1:sE/e/2PUdi/liOCUjSTXgM1o87ZssimdTWN964YiIeI= github.com/codegangsta/negroni v1.0.0/go.mod h1:v0y3T5G7Y1UlFfyxFn/QLRU4a2EuNau2iZY63YTKWo0= github.com/container-storage-interface/spec v1.2.0/go.mod h1:6URME8mwIBbpVyZV93Ce5St17xBiQJQY67NDsuohiy4= +github.com/container-storage-interface/spec v1.3.0/go.mod h1:6URME8mwIBbpVyZV93Ce5St17xBiQJQY67NDsuohiy4= +github.com/containerd/cgroups v0.0.0-20190919134610-bf292b21730f/go.mod h1:OApqhQ4XNSNC13gXIwDjhOQxjWa/NxkwZXJ1EvqT0ko= github.com/containerd/cgroups v0.0.0-20200531161412-0dbf7f05ba59/go.mod h1:pA0z1pT8KYB3TCXK/ocprsh7MAkoW8bZVzPdih9snmM= github.com/containerd/console v0.0.0-20180822173158-c12b1e7919c1/go.mod h1:Tj/on1eG8kiEhd0+fhSDzsPAFESxzBBvdyEgyryXffw= github.com/containerd/console v1.0.0/go.mod h1:8Pf4gM6VEbTNRIT26AyyU7hxdQU3MvAvxVI0sc00XBE= +github.com/containerd/containerd v1.3.0-beta.2.0.20190828155532-0293cbd26c69/go.mod h1:bC6axHOhabU15QhwfG7w5PipXdVtMXFTttgp+kVtyUA= github.com/containerd/containerd v1.3.2/go.mod h1:bC6axHOhabU15QhwfG7w5PipXdVtMXFTttgp+kVtyUA= github.com/containerd/containerd v1.3.3/go.mod h1:bC6axHOhabU15QhwfG7w5PipXdVtMXFTttgp+kVtyUA= +github.com/containerd/containerd v1.3.4/go.mod h1:bC6axHOhabU15QhwfG7w5PipXdVtMXFTttgp+kVtyUA= github.com/containerd/continuity v0.0.0-20190426062206-aaeac12a7ffc/go.mod h1:GL3xCUCBDV3CZiTSEKksMWbLE66hEyuu9qyDOOqM47Y= +github.com/containerd/continuity v0.0.0-20200107194136-26c1120b8d41/go.mod h1:Dq467ZllaHgAtVp4p1xUQWBrFXR9s/wyoTpG8zOJGkY= github.com/containerd/fifo v0.0.0-20190226154929-a9fb20d87448/go.mod h1:ODA38xgv3Kuk8dQz2ZQXpnv/UZZUHUCL7pnLehbXgQI= github.com/containerd/go-runc v0.0.0-20180907222934-5a6d9f37cfa3/go.mod h1:IV7qH3hrUgRmyYrtgEeGWJfWbgcHL9CSRruz2Vqcph0= github.com/containerd/ttrpc v0.0.0-20190828154514-0e0f228740de/go.mod h1:PvCDdDGpgqzQIzDW1TphrGLssLDZp2GuS+X5DkEJB8o= @@ -448,7 +480,6 @@ github.com/coredns/corefile-migration v1.0.10/go.mod h1:RMy/mXdeDlYwzt0vdMEJvT2h github.com/coreos/bbolt v1.3.2/go.mod h1:iRUV2dpdMOn7Bo10OQBFzIJO9kkE559Wcmn+qkEiiKk= github.com/coreos/etcd v3.3.10+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE= github.com/coreos/etcd v3.3.13+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE= -github.com/coreos/etcd v3.3.17+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE= github.com/coreos/go-etcd v2.0.0+incompatible/go.mod h1:Jez6KQU2B/sWsbdaef3ED8NzMklzPG4d5KIOhIy30Tk= github.com/coreos/go-oidc v2.1.0+incompatible/go.mod h1:CgnwVTmzoESiwO9qyAFEMiHoZ1nMCKZlZ9V6mm3/LKc= github.com/coreos/go-semver v0.2.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk= @@ -464,6 +495,7 @@ github.com/coreos/go-systemd/v22 v22.3.2 h1:D9/bQk5vlXQFZ6Kwuu6zaiXJ9oTPe68++AzA github.com/coreos/go-systemd/v22 v22.3.2/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc= github.com/coreos/pkg v0.0.0-20160727233714-3ac0863d7acf/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA= github.com/coreos/pkg v0.0.0-20180928190104-399ea9e2e55f/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA= +github.com/cpu/goacmedns v0.0.3/go.mod h1:4MipLkI+qScwqtVxcNO6okBhbgRrr7/tKXUSgSL0teQ= github.com/cpuguy83/go-md2man v1.0.10 h1:BSKMNlYxDvnunlTymqtgONjNnaRV1sTpcovwwjF22jk= github.com/cpuguy83/go-md2man v1.0.10/go.mod h1:SmD6nW6nTyfqj6ABTjUi3V3JVMnlJmwcJI5acqYI6dE= github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= @@ -484,11 +516,14 @@ github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSs github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/daviddengcn/go-colortext v0.0.0-20160507010035-511bcaf42ccd/go.mod h1:dv4zxwHi5C/8AeI+4gX4dCWOIvNi7I6JCSX0HvlKPgE= +github.com/deislabs/oras v0.8.1/go.mod h1:Mx0rMSbBNaNfY9hjpccEnxkOqJL6KGjtxNHPLC4G4As= github.com/denis-tingajkin/go-header v0.4.2 h1:jEeSF4sdv8/3cT/WY8AgDHUoItNSoEZ7qg9dX7pc218= github.com/denis-tingajkin/go-header v0.4.2/go.mod h1:eLRHAVXzE5atsKAnNRDB90WHCFFnBUn4RN0nRcs1LJA= +github.com/denisenkom/go-mssqldb v0.0.0-20191001013358-cfbb681360f0/go.mod h1:xbL0rPBG9cCiLr28tMa8zpbdarY27NDyej4t/EjAShU= github.com/denisenkom/go-mssqldb v0.9.0/go.mod h1:xbL0rPBG9cCiLr28tMa8zpbdarY27NDyej4t/EjAShU= -github.com/denverdino/aliyungo v0.0.0-20191128015008-acd8035bbb1d h1:Rw/qE0ALLN27jXBKR9xTR+RFAA9s1yIZCKhfT1GgCGA= -github.com/denverdino/aliyungo v0.0.0-20191128015008-acd8035bbb1d/go.mod h1:dV8lFg6daOBZbT6/BDGIz6Y3WFGn8juu6G+CQ6LHtl0= +github.com/denverdino/aliyungo v0.0.0-20190125010748-a747050bb1ba/go.mod h1:dV8lFg6daOBZbT6/BDGIz6Y3WFGn8juu6G+CQ6LHtl0= +github.com/denverdino/aliyungo v0.0.0-20210425065611-55bee4942cba h1:3g+YC/AyMKyPBDTKKMxTHekNFhBZPSxa/ckOPjOJPuU= +github.com/denverdino/aliyungo v0.0.0-20210425065611-55bee4942cba/go.mod h1:dV8lFg6daOBZbT6/BDGIz6Y3WFGn8juu6G+CQ6LHtl0= github.com/devigned/tab v0.1.1/go.mod h1:XG9mPq0dFghrYvoBF3xdRrJzSTX1b7IQrvaL9mzjeJY= github.com/dghubble/go-twitter v0.0.0-20210609183100-2fdbf421508e h1:o0sI/cfhAXdtAbiIVeTd4hmwtwgs4cQFwRBhmbx8AKY= github.com/dghubble/go-twitter v0.0.0-20210609183100-2fdbf421508e/go.mod h1:xfg4uS5LEzOj8PgZV7SQYRHbG7jPUnelEiaAVJxmhJE= @@ -496,23 +531,31 @@ github.com/dghubble/oauth1 v0.7.0 h1:AlpZdbRiJM4XGHIlQ8BuJ/wlpGwFEJNnB4Mc+78tA/w github.com/dghubble/oauth1 v0.7.0/go.mod h1:8pFdfPkv/jr8mkChVbNVuJ0suiHe278BtWI4Tk1ujxk= github.com/dghubble/sling v1.3.0 h1:pZHjCJq4zJvc6qVQ5wN1jo5oNZlNE0+8T/h0XeXBUKU= github.com/dghubble/sling v1.3.0/go.mod h1:XXShWaBWKzNLhu2OxikSNFrlsvowtz4kyRuXUG7oQKY= +github.com/dgrijalva/jwt-go v0.0.0-20170104182250-a601269ab70c/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ= github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ= github.com/dgryski/go-sip13 v0.0.0-20181026042036-e10d5fee7954/go.mod h1:vAd38F8PWV+bWy6jNmig1y/TA+kYO4g3RSRF0IAv0no= -github.com/digitalocean/godo v1.54.0/go.mod h1:p7dOjjtSBqCTUksqtA5Fd3uaKs9kyTq2xcz76ulEJRU= +github.com/digitalocean/godo v1.44.0/go.mod h1:p7dOjjtSBqCTUksqtA5Fd3uaKs9kyTq2xcz76ulEJRU= +github.com/digitalocean/godo v1.60.0/go.mod h1:p7dOjjtSBqCTUksqtA5Fd3uaKs9kyTq2xcz76ulEJRU= github.com/dimchansky/utfbom v1.1.0/go.mod h1:rO41eb7gLfo8SF1jd9F8HplJm1Fewwi4mQvIirEdv+8= github.com/dimchansky/utfbom v1.1.1 h1:vV6w1AhK4VMnhBno/TPVCoK9U/LP0PkLCS9tbxHdi/U= github.com/dimchansky/utfbom v1.1.1/go.mod h1:SxdoEBH5qIqFocHMyGOXVAybYJdr71b1Q/j0mACtrfE= github.com/dlespiau/kube-test-harness v0.0.0-20200915102055-a03579200ae8 h1:pxDCsB4pEs/4FG8pEnNHG7rzr8RvDEdLyDGL653gnB0= github.com/dlespiau/kube-test-harness v0.0.0-20200915102055-a03579200ae8/go.mod h1:DPS/2w0SxCgLfTwNw+/806eccMQ1WjgHb1B70w75wSk= github.com/dnaeon/go-vcr v1.0.1/go.mod h1:aBB1+wY4s93YsC3HHjMBMrwTj2R9FHDzUr9KyGc8n1E= +github.com/docker/cli v0.0.0-20200130152716-5d0cf8839492/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8= +github.com/docker/distribution v0.0.0-20191216044856-a8371794149d/go.mod h1:0+TTO4EOBfRPhZXAeF1Vu+W3hHZ8eLp8PgKVZlcvtFY= github.com/docker/distribution v2.7.1-0.20190205005809-0d3efadf0154+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w= github.com/docker/distribution v2.7.1+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w= +github.com/docker/docker v1.4.2-0.20200203170920-46ec8731fbce/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= github.com/docker/docker v1.4.2-0.20200309214505-aa6a9891b09c/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= +github.com/docker/docker v20.10.6+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= +github.com/docker/docker-credential-helpers v0.6.3/go.mod h1:WRaJzqw3CTB9bk10avuGsjVBZsD05qeibJ1/TYlvc0Y= github.com/docker/go-connections v0.4.0/go.mod h1:Gbd7IOopHjR8Iph03tsViu4nIes5XhDvyHbTtUxmeec= +github.com/docker/go-metrics v0.0.0-20180209012529-399ea8c73916/go.mod h1:/u0gXw0Gay3ceNrsHubL3BtdOL2fHf93USgMTe0W5dI= github.com/docker/go-units v0.3.3/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk= github.com/docker/go-units v0.4.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk= +github.com/docker/libtrust v0.0.0-20150114040149-fa567046d9b1/go.mod h1:cyGadeNEkKy96OOhEzfZl+yxihPEzKnqJwvfuSUqbZE= github.com/docker/spdystream v0.0.0-20170912183627-bc6354cbbc29/go.mod h1:Qh8CwZgvJUkLughtfhJv5dyTYa91l1fOUCrgjqmcifM= -github.com/docker/spdystream v0.0.0-20181023171402-6480d4af844c/go.mod h1:Qh8CwZgvJUkLughtfhJv5dyTYa91l1fOUCrgjqmcifM= github.com/docopt/docopt-go v0.0.0-20180111231733-ee0de3bc6815/go.mod h1:WwZ+bS3ebgob9U8Nd0kOddGdZWjyMGR8Wziv+TBNwSE= github.com/dustin/go-humanize v0.0.0-20171111073723-bb3d318650d4/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk= github.com/dustin/go-humanize v1.0.0 h1:VSnTsYCnlFHaM2/igO1h6X3HA71jcobQuxemgkq4zYo= @@ -584,7 +627,6 @@ github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMo github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ= github.com/fsnotify/fsnotify v1.5.1 h1:mZcQUHVQUQWoPXXtuf9yuEXKudkV2sx1E06UadKWpgI= github.com/fsnotify/fsnotify v1.5.1/go.mod h1:T3375wBYaZdLLcVNkcVbzGHY7f1l/uK5T5Ai1i3InKU= -github.com/fullsailor/pkcs7 v0.0.0-20180422025557-ae226422660e/go.mod h1:KnogPXtdwXqoenmZCw6S+25EAm2MkxbG0deNDu4cbSA= github.com/fullstorydev/grpcurl v1.6.0/go.mod h1:ZQ+ayqbKMJNhzLmbpCiurTVlaK2M/3nqZCxaQ2Ze/sM= github.com/fullstorydev/grpcurl v1.8.0/go.mod h1:Mn2jWbdMrQGJQ8UD62uNyMumT2acsZUCkZIqFxsQf1o= github.com/fullstorydev/grpcurl v1.8.1 h1:Pp648wlTTg3OKySeqxM5pzh8XF6vLqrm8wRq66+5Xo0= @@ -592,6 +634,7 @@ github.com/fullstorydev/grpcurl v1.8.1/go.mod h1:3BWhvHZwNO7iLXaQlojdg5NA6SxUDeP github.com/fvbommel/sortorder v1.0.1/go.mod h1:uk88iVf1ovNn1iLfgUVU2F9o5eO30ui720w+kxuqRs0= github.com/fzipp/gocyclo v0.3.1 h1:A9UeX3HJSXTBzvHzhqoYVuE0eAhe+aM8XBCCwsPMZOc= github.com/fzipp/gocyclo v0.3.1/go.mod h1:DJHO6AUmbdqj2ET4Z9iArSuwWgYDRryYt2wASxc7x3E= +github.com/garyburd/redigo v0.0.0-20150301180006-535138d7bcd7/go.mod h1:NR3MbYisc3/PwhQ00EMzDiPmrwpPxAn5GI05/YaO1SY= github.com/getsentry/raven-go v0.2.0 h1:no+xWJRb5ZI7eE8TWgIq1jLulQiIoLG0IfYxv5JYMGs= github.com/getsentry/raven-go v0.2.0/go.mod h1:KungGk8q33+aIAZUIVWZDr2OfAEBsO49PX4NzFV5kcQ= github.com/ghodss/yaml v0.0.0-20150909031657-73d445a93680/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= @@ -606,9 +649,8 @@ github.com/gliderlabs/ssh v0.2.2/go.mod h1:U7qILu1NlMHj9FlMhZLlkCdDnU1DBEAqr0aev github.com/globalsign/mgo v0.0.0-20180905125535-1ca0a4f7cbcb/go.mod h1:xkRDCp4j0OGD1HRkm4kmhM+pmpv3AKq5SU7GMg4oO/Q= github.com/globalsign/mgo v0.0.0-20181015135952-eeefdecb41b8/go.mod h1:xkRDCp4j0OGD1HRkm4kmhM+pmpv3AKq5SU7GMg4oO/Q= github.com/go-acme/lego v2.5.0+incompatible/go.mod h1:yzMNe9CasVUhkquNvti5nAtPmG94USbYxYrZfTkIn0M= +github.com/go-asn1-ber/asn1-ber v1.3.1/go.mod h1:hEBeB/ic+5LoWskz+yKT7vGhhPYkProFKoKdwZRWMe0= github.com/go-bindata/go-bindata v3.1.1+incompatible/go.mod h1:xK8Dsgwmeed+BBsSy2XTopBn/8uK2HWuGSnA11C3Joo= -github.com/go-bindata/go-bindata v3.1.2+incompatible h1:5vjJMVhowQdPzjE1LdxyFF7YFTXg5IgGVW4gBr5IbvE= -github.com/go-bindata/go-bindata v3.1.2+incompatible/go.mod h1:xK8Dsgwmeed+BBsSy2XTopBn/8uK2HWuGSnA11C3Joo= github.com/go-critic/go-critic v0.5.6 h1:siUR1+322iVikWXoV75I1YRfNaC/yaLzhdF9Zwd8Tus= github.com/go-critic/go-critic v0.5.6/go.mod h1:cVjj0DfqewQVIlIAGexPCaGaZDAqGE29PYDDADIVNEo= github.com/go-errors/errors v1.0.1 h1:LUHzmkK3GUKUrL/1gfBUxAHzcev3apQlezX/+O7ma6w= @@ -628,12 +670,13 @@ github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2 github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= github.com/go-ini/ini v1.9.0/go.mod h1:ByCAeIL28uOIIG0E3PJtZPDL8WnHpFKFOtgjp+3Ies8= github.com/go-ini/ini v1.25.4/go.mod h1:ByCAeIL28uOIIG0E3PJtZPDL8WnHpFKFOtgjp+3Ies8= -github.com/go-ini/ini v1.51.0 h1:VPJKXGzbKlyExUE8f41aV57yxkYx5R49yR6n7flp0M0= -github.com/go-ini/ini v1.51.0/go.mod h1:ByCAeIL28uOIIG0E3PJtZPDL8WnHpFKFOtgjp+3Ies8= +github.com/go-ini/ini v1.62.0 h1:7VJT/ZXjzqSrvtraFp4ONq80hTcRQth1c9ZnQ3uNQvU= +github.com/go-ini/ini v1.62.0/go.mod h1:ByCAeIL28uOIIG0E3PJtZPDL8WnHpFKFOtgjp+3Ies8= github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= github.com/go-kit/kit v0.9.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= github.com/go-kit/kit v0.10.0/go.mod h1:xUsJbQ/Fp4kEt7AFgCuvyX4a71u8h9jB8tj/ORgOZ7o= github.com/go-ldap/ldap v3.0.2+incompatible/go.mod h1:qfd9rJvER9Q0/D/Sqn1DfHRoBp40uXYvFoEVrNEPqRc= +github.com/go-ldap/ldap/v3 v3.1.3/go.mod h1:3rbOH3jRS2u6jg2rJnKAMLE/xQyCKIveG2Sa/Cohzb8= github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE= github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk= github.com/go-logfmt/logfmt v0.5.0/go.mod h1:wCYkCAKZfumFQihp8CzCvQ3paCTfi41vtzG1KdI/P7A= @@ -643,6 +686,8 @@ github.com/go-logr/logr v0.2.1-0.20200730175230-ee2de8da5be6/go.mod h1:z6/tIYblk github.com/go-logr/logr v0.4.0 h1:K7/B1jt6fIBQVd4Owv2MqGQClcgf0R266+7C/QjRcLc= github.com/go-logr/logr v0.4.0/go.mod h1:z6/tIYblkpsD+a4lm/fGIIU9mZ+XfAiaFtq7xTgseGU= github.com/go-logr/zapr v0.1.0/go.mod h1:tabnROwaDl0UNxkVeFRbY8bwB37GwRv0P8lg6aAiEnk= +github.com/go-logr/zapr v0.1.1/go.mod h1:tabnROwaDl0UNxkVeFRbY8bwB37GwRv0P8lg6aAiEnk= +github.com/go-logr/zapr v0.4.0/go.mod h1:tabnROwaDl0UNxkVeFRbY8bwB37GwRv0P8lg6aAiEnk= github.com/go-ole/go-ole v1.2.5/go.mod h1:pprOEPIfldk/42T2oK7lQ4v4JSDwmV0As9GaiUsvbm0= github.com/go-openapi/analysis v0.0.0-20180825180245-b006789cd277/go.mod h1:k70tL6pCuVxPJOHXQ+wIac1FUrvNkHolPie/cLEU6hI= github.com/go-openapi/analysis v0.17.0/go.mod h1:IowGgpVeD0vNm45So8nr+IcQ3pxVtpRoBWb8PVZO0ik= @@ -710,6 +755,7 @@ github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0/go.mod h1:fyg78 github.com/go-telegram-bot-api/telegram-bot-api v4.6.4+incompatible h1:2cauKuaELYAEARXRkq2LrJ0yDDv1rW7+wrTEdVL3uaU= github.com/go-telegram-bot-api/telegram-bot-api v4.6.4+incompatible/go.mod h1:qf9acutJ8cwBUhm1bqgz6Bei9/C/c93FPDljKWwsOgM= github.com/go-test/deep v1.0.2-0.20181118220953-042da051cf31/go.mod h1:wGDj63lr65AM2AQyKZd/NYHGb0R+1RLqB8NKt3aSFNA= +github.com/go-test/deep v1.0.2/go.mod h1:wGDj63lr65AM2AQyKZd/NYHGb0R+1RLqB8NKt3aSFNA= github.com/go-test/deep v1.0.3/go.mod h1:wGDj63lr65AM2AQyKZd/NYHGb0R+1RLqB8NKt3aSFNA= github.com/go-test/deep v1.0.4 h1:u2CU3YKy9I2pmu9pX0eq50wCgjfGIt539SqR7FbHiho= github.com/go-test/deep v1.0.4/go.mod h1:wGDj63lr65AM2AQyKZd/NYHGb0R+1RLqB8NKt3aSFNA= @@ -733,17 +779,24 @@ github.com/go-toolsmith/typep v1.0.2 h1:8xdsa1+FSIH/RhEkgnD1j2CJOy5mNllW1Q9tRiYw github.com/go-toolsmith/typep v1.0.2/go.mod h1:JSQCQMUPdRlMZFswiq3TGpNp1GMktqkR2Ns5AIQkATU= github.com/go-xmlfmt/xmlfmt v0.0.0-20191208150333-d5b6f63a941b h1:khEcpUM4yFcxg4/FHQWkvVRmgijNXRfzkIDHh23ggEo= github.com/go-xmlfmt/xmlfmt v0.0.0-20191208150333-d5b6f63a941b/go.mod h1:aUCEOzzezBEjDBbFBoSiya/gduyIiWYRP6CnSFIV8AM= -github.com/gobuffalo/flect v0.2.0 h1:EWCvMGGxOjsgwlWaP+f4+Hh6yrrte7JeFL2S6b+0hdM= +github.com/gobuffalo/envy v1.7.0/go.mod h1:n7DRkBerg/aorDM8kbduw5dN3oXGswK5liaSCx4T5NI= +github.com/gobuffalo/envy v1.7.1/go.mod h1:FurDp9+EDPE4aIUS3ZLyD+7/9fpx7YRt/ukY6jIHf0w= github.com/gobuffalo/flect v0.2.0/go.mod h1:W3K3X9ksuZfir8f/LrfVtWmCDQFfayuylOJ7sz/Fj80= github.com/gobuffalo/here v0.6.0/go.mod h1:wAG085dHOYqUpf+Ap+WOdrPTp5IYcDAs/x7PLa8Y5fM= +github.com/gobuffalo/logger v1.0.1/go.mod h1:2zbswyIUa45I+c+FLXuWl9zSWEiVuthsk8ze5s8JvPs= +github.com/gobuffalo/packd v0.3.0/go.mod h1:zC7QkmNkYVGKPw4tHpBQ+ml7W/3tIebgeo1b36chA3Q= +github.com/gobuffalo/packr/v2 v2.7.1/go.mod h1:qYEvAazPaVxy7Y7KR0W8qYEE+RymX74kETFqjFoFlOc= github.com/gobwas/glob v0.2.3 h1:A4xDbljILXROh+kObIiy5kIaPYD8e96x1tgBhUI5J+Y= github.com/gobwas/glob v0.2.3/go.mod h1:d3Ez4x06l9bZtSvzIay5+Yzi0fmZzPgnTbPcKjJAkT8= github.com/gobwas/httphead v0.0.0-20180130184737-2c6c146eadee/go.mod h1:L0fX3K22YWvt/FAX9NnzrNzcI4wNYi9Yku4O0LKYflo= github.com/gobwas/pool v0.2.0/go.mod h1:q8bcK0KcYlCgd9e7WYLm9LpyS+YeLd8JVDW6WezmKEw= github.com/gobwas/ws v1.0.2/go.mod h1:szmBTxLgaFppYjEmNtny/v3w89xOydFnnZMcgRRu/EM= +github.com/godbus/dbus v0.0.0-20190422162347-ade71ed3457e/go.mod h1:bBOAhwG1umN6/6ZUMtDFBMQR8jRg9O75tm9K00oMsK4= github.com/godbus/dbus/v5 v5.0.3/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= +github.com/godror/godror v0.13.3/go.mod h1:2ouUT4kdhUBk7TAkHWD4SN0CdI0pgEQbo8FVHhbSKWg= github.com/gofrs/flock v0.7.0/go.mod h1:F1TvTiK9OcQqauNUHlbJvyl9Qa1QvF/gOUDKA14jxHU= +github.com/gofrs/flock v0.8.0/go.mod h1:F1TvTiK9OcQqauNUHlbJvyl9Qa1QvF/gOUDKA14jxHU= github.com/gofrs/flock v0.8.1 h1:+gYjHKf32LDeiEEFhQaotPbLuUXjY5ZqxKgXy7n59aw= github.com/gofrs/flock v0.8.1/go.mod h1:F1TvTiK9OcQqauNUHlbJvyl9Qa1QvF/gOUDKA14jxHU= github.com/gogo/googleapis v1.1.0/go.mod h1:gf4bu3Q80BeJ6H1S1vYPm8/ELATdvryBaNFGgqEef3s= @@ -865,8 +918,9 @@ github.com/google/go-replayers/httpreplay v0.1.0/go.mod h1:YKZViNhiGgqdBlUbI2MwG github.com/google/go-replayers/httpreplay v1.0.0 h1:8SmT8fUYM4nueF+UnXIX8LJxNTb1vpPuknXz+yTWzL4= github.com/google/go-replayers/httpreplay v1.0.0/go.mod h1:LJhKoTwS5Wy5Ld/peq8dFFG5OfJyHEz7ft+DsTUv25M= 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= +github.com/google/gofuzz v1.2.0 h1:xRy4A+RhZaiKjJ1bPfwQ8sedCA+YS2YcCHW6ec7JMi0= +github.com/google/gofuzz v1.2.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= github.com/google/licenseclassifier v0.0.0-20210325184830-bb04aff29e72/go.mod h1:qsqn2hxC+vURpyBRygGUuinTO42MFRLcsmQ/P8v94+M= github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs= github.com/google/martian v2.1.1-0.20190517191504-25dcb96d9e51+incompatible h1:xmapqc1AyLoB+ddYT6r04bD9lIjlOqGaREovi0SzFaE= @@ -920,13 +974,15 @@ github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5m github.com/googleapis/gax-go/v2 v2.1.0 h1:6DWmvNpomjL1+3liNSZbVns3zsYzzCjm6pRBO1tLeso= github.com/googleapis/gax-go/v2 v2.1.0/go.mod h1:Q3nei7sK6ybPYH7twZdmQpAd1MKb7pfu6SK+H1/DsU0= github.com/googleapis/gnostic v0.3.1/go.mod h1:on+2t9HRStVgn95RSsFWFz+6Q0Snyqv1awfrALZdbtU= -github.com/googleapis/gnostic v0.4.1 h1:DLJCy1n/vrD4HPjOvYcT8aYQXpPIzoRZONaYwyycI+I= github.com/googleapis/gnostic v0.4.1/go.mod h1:LRhVm6pbyptWbWbuZ38d1eyptfvIytN3ir6b65WBswg= +github.com/googleapis/gnostic v0.5.4 h1:ynbQIWjLw7iv6HAFdixb30U7Uvcmx+f4KlLJpmhkTK0= +github.com/googleapis/gnostic v0.5.4/go.mod h1:TRWw1s4gxBGjSe301Dai3c7wXJAZy57+/6tawkOvqHQ= github.com/gookit/color v1.4.2/go.mod h1:fqRyamkC1W8uxl+lxCQxOT09l/vYfZ+QeiX3rKQHCoQ= github.com/gophercloud/gophercloud v0.1.0/go.mod h1:vxM41WHh5uqHVBMZHzuwNOHh8XEoIEcSTewFxm1c5g8= github.com/gophercloud/gophercloud v0.6.1-0.20191122030953-d8ac278c1c9d/go.mod h1:ozGNgr9KYOVATV5jsgHl/ceCDXGuguqOZAzoQ/2vcNM= -github.com/gophercloud/gophercloud v0.11.1-0.20200518183226-7aec46f32c19 h1:Amaxs7PsvtzbahUHadno+OZI0IrMqwbPhoGUVLdM1NA= -github.com/gophercloud/gophercloud v0.11.1-0.20200518183226-7aec46f32c19/go.mod h1:gmC5oQqMDOMO1t1gq5DquX/yAU808e/4mzjjDA76+Ss= +github.com/gophercloud/gophercloud v0.15.1-0.20210105012856-e34a44dc6580/go.mod h1:VX0Ibx85B60B5XOrZr6kaNwrmPUzcmMpwxvQ1WQIIWM= +github.com/gophercloud/gophercloud v0.18.0 h1:V6hcuMPmjXg+js9flU8T3RIHDCjV7F5CG5GD0MRhP/w= +github.com/gophercloud/gophercloud v0.18.0/go.mod h1:wRtmUelyIIv3CSSDI47aUwbs075O6i+LY+pXsKCBsb4= github.com/gophercloud/utils v0.0.0-20200423144003-7c72efc7435d/go.mod h1:ehWUbLQJPqS0Ep+CxeD559hsm9pthPXadJNKwZkp43w= github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1 h1:EGx4pi6eqNxGaHF6qqu48+N2wcFQ5qg5FXgOdqsJ5d8= github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY= @@ -946,7 +1002,9 @@ github.com/goreleaser/nfpm/v2 v2.6.0 h1:bwDU9o4/CVTSpqASJA7+r+rkqpTGamQKYHMRH3wD github.com/goreleaser/nfpm/v2 v2.6.0/go.mod h1:qaMnjBaZz/2vInOIWx0IbuKuaZpaVB6O8oLG0u4qH1Y= github.com/gorhill/cronexpr v0.0.0-20180427100037-88b0669f7d75/go.mod h1:g2644b03hfBX9Ov0ZBDgXXens4rxSxmqFBbhvKv2yVA= github.com/gorilla/context v1.1.1/go.mod h1:kBGZzfjB9CEq2AlWe17Uuf7NDRt0dE0s8S51q0aT7Yg= +github.com/gorilla/handlers v0.0.0-20150720190736-60c7bfde3e33/go.mod h1:Qkdc/uu4tH4g6mTK6auzZ766c4CA0Ng8+o/OAirnOIQ= github.com/gorilla/mux v1.6.2/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs= +github.com/gorilla/mux v1.7.2/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs= github.com/gorilla/mux v1.7.3/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs= github.com/gorilla/mux v1.8.0/go.mod h1:DVbg23sWSpFRCP0SfiEN6jmj59UnW/n46BH5rLB71So= github.com/gorilla/websocket v0.0.0-20170926233335-4201258b820c/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ= @@ -966,6 +1024,7 @@ github.com/gostaticanalysis/forcetypeassert v0.0.0-20200621232751-01d4955beaa5 h github.com/gostaticanalysis/forcetypeassert v0.0.0-20200621232751-01d4955beaa5/go.mod h1:qZEedyP/sY1lTGV1uJ3VhWZ2mqag3IkWsDHVbplHXak= github.com/gostaticanalysis/nilerr v0.1.1 h1:ThE+hJP0fEp4zWLkWHWcRyI2Od0p7DlgYG3Uqrmrcpk= github.com/gostaticanalysis/nilerr v0.1.1/go.mod h1:wZYb6YI5YAxxq0i1+VJbY0s2YONW0HU0GPE3+5PWN4A= +github.com/gosuri/uitable v0.0.4/go.mod h1:tKR86bXuXPZazfOTG1FIzvjIdXzd0mo4Vtn16vt0PJo= github.com/gregjones/httpcache v0.0.0-20180305231024-9cad4c3443a7/go.mod h1:FecbI9+v66THATjSRHfNgh1IVFe/9kFxbXtjV0ctIMA= github.com/gregjones/httpcache v0.0.0-20190611155906-901d90724c79 h1:+ngKgrYPPJrOjhax5N+uePQ0Fh1Z7PheYoUI/0nzkPA= github.com/gregjones/httpcache v0.0.0-20190611155906-901d90724c79/go.mod h1:FecbI9+v66THATjSRHfNgh1IVFe/9kFxbXtjV0ctIMA= @@ -988,6 +1047,7 @@ github.com/hashicorp/consul/api v1.1.0/go.mod h1:VmuI/Lkw1nC05EYQWNKwWGbkg+FbDBt github.com/hashicorp/consul/api v1.3.0/go.mod h1:MmDNSzIMUjNpY/mQ398R4bk2FnqQLoPndWW5VkKPlCE= github.com/hashicorp/consul/sdk v0.1.1/go.mod h1:VKf9jXwCTEY1QZP2MOLRhb5i/I/ssyNV1vwHyQBF0x8= github.com/hashicorp/consul/sdk v0.3.0/go.mod h1:VKf9jXwCTEY1QZP2MOLRhb5i/I/ssyNV1vwHyQBF0x8= +github.com/hashicorp/errwrap v0.0.0-20141028054710-7554cd9344ce/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= github.com/hashicorp/errwrap v0.0.0-20180715044906-d6c0cd880357/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= github.com/hashicorp/errwrap v1.0.0 h1:hLrqtEDnRye3+sgx6z4qVLNuviH3MR5aQ0ykNJa/UYA= github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= @@ -996,28 +1056,36 @@ github.com/hashicorp/go-cleanhttp v0.5.1 h1:dH3aiDG9Jvb5r5+bYHsikaOUIpcM0xvgMXVo github.com/hashicorp/go-cleanhttp v0.5.1/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtngrth3wmdIIUrZ80= github.com/hashicorp/go-hclog v0.0.0-20180709165350-ff2cf002a8dd/go.mod h1:9bjs9uLqI8l75knNv3lV1kA55veR+WUPSiKIWcQHudI= github.com/hashicorp/go-hclog v0.8.0/go.mod h1:5CU+agLiy3J7N7QjHK5d05KxGsuXiQLrjA0H7acj2lQ= -github.com/hashicorp/go-hclog v0.9.2 h1:CG6TE5H9/JXsFWJCfoIVpKFIkFe6ysEuHirp4DxCsHI= github.com/hashicorp/go-hclog v0.9.2/go.mod h1:5CU+agLiy3J7N7QjHK5d05KxGsuXiQLrjA0H7acj2lQ= +github.com/hashicorp/go-hclog v0.12.0 h1:d4QkX8FRTYaKaCZBoXYY8zJX2BXjWxurN/GA2tkrmZM= +github.com/hashicorp/go-hclog v0.12.0/go.mod h1:whpDNt7SSdeAju8AWKIWsul05p54N/39EeqMAyrmvFQ= github.com/hashicorp/go-immutable-radix v1.0.0/go.mod h1:0y9vanUI8NX6FsYoO3zeMjhV/C5i9g4Q3DwcSNZ4P60= +github.com/hashicorp/go-kms-wrapping/entropy v0.1.0/go.mod h1:d1g9WGtAunDNpek8jUIEJnBlbgKS1N2Q61QkHiZyR1g= github.com/hashicorp/go-msgpack v0.5.3/go.mod h1:ahLV/dePpqEmjfWmKiqvPkv/twdG7iPBM1vqhUKIvfM= +github.com/hashicorp/go-multierror v0.0.0-20161216184304-ed905158d874/go.mod h1:JMRHfdO9jKNzS/+BTlxCjKNQHg/jZAft8U7LloJvN7I= github.com/hashicorp/go-multierror v0.0.0-20180717150148-3d5d8f294aa0/go.mod h1:JMRHfdO9jKNzS/+BTlxCjKNQHg/jZAft8U7LloJvN7I= github.com/hashicorp/go-multierror v1.0.0/go.mod h1:dHtQlpGsu+cZNNAkkCN/P3hoUDHhCYQXV3UM06sGGrk= +github.com/hashicorp/go-multierror v1.1.0/go.mod h1:spPvp8C1qA32ftKqdAHm4hHTbPw+vmowP0z+KUhOZdA= github.com/hashicorp/go-multierror v1.1.1 h1:H5DkEtf6CXdFp0N0Em5UCwQpXMWke8IA0+lD48awMYo= github.com/hashicorp/go-multierror v1.1.1/go.mod h1:iw975J/qwKPdAO1clOe2L8331t/9/fmwbPZ6JB6eMoM= github.com/hashicorp/go-plugin v1.0.1/go.mod h1:++UyYGoz3o5w9ZzAdZxtQKrWWP+iqPBn3cQptSMzBuY= +github.com/hashicorp/go-retryablehttp v0.5.3/go.mod h1:9B5zBasrRhHXnJnui7y6sL7es7NDiJgTc6Er0maI1Xs= github.com/hashicorp/go-retryablehttp v0.5.4/go.mod h1:9B5zBasrRhHXnJnui7y6sL7es7NDiJgTc6Er0maI1Xs= github.com/hashicorp/go-retryablehttp v0.6.4/go.mod h1:vAew36LZh98gCBJNLH42IQ1ER/9wtLZZ8meHqQvEYWY= +github.com/hashicorp/go-retryablehttp v0.6.6/go.mod h1:vAew36LZh98gCBJNLH42IQ1ER/9wtLZZ8meHqQvEYWY= github.com/hashicorp/go-retryablehttp v0.6.8 h1:92lWxgpa+fF3FozM4B3UZtHZMJX8T5XT+TFdCxsPyWs= github.com/hashicorp/go-retryablehttp v0.6.8/go.mod h1:vAew36LZh98gCBJNLH42IQ1ER/9wtLZZ8meHqQvEYWY= github.com/hashicorp/go-rootcerts v1.0.0/go.mod h1:K6zTfqpRlCUIjkwsN4Z+hiSfzSTQa6eBIzfwKfwNnHU= -github.com/hashicorp/go-rootcerts v1.0.1 h1:DMo4fmknnz0E0evoNYnV48RjWndOsmd6OW+09R3cEP8= github.com/hashicorp/go-rootcerts v1.0.1/go.mod h1:pqUvnprVnM5bf7AOirdbb01K4ccR319Vf4pU3K5EGc8= +github.com/hashicorp/go-rootcerts v1.0.2 h1:jzhAVGtqPKbwpyCPELlgNWhE1znq+qwJtW5Oi2viEzc= +github.com/hashicorp/go-rootcerts v1.0.2/go.mod h1:pqUvnprVnM5bf7AOirdbb01K4ccR319Vf4pU3K5EGc8= github.com/hashicorp/go-sockaddr v1.0.0/go.mod h1:7Xibr9yA9JjQq1JpNB2Vw7kxv8xerXegt+ozgdvDeDU= github.com/hashicorp/go-sockaddr v1.0.2 h1:ztczhD1jLxIRjVejw8gFomI1BQZOe2WoVOu0SyteCQc= github.com/hashicorp/go-sockaddr v1.0.2/go.mod h1:rB4wwRAUzs07qva3c5SdrY/NEtAUjGlgmH/UkBUC97A= github.com/hashicorp/go-syslog v1.0.0/go.mod h1:qPfqrKkXGihmCqbJM2mZgkZGvKG1dFdvsLplgctolz4= github.com/hashicorp/go-uuid v1.0.0/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= github.com/hashicorp/go-uuid v1.0.1/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= +github.com/hashicorp/go-uuid v1.0.2/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= github.com/hashicorp/go-version v1.1.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA= github.com/hashicorp/go-version v1.2.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA= github.com/hashicorp/go-version v1.2.1/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA= @@ -1033,23 +1101,27 @@ github.com/hashicorp/golang-lru v0.5.4/go.mod h1:iADmTwqILo4mZ8BN3D2Q6+9jd8WM5uG github.com/hashicorp/hcl v0.0.0-20180404174102-ef8a98b0bbce/go.mod h1:oZtUIOe8dh44I2q6ScRibXws4Ajl+d+nod3AaR9vL5w= github.com/hashicorp/hcl v1.0.0 h1:0Anlzjpi4vEasTeNFn2mLJgTSwt0+6sfsiTG8qcWGx4= github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ= -github.com/hashicorp/hcl/v2 v2.3.0/go.mod h1:d+FwDBbOLvpAM3Z6J7gPj/VoAGkNe/gm352ZhjJ/Zv8= +github.com/hashicorp/hcl/v2 v2.10.0/go.mod h1:FwWsfWEjyV/CMj8s/gqAuiviY72rJ1/oayI9WftqcKg= github.com/hashicorp/logutils v1.0.0/go.mod h1:QIAnNjmIWmVIIkWDTG1z5v++HQmx9WQRO+LraFDTW64= github.com/hashicorp/mdns v1.0.0/go.mod h1:tL+uN++7HEJ6SQLQ2/p+z2pH24WQKWjBPkE0mNTz8vQ= github.com/hashicorp/memberlist v0.1.3/go.mod h1:ajVTdAv/9Im8oMAAj5G31PhhMCZJV2pPBoIllUwCN7I= github.com/hashicorp/memberlist v0.1.4/go.mod h1:ajVTdAv/9Im8oMAAj5G31PhhMCZJV2pPBoIllUwCN7I= github.com/hashicorp/serf v0.8.2/go.mod h1:6hOLApaqBFA1NXqRQAsxw9QxuDEvNxSQRwA/JwenrHc= -github.com/hashicorp/vault/api v1.0.4 h1:j08Or/wryXT4AcHj1oCbMd7IijXcKzYUGw59LGu9onU= github.com/hashicorp/vault/api v1.0.4/go.mod h1:gDcqh3WGcR1cpF5AJz/B1UFheUEneMoIospckxBxk6Q= -github.com/hashicorp/vault/sdk v0.1.13 h1:mOEPeOhT7jl0J4AMl1E705+BcmeRs1VmKNb9F0sMLy8= +github.com/hashicorp/vault/api v1.1.0 h1:QcxC7FuqEl0sZaIjcXB/kNEeBa0DH5z57qbWBvZwLC4= +github.com/hashicorp/vault/api v1.1.0/go.mod h1:R3Umvhlxi2TN7Ex2hzOowyeNb+SfbVWI973N+ctaFMk= github.com/hashicorp/vault/sdk v0.1.13/go.mod h1:B+hVj7TpuQY1Y/GPbCpffmgd+tSEwvhkWnjtSYCaS2M= +github.com/hashicorp/vault/sdk v0.1.14-0.20200519221838-e0cfd64bc267 h1:e1ok06zGrWJW91rzRroyl5nRNqraaBe4d5hiKcVZuHM= +github.com/hashicorp/vault/sdk v0.1.14-0.20200519221838-e0cfd64bc267/go.mod h1:WX57W2PwkrOPQ6rVQk+dy5/htHIaB4aBM70EwKThu10= github.com/hashicorp/yamux v0.0.0-20180604194846-3520598351bb/go.mod h1:+NfK9FKeTrX5uv1uIXGdwYDTeHna2qgaIlx54MXqjAM= github.com/hashicorp/yamux v0.0.0-20181012175058-2f1d1f20f75d/go.mod h1:+NfK9FKeTrX5uv1uIXGdwYDTeHna2qgaIlx54MXqjAM= github.com/heketi/heketi v9.0.1-0.20190917153846-c2e2a4ab7ab9+incompatible/go.mod h1:bB9ly3RchcQqsQ9CpyaQwvva7RS5ytVoSoholZQON6o= github.com/heketi/tests v0.0.0-20151005000721-f3775cbcefd6/go.mod h1:xGMAM8JLi7UkZt1i4FQeQy0R2T8GLUwQhOP5M1gBhy4= +github.com/howeyc/gopass v0.0.0-20170109162249-bf9dde6d0d2c/go.mod h1:lADxMC39cJJqL93Duh1xhAs4I2Zs8mKS89XWXFGp9cs= github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= github.com/huandu/xstrings v1.0.0/go.mod h1:4qWG/gcEcfX4z/mBDHJ++3ReCw9ibxbsNJbcucJdbSo= github.com/huandu/xstrings v1.2.0/go.mod h1:DvyZB1rfVYsBIigL8HwpZgxHwXozlTgGqn63UyNX5k4= +github.com/huandu/xstrings v1.3.1/go.mod h1:y5/lhBue+AyNmUVz9RLU9xbLR0o4KIIExikq4ovT0aE= github.com/huandu/xstrings v1.3.2 h1:L18LIDzqlW6xN2rEkpdV8+oL/IXWJ1APd+vsdYy4Wdw= github.com/huandu/xstrings v1.3.2/go.mod h1:y5/lhBue+AyNmUVz9RLU9xbLR0o4KIIExikq4ovT0aE= github.com/hudl/fargo v1.3.0/go.mod h1:y3CKSmjA+wD2gak7sUSXTAoopbhU08POFhmITJgmKTg= @@ -1079,6 +1151,7 @@ github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 h1:BQSFePA1RWJOl github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99/go.mod h1:1lJo3i6rXxKeerYnT8Nvf0QmHCRC1n8sfWVwXF2Frvo= github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI= github.com/jessevdk/go-flags v1.5.0/go.mod h1:Fw0T6WPc1dYxT4mKEZRfG5kJhaTDP9pj1c2EWnYs/m4= +github.com/jetstack/cert-manager v1.3.1/go.mod h1:Hfe4GE3QuRzbrsuReQD5R3PXZqrdfJ2kZ42K67V/V0w= github.com/jgautheron/goconst v1.5.1 h1:HxVbL1MhydKs8R8n/HE5NPvzfaYmQJA3o879lE4+WcM= github.com/jgautheron/goconst v1.5.1/go.mod h1:aAosetZ5zaeC/2EfMeRswtxUFBpe2Hr7HzkgX4fanO4= github.com/jhump/protoreflect v1.6.1/go.mod h1:RZQ/lnuN+zqeRVpQigTwO6o0AJUkxbnSnpuG7toUTG4= @@ -1090,6 +1163,7 @@ github.com/jingyugao/rowserrcheck v1.1.0/go.mod h1:TOQpc2SLx6huPfoFGK3UOnEG+u02D github.com/jirfag/go-printf-func-name v0.0.0-20200119135958-7558a9eaa5af h1:KA9BjwUk7KlCh6S9EAGWBt1oExIUv9WyNCiRz5amv48= github.com/jirfag/go-printf-func-name v0.0.0-20200119135958-7558a9eaa5af/go.mod h1:HEWGJkRDzjJY2sqdDwxccsGicWEf9BQOZsq2tV+xzM0= github.com/jmespath/go-jmespath v0.0.0-20160202185014-0b12d6b521d8/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k= +github.com/jmespath/go-jmespath v0.0.0-20160803190731-bd40a432e4c7/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k= github.com/jmespath/go-jmespath v0.0.0-20180206201540-c2b33e8439af/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k= github.com/jmespath/go-jmespath v0.3.0/go.mod h1:9QtRXoHjLGCJ5IBSaohpXITPlowMeeYCZ7fLUTSywik= github.com/jmespath/go-jmespath v0.4.0 h1:BEgLn5cpjn8UN1mAw4NjwDrS35OdebyEtFe+9YPoQUg= @@ -1104,7 +1178,6 @@ github.com/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22 github.com/jonboulle/clockwork v0.2.0/go.mod h1:Pkfl5aHPm1nk2H9h0bjmnJD/BcgbGXUBGnn1kMkgxc8= github.com/jonboulle/clockwork v0.2.2 h1:UOGuzwb1PwsrDAObMuhUnj0p5ULPj8V/xJ7Kx9qUBdQ= github.com/jonboulle/clockwork v0.2.2/go.mod h1:Pkfl5aHPm1nk2H9h0bjmnJD/BcgbGXUBGnn1kMkgxc8= -github.com/jpillora/backoff v0.0.0-20170918002102-8eab2debe79d/go.mod h1:2iMrUgbbvHEiQClaW2NsSzMyGHqN+rDFqY705q49KG0= github.com/jpillora/backoff v0.0.0-20180909062703-3050d21c67d7/go.mod h1:2iMrUgbbvHEiQClaW2NsSzMyGHqN+rDFqY705q49KG0= github.com/jpillora/backoff v1.0.0/go.mod h1:J/6gKK9jxlEcS3zixgDgUAsiuZ7yrSoa/FX5e0EB2j4= github.com/json-iterator/go v1.1.5/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= @@ -1189,6 +1262,8 @@ github.com/kylelemons/godebug v0.0.0-20170820004349-d65d576e9348/go.mod h1:B69LE github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw= github.com/kyoh86/exportloopref v0.1.8 h1:5Ry/at+eFdkX9Vsdw3qU4YkvGtzuVfzT4X7S77LoN/M= github.com/kyoh86/exportloopref v0.1.8/go.mod h1:1tUcJeiioIs7VWe5gcOObrux3lb66+sBqGZrRkMwPgg= +github.com/lann/builder v0.0.0-20180802200727-47ae307949d0/go.mod h1:dXGbAdH5GtBTC4WfIxhKZfyBF/HBFgRZSWwZ9g/He9o= +github.com/lann/ps v0.0.0-20150810152359-62de8c46ede0/go.mod h1:vmVJ0l/dxyfGW6FmdpVm2joNMFikkuWg0EoCKLGUMNw= github.com/ldez/gomoddirectives v0.2.2 h1:p9/sXuNFArS2RLc+UpYZSI4KQwGMEDWC/LbtF5OPFVg= github.com/ldez/gomoddirectives v0.2.2/go.mod h1:cpgBogWITnCfRq2qGoDkKMEVSaarhdBr6g8G04uz6d0= github.com/ldez/tagliatelle v0.2.0 h1:693V8Bf1NdShJ8eu/s84QySA0J2VWBanVBa2WwXD/Wk= @@ -1232,11 +1307,13 @@ github.com/mailru/easyjson v0.7.0/go.mod h1:KAzv3t3aY1NaHWoQz1+4F1ccyAH66Jk7yos7 github.com/maratori/testpackage v1.0.1 h1:QtJ5ZjqapShm0w5DosRjg0PRlSdAdlx+W6cCKoALdbQ= github.com/maratori/testpackage v1.0.1/go.mod h1:ddKdw+XG0Phzhx8BFDTKgpWP4i7MpApTE5fXSKAqwDU= github.com/markbates/pkger v0.17.1/go.mod h1:0JoVlrol20BSywW79rN3kdFFsE5xYM+rSCQDXbLhiuI= +github.com/marstr/guid v1.1.0/go.mod h1:74gB1z2wpxxInTG6yaqA7KrtM0NZ+RbrcqDvYHefzho= github.com/marten-seemann/qtls v0.2.3/go.mod h1:xzjG7avBwGGbdZ8dTGxlBnLArsVKLvwmjgmPuiQEcYk= github.com/matoous/godox v0.0.0-20210227103229-6504466cf951 h1:pWxk9e//NbPwfxat7RXkts09K+dEBJWakUWwICVqYbA= github.com/matoous/godox v0.0.0-20210227103229-6504466cf951/go.mod h1:1BELzlh859Sh1c6+90blK8lbYy0kwQf1bYlBhBysy1s= github.com/matryer/is v1.4.0 h1:sosSmIWwkYITGrxZ25ULNDeKiMNzFSr4V/eqBQP0PeE= github.com/matryer/is v1.4.0/go.mod h1:8I/i5uYgLzgsgEloJE1U6xx5HkBQpAZvepWuujKwMRU= +github.com/mattbaird/jsonpatch v0.0.0-20171005235357-81af80346b1a/go.mod h1:M1qoD/MqPgTZIk0EWKB38wE28ACRfVcn+cU08jyArI0= github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU= github.com/mattn/go-colorable v0.1.0/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU= github.com/mattn/go-colorable v0.1.1/go.mod h1:FuOcm+DKB9mbwrcAfNl7/TZVBZ6rcnceauSikq3lYCQ= @@ -1255,6 +1332,7 @@ github.com/mattn/go-isatty v0.0.10/go.mod h1:qgIWMr58cqv1PHHyhnkY9lrL7etaEgOFcME github.com/mattn/go-isatty v0.0.11/go.mod h1:PhnuNfih5lzO57/f3n+odYbM4JtupLOxQOAqxQCu2WE= 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/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU= github.com/mattn/go-runewidth v0.0.6/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI= @@ -1264,6 +1342,7 @@ github.com/mattn/go-runewidth v0.0.12 h1:Y41i/hVW3Pgwr8gV+J23B9YEY0zxjptBuCWEaxm github.com/mattn/go-runewidth v0.0.12/go.mod h1:RAqKPSqVFrSLVXbA8x7dzmKdmGzieGRCM46jaSJTDAk= github.com/mattn/go-shellwords v1.0.10/go.mod h1:EZzvwXDESEeg03EKmM+RmDnNOPKG4lLtQsUlTZDWQ8Y= github.com/mattn/go-sqlite3 v1.9.0/go.mod h1:FPy6KqzDD04eiIsT53CuJW3U88zkxoIYsOqkbpncsNc= +github.com/mattn/go-sqlite3 v1.12.0/go.mod h1:FPy6KqzDD04eiIsT53CuJW3U88zkxoIYsOqkbpncsNc= github.com/mattn/go-sqlite3 v1.14.6/go.mod h1:NyWgC/yNuGj7Q9rpYnZvas74GogHl5/Z4A/KQRfk6bU= github.com/mattn/go-sqlite3 v1.14.7/go.mod h1:NyWgC/yNuGj7Q9rpYnZvas74GogHl5/Z4A/KQRfk6bU= github.com/mattn/go-zglob v0.0.1/go.mod h1:9fxibJccNxU2cnpIKLRRFA7zX7qhkJIQWBb449FYHOo= @@ -1280,11 +1359,12 @@ github.com/mgechev/dots v0.0.0-20190921121421-c36f7dcfbb81/go.mod h1:KQ7+USdGKfp github.com/mgechev/revive v1.1.0 h1:TvabpsolbtlzZTyJcgMRN38MHrgi8C0DhmGE5dhscGY= github.com/mgechev/revive v1.1.0/go.mod h1:PKqk4L74K6wVNwY2b6fr+9Qqr/3hIsHVfZCJdbvozrY= github.com/mgutz/ansi v0.0.0-20170206155736-9520e82c474b/go.mod h1:01TrycV0kFyexm33Z7vhZRXopbI8J3TDReVlkTgMUxE= +github.com/mgutz/str v1.2.0/go.mod h1:w1v0ofgLaJdoD0HpQ3fycxKD1WtxpjSo151pK/31q6w= github.com/mholt/certmagic v0.6.2-0.20190624175158-6a42ef9fe8c2/go.mod h1:g4cOPxcjV0oFq3qwpjSA30LReKD8AoIfwAY9VvG35NY= -github.com/miekg/coredns v0.0.0-20161111164017-20e25559d5ea/go.mod h1:ulj34RFTnjlzXt4MMq5AcKBIiXNiru0D2fe3enowwU4= github.com/miekg/dns v1.0.14/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg= github.com/miekg/dns v1.1.3/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg= github.com/miekg/dns v1.1.4/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg= +github.com/miekg/dns v1.1.31/go.mod h1:KNUDUusw/aVsxyTYZM1oqvCicbwhgbNgztCETuNZ7xM= github.com/miekg/dns v1.1.35/go.mod h1:KNUDUusw/aVsxyTYZM1oqvCicbwhgbNgztCETuNZ7xM= github.com/miekg/pkcs11 v1.0.2/go.mod h1:XsNlhZGX73bx86s2hdc/FuaLm2CPZJemRLMA+WTFxgs= github.com/miekg/pkcs11 v1.0.3/go.mod h1:XsNlhZGX73bx86s2hdc/FuaLm2CPZJemRLMA+WTFxgs= @@ -1308,9 +1388,11 @@ github.com/mitchellh/mapstructure v0.0.0-20160808181253-ca63d7c062ee/go.mod h1:F github.com/mitchellh/mapstructure v0.0.0-20180220230111-00c29f56e238/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= github.com/mitchellh/mapstructure v0.0.0-20180715050151-f15292f7a699/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= +github.com/mitchellh/mapstructure v1.3.2/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= github.com/mitchellh/mapstructure v1.3.3/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= github.com/mitchellh/mapstructure v1.4.1 h1:CpVNEelQCZBooIPDn+AR3NpivK/TIKU8bDxdASFVQag= github.com/mitchellh/mapstructure v1.4.1/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= +github.com/mitchellh/osext v0.0.0-20151018003038-5e2d6d41470f/go.mod h1:OkQIRizQZAeMln+1tSwduZz7+Af5oFlKirV/MSYes2A= github.com/mitchellh/reflectwalk v1.0.0/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx0jmZXqmk4esnw= github.com/mitchellh/reflectwalk v1.0.1 h1:FVzMWA5RllMAKIdUSC8mdWo3XtwoecrH79BY70sEEpE= github.com/mitchellh/reflectwalk v1.0.1/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx0jmZXqmk4esnw= @@ -1339,6 +1421,7 @@ github.com/mozilla/tls-observatory v0.0.0-20210609171429-7bc42856d2e5/go.mod h1: github.com/mreiferson/go-httpclient v0.0.0-20160630210159-31f0106b4474/go.mod h1:OQA4XLvDbMgS8P0CevmM4m9Q3Jq4phKUzcocxuGJ5m8= github.com/mrunalp/fileutils v0.0.0-20171103030105-7d4729fb3618/go.mod h1:x8F1gnqOkIEiO4rqoeEEEqQbo7HjGMTvyoq3gej4iT0= github.com/mrunalp/fileutils v0.0.0-20200520151820-abd8a0e76976/go.mod h1:x8F1gnqOkIEiO4rqoeEEEqQbo7HjGMTvyoq3gej4iT0= +github.com/munnerz/crd-schema-fuzz v1.0.0/go.mod h1:4z/rcm37JxUkSsExFcLL6ZIT1SgDRdLiu7qq1evdVS0= github.com/munnerz/goautoneg v0.0.0-20120707110453-a547fc61f48d/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ= github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ= github.com/mvdan/xurls v1.1.0/go.mod h1:tQlNn3BED8bE/15hnSL2HLkDeLWpNPAwtw7wkEq44oU= @@ -1360,6 +1443,7 @@ github.com/nats-io/nkeys v0.1.3/go.mod h1:xpnFELMwJABBLVhffcfd1MZx6VsNRFpEugbxzi github.com/nats-io/nuid v1.0.1/go.mod h1:19wcPz3Ph3q0Jbyiqsd0kePYG7A95tJPxeL+1OSON2c= github.com/nbutton23/zxcvbn-go v0.0.0-20210217022336-fa2cb2858354 h1:4kuARK6Y6FxaNu/BnU2OAaLF86eTVhP2hjTB6iMvItA= github.com/nbutton23/zxcvbn-go v0.0.0-20210217022336-fa2cb2858354/go.mod h1:KSVJerMDfblTH7p5MZaTt+8zaT2iEk3AkVb9PQdZuE8= +github.com/ncw/swift v1.0.47/go.mod h1:23YIA4yWVnGwv2dQlN4bB7egfYX6YLn0Yo/S6zZO/ZM= github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno= github.com/nishanths/exhaustive v0.2.3 h1:+ANTMqRNrqwInnP9aszg/0jDo+zbXa4x66U19Bx/oTk= github.com/nishanths/exhaustive v0.2.3/go.mod h1:bhIX678Nx8inLM9PbpvK1yv6oGtoP8BfaIeMzgBNKvc= @@ -1381,6 +1465,7 @@ github.com/olekukonko/tablewriter v0.0.4/go.mod h1:zq6QwlOf5SlnkVbMSr5EoBv3636FW github.com/olekukonko/tablewriter v0.0.5 h1:P2Ga83D34wi1o9J6Wh1mRuqd4mF/x/lgBS7N7AbDhec= github.com/olekukonko/tablewriter v0.0.5/go.mod h1:hPp6KlRPjbx+hW8ykQs1w3UBbZlj6HuIJcUGPhkA7kY= github.com/onsi/ginkgo v0.0.0-20170829012221-11459a886d9c/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= +github.com/onsi/ginkgo v1.4.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/ginkgo v1.7.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/ginkgo v1.8.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= @@ -1391,17 +1476,21 @@ github.com/onsi/ginkgo v1.12.0/go.mod h1:oUhWkIvk5aDxtKvDDuw8gItl8pKl42LzjC9KZE0 github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk= github.com/onsi/ginkgo v1.14.0/go.mod h1:iSB4RoI2tjJc9BBv4NKIKWKya62Rps+oPG/Lv9klQyY= github.com/onsi/ginkgo v1.14.2/go.mod h1:iSB4RoI2tjJc9BBv4NKIKWKya62Rps+oPG/Lv9klQyY= +github.com/onsi/ginkgo v1.15.0/go.mod h1:hF8qUzuuC8DJGygJH3726JnCZX4MYbRB8yFfISqnKUg= github.com/onsi/ginkgo v1.16.2/go.mod h1:CObGmKUOKaSC0RjmoAK7tKyn4Azo5P2IWuoMnvwxz1E= github.com/onsi/ginkgo v1.16.4 h1:29JGrr5oVBm5ulCWet69zQkzWipVXIol6ygQUe/EzNc= github.com/onsi/ginkgo v1.16.4/go.mod h1:dX+/inL/fNMqNlz0e9LfyB9TswhZpCVdJM/Z6Vvnwo0= github.com/onsi/gomega v0.0.0-20170829124025-dcabb60a477c/go.mod h1:C1qb7wdrVGGVU+Z6iS04AVkA3Q65CEZX59MT0QO5uiA= +github.com/onsi/gomega v1.3.0/go.mod h1:C1qb7wdrVGGVU+Z6iS04AVkA3Q65CEZX59MT0QO5uiA= github.com/onsi/gomega v1.4.3/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= github.com/onsi/gomega v1.5.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= github.com/onsi/gomega v1.7.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY= +github.com/onsi/gomega v1.8.1/go.mod h1:Ho0h+IUsWyvy1OpqCwxlQ/21gkhVunqlU8fDGcoTdcA= github.com/onsi/gomega v1.9.0/go.mod h1:Ho0h+IUsWyvy1OpqCwxlQ/21gkhVunqlU8fDGcoTdcA= github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo= github.com/onsi/gomega v1.10.3/go.mod h1:V9xEwhxec5O8UDM77eCW8vLymOMltsqPVYWrpDsH8xc= +github.com/onsi/gomega v1.10.5/go.mod h1:gza4q3jKQJijlu05nKWRCW/GavJumGt8aNRxWg7mt48= github.com/onsi/gomega v1.11.0/go.mod h1:azGKhqFUon9Vuj0YmTfLSmx0FUwqXYSTl5re8lQLTUg= github.com/onsi/gomega v1.13.0/go.mod h1:lRk9szgn8TxENtWd0Tp4c3wjlRfMTMH27I+3Je41yGY= github.com/onsi/gomega v1.14.0/go.mod h1:cIuvLEne0aoVhAgh/O6ac0Op8WWw9H6eYCriF+tEHG0= @@ -1409,15 +1498,20 @@ github.com/onsi/gomega v1.16.0 h1:6gjqkI8iiRHMvdccRJM8rVKjCWk6ZIm6FTm3ddIe4/c= github.com/onsi/gomega v1.16.0/go.mod h1:HnhC7FXeEQY45zxNK3PPoIUhzk/80Xly9PcubAlGdZY= github.com/op/go-logging v0.0.0-20160315200505-970db520ece7 h1:lDH9UUVJtmYCjyT0CI4q8xvlXPxeZ0gYCVvWbmPlp88= github.com/op/go-logging v0.0.0-20160315200505-970db520ece7/go.mod h1:HzydrMdWErDVzsI23lYNej1Htcns9BCg93Dk0bBINWk= +github.com/opencontainers/go-digest v0.0.0-20170106003457-a6d0ee40d420/go.mod h1:cMLVZDEM3+U2I4VmLI6N8jQYUd2OVphdqWwCJHrFt2s= github.com/opencontainers/go-digest v0.0.0-20180430190053-c9281466c8b2/go.mod h1:cMLVZDEM3+U2I4VmLI6N8jQYUd2OVphdqWwCJHrFt2s= github.com/opencontainers/go-digest v1.0.0-rc1/go.mod h1:cMLVZDEM3+U2I4VmLI6N8jQYUd2OVphdqWwCJHrFt2s= github.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3IKzErnv2BNG4W4MAM= +github.com/opencontainers/image-spec v1.0.0/go.mod h1:BtxoFyWECRxE4U/7sNtV5W15zMzWCbyJoFRP3s7yZA0= github.com/opencontainers/image-spec v1.0.1/go.mod h1:BtxoFyWECRxE4U/7sNtV5W15zMzWCbyJoFRP3s7yZA0= github.com/opencontainers/runc v0.0.0-20190115041553-12f6a991201f/go.mod h1:qT5XzbpPznkRYVz/mWwUaVBUv2rmF59PVA73FjuZG0U= +github.com/opencontainers/runc v0.1.1/go.mod h1:qT5XzbpPznkRYVz/mWwUaVBUv2rmF59PVA73FjuZG0U= github.com/opencontainers/runc v1.0.0-rc90.0.20200616040943-82d2fa4eb069/go.mod h1:3Sm6Dt7OT8z88EbdQqqcRN2oCT54jbi72tT/HqgflT8= github.com/opencontainers/runc v1.0.0-rc91.0.20200707015106-819fcc687efb/go.mod h1:ZuXhqlr4EiRYgDrBDNfSbE4+n9JX4+V107NwAmF7sZA= +github.com/opencontainers/runtime-spec v0.1.2-0.20190507144316-5b71a03e2700/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0= github.com/opencontainers/runtime-spec v1.0.2/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0= github.com/opencontainers/runtime-spec v1.0.3-0.20200520003142-237cc4f519e2/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0= +github.com/opencontainers/runtime-tools v0.0.0-20181011054405-1d69bd0f9c39/go.mod h1:r3f7wjNzSs2extwzU3Y+6pKfobzPh+kKFJ3ofN+3nfs= github.com/opencontainers/selinux v1.5.1/go.mod h1:yTcKuYAh6R95iDpefGLQaPaRwJFwyzAJufJyiTt7s0g= github.com/opencontainers/selinux v1.5.2/go.mod h1:yTcKuYAh6R95iDpefGLQaPaRwJFwyzAJufJyiTt7s0g= github.com/opentracing-contrib/go-observer v0.0.0-20170622124052-a52f23424492/go.mod h1:Ngi6UdF0k5OKD5t5wlmGhe/EDKPoUM3BXZSSfIuJbis= @@ -1436,29 +1530,34 @@ github.com/otiai10/mint v1.3.1/go.mod h1:/yxELlJQ0ufhjUwhshSj+wFjZ78CnZ48/1wtmBH github.com/pact-foundation/pact-go v1.0.4/go.mod h1:uExwJY4kCzNPcHRj+hCR/HBbOOIwwtUjcrb0b5/5kLM= github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc= github.com/pascaldekloe/goe v0.1.0/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc= +github.com/pavel-v-chernykh/keystore-go v2.1.0+incompatible/go.mod h1:xlUlxe/2ItGlQyMTstqeDv9r3U4obH7xYd26TbDQutY= +github.com/pavel-v-chernykh/keystore-go/v4 v4.1.0/go.mod h1:2ejgys4qY+iNVW1IittZhyRYA6MNv8TgM6VHqojbB9g= github.com/pborman/uuid v1.2.0/go.mod h1:X/NO0urCmaxf9VXbdlT7C2Yzkj2IKimNn4k+gtPdI/k= github.com/pelletier/go-buffruneio v0.2.0/go.mod h1:JkE26KsDizTr40EUHkXVtNPvgGtbSNq5BcowyYOWdKo= github.com/pelletier/go-toml v0.0.0-20180724185102-c2dbbc24a979/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic= github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic= github.com/pelletier/go-toml v1.4.0/go.mod h1:PN7xzY2wHTK0K9p34ErDQMlFxa51Fk0OUruD3k1mMwo= github.com/pelletier/go-toml v1.8.1/go.mod h1:T2/BmBdy8dvIRq1a/8aqjN41wvWlN4lrapLU/GW4pbc= +github.com/pelletier/go-toml v1.9.0/go.mod h1:u1nR/EPcESfeI/szUZKdtJ0xRNbUoANCkoOuaOx1Y+c= github.com/pelletier/go-toml v1.9.3 h1:zeC5b1GviRUyKYd6OJPvBU/mcVDVoL1OhT17FCt5dSQ= github.com/pelletier/go-toml v1.9.3/go.mod h1:u1nR/EPcESfeI/szUZKdtJ0xRNbUoANCkoOuaOx1Y+c= github.com/performancecopilot/speed v3.0.0+incompatible/go.mod h1:/CLtqpZ5gBg1M9iaPbIdPPGyKcA8hKdoy6hAWba7Yac= github.com/peterbourgon/diskv v2.0.1+incompatible/go.mod h1:uqqh8zWWbv1HBMNONnaR/tNboyR3/BZd58JJSHlUSCU= github.com/phayes/checkstyle v0.0.0-20170904204023-bfd46e6a821d h1:CdDQnGF8Nq9ocOS/xlSptM1N3BbrA6/kmaep5ggwaIA= github.com/phayes/checkstyle v0.0.0-20170904204023-bfd46e6a821d/go.mod h1:3OzsM7FXDQlpCiw2j81fOmAwQLnZnLGXVKUzeKQXIAw= +github.com/phayes/freeport v0.0.0-20180830031419-95f893ade6f2/go.mod h1:iIss55rKnNBTvrwdmkUpLnDpZoAHvWaiq5+iMmen4AE= github.com/pierrec/lz4 v1.0.2-0.20190131084431-473cd7ce01a1/go.mod h1:3/3N9NVKO0jef7pBehbT1qWhCMrIgbYNnFAZCqQ5LRc= github.com/pierrec/lz4 v2.0.5+incompatible h1:2xWsjqPFWcplujydGg4WmhC/6fZqK42wMM8aXeqhl0I= github.com/pierrec/lz4 v2.0.5+incompatible/go.mod h1:pdkljMzZIN41W+lC3N2tnIh5sFi+IEE17M5jbnwPHcY= github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +github.com/pkg/errors v0.8.1-0.20171018195549-f15c970de5b7/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/profile v1.2.1/go.mod h1:hJw3o1OdXxsrSjjVksARp5W95eeEaEfptyVZyv6JUPA= -github.com/pkg/sftp v0.0.0-20160930220758-4d0e916071f6/go.mod h1:NxmoDg/QLVWluQDUYG7XBZTLUpKeFa8e3aMf1BfjyHk= -github.com/pkg/sftp v1.10.1 h1:VasscCm72135zRysgrJDKsntdmPN+OuU3+nnHYA9wyc= github.com/pkg/sftp v1.10.1/go.mod h1:lYOWFsE0bwd1+KfKJaKeuokY15vzFx25BLbzYYoAxZI= +github.com/pkg/sftp v1.13.0 h1:Riw6pgOKK41foc1I1Uu03CjvbLZDXeGpInycM4shXoI= +github.com/pkg/sftp v1.13.0/go.mod h1:41g+FIPlQUTDCveupEmEA65IoiQFrtgCeDopC4ajGIM= github.com/pmezard/go-difflib v0.0.0-20151028094244-d8ed2627bdf0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= @@ -1466,6 +1565,7 @@ github.com/polyfloyd/go-errorlint v0.0.0-20210510181950-ab96adb96fea h1:Sk6Xawg5 github.com/polyfloyd/go-errorlint v0.0.0-20210510181950-ab96adb96fea/go.mod h1:wi9BfjxjF/bwiZ701TzmfKu6UKC357IOAtNr0Td0Lvw= github.com/posener/complete v1.1.1/go.mod h1:em0nMJCgc9GFtwrmVmEMR/ZL6WyhyjMBndrE9hABlRI= github.com/pquerna/cachecontrol v0.0.0-20171018203845-0dec1b30a021/go.mod h1:prYjPmNq4d1NPVmpShWobRqXY3q7Vp+80DqgxxUrUIA= +github.com/prometheus/client_golang v0.0.0-20180209125602-c332b6f63c06/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= github.com/prometheus/client_golang v0.9.2/go.mod h1:OsXs2jCmiKlQ1lTBmv21f2mNfw4xf/QclQDMrYNZzcM= github.com/prometheus/client_golang v0.9.3-0.20190127221311-3c4408c8b829/go.mod h1:p2iRAGwDERtqlqzRXnrOVns+ignqQo//hLXqYxZYVNs= @@ -1475,8 +1575,10 @@ github.com/prometheus/client_golang v1.1.0/go.mod h1:I1FGZT9+L76gKKOs5djB6ezCbFQ github.com/prometheus/client_golang v1.3.0/go.mod h1:hJaj2vgQTGQmVCsAACORcieXFeDPbaTKGT+JTgUa3og= github.com/prometheus/client_golang v1.5.1/go.mod h1:e9GMxYsXl05ICDXkRhurwBS4Q3OK1iX/F2sw+iXX5zU= github.com/prometheus/client_golang v1.7.1/go.mod h1:PY5Wy2awLA44sXw4AOSfFBetzPP4j5+D6mVACh+pe2M= +github.com/prometheus/client_golang v1.9.0/go.mod h1:FqZLKOZnGdFAhOK4nqGHa7D66IdsO+O441Eve7ptJDU= github.com/prometheus/client_golang v1.10.0 h1:/o0BDeWzLWXNZ+4q5gXltUvaMpJqckTa+jTNoB+z4cg= github.com/prometheus/client_golang v1.10.0/go.mod h1:WJM3cc3yu7XKBKa/I8WeZm+V3eltZnBwfENSU7mdogU= +github.com/prometheus/client_model v0.0.0-20171117100541-99fa1f4be8e5/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= github.com/prometheus/client_model v0.0.0-20190115171406-56726106282f/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= @@ -1484,6 +1586,7 @@ github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1: github.com/prometheus/client_model v0.1.0/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/prometheus/client_model v0.2.0 h1:uq5h0d+GuxiXLJLNABMgp2qUWDPiLvgCzz2dUR+/W/M= github.com/prometheus/client_model v0.2.0/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= +github.com/prometheus/common v0.0.0-20180110214958-89604d197083/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro= github.com/prometheus/common v0.0.0-20181113130724-41aa239b4cce/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro= github.com/prometheus/common v0.0.0-20181126121408-4724e9255275/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro= github.com/prometheus/common v0.2.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= @@ -1493,6 +1596,7 @@ github.com/prometheus/common v0.6.0/go.mod h1:eBmuwkDJBwy6iBfxCBob6t6dR6ENT/y+J+ github.com/prometheus/common v0.7.0/go.mod h1:DjGbpBbp5NYNiECxcL/VnbXCCaQpKd3tt26CguLLsqA= github.com/prometheus/common v0.9.1/go.mod h1:yhUN8i9wzaXS3w1O07YhxHEBxD+W35wd8bs7vj7HSQ4= github.com/prometheus/common v0.10.0/go.mod h1:Tlit/dnDKsSWFlCLTWaA1cyBgKHSMdTB80sz/V91rCo= +github.com/prometheus/common v0.15.0/go.mod h1:U+gB1OBLb1lF3O42bTCL+FK18tX9Oar16Clt/msog/s= github.com/prometheus/common v0.18.0/go.mod h1:U+gB1OBLb1lF3O42bTCL+FK18tX9Oar16Clt/msog/s= github.com/prometheus/common v0.24.0 h1:aIycr3wRFxPUq8XlLQlGQ9aNXV3dFi5y62pe/SB262k= github.com/prometheus/common v0.24.0/go.mod h1:H6QK/N6XVT42whUeIdI3dp36w49c+/iMDk7UAI2qm7Q= @@ -1503,6 +1607,7 @@ github.com/prometheus/procfs v0.0.0-20190117184657-bf6a532e95b1/go.mod h1:c3At6R github.com/prometheus/procfs v0.0.0-20190507164030-5867b95ac084/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= github.com/prometheus/procfs v0.0.3/go.mod h1:4A/X28fw3Fc593LaREMrKMqOKvUAntwMDaekg4FpcdQ= +github.com/prometheus/procfs v0.0.5/go.mod h1:4A/X28fw3Fc593LaREMrKMqOKvUAntwMDaekg4FpcdQ= github.com/prometheus/procfs v0.0.8/go.mod h1:7Qr8sr6344vo1JqZ6HhLceV9o3AJ1Ff+GxbHq6oeK9A= github.com/prometheus/procfs v0.0.11/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU= github.com/prometheus/procfs v0.1.3/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU= @@ -1535,9 +1640,13 @@ github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6So github.com/rogpeppe/fastuuid v1.1.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ= github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ= github.com/rogpeppe/go-charset v0.0.0-20180617210344-2471d30d28b4/go.mod h1:qgYeAmZ5ZIpBWTGllZSQnw97Dj+woV0toclVaRGI8pc= +github.com/rogpeppe/go-internal v1.1.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= +github.com/rogpeppe/go-internal v1.3.2/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc= +github.com/rogpeppe/go-internal v1.4.0/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc= github.com/rogpeppe/go-internal v1.6.2/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc= github.com/rs/cors v1.7.0/go.mod h1:gFx+x8UowdsKA9AchylcLynDq+nNFfI8FkUZdN/jGCU= +github.com/rubenv/sql-migrate v0.0.0-20200616145509-8d140a17f351/go.mod h1:DCgfY80j8GYL7MLEfvcpSFvjD0L5yZq/aZUJmhZklyg= github.com/rubiojr/go-vhd v0.0.0-20200706105327-02e210299021/go.mod h1:DM5xW0nvfNNm2uytzsvhI3OnX8uzaRAg8UX/CnDqbto= github.com/russross/blackfriday v0.0.0-20170610170232-067529f716f4/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR/rfWxYHBV53g= github.com/russross/blackfriday v1.5.2 h1:HyvC0ARfnZBqnXwABFeSZHpKvJHJJfPz81GNueLj0oo= @@ -1576,6 +1685,7 @@ github.com/sergi/go-diff v1.2.0/go.mod h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNX github.com/shazow/go-diff v0.0.0-20160112020656-b6b7b6733b8c h1:W65qqJCIOVP4jpqPQ0YvHYKwcMEMVWIzWC5iNQQfBTU= github.com/shazow/go-diff v0.0.0-20160112020656-b6b7b6733b8c/go.mod h1:/PevMnwAxekIXwN8qQyfc5gl2NlkB3CQlkizAbOkeBs= github.com/shirou/gopsutil/v3 v3.21.7/go.mod h1:RGl11Y7XMTQPmHh8F0ayC6haKNBgH4PXMJuTAcMOlz4= +github.com/shopspring/decimal v1.2.0/go.mod h1:DKyhrW/HYNuLGql+MJL6WCR6knT2jwCFRcu2hWCYk4o= github.com/shurcooL/go v0.0.0-20180423040247-9e1955d9fb6e/go.mod h1:TDJrrUr11Vxrven61rcy3hJMUqaf/CLWYhHNPmT14Lk= github.com/shurcooL/go-goon v0.0.0-20170922171312-37c2f522c041/go.mod h1:N5mDOmsrJOB+vfqUK+7DmDyjhSLIIBnXo9lvZJj3MWQ= github.com/shurcooL/httpfs v0.0.0-20190707220628-8d4bc4ba7749 h1:bUGsEnyNbVPw06Bs80sCeARAlK8lhwqGyi6UT8ymuGk= @@ -1583,6 +1693,7 @@ github.com/shurcooL/httpfs v0.0.0-20190707220628-8d4bc4ba7749/go.mod h1:ZY1cvUeJ github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc= github.com/shurcooL/vfsgen v0.0.0-20181202132449-6a9ea43bcacd h1:ug7PpSOB5RBPK1Kg6qskGBoP3Vnj/aNYFTznWvlkGo0= github.com/shurcooL/vfsgen v0.0.0-20181202132449-6a9ea43bcacd/go.mod h1:TrYk7fJVaAttu97ZZKrO9UbRa8izdowaMIZcxYMbVaw= +github.com/sirupsen/logrus v1.0.4-0.20170822132746-89742aefa4b2/go.mod h1:pMByvHTf9Beacp5x1UXfOR9xyW/9antXMhjMPG0dEzc= github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= github.com/sirupsen/logrus v1.3.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= github.com/sirupsen/logrus v1.4.1/go.mod h1:ni0Sbl8bgC9z8RoU9G6nDWqqs/fq4eDPysMBDgk/93Q= @@ -1594,8 +1705,9 @@ github.com/sirupsen/logrus v1.8.1/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic github.com/slack-go/slack v0.9.4 h1:C+FC3zLxLxUTQjDy2RZeMHYon005zsCROiZNWVo+opQ= github.com/slack-go/slack v0.9.4/go.mod h1:wWL//kk0ho+FcQXcBTmEafUI5dz4qz5f4mMk8oIkioQ= github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc= -github.com/smartystreets/assertions v1.0.0 h1:UVQPSSmc3qtTi+zPPkCXvZX9VvW/xT/NsRvKfwY81a8= github.com/smartystreets/assertions v1.0.0/go.mod h1:kHHU4qYBaI3q23Pp3VPrmWhuIUrLW/7eUrw0BU5VaoM= +github.com/smartystreets/assertions v1.2.0 h1:42S6lae5dvLc7BrLu/0ugRtcFVjoJNMC/N3yZFZkDFs= +github.com/smartystreets/assertions v1.2.0/go.mod h1:tcbTF8ujkAEcZ8TElKY+i30BzYlVhC/LOxJk7iOWnoo= github.com/smartystreets/go-aws-auth v0.0.0-20180515143844-0c1422d1fdb9/go.mod h1:SnhjPscd9TpLiy1LpzGSKh3bXCfxxXuqd9xmQJy3slM= github.com/smartystreets/goconvey v0.0.0-20190330032615-68dc04aab96a/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA= github.com/smartystreets/goconvey v1.6.4 h1:fv0U8FUIMPNf1L9lnHLvLhgicrIVChEkdzIKYqbNC9s= @@ -1625,6 +1737,7 @@ github.com/spf13/cast v1.3.0/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkU github.com/spf13/cast v1.3.1 h1:nFm6S0SMdyzrzcmThSipiEubIDy8WEXKNZ0UOgiRpng= github.com/spf13/cast v1.3.1/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE= github.com/spf13/cobra v0.0.0-20180820174524-ff0d02e85550/go.mod h1:1l0Ry5zgKvJasoi3XT1TypsSe7PqH0Sj9dhYf7v3XqQ= +github.com/spf13/cobra v0.0.2-0.20171109065643-2da4a54c5cee/go.mod h1:1l0Ry5zgKvJasoi3XT1TypsSe7PqH0Sj9dhYf7v3XqQ= github.com/spf13/cobra v0.0.3/go.mod h1:1l0Ry5zgKvJasoi3XT1TypsSe7PqH0Sj9dhYf7v3XqQ= github.com/spf13/cobra v0.0.5/go.mod h1:3K3wKZymM7VvHMDS9+Akkh4K60UwM26emMESw8tLCHU= github.com/spf13/cobra v0.0.7/go.mod h1:/6GTrnGXV9HjY+aR4k0oJ5tcvakLuG6EuKReYlHNrgE= @@ -1639,6 +1752,7 @@ github.com/spf13/jwalterweatherman v1.1.0 h1:ue6voC5bR5F8YxI5S67j9i582FU4Qvo2bmq github.com/spf13/jwalterweatherman v1.1.0/go.mod h1:aNWZUN0dPAAO/Ljvb5BEdw96iTZ0EXowPYD95IqWIGo= github.com/spf13/pflag v0.0.0-20170130214245-9ff6c6923cff/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= github.com/spf13/pflag v0.0.0-20180821114517-d929dcbb1086/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= +github.com/spf13/pflag v1.0.1-0.20171106142849-4c012f6dcd95/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= github.com/spf13/pflag v1.0.1/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= github.com/spf13/pflag v1.0.2/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= @@ -1651,11 +1765,12 @@ github.com/spf13/viper v1.7.0/go.mod h1:8WkrPz2fc9jxqZNCJI/76HCieCp4Q8HaLFoCha5q github.com/spf13/viper v1.7.1/go.mod h1:8WkrPz2fc9jxqZNCJI/76HCieCp4Q8HaLFoCha5qpdg= github.com/spf13/viper v1.8.1 h1:Kq1fyeebqsBfbjZj4EL7gj2IO0mMaiyjYUWcUsl2O44= github.com/spf13/viper v1.8.1/go.mod h1:o0Pch8wJ9BVSWGQMbra6iw0oQ5oktSIBaujf1rJH9Ns= -github.com/spotinst/spotinst-sdk-go v1.58.0 h1:h7617CMlfHL3W+CMlhs883kVy3MPdGML/Z4+mW+ddgc= -github.com/spotinst/spotinst-sdk-go v1.58.0/go.mod h1:nWi2DyjUi1WUZclpsqZFXvImsU0T39ppqqHwC4/T5mw= +github.com/spotinst/spotinst-sdk-go v1.85.0 h1:tMXKhxfmU7BnqTnUpR2s/hEyTASfrxkgPb/3Tqn6tmM= +github.com/spotinst/spotinst-sdk-go v1.85.0/go.mod h1:RuKksd1/RyQogMCxKFI5B75NeFRcgl3W+26DVX6S4m0= github.com/src-d/gcfg v1.4.0/go.mod h1:p/UMsR43ujA89BJY9duynAwIpvqEujIH/jFlfL7jWoI= github.com/ssgreg/nlreturn/v2 v2.1.0 h1:6/s4Rc49L6Uo6RLjhWZGBpWWjfzk2yrf1nIW8m4wgVA= github.com/ssgreg/nlreturn/v2 v2.1.0/go.mod h1:E/iiPB78hV7Szg2YfRgyIrk1AD6JVMTRkkxBiELzh2I= +github.com/stoewer/go-strcase v1.2.0/go.mod h1:IBiWB2sKIp3wVVQ3Y035++gc+knqhUQag1KpM8ahLw8= github.com/storageos/go-api v0.0.0-20180912212459-343b3eff91fc/go.mod h1:ZrLn+e0ZuF3Y65PNF6dIwbJPZqfmtCXxFm9ckv0agOY= github.com/streadway/amqp v0.0.0-20190404075320-75d898a42a94/go.mod h1:AZpEONHx3DKn8O/DFsRAY58/XVQiIPMTMB1SddzLXVw= github.com/streadway/amqp v0.0.0-20190827072141-edfb9018d271/go.mod h1:AZpEONHx3DKn8O/DFsRAY58/XVQiIPMTMB1SddzLXVw= @@ -1676,6 +1791,7 @@ github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5Cc github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/subosito/gotenv v1.2.0 h1:Slr1R9HxAlEKefgq5jn9U+DnETlIUa6HfgEzj0g5d7s= github.com/subosito/gotenv v1.2.0/go.mod h1:N0PQaV/YGNqwC0u51sEeR/aUtSLEXKX9iv69rRypqCw= +github.com/syndtr/gocapability v0.0.0-20170704070218-db04d3cc01c8/go.mod h1:hkRG7XYTFWNJGYcbNJQlaLq0fg1yr4J4t/NcTQtrfww= github.com/syndtr/gocapability v0.0.0-20180916011248-d98352740cb2/go.mod h1:hkRG7XYTFWNJGYcbNJQlaLq0fg1yr4J4t/NcTQtrfww= github.com/tdakkota/asciicheck v0.0.0-20200416200610-e657995f937b h1:HxLVTlqcHhFAz3nWUcuvpH7WuOMv8LQoCWmruLfFH2U= github.com/tdakkota/asciicheck v0.0.0-20200416200610-e657995f937b/go.mod h1:yHp0ai0Z9gUljN3o0xMhYJnH/IcvkdTBOX2fmJ93JEM= @@ -1719,6 +1835,7 @@ github.com/tommy-muehle/go-mnd/v2 v2.4.0 h1:1t0f8Uiaq+fqKteUR4N9Umr6E99R+lDnLnq7 github.com/tommy-muehle/go-mnd/v2 v2.4.0/go.mod h1:WsUAkMJMYww6l/ufffCD3m+P7LEvr8TnZn9lwVDlgzw= github.com/tomnomnom/linkheader v0.0.0-20180905144013-02ca5825eb80 h1:nrZ3ySNYwJbSpD6ce9duiP+QkD3JuLCcWkdaehUS/3Y= github.com/tomnomnom/linkheader v0.0.0-20180905144013-02ca5825eb80/go.mod h1:iFyPdL66DjUD96XmzVL3ZntbzcflLnznH0fr99w5VqE= +github.com/tv42/httpunix v0.0.0-20150427012821-b75d8614f926/go.mod h1:9ESjWnEqriFuLhtthL60Sar/7RFoluCcXsuvEwTV5KM= github.com/ugorji/go v1.1.4/go.mod h1:uQMGLiO92mf5W77hV/PUCpI3pbzQx3CRekS0kk+RGrc= github.com/ugorji/go v1.1.7/go.mod h1:kZn38zHttfInRq0xu/PH0az30d+z6vm202qpg1oXVMw= github.com/ugorji/go/codec v0.0.0-20181204163529-d75b2dcb6bc8/go.mod h1:VFNgLljTbGfSG7qAOspJ7OScBnGdDN/yBr0sguwnwf0= @@ -1732,12 +1849,14 @@ github.com/ultraware/funlen v0.0.3 h1:5ylVWm8wsNwH5aWo9438pwvsK0QiqVuUrt9bn7S/iL github.com/ultraware/funlen v0.0.3/go.mod h1:Dp4UiAus7Wdb9KUZsYWZEWiRzGuM2kXM1lPbfaF6xhA= github.com/ultraware/whitespace v0.0.4 h1:If7Va4cM03mpgrNH9k49/VOicWpGoG70XPBFFODYDsg= github.com/ultraware/whitespace v0.0.4/go.mod h1:aVMh/gQve5Maj9hQ/hg+F75lr/X5A89uZnzAmWSineA= +github.com/urfave/cli v0.0.0-20171014202726-7bc6a0acffa5/go.mod h1:70zkFmudgCuE/ngEzBv17Jvp/497gISqfk5gWijbERA= github.com/urfave/cli v1.20.0/go.mod h1:70zkFmudgCuE/ngEzBv17Jvp/497gISqfk5gWijbERA= github.com/urfave/cli v1.22.1/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0= github.com/urfave/cli v1.22.2/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0= github.com/urfave/cli v1.22.4/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0= github.com/urfave/cli v1.22.5 h1:lNq9sAHXK2qfdI8W+GRItjCEkI+2oR4d+MEHy1CKXoU= github.com/urfave/cli v1.22.5/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0= +github.com/urfave/cli/v2 v2.1.1/go.mod h1:SE9GqnLQmjVa0iPEY0f1w3ygNIYcIJ0OKPMoW2caLfQ= github.com/urfave/negroni v1.0.0/go.mod h1:Meg73S6kFm/4PpbYdq35yYWoCZ9mS/YSx+lKnmiohz4= github.com/uudashr/gocognit v1.0.5 h1:rrSex7oHr3/pPLQ0xoWq108XMU8s678FJcQ+aSfOHa4= github.com/uudashr/gocognit v1.0.5/go.mod h1:wgYz0mitoKOTysqxTDMOUXg+Jb5SvtihkfmugIZYpEA= @@ -1756,6 +1875,8 @@ github.com/vishvananda/netlink v1.1.0/go.mod h1:cTgwzPIzzgDAYoQrMm0EdrjRUBkTqKYp github.com/vishvananda/netns v0.0.0-20191106174202-0a2b9b5464df/go.mod h1:JP3t17pCcGlemwknint6hfoeCVQrEMVwxRLRjXpq+BU= github.com/vishvananda/netns v0.0.0-20200520041808-52d707b772fe/go.mod h1:DD4vA1DwXk04H54A1oHXtwZmA0grkVMdPxx/VGLCah0= github.com/vmihailenco/msgpack v3.3.3+incompatible/go.mod h1:fy3FlTQTDXWkZ7Bh6AcGMlsjHatGryHQYUTf1ShIgkk= +github.com/vmihailenco/msgpack/v4 v4.3.12/go.mod h1:gborTTJjAo/GWTqqRjrLCn9pgNN+NXzzngzBKDPIqw4= +github.com/vmihailenco/tagparser v0.1.1/go.mod h1:OeAg3pn3UbLjkWt+rN9oFYB6u/cQgqMEUPoW2WPyhdI= github.com/vmware/govmomi v0.20.3/go.mod h1:URlwyTFZX72RmxtxuaFL2Uj3fD1JTvZdx59bHWk6aFU= github.com/voxelbrain/goptions v0.0.0-20180630082107-58cddc247ea2 h1:txplJASvd6b/hrE0s/Ixfpp2cuwH9IO9oZBAN9iYa4A= github.com/voxelbrain/goptions v0.0.0-20180630082107-58cddc247ea2/go.mod h1:DGCIhurYgnLz8J9ga1fMV/fbLDyUvTyrWXVWUIyJon4= @@ -1763,7 +1884,7 @@ github.com/weaveworks/goformation/v4 v4.10.2-0.20210609082249-532b27315cf1 h1:yX github.com/weaveworks/goformation/v4 v4.10.2-0.20210609082249-532b27315cf1/go.mod h1:x92o12+Azh6DQ4yoXT5oEuE7dhQHR5V2vy/fmZ6pO7k= github.com/weaveworks/launcher v0.0.2-0.20200715141516-1ca323f1de15 h1:i/RhLevywqC6cuUWtGdoaNrsJd+/zWh3PXbkXZIyZsU= github.com/weaveworks/launcher v0.0.2-0.20200715141516-1ca323f1de15/go.mod h1:w9Z1vnQmPobkEZ0F3oyiqRYP+62qDqTGnK6t5uhe1kg= -github.com/weaveworks/mesh v0.0.0-20170419100114-1f158d31de55/go.mod h1:mcON9Ws1aW0crSErpXWp7U1ErCDEKliDX2OhVlbWRKk= +github.com/weaveworks/mesh v0.0.0-20191105120815-58dbcc3e8e63/go.mod h1:RZebXKv56dax5zXcLIJZm1Awk28sx0XODXF94Z8WssY= github.com/weaveworks/schemer v0.0.0-20210802122110-338b258ad2ca h1:2P7ELY25OkuvkzAkLrIAXwYCZZEaEEHUshssVKslz8k= github.com/weaveworks/schemer v0.0.0-20210802122110-338b258ad2ca/go.mod h1:y8Luzq6JDsYVoIV0QAlnvIiq8bSaap0myMjWKyzVFTY= github.com/weppos/publicsuffix-go v0.13.1-0.20210123135404-5fd73613514e/go.mod h1:HYux0V0Zi04bHNwOHy4cXJVz/TQjYonnF6aoYhj+3QE= @@ -1782,9 +1903,11 @@ github.com/xeipuuv/gojsonpointer v0.0.0-20190905194746-02993c407bfb h1:zGWFAtiMc github.com/xeipuuv/gojsonpointer v0.0.0-20190905194746-02993c407bfb/go.mod h1:N2zxlSyiKSe5eX1tZViRH5QA0qijqEDrYZiPEAiq3wU= github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415 h1:EzJWgHovont7NscjpAxXsDA8S8BMYve8Y5+7cuRE7R0= github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415/go.mod h1:GwrjFmJcFw6At/Gs6z4yjiIwzuJ1/+UwLxMQDVQXShQ= +github.com/xeipuuv/gojsonschema v0.0.0-20180618132009-1d523034197f/go.mod h1:5yf86TLmAcydyeJq5YvxkGPE2fm/u4myDekKRoLuqhs= github.com/xeipuuv/gojsonschema v0.0.0-20180816142147-da425ebb7609/go.mod h1:5yf86TLmAcydyeJq5YvxkGPE2fm/u4myDekKRoLuqhs= -github.com/xeipuuv/gojsonschema v0.0.0-20181112162635-ac52e6811b56 h1:yhqBHs09SmmUoNOHc9jgK4a60T3XFRtPAkYxVnqgY50= github.com/xeipuuv/gojsonschema v0.0.0-20181112162635-ac52e6811b56/go.mod h1:5yf86TLmAcydyeJq5YvxkGPE2fm/u4myDekKRoLuqhs= +github.com/xeipuuv/gojsonschema v1.2.0 h1:LhYJRs+L4fBtjZUfuSZIKGeVu0QRy8e5Xi7D17UxZ74= +github.com/xeipuuv/gojsonschema v1.2.0/go.mod h1:anYRn/JVcOK2ZgGU+IjEV4nwlhoK5sQluxsYJ78Id3Y= github.com/xi2/xz v0.0.0-20171230120015-48954b6210f8 h1:nIPpBwaJSVYIxUFsDv3M8ofmx9yWTog9BfvIu0q41lo= github.com/xi2/xz v0.0.0-20171230120015-48954b6210f8/go.mod h1:HUYIGzjTL3rfEspMxjDjgmT5uz5wzYJKVo23qUhYTos= github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2 h1:eY9dn8+vbi4tKz5Qo6v2eYzo7kUS51QINcR5jNpbZS8= @@ -1803,8 +1926,13 @@ github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9de github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= +github.com/yvasiyarov/go-metrics v0.0.0-20140926110328-57bccd1ccd43/go.mod h1:aX5oPXxHm3bOH+xeAttToC8pqch2ScQN/JoXYupl6xs= +github.com/yvasiyarov/gorelic v0.0.0-20141212073537-a9bba5b9ab50/go.mod h1:NUSPSUX/bi6SeDMUh6brw0nXpxHnc96TguQh0+r/ssA= +github.com/yvasiyarov/newrelic_platform_go v0.0.0-20140908184405-b21fdbd4370f/go.mod h1:GlGEuHIJweS1mbCqG+7vt2nvWLzLLnRHbXz5JKd/Qbg= github.com/zclconf/go-cty v1.2.0/go.mod h1:hOPWgoHbaTUnI5k4D2ld+GRpFJSCe6bCM7m1q/N4PQ8= -github.com/zclconf/go-cty v1.3.1/go.mod h1:YO23e2L18AG+ZYQfSobnY4G65nvwvprPCxBHkufUH1k= +github.com/zclconf/go-cty v1.8.0/go.mod h1:vVKLxnk3puL4qRAv72AO+W99LUD4da90g3uUAzyuvAk= +github.com/zclconf/go-cty v1.8.2/go.mod h1:vVKLxnk3puL4qRAv72AO+W99LUD4da90g3uUAzyuvAk= +github.com/zclconf/go-cty-debug v0.0.0-20191215020915-b22d67c1ba0b/go.mod h1:ZRKQfBXbGkpdV6QMzT3rU1kSTAnfu1dO8dPKjYprgj8= github.com/ziutek/mymysql v1.5.4/go.mod h1:LMSpPZ6DbqWFxNCHW77HeMg9I646SAhApZ/wKdgO/C0= github.com/zmap/rc2 v0.0.0-20131011165748-24b9757f5521/go.mod h1:3YZ9o3WnatTIZhuOtot4IcUfzoKVjUHqu6WALIyI0nE= github.com/zmap/zcertificate v0.0.0-20180516150559-0e3d58b1bac4/go.mod h1:5iU54tB79AMBcySS0R2XIyZBAVmeHranShAFELYx7is= @@ -1892,6 +2020,7 @@ gocloud.dev v0.19.0/go.mod h1:SmKwiR8YwIMMJvQBKLsC3fHNyMwXLw3PMDO+VVteJMI= gocloud.dev v0.24.0 h1:cNtHD07zQQiv02OiwwDyVMuHmR7iQt2RLkzoAgz7wBs= gocloud.dev v0.24.0/go.mod h1:uA+als++iBX5ShuG4upQo/3Zoz49iIPlYUWHV5mM8w8= golang.org/dl v0.0.0-20190829154251-82a15e2f2ead/go.mod h1:IUMfjQLJQd4UTqG1Z90tenwKoCX93Gn3MAQJMOSBsDQ= +golang.org/x/crypto v0.0.0-20171113213409-9f005a07e0d3/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20180501155221-613d6eafa307/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20181029021203-45a5f77698d3/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= @@ -1903,11 +2032,13 @@ golang.org/x/crypto v0.0.0-20190228161510-8dd112bcdc25/go.mod h1:djNgcEr1/C05ACk golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20190320223903-b7391e95e576/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20190325154230-a5d413f7728c/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= +golang.org/x/crypto v0.0.0-20190418165655-df01cb2cc480/go.mod h1:WFFai1msRO1wXaEeE5yQxYXgSfI8pQAWXbQop6sCtWE= golang.org/x/crypto v0.0.0-20190426145343-a29dc8fdc734/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20190611184440-5c40567a22f8/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20190617133340-57b3e21c3d56/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20190621222207-cc06ce4a13d4/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20190701094942-4def268fd1a4/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20190820162420-60c769a6c586/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20191002192127-34f69633bfdc/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= @@ -1915,7 +2046,9 @@ golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8U golang.org/x/crypto v0.0.0-20191117063200-497ca9f6d64f/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20191202143827-86a70503ff7e/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20191206172530-e9b2fee46413/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/crypto v0.0.0-20200128174031-69ecbb4d6d5d/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20200302210943-78000ba7a073/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/crypto v0.0.0-20200414173820-0848c9571904/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20200728195943-123391ffb6de/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20201002170205-7f63de1d35b0/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= @@ -1976,6 +2109,7 @@ golang.org/x/mod v0.4.1/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.5.0 h1:UG21uOlmZabA4fW5i7ZX6bjw1xELEGg/ZLgZq9auk/Q= golang.org/x/mod v0.5.0/go.mod h1:5OXOZSfqPIIbmVBIIKWRFfZjPR0E5r58TLhUjH0a2Ro= +golang.org/x/net v0.0.0-20180112015858-5ccada7d0a7b/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180218175443-cbe0f9307d01/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180811021610-c39426892332/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= @@ -2010,7 +2144,6 @@ golang.org/x/net v0.0.0-20191002035440-2ec189313ef0/go.mod h1:z5CRVTTTmAJ677TzLL golang.org/x/net v0.0.0-20191004110552-13f9640d40b9/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20191112182307-2180aed22343/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20191119073136-fc4aabc6c914/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20191126235420-ef20fe5d7933/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20191209160850-c0dbc17a3553/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200114155413-6afb5195e5aa/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200202094626-16171245cfb2/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= @@ -2046,6 +2179,7 @@ golang.org/x/net v0.0.0-20210410081132-afb366fc7cd1/go.mod h1:9tjilg8BloeKEkVJvy golang.org/x/net v0.0.0-20210428140749-89ef3d95e781/go.mod h1:OJAsFXCWl8Ukc7SiCT/9KSuxbyM7479/AVlXFRxuMCk= golang.org/x/net v0.0.0-20210503060351-7fd8e65b6420/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20210510120150-4163338589ed/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= +golang.org/x/net v0.0.0-20210525063256-abc453219eb5/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20210614182718-04defd469f4e/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20210726213435-c6fcb2dbf985/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20210825183410-e898025ed96a h1:bRuuGXV8wwSdGTB+CtJf+FjgO1APK1CoO39T4BN/XBw= @@ -2086,6 +2220,7 @@ golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJ golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20210220032951-036812b2e83c h1:5KslGYwFpkhGh+Q16bwMP3cOontH8FOep7tGV86Y7SQ= golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sys v0.0.0-20180117170059-2c42eef0765b/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180224232135-f6cff0780e54/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180821044426-4ea2f632f6e9/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= @@ -2097,7 +2232,6 @@ golang.org/x/sys v0.0.0-20181107165924-66b7b1311ac8/go.mod h1:STP8DvDyc/dI5b8T5h golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20181122145206-62eef0e2fa9b/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20181205085412-a5c9d58dba9a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20190122071731-054c452bb702/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190124100055-b90733256f2e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190129075346-302c3dd5f1cc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190209173611-3b5209105503/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= @@ -2113,6 +2247,9 @@ golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20190502145724-3ef323f4f1fd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190502175342-a43fa875dd82/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190514135907-3a4b5fb9f71f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190515120540-06a5c4944438/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190602015325-4c4f7f33c9ed/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190606165138-5da285871e9c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190606203320-7fc4e5ec1444/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190616124812-15dcb6c0061f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -2162,7 +2299,6 @@ golang.org/x/sys v0.0.0-20200519105757-fe76b779f299/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20200523222454-059865788121/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200602225109-6fdc65e7d980/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200615200032-f1bc736245b1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200622214017-ed371f2e16b4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200625212154-ddb9806d33ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200803210538-64077c9b5642/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200828194041-157a740278f4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -2175,12 +2311,14 @@ golang.org/x/sys v0.0.0-20201112073958-5cba982894dd/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201126233918-771906719818/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201201145000-ef89a241ccb3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20201214210602-f9fddec55a1e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210104204734-6f8348627aad/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210112080510-489259a85091/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/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210220050731-9a76102bfb43/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210223095934-7937bea0104d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210225134936-a50acf3fe073/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210305230114-8fe3ee5dd75b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210309074719-68d13333faf2/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210315160823-c6e025ad8005/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -2195,6 +2333,7 @@ golang.org/x/sys v0.0.0-20210503080704-8803ae5d1324/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210511113859-b0526f3d8744/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210514084401-e8d321eab015/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210525143221-35b2ab0089ea/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210603125802-9665404d3644/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210616094352-59db8d763f22/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= @@ -2210,6 +2349,7 @@ golang.org/x/term v0.0.0-20210220032956-6a3ed077a48d/go.mod h1:bj7SfCRtBDWHUb9sn golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.0.0-20180810153555-6e3c4e7365dd/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/text v0.3.1-0.20171227012246-e19ae1496984/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.1-0.20181227161524-e6919f6577db/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= @@ -2236,7 +2376,6 @@ golang.org/x/tools v0.0.0-20181011042414-1f849cf54d09/go.mod h1:n7NCudcB/nEzxVGm golang.org/x/tools v0.0.0-20181030221726-6c7e314b6563/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190110163146-51295c7ec13a/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= -golang.org/x/tools v0.0.0-20190122202912-9c309ee22fab/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190125232054-d66bd3c5d5a6/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190206041539-40960b6deb8e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= @@ -2265,6 +2404,7 @@ golang.org/x/tools v0.0.0-20190910044552-dd2b5c81c578/go.mod h1:b+2E5dAYhXwXZwtn golang.org/x/tools v0.0.0-20190911174233-4f2ddba30aff/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20190916130336-e45ffcd953cc/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20190920225731-5eefd052ad72/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191004055002-72853e10c5a3/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191010075000-0337d82405ff/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191012152004-8de300cfc20a/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191029041327-9cc4af7d6b2c/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= @@ -2277,7 +2417,6 @@ golang.org/x/tools v0.0.0-20191118222007-07fc4c7f2b98/go.mod h1:b+2E5dAYhXwXZwtn golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191125144606-a911d9008d1f/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191130070609-6e064ea0cf2d/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191203134012-c197fd4bf371/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191216052735-49a3e744a425/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= golang.org/x/tools v0.0.0-20191216173652-a0e659d51361/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= golang.org/x/tools v0.0.0-20191227053925-7b8e75db28f4/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= @@ -2300,7 +2439,6 @@ golang.org/x/tools v0.0.0-20200324003944-a576cf524670/go.mod h1:Sl4aGygMT6LrqrWc golang.org/x/tools v0.0.0-20200325010219-a49f79bcc224/go.mod h1:Sl4aGygMT6LrqrWclx+PTx3U+LnKx/seiNR+3G19Ar8= golang.org/x/tools v0.0.0-20200329025819-fd4102a86c65/go.mod h1:Sl4aGygMT6LrqrWclx+PTx3U+LnKx/seiNR+3G19Ar8= golang.org/x/tools v0.0.0-20200331025713-a30bf2db82d4/go.mod h1:Sl4aGygMT6LrqrWclx+PTx3U+LnKx/seiNR+3G19Ar8= -golang.org/x/tools v0.0.0-20200410194907-79a7a3126eef/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= golang.org/x/tools v0.0.0-20200414032229-332987a829c3/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= golang.org/x/tools v0.0.0-20200422022333-3d57cf2e726e/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= golang.org/x/tools v0.0.0-20200426102838-f3a5411a4c3b/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= @@ -2357,12 +2495,14 @@ golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8T golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= gomodules.xyz/jsonpatch/v2 v2.0.1/go.mod h1:IhYNNY4jnS53ZnfE4PAmpKtDpTCj1JFXc+3mwe7XcUU= +gomodules.xyz/jsonpatch/v2 v2.1.0/go.mod h1:IhYNNY4jnS53ZnfE4PAmpKtDpTCj1JFXc+3mwe7XcUU= gonum.org/v1/gonum v0.0.0-20180816165407-929014505bf4/go.mod h1:Y+Yx5eoAFn32cQvJDxZx5Dpnq+c3wtXuadVZAcxbbBo= gonum.org/v1/gonum v0.0.0-20190331200053-3d26580ed485/go.mod h1:2ltnJ7xHfj0zHS40VVPYEAAMTa3ZGguvHGBSJeRWqE0= gonum.org/v1/gonum v0.6.2/go.mod h1:9mxDZsDKxgMAuccQkewq682L+0eCu4dCN2yonUJTCLU= gonum.org/v1/netlib v0.0.0-20190313105609-8cb42192e0e0/go.mod h1:wa6Ws7BG/ESfp6dHfk7C6KdzKA7wR7u/rKwOGE66zvw= gonum.org/v1/netlib v0.0.0-20190331212654-76723241ea4e/go.mod h1:kS+toOQn6AQKjmKJ7gzohV1XkqsFehRA2FbsbkopSuQ= gonum.org/v1/plot v0.0.0-20190515093506-e2840ee46a6b/go.mod h1:Wt8AAjI+ypCyYX3nZBvf6cAIx93T+c/OS2HFAYskSZc= +google.golang.org/api v0.0.0-20160322025152-9bf6e6e569ff/go.mod h1:4mhQ8q/RsB7i+udVvVy5NUi08OU8ZlA0gRVgrF7VFY0= google.golang.org/api v0.3.1/go.mod h1:6wY9I6uQWHQ8EM57III9mq/AjF+i8G65rmVagqKMtkk= google.golang.org/api v0.4.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE= google.golang.org/api v0.5.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE= @@ -2415,6 +2555,7 @@ google.golang.org/appengine v1.6.5/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCID google.golang.org/appengine v1.6.6/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= google.golang.org/appengine v1.6.7 h1:FZR1q0exgwxzPzp/aF+VccGrSfxfPpkBqjIIEq3ru6c= google.golang.org/appengine v1.6.7/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= +google.golang.org/cloud v0.0.0-20151119220103-975617b05ea8/go.mod h1:0H1ncTHf11KCFhTc/+EFRbzSCOZx+VUbRMk55Yv5MYk= google.golang.org/genproto v0.0.0-20170818010345-ee236bd376b0/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= google.golang.org/genproto v0.0.0-20181107211654-5fc9ac540362/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= @@ -2457,6 +2598,7 @@ google.golang.org/genproto v0.0.0-20200729003335-053ba62fc06f/go.mod h1:FWY/as6D google.golang.org/genproto v0.0.0-20200804131852-c06518451d9c/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20200825200019-8632dd797987/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20200904004341-0bd0a958aa1d/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20201019141844-1ed22bb0c154/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20201109203340-2640f1f9cdfb/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20201110150050-8816d57aaa9a/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20201201144952-b05cb90ed32e/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= @@ -2491,6 +2633,7 @@ google.golang.org/genproto v0.0.0-20210825212027-de86158e7fda/go.mod h1:eFjDcFEc google.golang.org/genproto v0.0.0-20210828152312-66f60bf46e71/go.mod h1:eFjDcFEctNawg4eG61bRv87N7iHBWyVhJu7u1kqDUXY= google.golang.org/genproto v0.0.0-20210831024726-fe130286e0e2 h1:NHN4wOCScVzKhPenJ2dt+BTs3X/XkBVI/Rh4iDt55T8= google.golang.org/genproto v0.0.0-20210831024726-fe130286e0e2/go.mod h1:eFjDcFEctNawg4eG61bRv87N7iHBWyVhJu7u1kqDUXY= +google.golang.org/grpc v0.0.0-20160317175043-d3ddb4469d5a/go.mod h1:yo6s7OP7yaDglbqo1J04qKzAhqBH6lvTonzMVmEdcZw= google.golang.org/grpc v1.8.0/go.mod h1:yo6s7OP7yaDglbqo1J04qKzAhqBH6lvTonzMVmEdcZw= google.golang.org/grpc v1.14.0/go.mod h1:yo6s7OP7yaDglbqo1J04qKzAhqBH6lvTonzMVmEdcZw= google.golang.org/grpc v1.17.0/go.mod h1:6QZJwpn2B+Zp71q/5VxRsJ6NXXVCE5NRUHRo+f3cWCs= @@ -2544,11 +2687,13 @@ google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp0 google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= google.golang.org/protobuf v1.27.1 h1:SnqbnDw1V7RiZcXPx5MEeqPv2s79L9i7BJUlG/+RurQ= google.golang.org/protobuf v1.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= +gopkg.in/airbrake/gobrake.v2 v2.0.9/go.mod h1:/h5ZAUhDkGaJfjzjKLSjv6zCL6O0LLBxU4K+aSYdM/U= gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= gopkg.in/alexcesaro/quotedprintable.v3 v3.0.0-20150716171945-2caba252f4dc h1:2gGKlE2+asNV9m7xrywl36YYNnBG5ZQ0r/BOOxqPpmk= gopkg.in/alexcesaro/quotedprintable.v3 v3.0.0-20150716171945-2caba252f4dc/go.mod h1:m7x9LTH6d71AHyAX77c9yqWCCa3UKHcVEj9y7hAtKDk= gopkg.in/asn1-ber.v1 v1.0.0-20181015200546-f715ec2f112d/go.mod h1:cuepJuh7vyXfUyUwEgHQXw849cJrilpS5NeIjOWESAw= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20141024133853-64131543e789/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= @@ -2563,10 +2708,14 @@ gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMy gopkg.in/gcfg.v1 v1.2.0/go.mod h1:yesOnuUOFQAhST5vPY4nbZsb/huCgGGXlipJsBn0b3o= gopkg.in/gcfg.v1 v1.2.3 h1:m8OOJ4ccYHnx2f4gQwpno8nAX5OGOh7RLaaz0pj3Ogs= gopkg.in/gcfg.v1 v1.2.3/go.mod h1:yesOnuUOFQAhST5vPY4nbZsb/huCgGGXlipJsBn0b3o= +gopkg.in/gemnasium/logrus-airbrake-hook.v2 v2.1.2/go.mod h1:Xk6kEKp8OKb+X14hQBKWaSkCsqBpgog8nAV2xsGOxlo= +gopkg.in/godo.v2 v2.0.9/go.mod h1:wgvPPKLsWN0hPIJ4JyxvFGGbIW3fJMSrXhdvSuZ1z/8= +gopkg.in/gorp.v1 v1.7.2/go.mod h1:Wo3h+DBQZIxATwftsglhdD/62zRFPhGhTiu5jUJmCaw= gopkg.in/inf.v0 v0.9.1 h1:73M5CoZyi3ZLMOyDlQh031Cx6N9NDJ2Vvfl76EDAgDc= gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw= gopkg.in/ini.v1 v1.42.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= gopkg.in/ini.v1 v1.51.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= +gopkg.in/ini.v1 v1.52.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= gopkg.in/ini.v1 v1.57.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= gopkg.in/ini.v1 v1.62.0 h1:duBzk771uxoUuOlyRLkHsygud9+5lrlGjdFBb4mSKDU= gopkg.in/ini.v1 v1.62.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= @@ -2577,8 +2726,9 @@ gopkg.in/natefinch/lumberjack.v2 v2.0.0/go.mod h1:l0ndWWf7gzL7RNwBG7wST/UCcT4T24 gopkg.in/resty.v1 v1.12.0/go.mod h1:mDo4pnntr5jdWRML875a/NmxYqAlA73dVijT2AXvQQo= gopkg.in/sourcemap.v1 v1.0.5/go.mod h1:2RlvNNSMglmRrcvhfuzp4hQHwOtjxlbjX7UPY/GXb78= gopkg.in/square/go-jose.v2 v2.2.2/go.mod h1:M9dMgbHiYLoDGQrXy7OpJDJWiKiU//h+vD76mk0e1AI= -gopkg.in/square/go-jose.v2 v2.3.1 h1:SK5KegNXmKmqE342YYN2qPHEnUYeoMiXXl1poUlI+o4= gopkg.in/square/go-jose.v2 v2.3.1/go.mod h1:M9dMgbHiYLoDGQrXy7OpJDJWiKiU//h+vD76mk0e1AI= +gopkg.in/square/go-jose.v2 v2.5.1 h1:7odma5RETjNHWJnR32wx8t+Io4djHE1PqxCFx3iiZ2w= +gopkg.in/square/go-jose.v2 v2.5.1/go.mod h1:M9dMgbHiYLoDGQrXy7OpJDJWiKiU//h+vD76mk0e1AI= gopkg.in/src-d/go-billy.v4 v4.3.2/go.mod h1:nDjArDMp+XMs1aFAESLRjfGSgfvoYN0hDfzEk0GjC98= gopkg.in/src-d/go-git-fixtures.v3 v3.5.0/go.mod h1:dLBcvytrw/TYZsNTWCnkNF2DSIlzWYqTe3rJR56Ac7g= gopkg.in/src-d/go-git.v4 v4.13.1/go.mod h1:nx5NYcxdKxq5fpltdHnPa2Exj4Sx0EclMWZQbYDu2z8= @@ -2588,6 +2738,7 @@ gopkg.in/warnings.v0 v0.1.1/go.mod h1:jksf8JmL6Qr/oQM2OXTHunEvvTAsrWBLb6OOjuVWRN gopkg.in/warnings.v0 v0.1.2 h1:wFXVbFY8DY5/xOe1ECiWdKCzZlxgshcYVNkBHstARME= gopkg.in/warnings.v0 v0.1.2/go.mod h1:jksf8JmL6Qr/oQM2OXTHunEvvTAsrWBLb6OOjuVWRNI= gopkg.in/yaml.v2 v2.0.0-20170812160011-eb3733d160e7/go.mod h1:JAlM8MvJe8wmxCU4Bli9HhUf9+ttbYbLASfIpnQbh74= +gopkg.in/yaml.v2 v2.0.0/go.mod h1:JAlM8MvJe8wmxCU4Bli9HhUf9+ttbYbLASfIpnQbh74= gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.3/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= @@ -2602,11 +2753,13 @@ gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= gopkg.in/yaml.v3 v3.0.0-20190905181640-827449938966/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.0-20200605160147-a5ece683394c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gopkg.in/yaml.v3 v3.0.0-20200615113413-eeeca48fe776/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b h1:h8qDotaEPuJATrMmW04NCwg7v22aHH28wwpauUhK9Oo= gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gotest.tools v2.2.0+incompatible/go.mod h1:DsYFclhRJ6vuDpmuTbkuFWG+y2sxOXAzmJt81HFBacw= gotest.tools/v3 v3.0.2/go.mod h1:3SzNCllyD9/Y+b5r9JIKQ474KzkZyqLqEfYqMsX94Bk= gotest.tools/v3 v3.0.3/go.mod h1:Z7Lb0S5l+klDB31fvDQX8ss/FlKDxtlFlw3Oa8Ymbl8= +helm.sh/helm/v3 v3.5.1/go.mod h1:bjwXfmGAF+SEuJZ2AtN1xmTuz4FqaNYOJrXP+vtj6Tw= honnef.co/go/tools v0.0.0-20180728063816-88497007e858/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= @@ -2615,7 +2768,6 @@ honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWh honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg= honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= honnef.co/go/tools v0.0.1-2020.1.4/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= -honnef.co/go/tools v0.0.1-2020.1.6/go.mod h1:pyyisuGw24ruLjrr1ddx39WE0y9OooInRzEYLhQB2YY= honnef.co/go/tools v0.1.4/go.mod h1:NgwopIslSNH47DimFoV78dnkksY2EFtX0ajyb3K/las= honnef.co/go/tools v0.2.1 h1:/EPr//+UMMXwMTkXvCCoaJDq8cpjMO80Ou+L4PDo2mY= honnef.co/go/tools v0.2.1/go.mod h1:lPVVZ2BS5TfnjLyizF7o7hv7j9/L+8cZY2hLyjP9cGY= @@ -2632,7 +2784,7 @@ k8s.io/client-go v0.21.2 h1:Q1j4L/iMN4pTw6Y4DWppBoUxgKO8LbffEMVEV00MUp0= k8s.io/client-go v0.21.2/go.mod h1:HdJ9iknWpbl3vMGtib6T2PyI/VYxiZfq936WNVHBRrA= k8s.io/cloud-provider v0.21.2 h1:zF74hZLfKq9lw+MT5DSUUNk57M84+WcEcpdwjIrPE94= k8s.io/cloud-provider v0.21.2/go.mod h1:2mYI/l+eJESZ0Ye0fRHKMJ55t/j/TZ+gj3NUQkgIcBI= -k8s.io/cloud-provider-openstack v1.19.3/go.mod h1:J/X/tgKwUDtsrfdJ4aL0iEQLi/8chdbs4rAiYznYwPQ= +k8s.io/cloud-provider-openstack v1.21.0/go.mod h1:N0Tnl9sMDSuW8CXJqT0XK8f/KSuQ1I0ClhOBgTAv3fc= k8s.io/cluster-bootstrap v0.21.2/go.mod h1:OEm/gajtWz/ohbS4NGxkyTp/6f1fW3TBThgCQ1ljhHo= k8s.io/code-generator v0.21.2 h1:EyHysEtLHTsNMoace0b3Yec9feD0qkV+5RZRoeSh+sc= k8s.io/code-generator v0.21.2/go.mod h1:8mXJDCB7HcRo1xiEQstcguZkbxZaqeUOrO9SsicWs3U= @@ -2645,21 +2797,21 @@ k8s.io/csi-translation-lib v0.21.2 h1:TflEX56q+TpE17bELMoZNRtFuVZNFmzG6aBxNXSqPf k8s.io/csi-translation-lib v0.21.2/go.mod h1:LgswOMSIdOntgqxcHsspcG61R34t954N//9jiSD/TTM= k8s.io/gengo v0.0.0-20200413195148-3a45101e95ac/go.mod h1:ezvh/TsK7cY6rbqRK0oQQ8IAqLxYwwyPxAX1Pzy0ii0= k8s.io/gengo v0.0.0-20200428234225-8167cfdcfc14/go.mod h1:ezvh/TsK7cY6rbqRK0oQQ8IAqLxYwwyPxAX1Pzy0ii0= -k8s.io/gengo v0.0.0-20200710205751-c0d492a0f3ca/go.mod h1:aG2eeomYfcUw8sE3fa7YdkjgnGtyY56TjZlaJJ0ZoWo= -k8s.io/gengo v0.0.0-20201214224949-b6c5ce23f027 h1:Uusb3oh8XcdzDF/ndlI4ToKTYVlkCSJP39SRY2mfRAw= k8s.io/gengo v0.0.0-20201214224949-b6c5ce23f027/go.mod h1:FiNAH4ZV3gBg2Kwh89tzAEV2be7d5xI0vBa/VySYy3E= +k8s.io/gengo v0.0.0-20210203185629-de9496dff47b h1:bAU8IlrMA6KbP0dIg/sVSJn95pDCUHDZx0DpTGrf2v4= +k8s.io/gengo v0.0.0-20210203185629-de9496dff47b/go.mod h1:FiNAH4ZV3gBg2Kwh89tzAEV2be7d5xI0vBa/VySYy3E= k8s.io/heapster v1.2.0-beta.1/go.mod h1:h1uhptVXMwC8xtZBYsPXKVi8fpdlYkTs6k949KozGrM= -k8s.io/helm v2.9.0+incompatible/go.mod h1:LZzlS4LQBHfciFOurYBFkCMTaZ0D1l+p0teMg7TSULI= k8s.io/klog v0.3.1/go.mod h1:Gq+BEi5rUBO/HRz0bTSXDUcqjScdoY3a9IHpCEIOOfk= k8s.io/klog v1.0.0 h1:Pt+yjF5aB1xDSVbau4VsWe+dQNzA0qv1LlXdC2dF6Q8= k8s.io/klog v1.0.0/go.mod h1:4Bi6QPql/J/LkTDqv7R/cd3hPo4k2DG6Ptcz060Ez5I= k8s.io/klog/v2 v2.0.0/go.mod h1:PBfzABfn139FHAV07az/IF9Wp1bkk3vpT2XSJ76fSDE= k8s.io/klog/v2 v2.2.0/go.mod h1:Od+F08eJP+W3HUb4pSrPpgp9DGU4GzlpG/TmITuYh/Y= k8s.io/klog/v2 v2.3.0/go.mod h1:Od+F08eJP+W3HUb4pSrPpgp9DGU4GzlpG/TmITuYh/Y= +k8s.io/klog/v2 v2.4.0/go.mod h1:Od+F08eJP+W3HUb4pSrPpgp9DGU4GzlpG/TmITuYh/Y= k8s.io/klog/v2 v2.8.0 h1:Q3gmuM9hKEjefWFFYF0Mat+YyFJvsUyYuwyNNJ5C9Ts= k8s.io/klog/v2 v2.8.0/go.mod h1:hy9LJ/NvuK+iVyP4Ehqva4HxZG/oXyIS3n3Jmire4Ec= -k8s.io/kops v1.19.0 h1:g6rrfzy5+E3Q9I+6EWrwyjqr+JRfUORf+1/AmfzNfJg= -k8s.io/kops v1.19.0/go.mod h1:io9PpBPuALwy5DBFLabx3w6VrfWyTL731xbjVy4eY0U= +k8s.io/kops v1.21.2 h1:1M5644J4/JBrnh0YLuOtJ5xG8nPjzmcrYmhv+Lk4GEg= +k8s.io/kops v1.21.2/go.mod h1:dFhAKdCzIHgTIN/YtyR4PNQ90cPe7DHbMkPM9QqWv3s= k8s.io/kube-aggregator v0.21.2/go.mod h1:7NgmUXJziySAJ7GxMRBBwcJay7MLUoxms31fw/ICpYk= k8s.io/kube-controller-manager v0.21.2/go.mod h1:gu0rV2UWy1k05E3kZxJFQE1F7RR1PZlq83+9J+lWlno= k8s.io/kube-openapi v0.0.0-20200805222855-6aeccd4b50c6/go.mod h1:UuqjUnNftUyPE5H64/qeyjQoUZhGpeFDVdxjTeEVN2o= @@ -2674,6 +2826,7 @@ k8s.io/kubernetes v1.19.5/go.mod h1:C5hGC62q7CF0806SpBOSf11RyBaM1oQpl01BWRPK81o= k8s.io/legacy-cloud-providers v0.21.2 h1:W8KdwSbc764/mB4ltFWVRLouv6O0U7T/ji6OvZxVDAk= k8s.io/legacy-cloud-providers v0.21.2/go.mod h1:9dFEf/WGCqPhOIGQiAwcPfgAYWRot6txrCshWCg225c= k8s.io/metrics v0.21.2/go.mod h1:wzlOINZMCtWq8dR9gHlyaOemmYlOpAoldEIXE82gAhI= +k8s.io/mount-utils v0.21.0/go.mod h1:dwXbIPxKtTjrBEaX1aK/CMEf1KZ8GzMHpe3NEBfdFXI= k8s.io/sample-apiserver v0.21.2/go.mod h1:NXFq8jUrB3UyYhoGstFMXdHFSxfHZSHX6cUdVBVZKFM= k8s.io/sample-controller v0.16.8 h1:8+vMrwOl2SytJcB4u0EwYsyf1NaFvYD5nab7fo6Qt4U= k8s.io/sample-controller v0.16.8/go.mod h1:aXlORS1ekU77qhGybB5t3JORDurzDpWgvMYxmCsiuos= @@ -2681,8 +2834,10 @@ k8s.io/system-validators v1.1.2/go.mod h1:bPldcLgkIUK22ALflnsXk8pvkTEndYdNuaHH6g k8s.io/utils v0.0.0-20200414100711-2df71ebbae66/go.mod h1:jPW/WVKK9YHAvNhRxK0md/EJ228hCsBRufyofKtW8HA= k8s.io/utils v0.0.0-20200603063816-c1c6865ac451/go.mod h1:jPW/WVKK9YHAvNhRxK0md/EJ228hCsBRufyofKtW8HA= k8s.io/utils v0.0.0-20200729134348-d5654de09c73/go.mod h1:jPW/WVKK9YHAvNhRxK0md/EJ228hCsBRufyofKtW8HA= -k8s.io/utils v0.0.0-20201110183641-67b214c5f920 h1:CbnUZsM497iRC5QMVkHwyl8s2tB3g7yaSHkYPkpgelw= k8s.io/utils v0.0.0-20201110183641-67b214c5f920/go.mod h1:jPW/WVKK9YHAvNhRxK0md/EJ228hCsBRufyofKtW8HA= +k8s.io/utils v0.0.0-20210111153108-fddb29f9d009/go.mod h1:jPW/WVKK9YHAvNhRxK0md/EJ228hCsBRufyofKtW8HA= +k8s.io/utils v0.0.0-20210305010621-2afb4311ab10 h1:u5rPykqiCpL+LBfjRkXvnK71gOgIdmq3eHUEkPrbeTI= +k8s.io/utils v0.0.0-20210305010621-2afb4311ab10/go.mod h1:jPW/WVKK9YHAvNhRxK0md/EJ228hCsBRufyofKtW8HA= modernc.org/cc v1.0.0/go.mod h1:1Sk4//wdnYJiUIxnW8ddKpaOJCF37yAdqYnkxUpaYxw= modernc.org/golex v1.0.0/go.mod h1:b/QX9oBD/LhixY6NDh+IdGv17hgB+51fET1i2kPSmvk= modernc.org/mathutil v1.0.0/go.mod h1:wU0vUrJsVWBZ4P6e7xtFJEhFSNsfRLJ8H458uRjg03k= @@ -2700,15 +2855,16 @@ nhooyr.io/websocket v1.8.6/go.mod h1:B70DZP8IakI65RVQ51MsWP/8jndNma26DVA/nFSCgW0 nhooyr.io/websocket v1.8.7/go.mod h1:B70DZP8IakI65RVQ51MsWP/8jndNma26DVA/nFSCgW0= pack.ag/amqp v0.11.2/go.mod h1:4/cbmt4EJXSKlG6LCfWHoqmN0uFdy5i/+YFz+fTfhV4= rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8= +rsc.io/letsencrypt v0.0.3/go.mod h1:buyQKZ6IXrRnB7TdkHP0RyEybLx18HHyOSoTyoOLqNY= rsc.io/pdf v0.1.1/go.mod h1:n8OzWcQ6Sp37PL01nO98y4iUCRdTGarVfzxY20ICaU4= rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0= rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA= sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.0.19/go.mod h1:LEScyzhFmoF5pso/YSeBstl57mOzx9xlU9n85RGrDQg= sigs.k8s.io/aws-iam-authenticator v0.5.2 h1:eGCtm6lLVpVVpsIBC1y4OwyQRhmg+A/OPXVMTlDKONc= sigs.k8s.io/aws-iam-authenticator v0.5.2/go.mod h1:yPDLi58MDx1UtCrRMOykLm1IyKKPGHgcGCafcbn2s3E= -sigs.k8s.io/controller-runtime v0.6.1/go.mod h1:XRYBPdbf5XJu9kpS84VJiZ7h/u1hF3gEORz0efEja7A= -sigs.k8s.io/controller-tools v0.2.8 h1:UmYsnu89dn8/wBhjKL3lkGyaDGRnPDYUx2+iwXRnylA= -sigs.k8s.io/controller-tools v0.2.8/go.mod h1:9VKHPszmf2DHz/QmHkcfZoewO6BL7pPs9uAiBVsaJSE= +sigs.k8s.io/controller-runtime v0.6.2/go.mod h1:vhcq/rlnENJ09SIRp3EveTaZ0yqH526hjf9iJdbUJ/E= +sigs.k8s.io/controller-runtime v0.9.0-beta.0/go.mod h1:ufPDuvefw2Y1KnBgHQrLdOjueYlj+XJV2AszbT+WTxs= +sigs.k8s.io/controller-tools v0.2.9-0.20200414181213-645d44dca7c0/go.mod h1:YKE/iHvcKITCljdnlqHYe+kAt7ZldvtAwUzQff0k1T0= sigs.k8s.io/kustomize v2.0.3+incompatible h1:JUufWFNlI44MdtnjUqVnvh29rR37PQFzPbLXqhyOyX0= sigs.k8s.io/kustomize v2.0.3+incompatible/go.mod h1:MkjgH3RdOWrievjo6c9T245dYlB5QeXV4WCbnt/PEpU= sigs.k8s.io/kustomize/api v0.8.8 h1:G2z6JPSSjtWWgMeWSoHdXqyftJNmMmyxXpwENGoOtGE= @@ -2723,8 +2879,11 @@ sigs.k8s.io/structured-merge-diff/v4 v4.0.1/go.mod h1:bJZC9H9iH24zzfZ/41RGcq60oK sigs.k8s.io/structured-merge-diff/v4 v4.0.2/go.mod h1:bJZC9H9iH24zzfZ/41RGcq60oK1F7G282QMXDPYydCw= sigs.k8s.io/structured-merge-diff/v4 v4.1.0 h1:C4r9BgJ98vrKnnVCjwCSXcWjWe0NKcUQkmzDXZXGwH8= sigs.k8s.io/structured-merge-diff/v4 v4.1.0/go.mod h1:bJZC9H9iH24zzfZ/41RGcq60oK1F7G282QMXDPYydCw= +sigs.k8s.io/testing_frameworks v0.1.2/go.mod h1:ToQrwSC3s8Xf/lADdZp3Mktcql9CG0UAmdJG9th5i0w= sigs.k8s.io/yaml v1.1.0/go.mod h1:UJmg0vDUVViEyp3mgSv9WPwZCDxu4rQW1olrI1uml+o= sigs.k8s.io/yaml v1.2.0 h1:kr/MCeFWJWTwyaHoR9c8EjH9OumOmoF9YGiZd7lFm/Q= sigs.k8s.io/yaml v1.2.0/go.mod h1:yfXDCHCao9+ENCvLSE62v9VSji2MKu5jeNfTrofGhJc= +software.sslmate.com/src/go-pkcs12 v0.0.0-20180114231543-2291e8f0f237/go.mod h1:/xvNRWUqm0+/ZMiF4EX00vrSCMsE4/NHb+Pt3freEeQ= software.sslmate.com/src/go-pkcs12 v0.0.0-20190209200317-47dd539968c4/go.mod h1:/xvNRWUqm0+/ZMiF4EX00vrSCMsE4/NHb+Pt3freEeQ= +software.sslmate.com/src/go-pkcs12 v0.0.0-20200830195227-52f69702a001/go.mod h1:/xvNRWUqm0+/ZMiF4EX00vrSCMsE4/NHb+Pt3freEeQ= sourcegraph.com/sourcegraph/appdash v0.0.0-20190731080439-ebfcffb1b5c0/go.mod h1:hI742Nqp5OhwiqlzhgfbWU4mW4yO10fP+LoT9WOswdU= From ac607f935d11ceaaa41aa4e2671ab17a13308631 Mon Sep 17 00:00:00 2001 From: nikimanoledaki <18622989+nikimanoledaki@users.noreply.github.com> Date: Fri, 5 Nov 2021 16:58:07 +0100 Subject: [PATCH 065/124] Add notes for 0.73.0 --- docs/release_notes/0.73.0.md | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) create mode 100644 docs/release_notes/0.73.0.md diff --git a/docs/release_notes/0.73.0.md b/docs/release_notes/0.73.0.md new file mode 100644 index 0000000000..a78c0b771e --- /dev/null +++ b/docs/release_notes/0.73.0.md @@ -0,0 +1,20 @@ +# Release 0.73.0 + +## Features + +- Support CloudWatch log retention (#4295) +- Add support for Windows Server 20H2 (#4390) + +## Improvements + +- Make kubernetes 1.21 default (#4394) +- Reduce API calls in upgrade cluster (#4366) + +## Bug Fixes + +- Fix wait for managed nodegroups (#4401) +- Scale managed nodegroup with --name flag (#4383) + +## Acknowledgments +Weaveworks would like to sincerely thank: + @abhipth and @adammw From 16ffb39f51bf6f9cd9af7a5a063b808b7b545ab3 Mon Sep 17 00:00:00 2001 From: weaveworksbot Date: Mon, 8 Nov 2021 10:15:35 +0000 Subject: [PATCH 066/124] Prepare for next development iteration --- pkg/version/release.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkg/version/release.go b/pkg/version/release.go index dfaa1692f0..afdba68c74 100644 --- a/pkg/version/release.go +++ b/pkg/version/release.go @@ -3,7 +3,7 @@ package version // This file was generated by release_generate.go; DO NOT EDIT. // Version is the version number in semver format X.Y.Z -var Version = "0.73.0" +var Version = "0.74.0" // PreReleaseID can be empty for releases, "rc.X" for release candidates and "dev" for snapshots var PreReleaseID = "dev" From ec2afa43a711df5a789bd2fc35d1cede6da0f873 Mon Sep 17 00:00:00 2001 From: Chetan Patwal Date: Mon, 8 Nov 2021 15:50:57 +0530 Subject: [PATCH 067/124] Fix validation for GPU instance types when AMIFamily is not set (#4403) --- pkg/apis/eksctl.io/v1alpha5/gpu_validation_test.go | 3 +++ pkg/apis/eksctl.io/v1alpha5/validation.go | 2 +- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/pkg/apis/eksctl.io/v1alpha5/gpu_validation_test.go b/pkg/apis/eksctl.io/v1alpha5/gpu_validation_test.go index b3eb5797d6..29d039baf6 100644 --- a/pkg/apis/eksctl.io/v1alpha5/gpu_validation_test.go +++ b/pkg/apis/eksctl.io/v1alpha5/gpu_validation_test.go @@ -62,6 +62,9 @@ var _ = Describe("GPU instance support", func() { gpuInstanceType: "g4dn.xlarge", amiFamily: api.NodeImageFamilyAmazonLinux2, }), + Entry("AMI unset", gpuInstanceEntry{ + gpuInstanceType: "g4dn.xlarge", + }), Entry("Bottlerocket", gpuInstanceEntry{ amiFamily: api.NodeImageFamilyBottlerocket, gpuInstanceType: "g4dn.xlarge", diff --git a/pkg/apis/eksctl.io/v1alpha5/validation.go b/pkg/apis/eksctl.io/v1alpha5/validation.go index 44e573a85f..bc39962e4a 100644 --- a/pkg/apis/eksctl.io/v1alpha5/validation.go +++ b/pkg/apis/eksctl.io/v1alpha5/validation.go @@ -305,7 +305,7 @@ func validateNodeGroupBase(np NodePool, path string) error { } } - if instanceutils.IsGPUInstanceType(SelectInstanceType(np)) && ng.AMIFamily != NodeImageFamilyAmazonLinux2 { + if instanceutils.IsGPUInstanceType(SelectInstanceType(np)) && (ng.AMIFamily != NodeImageFamilyAmazonLinux2 && ng.AMIFamily != "") { return errors.Errorf("GPU instance types are not supported for %s", ng.AMIFamily) } From 952f98e8591895dae912fa5f612351e7248cca0d Mon Sep 17 00:00:00 2001 From: Jake Klein Date: Mon, 8 Nov 2021 10:51:15 +0000 Subject: [PATCH 068/124] Use NotTo instead of ToNot in tests (#4425) --- integration/matchers/git.go | 2 +- integration/runner/runner_test.go | 6 +- integration/tests/addons/addons_test.go | 6 +- integration/tests/assertions.go | 2 +- .../backwards_compatibility_test.go | 6 +- .../createdeletebeforeactive_test.go | 2 +- .../cloudwatch_logging_test.go | 2 +- .../cluster_api/cluster_api_endpoints_test.go | 10 +-- .../tests/cluster_dns/cluster_dns_test.go | 4 +- .../tests/crud/creategetdelete_test.go | 26 +++--- integration/tests/dry_run/dry_run_test.go | 14 ++-- .../tests/eks_connector/eks_connector_test.go | 12 +-- integration/tests/fargate/fargate_test.go | 2 +- .../instance_selector_test.go | 4 +- .../tests/managed/managed_nodegroup_test.go | 16 ++-- .../quickstart_profiles_gen_test.go | 6 +- .../tests/update/update_cluster_test.go | 18 ++--- integration/tests/windows/windows_test.go | 4 +- integration/utilities/cluster/cluster.go | 8 +- pkg/actions/addon/create_test.go | 8 +- pkg/actions/addon/update_test.go | 2 +- pkg/actions/irsa/update_test.go | 2 +- pkg/addons/default/aws_node_test.go | 48 +++++------ pkg/addons/default/coredns_test.go | 12 +-- pkg/addons/default/helpers_test.go | 8 +- pkg/addons/default/kube_proxy_test.go | 12 +-- pkg/apis/eksctl.io/v1alpha5/defaults_test.go | 2 +- .../eksctl.io/v1alpha5/gpu_validation_test.go | 2 +- .../v1alpha5/instance_selector_test.go | 2 +- .../v1alpha5/managed_nodegroup_test.go | 4 +- .../eksctl.io/v1alpha5/validation_test.go | 56 ++++++------- pkg/authconfigmap/authconfigmap_test.go | 6 +- pkg/az/az_test.go | 2 +- pkg/cfn/builder/builder_suite_test.go | 2 +- pkg/cfn/builder/cluster_test.go | 32 ++++---- pkg/cfn/builder/iam_test.go | 10 +-- .../builder/managed_launch_template_test.go | 12 +-- .../managed_nodegroup_ami_type_test.go | 4 +- pkg/cfn/builder/nodegroup_test.go | 8 +- pkg/cfn/builder/vpc_endpoint_test.go | 6 +- pkg/cfn/builder/vpc_test.go | 26 +++--- pkg/cfn/manager/api_test.go | 6 +- pkg/cfn/manager/nodegroup_test.go | 6 +- pkg/cfn/template/api_test.go | 22 ++--- pkg/connector/connector_test.go | 6 +- pkg/connector/manifest_test.go | 4 +- pkg/connector/resources_test.go | 8 +- pkg/credentials/filecache_test.go | 24 +++--- pkg/ctl/cmdutils/configfile_test.go | 16 ++-- pkg/ctl/cmdutils/filter/filter_test.go | 18 ++--- .../filter/iamserviceaccount_filter_test.go | 10 +-- .../cmdutils/filter/nodegroup_filter_test.go | 36 ++++----- pkg/ctl/cmdutils/scale_test.go | 4 +- pkg/ctl/completion/completion_test.go | 4 +- pkg/ctl/create/cluster_test.go | 2 +- pkg/ctl/enable/flux_test.go | 4 +- pkg/ctl/enable/profile_test.go | 24 +++--- pkg/ctl/enable/repo_test.go | 24 +++--- pkg/ctl/generate/profile_test.go | 32 ++++---- pkg/ctl/upgrade/cluster_test.go | 16 ++-- pkg/eks/api_test.go | 8 +- pkg/eks/eks_test.go | 6 +- pkg/eks/nodegroup_service_test.go | 2 +- pkg/eks/update_test.go | 16 ++-- pkg/git/git_test.go | 12 +-- pkg/gitops/profile_test.go | 12 +-- pkg/iam/arn_test.go | 4 +- pkg/iam/oidc/api_test.go | 14 ++-- pkg/info/info_test.go | 12 +-- pkg/kubernetes/client_test.go | 80 +++++++++---------- pkg/kubernetes/manifests_test.go | 26 +++--- pkg/kubernetes/namespace_test.go | 8 +- pkg/kubernetes/nodegroup_test.go | 2 +- pkg/kubernetes/serviceaccount_test.go | 30 +++---- pkg/managed/release_version_test.go | 2 +- pkg/nodebootstrap/al2_test.go | 4 +- pkg/nodebootstrap/bottlerocket_test.go | 68 ++++++++-------- pkg/nodebootstrap/cluster_dns_test.go | 2 +- pkg/nodebootstrap/legacy/userdata_test.go | 34 ++++---- pkg/nodebootstrap/managed_al2_test.go | 4 +- .../managed_bottlerocket_test.go | 4 +- pkg/nodebootstrap/nodebootstrap_suite_test.go | 2 +- pkg/nodebootstrap/windows_test.go | 6 +- pkg/ssh/client/ssh_test.go | 10 +-- pkg/testutils/client.go | 6 +- pkg/utils/kubeconfig/kubeconfig_test.go | 2 +- pkg/vpc/vpc_test.go | 6 +- 87 files changed, 532 insertions(+), 532 deletions(-) diff --git a/integration/matchers/git.go b/integration/matchers/git.go index 9d0d557d43..73812ed605 100644 --- a/integration/matchers/git.go +++ b/integration/matchers/git.go @@ -28,6 +28,6 @@ func AssertQuickStartComponentsPresentInGit(branch string) { allFiles = append(allFiles, path) return nil }) - Expect(err).ToNot(HaveOccurred()) + Expect(err).NotTo(HaveOccurred()) fmt.Fprintf(ginkgo.GinkgoWriter, "\n all files:\n%v", allFiles) } diff --git a/integration/runner/runner_test.go b/integration/runner/runner_test.go index 55fe9153e5..613a57536d 100644 --- a/integration/runner/runner_test.go +++ b/integration/runner/runner_test.go @@ -76,13 +76,13 @@ var _ = Describe("command runner", func() { NewCmd("true"), NewCmd("false"), } - Expect(willFail).ToNot(RunSuccessfully()) + Expect(willFail).NotTo(RunSuccessfully()) }) It("can start a command and interrupt it", func() { session := NewCmd("sleep").WithArgs("20").Start() - Expect(session.Command.Process).ToNot(BeNil()) + Expect(session.Command.Process).NotTo(BeNil()) session.Interrupt().Wait() - Expect(session.ExitCode()).ToNot(BeZero()) + Expect(session.ExitCode()).NotTo(BeZero()) }) }) diff --git a/integration/tests/addons/addons_test.go b/integration/tests/addons/addons_test.go index e38363a5da..f053c68e28 100644 --- a/integration/tests/addons/addons_test.go +++ b/integration/tests/addons/addons_test.go @@ -64,7 +64,7 @@ var _ = Describe("(Integration) [EKS Addons test]", func() { clusterConfig.ManagedNodeGroups = []*api.ManagedNodeGroup{ng} data, err := json.Marshal(clusterConfig) - Expect(err).ToNot(HaveOccurred()) + Expect(err).NotTo(HaveOccurred()) cmd := params.EksctlCreateCmd. WithArgs( @@ -78,7 +78,7 @@ var _ = Describe("(Integration) [EKS Addons test]", func() { rawClient = getRawClient(clusterName) serverVersion, err := rawClient.ServerVersion() - Expect(err).ToNot(HaveOccurred()) + Expect(err).NotTo(HaveOccurred()) Expect(serverVersion).To(HavePrefix(api.LatestVersion)) }) @@ -196,6 +196,6 @@ func getRawClient(clusterName string) *kubewrapper.RawClient { err = ctl.RefreshClusterStatus(cfg) Expect(err).ShouldNot(HaveOccurred()) rawClient, err := ctl.NewRawClient(cfg) - Expect(err).ToNot(HaveOccurred()) + Expect(err).NotTo(HaveOccurred()) return rawClient } diff --git a/integration/tests/assertions.go b/integration/tests/assertions.go index d8dc4b1f85..81b892a38c 100644 --- a/integration/tests/assertions.go +++ b/integration/tests/assertions.go @@ -30,6 +30,6 @@ func ListNodes(clientset kubernetes.Interface, nodeGroupName string) *corev1.Nod nodeList, err := clientset.CoreV1().Nodes().List(context.Background(), metav1.ListOptions{ LabelSelector: fmt.Sprintf("%s=%s", api.NodeGroupNameLabel, nodeGroupName), }) - Expect(err).ToNot(HaveOccurred()) + Expect(err).NotTo(HaveOccurred()) return nodeList } diff --git a/integration/tests/backwards_compat/backwards_compatibility_test.go b/integration/tests/backwards_compat/backwards_compatibility_test.go index 2d29117358..1ef76876e1 100644 --- a/integration/tests/backwards_compat/backwards_compatibility_test.go +++ b/integration/tests/backwards_compat/backwards_compatibility_test.go @@ -54,10 +54,10 @@ var _ = Describe("(Integration) [Backwards compatibility test]", func() { By("downloading a previous release") eksctlDir, err := os.MkdirTemp(os.TempDir(), "eksctl") - Expect(err).ToNot(HaveOccurred()) + Expect(err).NotTo(HaveOccurred()) defer func() { - Expect(os.RemoveAll(eksctlDir)).ToNot(HaveOccurred()) + Expect(os.RemoveAll(eksctlDir)).NotTo(HaveOccurred()) }() downloadRelease(eksctlDir) @@ -65,7 +65,7 @@ var _ = Describe("(Integration) [Backwards compatibility test]", func() { eksctlPath := path.Join(eksctlDir, "eksctl") version, err := getVersion(eksctlPath) - Expect(err).ToNot(HaveOccurred()) + Expect(err).NotTo(HaveOccurred()) By(fmt.Sprintf("creating a cluster with release %q", version)) cmd := runner.NewCmd(eksctlPath). diff --git a/integration/tests/before_active/createdeletebeforeactive_test.go b/integration/tests/before_active/createdeletebeforeactive_test.go index 3c5bec2de3..b6a3296860 100644 --- a/integration/tests/before_active/createdeletebeforeactive_test.go +++ b/integration/tests/before_active/createdeletebeforeactive_test.go @@ -81,7 +81,7 @@ var _ = Describe("(Integration) Create & Delete before Active", func() { cmd := params.EksctlDeleteClusterCmd.WithArgs( "--name", params.ClusterName, ) - Expect(cmd).ToNot(RunSuccessfully()) + Expect(cmd).NotTo(RunSuccessfully()) }) }) }) diff --git a/integration/tests/cloudwatch_logging/cloudwatch_logging_test.go b/integration/tests/cloudwatch_logging/cloudwatch_logging_test.go index 732a85af0d..4081852a60 100644 --- a/integration/tests/cloudwatch_logging/cloudwatch_logging_test.go +++ b/integration/tests/cloudwatch_logging/cloudwatch_logging_test.go @@ -59,7 +59,7 @@ var _ = Describe("(Integration) [CloudWatch Logging test]", func() { logGroups, err := cloudWatchLogs.DescribeLogGroups(&cloudwatchlogs.DescribeLogGroupsInput{ LogGroupNamePrefix: aws.String(fmt.Sprintf("/aws/eks/%s/cluster", params.ClusterName)), }) - Expect(err).ToNot(HaveOccurred()) + Expect(err).NotTo(HaveOccurred()) Expect(logGroups.LogGroups).To(HaveLen(1)) Expect(*logGroups.LogGroups[0].RetentionInDays).To(Equal(int64(545))) }) diff --git a/integration/tests/cluster_api/cluster_api_endpoints_test.go b/integration/tests/cluster_api/cluster_api_endpoints_test.go index 83bb04fd1d..c1dd7727a4 100644 --- a/integration/tests/cluster_api/cluster_api_endpoints_test.go +++ b/integration/tests/cluster_api/cluster_api_endpoints_test.go @@ -81,17 +81,17 @@ var _ = Describe("(Integration) Create and Update Cluster with Endpoint Configs" // create and populate config file from clusterconfig bytes, err := json.Marshal(cfg) - Expect(err).ToNot(HaveOccurred()) - Expect(len(bytes)).ToNot(BeZero()) + Expect(err).NotTo(HaveOccurred()) + Expect(len(bytes)).NotTo(BeZero()) tmpfile, err := os.CreateTemp("", "clusterendpointtests") - Expect(err).ToNot(HaveOccurred()) + Expect(err).NotTo(HaveOccurred()) defer os.Remove(tmpfile.Name()) _, err = tmpfile.Write(bytes) - Expect(err).ToNot(HaveOccurred()) + Expect(err).NotTo(HaveOccurred()) err = tmpfile.Close() - Expect(err).ToNot(HaveOccurred()) + Expect(err).NotTo(HaveOccurred()) // create cluster with config file if e.Type == createCluster { diff --git a/integration/tests/cluster_dns/cluster_dns_test.go b/integration/tests/cluster_dns/cluster_dns_test.go index d86502035b..71d45e0c80 100644 --- a/integration/tests/cluster_dns/cluster_dns_test.go +++ b/integration/tests/cluster_dns/cluster_dns_test.go @@ -72,11 +72,11 @@ var _ = Describe("(Integration) [Cluster DNS test]", func() { It("cluster DNS should work", func() { test, err := kube.NewTest(params.KubeconfigPath) - Expect(err).ToNot(HaveOccurred()) + Expect(err).NotTo(HaveOccurred()) d := test.CreateDaemonSetFromFile(test.Namespace, "../../data/test-dns.yaml") test.WaitForDaemonSetReady(d, 2*time.Minute) ds, err := test.GetDaemonSet(test.Namespace, d.Name) - Expect(err).ToNot(HaveOccurred()) + Expect(err).NotTo(HaveOccurred()) fmt.Fprintf(GinkgoWriter, "ds.Status = %#v", ds.Status) }) diff --git a/integration/tests/crud/creategetdelete_test.go b/integration/tests/crud/creategetdelete_test.go index 7ae879e277..6942927cb0 100644 --- a/integration/tests/crud/creategetdelete_test.go +++ b/integration/tests/crud/creategetdelete_test.go @@ -230,9 +230,9 @@ var _ = Describe("(Integration) Create, Get, Scale & Delete", func() { Expect(cmd).To(RunSuccessfully()) config, err := clientcmd.BuildConfigFromFlags("", params.KubeconfigPath) - Expect(err).ToNot(HaveOccurred()) + Expect(err).NotTo(HaveOccurred()) clientset, err := kubernetes.NewForConfig(config) - Expect(err).ToNot(HaveOccurred()) + Expect(err).NotTo(HaveOccurred()) By("asserting that both formats for taints are supported") var ( @@ -750,8 +750,8 @@ var _ = Describe("(Integration) Create, Get, Scale & Delete", func() { stackNamePrefix := fmt.Sprintf("eksctl-%s-addon-iamserviceaccount-", params.ClusterName) - Expect(awsSession).ToNot(HaveExistingStack(stackNamePrefix + "default-s3-read-only")) - Expect(awsSession).ToNot(HaveExistingStack(stackNamePrefix + "app1-app-cache-access")) + Expect(awsSession).NotTo(HaveExistingStack(stackNamePrefix + "default-s3-read-only")) + Expect(awsSession).NotTo(HaveExistingStack(stackNamePrefix + "app1-app-cache-access")) }) }) @@ -878,10 +878,10 @@ var _ = Describe("(Integration) Create, Get, Scale & Delete", func() { Expect(so.SubjectFromWebIdentityToken).To(Equal("system:serviceaccount:" + test.Namespace + ":s3-reader")) - Expect(so.Credentials.SecretAccessKey).ToNot(BeEmpty()) - Expect(so.Credentials.SessionToken).ToNot(BeEmpty()) - Expect(so.Credentials.Expiration).ToNot(BeEmpty()) - Expect(so.Credentials.AccessKeyID).ToNot(BeEmpty()) + Expect(so.Credentials.SecretAccessKey).NotTo(BeEmpty()) + Expect(so.Credentials.SessionToken).NotTo(BeEmpty()) + Expect(so.Credentials.Expiration).NotTo(BeEmpty()) + Expect(so.Credentials.AccessKeyID).NotTo(BeEmpty()) } deleteCmd := params.EksctlDeleteCmd.WithArgs( @@ -951,7 +951,7 @@ var _ = Describe("(Integration) Create, Get, Scale & Delete", func() { "--arn", "arn:aws:iam::123456:role/idontexist", "-o", "yaml", ) - Expect(cmd).ToNot(RunSuccessfully()) + Expect(cmd).NotTo(RunSuccessfully()) }) It("fails getting unknown user mapping", func() { cmd := params.EksctlGetCmd.WithArgs( @@ -960,7 +960,7 @@ var _ = Describe("(Integration) Create, Get, Scale & Delete", func() { "--arn", "arn:aws:iam::123456:user/bob", "-o", "yaml", ) - Expect(cmd).ToNot(RunSuccessfully()) + Expect(cmd).NotTo(RunSuccessfully()) }) It("creates role mapping", func() { create := params.EksctlCreateCmd.WithArgs( @@ -1077,7 +1077,7 @@ var _ = Describe("(Integration) Create, Get, Scale & Delete", func() { "--cluster", params.ClusterName, "--arn", "arn:aws:iam::123456:role/idontexist", ) - Expect(deleteCmd).ToNot(RunSuccessfully()) + Expect(deleteCmd).NotTo(RunSuccessfully()) }) It("deletes duplicate role mappings with --all", func() { deleteCmd := params.EksctlDeleteCmd.WithArgs( @@ -1094,7 +1094,7 @@ var _ = Describe("(Integration) Create, Get, Scale & Delete", func() { "--arn", role1.ARN(), "-o", "yaml", ) - Expect(getCmd).ToNot(RunSuccessfully()) + Expect(getCmd).NotTo(RunSuccessfully()) }) It("deletes duplicate user mappings with --all", func() { deleteCmd := params.EksctlDeleteCmd.WithArgs( @@ -1111,7 +1111,7 @@ var _ = Describe("(Integration) Create, Get, Scale & Delete", func() { "--arn", user0.ARN(), "-o", "yaml", ) - Expect(getCmd).ToNot(RunSuccessfully()) + Expect(getCmd).NotTo(RunSuccessfully()) }) }) diff --git a/integration/tests/dry_run/dry_run_test.go b/integration/tests/dry_run/dry_run_test.go index 34ea1a6ca7..4fcb34ab10 100644 --- a/integration/tests/dry_run/dry_run_test.go +++ b/integration/tests/dry_run/dry_run_test.go @@ -150,9 +150,9 @@ vpc: var _ = Describe("(Integration) [Dry-Run test]", func() { parseOutput := func(output []byte) (*api.ClusterConfig, *api.ClusterConfig) { actual, err := eks.ParseConfig(output) - Expect(err).ToNot(HaveOccurred()) + Expect(err).NotTo(HaveOccurred()) defaultConfig, err := eks.ParseConfig([]byte(fmt.Sprintf(defaultClusterConfig, params.ClusterName))) - Expect(err).ToNot(HaveOccurred()) + Expect(err).NotTo(HaveOccurred()) return actual, defaultConfig } @@ -206,7 +206,7 @@ var _ = Describe("(Integration) [Dry-Run test]", func() { c.ManagedNodeGroups = nil c.NodeGroups = nil cidr, err := ipnet.ParseCIDR("192.168.0.0/24") - ExpectWithOffset(1, err).ToNot(HaveOccurred(), "unexpected error parsing CIDR") + ExpectWithOffset(1, err).NotTo(HaveOccurred(), "unexpected error parsing CIDR") c.VPC.CIDR = cidr c.VPC.NAT.Gateway = aws.String("HighlyAvailable") c.IAM.WithOIDC = aws.Bool(true) @@ -220,7 +220,7 @@ var _ = Describe("(Integration) [Dry-Run test]", func() { // TODO consider using a custom matcher session := cmd.Run() - Expect(session.ExitCode()).ToNot(Equal(0)) + Expect(session.ExitCode()).NotTo(Equal(0)) output := string(session.Err.Contents()) Expect(output).To(ContainSubstring(fmt.Sprintf("cannot use %s with --dry-run", strings.Split(flag, "=")[0]))) @@ -258,7 +258,7 @@ var _ = Describe("(Integration) [Dry-Run test]", func() { }, Entry("instance selector options with unmanaged nodegroup", func(actual, expected *api.ClusterConfig) { // This does not do an exact match because instance types matching the instance selector criteria may // change over time as EC2 adds more instance types - Expect(actual.NodeGroups[0].InstancesDistribution.InstanceTypes).ToNot(BeEmpty()) + Expect(actual.NodeGroups[0].InstancesDistribution.InstanceTypes).NotTo(BeEmpty()) actual.NodeGroups[0].InstancesDistribution.InstanceTypes = nil expected.ManagedNodeGroups = nil @@ -275,7 +275,7 @@ var _ = Describe("(Integration) [Dry-Run test]", func() { }, "--managed=false", "--instance-selector-vcpus=2", "--instance-selector-memory=4"), Entry("instance selector options with managed nodegroup", func(actual, expected *api.ClusterConfig) { - Expect(actual.ManagedNodeGroups[0].InstanceTypes).ToNot(BeEmpty()) + Expect(actual.ManagedNodeGroups[0].InstanceTypes).NotTo(BeEmpty()) actual.ManagedNodeGroups[0].InstanceTypes = nil expected.NodeGroups = nil @@ -355,7 +355,7 @@ var _ = Describe("(Integration) [Dry-Run test]", func() { ng := c.ManagedNodeGroups[0] actualNG := actual.ManagedNodeGroups[0] - Expect(actualNG.InstanceTypes).ToNot(BeEmpty()) + Expect(actualNG.InstanceTypes).NotTo(BeEmpty()) actualNG.InstanceTypes = nil ng.InstanceType = "" ng.InstanceSelector = &api.InstanceSelector{ diff --git a/integration/tests/eks_connector/eks_connector_test.go b/integration/tests/eks_connector/eks_connector_test.go index e19e5f9c3a..ed1be3f907 100644 --- a/integration/tests/eks_connector/eks_connector_test.go +++ b/integration/tests/eks_connector/eks_connector_test.go @@ -59,7 +59,7 @@ var _ = Describe("(Integration) [EKS Connector test]", func() { ) wd, err := os.Getwd() - Expect(err).ToNot(HaveOccurred()) + Expect(err).NotTo(HaveOccurred()) Expect(cmd).To(RunSuccessfullyWithOutputStringLines( ContainElement(ContainSubstring(fmt.Sprintf("registered cluster %q successfully", connectedClusterName))), @@ -87,7 +87,7 @@ var _ = Describe("(Integration) [EKS Connector test]", func() { rawClient := getRawClient(params.ClusterName, params.Region) for _, f := range resourcePaths { bytes, err := os.ReadFile(f) - Expect(err).ToNot(HaveOccurred()) + Expect(err).NotTo(HaveOccurred()) Expect(rawClient.CreateOrReplace(bytes, false)).To(Succeed()) } @@ -98,7 +98,7 @@ var _ = Describe("(Integration) [EKS Connector test]", func() { Region: params.Region, }, }) - Expect(err).ToNot(HaveOccurred()) + Expect(err).NotTo(HaveOccurred()) By("ensuring the registered cluster is active and visible") describeClusterInput := &awseks.DescribeClusterInput{ @@ -106,7 +106,7 @@ var _ = Describe("(Integration) [EKS Connector test]", func() { } Eventually(func() string { connectedCluster, err := provider.Provider.EKS().DescribeCluster(describeClusterInput) - Expect(err).ToNot(HaveOccurred()) + Expect(err).NotTo(HaveOccurred()) return *connectedCluster.Cluster.Status }, "5m", "8s").Should(Equal("ACTIVE")) @@ -121,7 +121,7 @@ var _ = Describe("(Integration) [EKS Connector test]", func() { ) session := cmd.Run() - Expect(session.ExitCode()).ToNot(Equal(0)) + Expect(session.ExitCode()).NotTo(Equal(0)) output := string(session.Err.Contents()) Expect(output).To(ContainSubstring(fmt.Sprintf("cannot perform this operation on a non-EKS cluster; please follow the documentation for "+ "cluster %s's Kubernetes provider", connectedClusterName))) @@ -176,6 +176,6 @@ func getRawClient(clusterName, region string) *kubewrapper.RawClient { err = ctl.RefreshClusterStatus(cfg) Expect(err).ShouldNot(HaveOccurred()) rawClient, err := ctl.NewRawClient(cfg) - Expect(err).ToNot(HaveOccurred()) + Expect(err).NotTo(HaveOccurred()) return rawClient } diff --git a/integration/tests/fargate/fargate_test.go b/integration/tests/fargate/fargate_test.go index fdd5067d80..3539398948 100644 --- a/integration/tests/fargate/fargate_test.go +++ b/integration/tests/fargate/fargate_test.go @@ -64,7 +64,7 @@ var _ = Describe("(Integration) Fargate", func() { var err error ft.kubeTest, err = kube.NewTest(params.KubeconfigPath) - Expect(err).ToNot(HaveOccurred()) + Expect(err).NotTo(HaveOccurred()) } testDefaultFargateProfile := func(clusterName string, kubeTest *harness.Test) { diff --git a/integration/tests/instance_selector/instance_selector_test.go b/integration/tests/instance_selector/instance_selector_test.go index f6168b71a3..755da69180 100644 --- a/integration/tests/instance_selector/instance_selector_test.go +++ b/integration/tests/instance_selector/instance_selector_test.go @@ -50,7 +50,7 @@ var _ = Describe("(Integration) [Instance Selector test]", func() { output := session.Buffer().Contents() clusterConfig, err := eks.ParseConfig(output) - Expect(err).ToNot(HaveOccurred()) + Expect(err).NotTo(HaveOccurred()) Expect(clusterConfig.ManagedNodeGroups).To(HaveLen(1)) if assertionFunc != nil { assertionFunc(clusterConfig.ManagedNodeGroups[0].InstanceTypes) @@ -58,7 +58,7 @@ var _ = Describe("(Integration) [Instance Selector test]", func() { }, Entry("non-GPU instances", func(instanceTypes []string) { for _, instanceType := range instanceTypes { - Expect(instanceType).ToNot(Satisfy(instanceutils.IsGPUInstanceType)) + Expect(instanceType).NotTo(Satisfy(instanceutils.IsGPUInstanceType)) } }, "--instance-selector-vcpus=8", "--instance-selector-memory=32", diff --git a/integration/tests/managed/managed_nodegroup_test.go b/integration/tests/managed/managed_nodegroup_test.go index b37c9ad027..71ed0701d4 100644 --- a/integration/tests/managed/managed_nodegroup_test.go +++ b/integration/tests/managed/managed_nodegroup_test.go @@ -143,7 +143,7 @@ var _ = Describe("(Integration) Create Managed Nodegroups", func() { if m.expectedErr != "" { session := cmd.Run() - Expect(session.ExitCode()).ToNot(Equal(0)) + Expect(session.ExitCode()).NotTo(Equal(0)) output := session.Err.Contents() Expect(string(output)).To(ContainSubstring(m.expectedErr)) return @@ -199,7 +199,7 @@ var _ = Describe("(Integration) Create Managed Nodegroups", func() { BeforeEach(func() { var err error kubeTest, err = kube.NewTest(params.KubeconfigPath) - Expect(err).ToNot(HaveOccurred()) + Expect(err).NotTo(HaveOccurred()) }) AfterEach(func() { @@ -225,7 +225,7 @@ var _ = Describe("(Integration) Create Managed Nodegroups", func() { nodeList := kubeTest.ListNodes(metav1.ListOptions{ LabelSelector: fmt.Sprintf("%s=%s", "eks.amazonaws.com/nodegroup", ng.Name), }) - Expect(nodeList.Items).ToNot(BeEmpty()) + Expect(nodeList.Items).NotTo(BeEmpty()) for _, node := range nodeList.Items { Expect(node.Status.NodeInfo.OSImage).To(ContainSubstring("Bottlerocket")) } @@ -477,13 +477,13 @@ var _ = Describe("(Integration) Create Managed Nodegroups", func() { } By(fmt.Sprintf("checking that control plane is updated to %v", nextVersion)) config, err := clientcmd.BuildConfigFromFlags("", params.KubeconfigPath) - Expect(err).ToNot(HaveOccurred()) + Expect(err).NotTo(HaveOccurred()) clientset, err := kubernetes.NewForConfig(config) - Expect(err).ToNot(HaveOccurred()) + Expect(err).NotTo(HaveOccurred()) Eventually(func() string { serverVersion, err := clientset.ServerVersion() - Expect(err).ToNot(HaveOccurred()) + Expect(err).NotTo(HaveOccurred()) return fmt.Sprintf("%s.%s", serverVersion.Major, strings.TrimSuffix(serverVersion.Minor, "+")) }, k8sUpdatePollTimeout, k8sUpdatePollInterval).Should(Equal(nextVersion)) @@ -538,9 +538,9 @@ var _ = Describe("(Integration) Create Managed Nodegroups", func() { Expect(cmd).To(RunSuccessfully()) config, err := clientcmd.BuildConfigFromFlags("", params.KubeconfigPath) - Expect(err).ToNot(HaveOccurred()) + Expect(err).NotTo(HaveOccurred()) clientset, err := kubernetes.NewForConfig(config) - Expect(err).ToNot(HaveOccurred()) + Expect(err).NotTo(HaveOccurred()) mapTaints := func(taints []api.NodeGroupTaint) []corev1.Taint { var ret []corev1.Taint diff --git a/integration/tests/quickstart_profiles_gen/quickstart_profiles_gen_test.go b/integration/tests/quickstart_profiles_gen/quickstart_profiles_gen_test.go index 7a6cd8f47a..13e957d6f7 100644 --- a/integration/tests/quickstart_profiles_gen/quickstart_profiles_gen_test.go +++ b/integration/tests/quickstart_profiles_gen/quickstart_profiles_gen_test.go @@ -58,7 +58,7 @@ var _ = Describe("(Integration) generate profile", func() { } contents, err := fs.ReadFile(filepath.Join(params.TestDirectory, "workloads/namespace.yaml")) - Expect(err).ToNot(HaveOccurred()) + Expect(err).NotTo(HaveOccurred()) Expect(string(contents)).To(MatchYAML(fmt.Sprintf( `--- apiVersion: v1 @@ -70,7 +70,7 @@ metadata: `, params.ClusterName, params.Region, params.ClusterName))) contents, err = fs.ReadFile(filepath.Join(params.TestDirectory, "workloads/services/service.yaml")) - Expect(err).ToNot(HaveOccurred()) + Expect(err).NotTo(HaveOccurred()) Expect(string(contents)).To(MatchYAML(fmt.Sprintf( `--- apiVersion: v1 @@ -87,7 +87,7 @@ spec: `, params.ClusterName))) contents, err = fs.ReadFile(filepath.Join(params.TestDirectory, "metadata.yaml")) - Expect(err).ToNot(HaveOccurred()) + Expect(err).NotTo(HaveOccurred()) Expect(string(contents)).To(MatchYAML( `--- somekey: diff --git a/integration/tests/update/update_cluster_test.go b/integration/tests/update/update_cluster_test.go index 88aa43fef4..7634ced6c1 100644 --- a/integration/tests/update/update_cluster_test.go +++ b/integration/tests/update/update_cluster_test.go @@ -140,14 +140,14 @@ var _ = Describe("(Integration) Update addons", func() { By(fmt.Sprintf("checking that control plane is updated to %v", nextEKSVersion)) config, err := clientcmd.BuildConfigFromFlags("", params.KubeconfigPath) - Expect(err).ToNot(HaveOccurred()) + Expect(err).NotTo(HaveOccurred()) clientSet, err := kubernetes.NewForConfig(config) - Expect(err).ToNot(HaveOccurred()) + Expect(err).NotTo(HaveOccurred()) Eventually(func() string { serverVersion, err := clientSet.ServerVersion() - Expect(err).ToNot(HaveOccurred()) + Expect(err).NotTo(HaveOccurred()) return fmt.Sprintf("%s.%s", serverVersion.Major, strings.TrimSuffix(serverVersion.Minor, "+")) }, k8sUpdatePollTimeout, k8sUpdatePollInterval).Should(Equal(nextEKSVersion)) }) @@ -163,12 +163,12 @@ var _ = Describe("(Integration) Update addons", func() { rawClient := getRawClient() kubernetesVersion, err := rawClient.ServerVersion() - Expect(err).ToNot(HaveOccurred()) + Expect(err).NotTo(HaveOccurred()) Eventually(func() string { daemonSet, err := rawClient.ClientSet().AppsV1().DaemonSets(metav1.NamespaceSystem).Get(context.TODO(), "kube-proxy", metav1.GetOptions{}) - Expect(err).ToNot(HaveOccurred()) + Expect(err).NotTo(HaveOccurred()) kubeProxyVersion, err := addons.ImageTag(daemonSet.Spec.Template.Spec.Containers[0].Image) - Expect(err).ToNot(HaveOccurred()) + Expect(err).NotTo(HaveOccurred()) return kubeProxyVersion }, k8sUpdatePollTimeout, k8sUpdatePollInterval).Should(Equal(fmt.Sprintf("v%s-eksbuild.1", kubernetesVersion))) }) @@ -177,9 +177,9 @@ var _ = Describe("(Integration) Update addons", func() { rawClient := getRawClient() getAWSNodeVersion := func() string { awsNode, err := rawClient.ClientSet().AppsV1().DaemonSets(metav1.NamespaceSystem).Get(context.TODO(), "aws-node", metav1.GetOptions{}) - Expect(err).ToNot(HaveOccurred()) + Expect(err).NotTo(HaveOccurred()) imageTag, err := addons.ImageTag(awsNode.Spec.Template.Spec.Containers[0].Image) - Expect(err).ToNot(HaveOccurred()) + Expect(err).NotTo(HaveOccurred()) return imageTag } preUpdateAWSNodeVersion := getAWSNodeVersion() @@ -221,6 +221,6 @@ func getRawClient() *kubewrapper.RawClient { err = ctl.RefreshClusterStatus(cfg) Expect(err).ShouldNot(HaveOccurred()) rawClient, err := ctl.NewRawClient(cfg) - Expect(err).ToNot(HaveOccurred()) + Expect(err).NotTo(HaveOccurred()) return rawClient } diff --git a/integration/tests/windows/windows_test.go b/integration/tests/windows/windows_test.go index 3fda1ee603..75a5bdb7c7 100644 --- a/integration/tests/windows/windows_test.go +++ b/integration/tests/windows/windows_test.go @@ -68,7 +68,7 @@ var _ = Describe("(Integration) [Windows Nodegroups]", func() { } data, err := json.Marshal(clusterConfig) - Expect(err).ToNot(HaveOccurred()) + Expect(err).NotTo(HaveOccurred()) cmd := params.EksctlCreateCmd. WithArgs( @@ -86,7 +86,7 @@ var _ = Describe("(Integration) [Windows Nodegroups]", func() { runWindowsPod := func() { By("scheduling a Windows pod") kubeTest, err := kube.NewTest(params.KubeconfigPath) - Expect(err).ToNot(HaveOccurred()) + Expect(err).NotTo(HaveOccurred()) d := kubeTest.CreateDeploymentFromFile("default", "../../data/windows-server-iis.yaml") kubeTest.WaitForDeploymentReady(d, 12*time.Minute) diff --git a/integration/utilities/cluster/cluster.go b/integration/utilities/cluster/cluster.go index 17487d2137..aaec11d94c 100644 --- a/integration/utilities/cluster/cluster.go +++ b/integration/utilities/cluster/cluster.go @@ -14,19 +14,19 @@ import ( func Reader(clusterConfig *v1alpha5.ClusterConfig) io.Reader { data, err := json.Marshal(clusterConfig) - Expect(err).ToNot(HaveOccurred()) + Expect(err).NotTo(HaveOccurred()) return bytes.NewReader(data) } func ReaderFromFile(clusterName, region, filename string) io.Reader { data, err := os.ReadFile(filename) - Expect(err).ToNot(HaveOccurred()) + Expect(err).NotTo(HaveOccurred()) clusterConfig, err := eks.ParseConfig(data) - Expect(err).ToNot(HaveOccurred()) + Expect(err).NotTo(HaveOccurred()) clusterConfig.Metadata.Name = clusterName clusterConfig.Metadata.Region = region data, err = json.Marshal(clusterConfig) - Expect(err).ToNot(HaveOccurred()) + Expect(err).NotTo(HaveOccurred()) return bytes.NewReader(data) } diff --git a/pkg/actions/addon/create_test.go b/pkg/actions/addon/create_test.go index 1452be625c..d63a1acf20 100644 --- a/pkg/actions/addon/create_test.go +++ b/pkg/actions/addon/create_test.go @@ -56,15 +56,15 @@ var _ = Describe("Create", func() { for _, item := range sampleAddons { rc, err := rawClient.NewRawResource(item) - Expect(err).ToNot(HaveOccurred()) + Expect(err).NotTo(HaveOccurred()) _, err = rc.CreateOrReplace(false) - Expect(err).ToNot(HaveOccurred()) + Expect(err).NotTo(HaveOccurred()) } ct := rawClient.Collection Expect(ct.Updated()).To(BeEmpty()) - Expect(ct.Created()).ToNot(BeEmpty()) + Expect(ct.Created()).NotTo(BeEmpty()) Expect(ct.CreatedItems()).To(HaveLen(10)) }) @@ -72,7 +72,7 @@ var _ = Describe("Create", func() { var err error oidc, err = iamoidc.NewOpenIDConnectManager(nil, "456123987123", "https://oidc.eks.us-west-2.amazonaws.com/id/A39A2842863C47208955D753DE205E6E", "aws", nil) - Expect(err).ToNot(HaveOccurred()) + Expect(err).NotTo(HaveOccurred()) oidc.ProviderARN = "arn:aws:iam::456123987123:oidc-provider/oidc.eks.us-west-2.amazonaws.com/id/A39A2842863C47208955D753DE205E6E" mockProvider.MockEKS().On("CreateAddon", mock.Anything).Run(func(args mock.Arguments) { diff --git a/pkg/actions/addon/update_test.go b/pkg/actions/addon/update_test.go index 8662b4c868..339a4e0e91 100644 --- a/pkg/actions/addon/update_test.go +++ b/pkg/actions/addon/update_test.go @@ -44,7 +44,7 @@ var _ = Describe("Update", func() { } oidc, err := iamoidc.NewOpenIDConnectManager(nil, "456123987123", "https://oidc.eks.us-west-2.amazonaws.com/id/A39A2842863C47208955D753DE205E6E", "aws", nil) - Expect(err).ToNot(HaveOccurred()) + Expect(err).NotTo(HaveOccurred()) oidc.ProviderARN = "arn:aws:iam::456123987123:oidc-provider/oidc.eks.us-west-2.amazonaws.com/id/A39A2842863C47208955D753DE205E6E" mockProvider.MockEKS().On("DescribeAddonVersions", mock.Anything).Run(func(args mock.Arguments) { diff --git a/pkg/actions/irsa/update_test.go b/pkg/actions/irsa/update_test.go index cbec2f442d..aa54181043 100644 --- a/pkg/actions/irsa/update_test.go +++ b/pkg/actions/irsa/update_test.go @@ -37,7 +37,7 @@ var _ = Describe("Update", func() { fakeStackManager = new(fakes.FakeStackManager) oidc, err = iamoidc.NewOpenIDConnectManager(nil, "456123987123", "https://oidc.eks.us-west-2.amazonaws.com/id/A39A2842863C47208955D753DE205E6E", "aws", nil) - Expect(err).ToNot(HaveOccurred()) + Expect(err).NotTo(HaveOccurred()) oidc.ProviderARN = "arn:aws:iam::456123987123:oidc-provider/oidc.eks.us-west-2.amazonaws.com/id/A39A2842863C47208955D753DE205E6E" irsaManager = irsa.New("my-cluster", fakeStackManager, oidc, nil) }) diff --git a/pkg/addons/default/aws_node_test.go b/pkg/addons/default/aws_node_test.go index 19cbed95b7..2aeb90d008 100644 --- a/pkg/addons/default/aws_node_test.go +++ b/pkg/addons/default/aws_node_test.go @@ -29,15 +29,15 @@ var _ = Describe("default addons - aws-node", func() { for _, item := range sampleAddons { rc, err := rawClient.NewRawResource(item) - Expect(err).ToNot(HaveOccurred()) + Expect(err).NotTo(HaveOccurred()) _, err = rc.CreateOrReplace(false) - Expect(err).ToNot(HaveOccurred()) + Expect(err).NotTo(HaveOccurred()) } ct = rawClient.Collection Expect(ct.Updated()).To(BeEmpty()) - Expect(ct.Created()).ToNot(BeEmpty()) + Expect(ct.Created()).NotTo(BeEmpty()) Expect(ct.CreatedItems()).To(HaveLen(10)) } It("reports that 1.15 sample needs an update", func() { @@ -45,7 +45,7 @@ var _ = Describe("default addons - aws-node", func() { rawClient.AssumeObjectsMissing = false needsUpdate, err := DoesAWSNodeSupportMultiArch(rawClient, "eu-west-1") - Expect(err).ToNot(HaveOccurred()) + Expect(err).NotTo(HaveOccurred()) Expect(needsUpdate).To(BeFalse()) }) It("reports that sample with 1.6.3-eksbuild.1 doesn't need an update", func() { @@ -53,7 +53,7 @@ var _ = Describe("default addons - aws-node", func() { rawClient.AssumeObjectsMissing = false needsUpdate, err := DoesAWSNodeSupportMultiArch(rawClient, "eu-west-1") - Expect(err).ToNot(HaveOccurred()) + Expect(err).NotTo(HaveOccurred()) Expect(needsUpdate).To(BeTrue()) }) It("reports that sample with 1.7.6 doesn't need an update", func() { @@ -61,7 +61,7 @@ var _ = Describe("default addons - aws-node", func() { rawClient.AssumeObjectsMissing = false needsUpdate, err := DoesAWSNodeSupportMultiArch(rawClient, "eu-west-1") - Expect(err).ToNot(HaveOccurred()) + Expect(err).NotTo(HaveOccurred()) Expect(needsUpdate).To(BeTrue()) }) }) @@ -81,15 +81,15 @@ var _ = Describe("default addons - aws-node", func() { for _, item := range sampleAddons { rc, err := rawClient.NewRawResource(item) - Expect(err).ToNot(HaveOccurred()) + Expect(err).NotTo(HaveOccurred()) _, err = rc.CreateOrReplace(false) - Expect(err).ToNot(HaveOccurred()) + Expect(err).NotTo(HaveOccurred()) } ct = rawClient.Collection Expect(ct.Updated()).To(BeEmpty()) - Expect(ct.Created()).ToNot(BeEmpty()) + Expect(ct.Created()).NotTo(BeEmpty()) Expect(ct.CreatedItems()).To(HaveLen(10)) }) @@ -97,7 +97,7 @@ var _ = Describe("default addons - aws-node", func() { rawClient.ClientSetUseUpdatedObjects = false // must be set for initial verification, and for subsequent UpdateAWSNode awsNode, err := rawClient.ClientSet().AppsV1().DaemonSets(metav1.NamespaceSystem).Get(context.TODO(), AWSNode, metav1.GetOptions{}) - Expect(err).ToNot(HaveOccurred()) + Expect(err).NotTo(HaveOccurred()) Expect(awsNode.Spec.Template.Spec.Containers).To(HaveLen(1)) Expect(awsNode.Spec.Template.Spec.Containers[0].Image).To( Equal("602401143452.dkr.ecr.eu-west-1.amazonaws.com/amazon-k8s-cni:v1.5.7"), @@ -109,11 +109,11 @@ var _ = Describe("default addons - aws-node", func() { rawClient.AssumeObjectsMissing = false preUpdateAwsNode, err := rawClient.ClientSet().AppsV1().DaemonSets(metav1.NamespaceSystem).Get(context.TODO(), AWSNode, metav1.GetOptions{}) - Expect(err).ToNot(HaveOccurred()) + Expect(err).NotTo(HaveOccurred()) _, err = UpdateAWSNode(rawClient, "eu-west-1", false) - Expect(err).ToNot(HaveOccurred()) + Expect(err).NotTo(HaveOccurred()) Expect(rawClient.Collection.UpdatedItems()).To(HaveLen(3)) - Expect(rawClient.Collection.UpdatedItems()).ToNot(ContainElement(PointTo(MatchFields(IgnoreMissing|IgnoreExtras, Fields{ + Expect(rawClient.Collection.UpdatedItems()).NotTo(ContainElement(PointTo(MatchFields(IgnoreMissing|IgnoreExtras, Fields{ "TypeMeta": MatchFields(IgnoreMissing|IgnoreExtras, Fields{"Kind": Equal("ServiceAccount")}), })))) Expect(rawClient.Collection.CreatedItems()).To(HaveLen(10)) @@ -121,9 +121,9 @@ var _ = Describe("default addons - aws-node", func() { rawClient.ClientSetUseUpdatedObjects = true // for verification of updated objects awsNode, err := rawClient.ClientSet().AppsV1().DaemonSets(metav1.NamespaceSystem).Get(context.TODO(), AWSNode, metav1.GetOptions{}) - Expect(err).ToNot(HaveOccurred()) + Expect(err).NotTo(HaveOccurred()) Expect(awsNode.Spec.Template.Spec.Containers).To(HaveLen(1)) - Expect(awsNode.Spec.Template.Spec.Containers[0].Image).ToNot( + Expect(awsNode.Spec.Template.Spec.Containers[0].Image).NotTo( Equal(preUpdateAwsNode.Spec.Template.Spec.Containers[0].Image), ) Expect(awsNode.Spec.Template.Spec.InitContainers).To(HaveLen(1)) @@ -137,16 +137,16 @@ var _ = Describe("default addons - aws-node", func() { rawClient.ClientSetUseUpdatedObjects = false // must be set for subsequent UpdateAWSNode preUpdateAwsNode, err := rawClient.ClientSet().AppsV1().DaemonSets(metav1.NamespaceSystem).Get(context.TODO(), AWSNode, metav1.GetOptions{}) - Expect(err).ToNot(HaveOccurred()) + Expect(err).NotTo(HaveOccurred()) _, err = UpdateAWSNode(rawClient, "us-east-1", false) - Expect(err).ToNot(HaveOccurred()) + Expect(err).NotTo(HaveOccurred()) rawClient.ClientSetUseUpdatedObjects = true // for verification of updated objects awsNode, err := rawClient.ClientSet().AppsV1().DaemonSets(metav1.NamespaceSystem).Get(context.TODO(), AWSNode, metav1.GetOptions{}) - Expect(err).ToNot(HaveOccurred()) + Expect(err).NotTo(HaveOccurred()) Expect(awsNode.Spec.Template.Spec.Containers).To(HaveLen(1)) - Expect(awsNode.Spec.Template.Spec.Containers[0].Image).ToNot( + Expect(awsNode.Spec.Template.Spec.Containers[0].Image).NotTo( Equal(preUpdateAwsNode.Spec.Template.Spec.Containers[0].Image), ) Expect(awsNode.Spec.Template.Spec.InitContainers).To(HaveLen(1)) @@ -159,16 +159,16 @@ var _ = Describe("default addons - aws-node", func() { rawClient.ClientSetUseUpdatedObjects = false // must be set for subsequent UpdateAWSNode preUpdateAwsNode, err := rawClient.ClientSet().AppsV1().DaemonSets(metav1.NamespaceSystem).Get(context.TODO(), AWSNode, metav1.GetOptions{}) - Expect(err).ToNot(HaveOccurred()) + Expect(err).NotTo(HaveOccurred()) _, err = UpdateAWSNode(rawClient, "cn-northwest-1", false) - Expect(err).ToNot(HaveOccurred()) + Expect(err).NotTo(HaveOccurred()) rawClient.ClientSetUseUpdatedObjects = true // for verification of updated objects awsNode, err := rawClient.ClientSet().AppsV1().DaemonSets(metav1.NamespaceSystem).Get(context.TODO(), AWSNode, metav1.GetOptions{}) - Expect(err).ToNot(HaveOccurred()) + Expect(err).NotTo(HaveOccurred()) Expect(awsNode.Spec.Template.Spec.Containers).To(HaveLen(1)) - Expect(awsNode.Spec.Template.Spec.Containers[0].Image).ToNot( + Expect(awsNode.Spec.Template.Spec.Containers[0].Image).NotTo( Equal(preUpdateAwsNode.Spec.Template.Spec.Containers[0].Image), ) Expect(awsNode.Spec.Template.Spec.InitContainers).To(HaveLen(1)) @@ -180,7 +180,7 @@ var _ = Describe("default addons - aws-node", func() { It("detects matching image version when determining plan", func() { // updating from latest to latest needs no updating needsUpdate, err := UpdateAWSNode(rawClient, "eu-west-2", true) - Expect(err).ToNot(HaveOccurred()) + Expect(err).NotTo(HaveOccurred()) Expect(needsUpdate).To(BeFalse()) }) }) diff --git a/pkg/addons/default/coredns_test.go b/pkg/addons/default/coredns_test.go index 5f54477cf1..5ff1bcc296 100644 --- a/pkg/addons/default/coredns_test.go +++ b/pkg/addons/default/coredns_test.go @@ -42,7 +42,7 @@ var _ = Describe("default addons - coredns", func() { It("updates coredns to the correct version", func() { _, err := da.UpdateCoreDNS(rawClient, region, controlPlaneVersion, false) - Expect(err).ToNot(HaveOccurred()) + Expect(err).NotTo(HaveOccurred()) updateReqs := []string{ "PUT [/namespaces/kube-system/serviceaccounts/coredns] (coredns)", @@ -68,7 +68,7 @@ var _ = Describe("default addons - coredns", func() { BeforeEach(func() { createCoreDNSFromTestSample(rawClient, ct, kubernetesVersion) _, err := da.UpdateCoreDNS(rawClient, region, controlPlaneVersion, false) - Expect(err).ToNot(HaveOccurred()) + Expect(err).NotTo(HaveOccurred()) }) Context("when CoreDNS is NOT up to date", func() { @@ -99,9 +99,9 @@ func createCoreDNSFromTestSample(rawClient *testutils.FakeRawClient, ct *testuti for _, item := range sampleAddons { rc, err := rawClient.NewRawResource(item) - Expect(err).ToNot(HaveOccurred()) + Expect(err).NotTo(HaveOccurred()) _, err = rc.CreateOrReplace(false) - Expect(err).ToNot(HaveOccurred()) + Expect(err).NotTo(HaveOccurred()) } createReqs := []string{ @@ -128,8 +128,8 @@ func createCoreDNSFromTestSample(rawClient *testutils.FakeRawClient, ct *testuti func coreDNSImage(rawClient *testutils.FakeRawClient) string { coreDNS, err := rawClient.ClientSet().AppsV1().Deployments(metav1.NamespaceSystem).Get(context.TODO(), da.CoreDNS, metav1.GetOptions{}) - Expect(err).ToNot(HaveOccurred()) - Expect(coreDNS).ToNot(BeNil()) + Expect(err).NotTo(HaveOccurred()) + Expect(coreDNS).NotTo(BeNil()) Expect(coreDNS.Spec.Template.Spec.Containers).To(HaveLen(1)) return coreDNS.Spec.Template.Spec.Containers[0].Image diff --git a/pkg/addons/default/helpers_test.go b/pkg/addons/default/helpers_test.go index 2229f7ce53..5aff765cf9 100644 --- a/pkg/addons/default/helpers_test.go +++ b/pkg/addons/default/helpers_test.go @@ -19,17 +19,17 @@ var _ = Describe("default addons", func() { clientSet, _ := testutils.NewFakeClientSetWithSamples("testdata/sample-1.16.json") nsl, err := clientSet.CoreV1().Namespaces().List(context.TODO(), metav1.ListOptions{}) - Expect(err).ToNot(HaveOccurred()) + Expect(err).NotTo(HaveOccurred()) Expect(nsl.Items).To(HaveLen(0)) dl, err := clientSet.AppsV1().Deployments(metav1.NamespaceAll).List(context.TODO(), metav1.ListOptions{}) - Expect(err).ToNot(HaveOccurred()) + Expect(err).NotTo(HaveOccurred()) Expect(dl.Items).To(HaveLen(1)) Expect(dl.Items[0].Spec.Template.Spec.Containers).To(HaveLen(1)) kubeProxy, err := clientSet.AppsV1().DaemonSets(metav1.NamespaceSystem).Get(context.TODO(), KubeProxy, metav1.GetOptions{}) - Expect(err).ToNot(HaveOccurred()) - Expect(kubeProxy).ToNot(BeNil()) + Expect(err).NotTo(HaveOccurred()) + Expect(kubeProxy).NotTo(BeNil()) Expect(kubeProxy.Spec.Template.Spec.Containers).To(HaveLen(1)) }) }) diff --git a/pkg/addons/default/kube_proxy_test.go b/pkg/addons/default/kube_proxy_test.go index 700e54c8ec..c48a4aea88 100644 --- a/pkg/addons/default/kube_proxy_test.go +++ b/pkg/addons/default/kube_proxy_test.go @@ -25,14 +25,14 @@ var _ = Describe("default addons - kube-proxy", func() { It("can update to multi-architecture image based on control plane version", func() { _, err := UpdateKubeProxy(clientSet, "1.16.0", false) - Expect(err).ToNot(HaveOccurred()) + Expect(err).NotTo(HaveOccurred()) Expect(kubeProxyImage(clientSet)).To(Equal("602401143452.dkr.ecr.eu-west-1.amazonaws.com/eks/kube-proxy:v1.16.0-eksbuild.1")) Expect(kubeProxyNodeSelectorValues(clientSet)).To(ConsistOf("amd64", "arm64")) }) It("can dry-run update based on control plane version", func() { _, err := UpdateKubeProxy(clientSet, "1.16.1", true) - Expect(err).ToNot(HaveOccurred()) + Expect(err).NotTo(HaveOccurred()) Expect(kubeProxyImage(clientSet)).To(Equal("602401143452.dkr.ecr.eu-west-1.amazonaws.com/eks/kube-proxy:v1.15.11")) }) }) @@ -41,8 +41,8 @@ var _ = Describe("default addons - kube-proxy", func() { func kubeProxyImage(clientSet *fake.Clientset) string { kubeProxy, err := clientSet.AppsV1().DaemonSets(metav1.NamespaceSystem).Get(context.TODO(), KubeProxy, metav1.GetOptions{}) - Expect(err).ToNot(HaveOccurred()) - Expect(kubeProxy).ToNot(BeNil()) + Expect(err).NotTo(HaveOccurred()) + Expect(kubeProxy).NotTo(BeNil()) Expect(kubeProxy.Spec.Template.Spec.Containers).To(HaveLen(1)) return kubeProxy.Spec.Template.Spec.Containers[0].Image @@ -51,8 +51,8 @@ func kubeProxyImage(clientSet *fake.Clientset) string { func kubeProxyNodeSelectorValues(clientSet *fake.Clientset) []string { kubeProxy, err := clientSet.AppsV1().DaemonSets(metav1.NamespaceSystem).Get(context.TODO(), KubeProxy, metav1.GetOptions{}) - Expect(err).ToNot(HaveOccurred()) - Expect(kubeProxy).ToNot(BeNil()) + Expect(err).NotTo(HaveOccurred()) + Expect(kubeProxy).NotTo(BeNil()) for _, nodeSelector := range kubeProxy.Spec.Template.Spec.Affinity.NodeAffinity.RequiredDuringSchedulingIgnoredDuringExecution.NodeSelectorTerms[0].MatchExpressions { if nodeSelector.Key == "beta.kubernetes.io/arch" { diff --git a/pkg/apis/eksctl.io/v1alpha5/defaults_test.go b/pkg/apis/eksctl.io/v1alpha5/defaults_test.go index 41a7bfe6c8..3b6f9d38ca 100644 --- a/pkg/apis/eksctl.io/v1alpha5/defaults_test.go +++ b/pkg/apis/eksctl.io/v1alpha5/defaults_test.go @@ -167,7 +167,7 @@ var _ = Describe("ClusterConfig validation", func() { SetNodeGroupDefaults(&testNodeGroup, &ClusterMeta{}) - Expect(testNodeGroup.Bottlerocket).ToNot(BeNil()) + Expect(testNodeGroup.Bottlerocket).NotTo(BeNil()) Expect(testNodeGroup.Bottlerocket.EnableAdminContainer).To(BeNil()) }) }) diff --git a/pkg/apis/eksctl.io/v1alpha5/gpu_validation_test.go b/pkg/apis/eksctl.io/v1alpha5/gpu_validation_test.go index 29d039baf6..db0f7bf3ea 100644 --- a/pkg/apis/eksctl.io/v1alpha5/gpu_validation_test.go +++ b/pkg/apis/eksctl.io/v1alpha5/gpu_validation_test.go @@ -25,7 +25,7 @@ var _ = Describe("GPU instance support", func() { Expect(err).To(MatchError(ContainSubstring(fmt.Sprintf("GPU instance types are not supported for %s", e.amiFamily)))) return } - Expect(err).ToNot(HaveOccurred()) + Expect(err).NotTo(HaveOccurred()) } DescribeTable("managed nodegroups", func(e gpuInstanceEntry) { diff --git a/pkg/apis/eksctl.io/v1alpha5/instance_selector_test.go b/pkg/apis/eksctl.io/v1alpha5/instance_selector_test.go index 2e2f719b1c..c7c39c8c19 100644 --- a/pkg/apis/eksctl.io/v1alpha5/instance_selector_test.go +++ b/pkg/apis/eksctl.io/v1alpha5/instance_selector_test.go @@ -16,7 +16,7 @@ var _ = Describe("Instance Selector Validation", func() { SetNodeGroupDefaults(n.ng, &ClusterMeta{Name: "cluster"}) err := ValidateNodeGroup(0, n.ng) if n.errMsg == "" { - Expect(err).ToNot(HaveOccurred()) + Expect(err).NotTo(HaveOccurred()) return } Expect(err).To(HaveOccurred()) diff --git a/pkg/apis/eksctl.io/v1alpha5/managed_nodegroup_test.go b/pkg/apis/eksctl.io/v1alpha5/managed_nodegroup_test.go index 84738467bf..8b9f2792dd 100644 --- a/pkg/apis/eksctl.io/v1alpha5/managed_nodegroup_test.go +++ b/pkg/apis/eksctl.io/v1alpha5/managed_nodegroup_test.go @@ -17,7 +17,7 @@ var _ = Describe("Managed Nodegroup Validation", func() { SetManagedNodeGroupDefaults(n.ng, &ClusterMeta{Name: "managed-cluster"}) err := ValidateManagedNodeGroup(n.ng, 0) if n.errMsg == "" { - Expect(err).ToNot(HaveOccurred()) + Expect(err).NotTo(HaveOccurred()) return } Expect(err).To(HaveOccurred()) @@ -189,7 +189,7 @@ var _ = Describe("Managed Nodegroup Validation", func() { SetManagedNodeGroupDefaults(mng, &ClusterMeta{Name: "managed-cluster"}) err := ValidateManagedNodeGroup(mng, 0) if e.valid { - Expect(err).ToNot(HaveOccurred()) + Expect(err).NotTo(HaveOccurred()) } else { Expect(err).To(HaveOccurred()) } diff --git a/pkg/apis/eksctl.io/v1alpha5/validation_test.go b/pkg/apis/eksctl.io/v1alpha5/validation_test.go index 968f92c25f..7f02e021ba 100644 --- a/pkg/apis/eksctl.io/v1alpha5/validation_test.go +++ b/pkg/apis/eksctl.io/v1alpha5/validation_test.go @@ -29,11 +29,11 @@ var _ = Describe("ClusterConfig validation", func() { It("should handle unique nodegroups", func() { err = api.ValidateClusterConfig(cfg) - Expect(err).ToNot(HaveOccurred()) + Expect(err).NotTo(HaveOccurred()) for i, ng := range cfg.NodeGroups { err = api.ValidateNodeGroup(i, ng) - Expect(err).ToNot(HaveOccurred()) + Expect(err).NotTo(HaveOccurred()) } }) @@ -71,7 +71,7 @@ var _ = Describe("ClusterConfig validation", func() { It("should reject invalid nodegroup names", func() { err = api.ValidateClusterConfig(cfg) - Expect(err).ToNot(HaveOccurred()) + Expect(err).NotTo(HaveOccurred()) for i, ng := range cfg.NodeGroups { err = api.ValidateNodeGroup(i, ng) @@ -87,7 +87,7 @@ var _ = Describe("ClusterConfig validation", func() { ng0.Name = "node-group" ng0.ContainerRuntime = aws.String("invalid") err := api.ValidateClusterConfig(cfg) - Expect(err).ToNot(HaveOccurred()) + Expect(err).NotTo(HaveOccurred()) err = api.ValidateNodeGroup(0, ng0) Expect(err).To(HaveOccurred()) }) @@ -98,7 +98,7 @@ var _ = Describe("ClusterConfig validation", func() { ng0.ContainerRuntime = aws.String(api.ContainerRuntimeContainerD) ng0.AMIFamily = api.NodeImageFamilyBottlerocket err := api.ValidateClusterConfig(cfg) - Expect(err).ToNot(HaveOccurred()) + Expect(err).NotTo(HaveOccurred()) err = api.ValidateNodeGroup(0, ng0) Expect(err).To(HaveOccurred()) }) @@ -242,11 +242,11 @@ var _ = Describe("ClusterConfig validation", func() { JustBeforeEach(func() { err = api.ValidateClusterConfig(cfg) - Expect(err).ToNot(HaveOccurred()) + Expect(err).NotTo(HaveOccurred()) for i, ng := range cfg.NodeGroups { err = api.ValidateNodeGroup(i, ng) - Expect(err).ToNot(HaveOccurred()) + Expect(err).NotTo(HaveOccurred()) } }) @@ -254,14 +254,14 @@ var _ = Describe("ClusterConfig validation", func() { ng1.IAM.InstanceProfileARN = "p1" err = api.ValidateNodeGroup(1, ng1) - Expect(err).ToNot(HaveOccurred()) + Expect(err).NotTo(HaveOccurred()) }) It("should allow setting only instanceRoleARN", func() { ng1.IAM.InstanceRoleARN = "r1" err = api.ValidateNodeGroup(1, ng1) - Expect(err).ToNot(HaveOccurred()) + Expect(err).NotTo(HaveOccurred()) }) It("should allow setting instanceProfileARN and instanceRoleARN", func() { @@ -269,7 +269,7 @@ var _ = Describe("ClusterConfig validation", func() { ng1.IAM.InstanceRoleARN = "r1" err = api.ValidateNodeGroup(1, ng1) - Expect(err).ToNot(HaveOccurred()) + Expect(err).NotTo(HaveOccurred()) }) It("should not allow setting instanceProfileARN and instanceRoleName", func() { @@ -346,21 +346,21 @@ var _ = Describe("ClusterConfig validation", func() { cfg.IAM.WithOIDC = nil err = api.ValidateClusterConfig(cfg) - Expect(err).ToNot(HaveOccurred()) + Expect(err).NotTo(HaveOccurred()) }) It("should pass when iam.withOIDC is disabled", func() { cfg.IAM.WithOIDC = api.Disabled() err = api.ValidateClusterConfig(cfg) - Expect(err).ToNot(HaveOccurred()) + Expect(err).NotTo(HaveOccurred()) }) It("should pass when iam.withOIDC is enabled", func() { cfg.IAM.WithOIDC = api.Enabled() err = api.ValidateClusterConfig(cfg) - Expect(err).ToNot(HaveOccurred()) + Expect(err).NotTo(HaveOccurred()) }) It("should fail when iam.withOIDC is disabled and some iam.serviceAccounts are given", func() { @@ -497,7 +497,7 @@ var _ = Describe("ClusterConfig validation", func() { return } - Expect(err).ToNot(HaveOccurred()) + Expect(err).NotTo(HaveOccurred()) }, Entry("invalid value", logRetentionEntry{ logging: &api.ClusterCloudWatchLogging{ @@ -539,21 +539,21 @@ var _ = Describe("ClusterConfig validation", func() { cfg.VPC.ClusterEndpoints = &api.ClusterEndpoints{PrivateAccess: api.Enabled(), PublicAccess: api.Enabled()} err = cfg.ValidateClusterEndpointConfig() - Expect(err).ToNot(HaveOccurred()) + Expect(err).NotTo(HaveOccurred()) }) It("should not error on private=false, public=true", func() { cfg.VPC.ClusterEndpoints = &api.ClusterEndpoints{PrivateAccess: api.Disabled(), PublicAccess: api.Enabled()} err = cfg.ValidateClusterEndpointConfig() - Expect(err).ToNot(HaveOccurred()) + Expect(err).NotTo(HaveOccurred()) }) It("should not error on private=true, public=false", func() { cfg.VPC.ClusterEndpoints = &api.ClusterEndpoints{PrivateAccess: api.Enabled(), PublicAccess: api.Disabled()} err = cfg.ValidateClusterEndpointConfig() - Expect(err).ToNot(HaveOccurred()) + Expect(err).NotTo(HaveOccurred()) }) It("should error on private=false, public=false", func() { @@ -579,12 +579,12 @@ var _ = Describe("ClusterConfig validation", func() { It("works independent of instanceType", func() { Context("unset", func() { err := api.ValidateNodeGroup(0, ng) - Expect(err).ToNot(HaveOccurred()) + Expect(err).NotTo(HaveOccurred()) }) Context("set", func() { ng.InstanceType = "mixed" err := api.ValidateNodeGroup(0, ng) - Expect(err).ToNot(HaveOccurred()) + Expect(err).NotTo(HaveOccurred()) }) }) @@ -666,7 +666,7 @@ var _ = Describe("ClusterConfig validation", func() { It("It doesn't panic when instance distribution is not enabled", func() { ng.InstancesDistribution = nil err := api.ValidateNodeGroup(0, ng) - Expect(err).ToNot(HaveOccurred()) + Expect(err).NotTo(HaveOccurred()) }) It("It doesn't fail when instance distribution is enabled and instanceType is \"mixed\"", func() { @@ -674,7 +674,7 @@ var _ = Describe("ClusterConfig validation", func() { ng.InstancesDistribution.InstanceTypes = []string{"t3.medium"} err := api.ValidateNodeGroup(0, ng) - Expect(err).ToNot(HaveOccurred()) + Expect(err).NotTo(HaveOccurred()) }) It("It fails when instance distribution is enabled and instanceType set", func() { @@ -751,7 +751,7 @@ var _ = Describe("ClusterConfig validation", func() { ng.InstancesDistribution.SpotInstancePools = newInt(2) err := api.ValidateNodeGroup(0, ng) - Expect(err).ToNot(HaveOccurred()) + Expect(err).NotTo(HaveOccurred()) }) }) }) @@ -792,7 +792,7 @@ var _ = Describe("ClusterConfig validation", func() { }, } err := api.ValidateNodeGroup(0, ng) - Expect(err).ToNot(HaveOccurred()) + Expect(err).NotTo(HaveOccurred()) }) }) }) @@ -837,7 +837,7 @@ var _ = Describe("ClusterConfig validation", func() { ng.VolumeEncrypted = &enabled ng.VolumeKmsKeyID = &kmsKeyID err := api.ValidateNodeGroup(0, ng) - Expect(err).ToNot(HaveOccurred()) + Expect(err).NotTo(HaveOccurred()) }) }) @@ -907,7 +907,7 @@ var _ = Describe("ClusterConfig validation", func() { }, } err := profile.Validate() - Expect(err).ToNot(HaveOccurred()) + Expect(err).NotTo(HaveOccurred()) }) It("passes when a name and multiple selectors with a namespace is defined", func() { @@ -923,7 +923,7 @@ var _ = Describe("ClusterConfig validation", func() { }, } err := profile.Validate() - Expect(err).ToNot(HaveOccurred()) + Expect(err).NotTo(HaveOccurred()) }) }) }) @@ -1006,7 +1006,7 @@ var _ = Describe("ClusterConfig validation", func() { Expect(err).To(HaveOccurred()) Expect(err.Error()).To(ContainSubstring(k.errSubstr)) } else { - Expect(err).ToNot(HaveOccurred()) + Expect(err).NotTo(HaveOccurred()) } }, Entry("Nil secretsEncryption", kmsFieldCase{ @@ -1084,7 +1084,7 @@ var _ = Describe("ClusterConfig validation", func() { ng.Taints = e.taints err := api.ValidateNodeGroup(0, ng) if e.valid { - Expect(err).ToNot(HaveOccurred()) + Expect(err).NotTo(HaveOccurred()) } else { Expect(err).To(HaveOccurred()) } diff --git a/pkg/authconfigmap/authconfigmap_test.go b/pkg/authconfigmap/authconfigmap_test.go index 6d893e94c8..104db44a4b 100644 --- a/pkg/authconfigmap/authconfigmap_test.go +++ b/pkg/authconfigmap/authconfigmap_test.go @@ -97,7 +97,7 @@ func makeExpectedAccounts(accounts ...string) string { func mustIdentity(arn string, username string, groups []string) iam.Identity { id, err := iam.NewIdentity(arn, username, groups) - Expect(err).ToNot(HaveOccurred()) + Expect(err).NotTo(HaveOccurred()) return id } @@ -404,7 +404,7 @@ var _ = Describe("AuthConfigMap{}", func() { cm := addAndSave(accountA) Expect(cm.Data["mapAccounts"]).To(MatchYAML(makeExpectedAccounts(accountA))) identities, err := acm.GetIdentities() - Expect(err).ToNot(HaveOccurred()) + Expect(err).NotTo(HaveOccurred()) Expect(identities).To(ContainElement(iam.AccountIdentity{KubernetesAccount: accountA})) }) When("the list of identities can consist of different identities", func() { @@ -416,7 +416,7 @@ var _ = Describe("AuthConfigMap{}", func() { err = acm.AddIdentity(mustIdentity(roleA, RoleNodeGroupUsername, RoleNodeGroupGroups)) Expect(err).NotTo(HaveOccurred()) identities, err := acm.GetIdentities() - Expect(err).ToNot(HaveOccurred()) + Expect(err).NotTo(HaveOccurred()) Expect(identities).To(ConsistOf( iam.AccountIdentity{KubernetesAccount: accountA}, iam.UserIdentity{ diff --git a/pkg/az/az_test.go b/pkg/az/az_test.go index 0587db6852..00201a87fe 100644 --- a/pkg/az/az_test.go +++ b/pkg/az/az_test.go @@ -277,7 +277,7 @@ var _ = Describe("AZ", func() { azSelector := NewSelectorWithDefaults(p.EC2(), region) selectedZones, err := azSelector.SelectZones() - Expect(err).ToNot(HaveOccurred()) + Expect(err).NotTo(HaveOccurred()) Expect(p.MockEC2().AssertNumberOfCalls(GinkgoT(), "DescribeAvailabilityZones", 1)).To(BeTrue()) Expect(selectedZones).To(ConsistOf("cn-north-1a", "cn-north-1b", "cn-north-1e")) }) diff --git a/pkg/cfn/builder/builder_suite_test.go b/pkg/cfn/builder/builder_suite_test.go index 880cd90014..f6d6958e0e 100644 --- a/pkg/cfn/builder/builder_suite_test.go +++ b/pkg/cfn/builder/builder_suite_test.go @@ -81,7 +81,7 @@ func vpcConfig() *api.ClusterVPC { } func isRefTo(obj interface{}, value string) bool { - Expect(obj).ToNot(BeEmpty()) + Expect(obj).NotTo(BeEmpty()) o, ok := obj.(map[string]interface{}) Expect(ok).To(BeTrue()) Expect(o).To(HaveKey(gfnt.Ref)) diff --git a/pkg/cfn/builder/cluster_test.go b/pkg/cfn/builder/cluster_test.go index 51e25faa7a..9955fa42a4 100644 --- a/pkg/cfn/builder/cluster_test.go +++ b/pkg/cfn/builder/cluster_test.go @@ -107,8 +107,8 @@ var _ = Describe("Cluster Template Builder", func() { Expect(clusterTemplate.Resources).To(HaveKey("ControlPlaneSecurityGroup")) Expect(clusterTemplate.Resources).To(HaveKey("ClusterSharedNodeSecurityGroup")) Expect(clusterTemplate.Resources).To(HaveKey("IngressInterNodeGroupSG")) - Expect(clusterTemplate.Resources).ToNot(HaveKey("IngressDefaultClusterToNodeSG")) - Expect(clusterTemplate.Resources).ToNot(HaveKey("IngressNodeToDefaultClusterSG")) + Expect(clusterTemplate.Resources).NotTo(HaveKey("IngressDefaultClusterToNodeSG")) + Expect(clusterTemplate.Resources).NotTo(HaveKey("IngressNodeToDefaultClusterSG")) Expect(clusterTemplate.Resources).To(HaveKey("ClusterSharedNodeSecurityGroup")) }) @@ -162,11 +162,11 @@ var _ = Describe("Cluster Template Builder", func() { }) It("should not add various shared security group resources", func() { - Expect(clusterTemplate.Resources).ToNot(HaveKey("ClusterSharedNodeSecurityGroup")) - Expect(clusterTemplate.Resources).ToNot(HaveKey("IngressInterNodeGroupSG")) - Expect(clusterTemplate.Resources).ToNot(HaveKey("IngressDefaultClusterToNodeSG")) - Expect(clusterTemplate.Resources).ToNot(HaveKey("IngressNodeToDefaultClusterSG")) - Expect(clusterTemplate.Resources).ToNot(HaveKey("ClusterSharedNodeSecurityGroup")) + Expect(clusterTemplate.Resources).NotTo(HaveKey("ClusterSharedNodeSecurityGroup")) + Expect(clusterTemplate.Resources).NotTo(HaveKey("IngressInterNodeGroupSG")) + Expect(clusterTemplate.Resources).NotTo(HaveKey("IngressDefaultClusterToNodeSG")) + Expect(clusterTemplate.Resources).NotTo(HaveKey("IngressNodeToDefaultClusterSG")) + Expect(clusterTemplate.Resources).NotTo(HaveKey("ClusterSharedNodeSecurityGroup")) }) }) @@ -176,7 +176,7 @@ var _ = Describe("Cluster Template Builder", func() { }) It("should not add the ControlPlaneSecurityGroup resources", func() { - Expect(clusterTemplate.Resources).ToNot(HaveKey("ControlPlaneSecurityGroup")) + Expect(clusterTemplate.Resources).NotTo(HaveKey("ControlPlaneSecurityGroup")) Expect(clusterTemplate.Resources["ControlPlane"].Properties.ResourcesVpcConfig.SecurityGroupIds).To(ContainElement("foo")) }) }) @@ -209,9 +209,9 @@ var _ = Describe("Cluster Template Builder", func() { }) It("should not add other iam resources", func() { - Expect(clusterTemplate.Resources).ToNot(HaveKey("ServiceRole")) - Expect(clusterTemplate.Resources).ToNot(HaveKey("PolicyELBPermissions")) - Expect(clusterTemplate.Resources).ToNot(HaveKey("PolicyCloudWatchMetrics")) + Expect(clusterTemplate.Resources).NotTo(HaveKey("ServiceRole")) + Expect(clusterTemplate.Resources).NotTo(HaveKey("PolicyELBPermissions")) + Expect(clusterTemplate.Resources).NotTo(HaveKey("PolicyCloudWatchMetrics")) }) }) @@ -277,7 +277,7 @@ var _ = Describe("Cluster Template Builder", func() { }) It("should add partition mappings", func() { - Expect(clusterTemplate.Mappings["ServicePrincipalPartitionMap"]).ToNot(BeNil()) + Expect(clusterTemplate.Mappings["ServicePrincipalPartitionMap"]).NotTo(BeNil()) }) Context("when private networking is set", func() { @@ -301,13 +301,13 @@ var _ = Describe("Cluster Template Builder", func() { }) It("no nat resources are set", func() { - Expect(clusterTemplate.Resources).ToNot(HaveKey("NATIP")) - Expect(clusterTemplate.Resources).ToNot(HaveKey("NATGateway")) + Expect(clusterTemplate.Resources).NotTo(HaveKey("NATIP")) + Expect(clusterTemplate.Resources).NotTo(HaveKey("NATGateway")) }) It("does not set public networking", func() { - Expect(clusterTemplate.Resources).ToNot(HaveKey("PublicSubnetRoute")) - Expect(clusterTemplate.Resources).ToNot(HaveKey("PublicSubnetRoute")) + Expect(clusterTemplate.Resources).NotTo(HaveKey("PublicSubnetRoute")) + Expect(clusterTemplate.Resources).NotTo(HaveKey("PublicSubnetRoute")) Expect(clusterTemplate.Resources).To(HaveKey(ContainSubstring("PrivateRouteTable"))) }) }) diff --git a/pkg/cfn/builder/iam_test.go b/pkg/cfn/builder/iam_test.go index 830d0b7bac..9c2284ac45 100644 --- a/pkg/cfn/builder/iam_test.go +++ b/pkg/cfn/builder/iam_test.go @@ -22,7 +22,7 @@ var _ = Describe("template builder for IAM", func() { BeforeEach(func() { oidc, err = iamoidc.NewOpenIDConnectManager(nil, "456123987123", "https://oidc.eks.us-west-2.amazonaws.com/id/A39A2842863C47208955D753DE205E6E", "aws", nil) - Expect(err).ToNot(HaveOccurred()) + Expect(err).NotTo(HaveOccurred()) oidc.ProviderARN = "arn:aws:iam::456123987123:oidc-provider/oidc.eks.us-west-2.amazonaws.com/id/A39A2842863C47208955D753DE205E6E" @@ -101,7 +101,7 @@ var _ = Describe("template builder for IAM", func() { Expect(t).To(HaveResource("Role1", "AWS::IAM::Role")) Expect(t).To(HaveResource("Policy1", "AWS::IAM::Policy")) - Expect(t).ToNot(HaveResourceWithProperties("Role1", "ManagedPolicyArns")) + Expect(t).NotTo(HaveResourceWithProperties("Role1", "ManagedPolicyArns")) Expect(t).To(HaveResourceWithPropertyValue("Role1", "AssumeRolePolicyDocument", expectedServiceAccountAssumeRolePolicyDocument)) Expect(t).To(HaveResourceWithPropertyValue("Policy1", "PolicyName", `{ "Fn::Sub": "${AWS::StackName}-Policy1" }`)) @@ -326,7 +326,7 @@ var _ = Describe("template builder for IAM", func() { BeforeEach(func() { oidc, err = iamoidc.NewOpenIDConnectManager(nil, "456123987123", "https://oidc.eks.us-west-2.amazonaws.com/id/A39A2842863C47208955D753DE205E6E", "aws", nil) - Expect(err).ToNot(HaveOccurred()) + Expect(err).NotTo(HaveOccurred()) oidc.ProviderARN = "arn:aws:iam::456123987123:oidc-provider/oidc.eks.us-west-2.amazonaws.com/id/A39A2842863C47208955D753DE205E6E" @@ -395,7 +395,7 @@ var _ = Describe("template builder for IAM", func() { Expect(t).To(HaveResource("Policy1", "AWS::IAM::Policy")) - Expect(t).ToNot(HaveResourceWithProperties("Role1", "ManagedPolicyArns")) + Expect(t).NotTo(HaveResourceWithProperties("Role1", "ManagedPolicyArns")) Expect(t).To(HaveResourceWithPropertyValue("Role1", "AssumeRolePolicyDocument", expectedAssumeRolePolicyDocument)) Expect(t).To(HaveResourceWithPropertyValue("Policy1", "PolicyName", `{ "Fn::Sub": "${AWS::StackName}-Policy1" }`)) @@ -422,7 +422,7 @@ func appendServiceAccountToClusterConfig(cfg *api.ClusterConfig, serviceAccount api.SetClusterConfigDefaults(cfg) err := api.ValidateClusterConfig(cfg) - Expect(err).ToNot(HaveOccurred()) + Expect(err).NotTo(HaveOccurred()) } const expectedServiceAccountAssumeRolePolicyDocument = `{ diff --git a/pkg/cfn/builder/managed_launch_template_test.go b/pkg/cfn/builder/managed_launch_template_test.go index 6fa087d40f..ca69084b35 100644 --- a/pkg/cfn/builder/managed_launch_template_test.go +++ b/pkg/cfn/builder/managed_launch_template_test.go @@ -66,19 +66,19 @@ var _ = Describe("ManagedNodeGroup builder", func() { return } - Expect(err).ToNot(HaveOccurred()) + Expect(err).NotTo(HaveOccurred()) bytes, err := stack.RenderJSON() - Expect(err).ToNot(HaveOccurred()) + Expect(err).NotTo(HaveOccurred()) template, err := goformation.ParseJSON(bytes) - Expect(err).ToNot(HaveOccurred()) - Expect(template).ToNot(BeNil()) + Expect(err).NotTo(HaveOccurred()) + Expect(template).NotTo(BeNil()) actual, err := json.Marshal(template.Resources) - Expect(err).ToNot(HaveOccurred()) + Expect(err).NotTo(HaveOccurred()) expected, err := os.ReadFile(path.Join("testdata", "launch_template", m.resourcesFilename)) - Expect(err).ToNot(HaveOccurred()) + Expect(err).NotTo(HaveOccurred()) Expect(actual).To(MatchOrderedJSON(expected, WithUnorderedListKeys("Tags"))) }, diff --git a/pkg/cfn/builder/managed_nodegroup_ami_type_test.go b/pkg/cfn/builder/managed_nodegroup_ami_type_test.go index 937fe65f0c..4a0b30309a 100644 --- a/pkg/cfn/builder/managed_nodegroup_ami_type_test.go +++ b/pkg/cfn/builder/managed_nodegroup_ami_type_test.go @@ -30,10 +30,10 @@ var _ = DescribeTable("Managed Nodegroup AMI type", func(e amiTypeEntry) { Expect(stack.AddAllResources()).To(Succeed()) bytes, err := stack.RenderJSON() - Expect(err).ToNot(HaveOccurred()) + Expect(err).NotTo(HaveOccurred()) template, err := goformation.ParseJSON(bytes) - Expect(err).ToNot(HaveOccurred()) + Expect(err).NotTo(HaveOccurred()) ngResource, ok := template.Resources["ManagedNodeGroup"] Expect(ok).To(BeTrue()) ng, ok := ngResource.(*gfneks.Nodegroup) diff --git a/pkg/cfn/builder/nodegroup_test.go b/pkg/cfn/builder/nodegroup_test.go index 480369406f..0d5d564c38 100644 --- a/pkg/cfn/builder/nodegroup_test.go +++ b/pkg/cfn/builder/nodegroup_test.go @@ -65,7 +65,7 @@ var _ = Describe("Unmanaged NodeGroup Template Builder", func() { }) It("should add partition mappings", func() { - Expect(ngTemplate.Mappings["ServicePrincipalPartitionMap"]).ToNot(BeNil()) + Expect(ngTemplate.Mappings["ServicePrincipalPartitionMap"]).NotTo(BeNil()) }) It("should add outputs", func() { @@ -196,7 +196,7 @@ var _ = Describe("Unmanaged NodeGroup Template Builder", func() { It("creates a new role", func() { Expect(ngTemplate.Resources).To(HaveKey("NodeInstanceRole")) Expect(ngTemplate.Resources["NodeInstanceRole"].Properties.Path).To(Equal("/")) - Expect(ngTemplate.Resources["NodeInstanceRole"].Properties.AssumeRolePolicyDocument).ToNot(BeNil()) + Expect(ngTemplate.Resources["NodeInstanceRole"].Properties.AssumeRolePolicyDocument).NotTo(BeNil()) }) It("sets the correct outputs", func() { @@ -280,7 +280,7 @@ var _ = Describe("Unmanaged NodeGroup Template Builder", func() { It("does not add the AmazonEKS_CNI_Policy", func() { Expect(ngTemplate.Resources["NodeInstanceRole"].Properties.ManagedPolicyArns).To(HaveLen(3)) - Expect(ngTemplate.Resources["NodeInstanceRole"].Properties.ManagedPolicyArns).ToNot(ContainElement(makePolicyARNRef("AmazonEKS_CNI_Policy"))) + Expect(ngTemplate.Resources["NodeInstanceRole"].Properties.ManagedPolicyArns).NotTo(ContainElement(makePolicyARNRef("AmazonEKS_CNI_Policy"))) }) }) }) @@ -467,7 +467,7 @@ var _ = Describe("Unmanaged NodeGroup Template Builder", func() { }) It("no sg resources are added", func() { - Expect(ngTemplate.Resources).ToNot(HaveKey("SG")) + Expect(ngTemplate.Resources).NotTo(HaveKey("SG")) }) }) diff --git a/pkg/cfn/builder/vpc_endpoint_test.go b/pkg/cfn/builder/vpc_endpoint_test.go index ce43a49fe1..02888d5958 100644 --- a/pkg/cfn/builder/vpc_endpoint_test.go +++ b/pkg/cfn/builder/vpc_endpoint_test.go @@ -62,7 +62,7 @@ var _ = Describe("VPC Endpoint Builder", func() { return } - Expect(err).ToNot(HaveOccurred()) + Expect(err).NotTo(HaveOccurred()) if vc.clusterConfig.PrivateCluster.Enabled { vpcEndpointResourceSet := NewVPCEndpointResourceSet(provider.EC2(), provider.Region(), rs, vc.clusterConfig, vpcResource.VPC, vpcResource.SubnetDetails.Private, gfnt.NewString("sg-test")) Expect(vpcEndpointResourceSet.AddResources()).To(Succeed()) @@ -78,10 +78,10 @@ var _ = Describe("VPC Endpoint Builder", func() { } resourceJSON, err := rs.template.JSON() - Expect(err).ToNot(HaveOccurred()) + Expect(err).NotTo(HaveOccurred()) expectedJSON, err := os.ReadFile("testdata/" + vc.expectedFile) - Expect(err).ToNot(HaveOccurred()) + Expect(err).NotTo(HaveOccurred()) Expect(resourceJSON).To(MatchJSON(expectedJSON)) }, Entry("Standard cluster", vpcResourceSetCase{ diff --git a/pkg/cfn/builder/vpc_test.go b/pkg/cfn/builder/vpc_test.go index 62835d8fae..52147745e4 100644 --- a/pkg/cfn/builder/vpc_test.go +++ b/pkg/cfn/builder/vpc_test.go @@ -239,10 +239,10 @@ var _ = Describe("VPC Template Builder", func() { }) It("adds HA nat gateway resources to the resource set", func() { - Expect(vpcTemplate.Resources).ToNot(HaveKey("NATIP")) - Expect(vpcTemplate.Resources).ToNot(HaveKey("NATGateway")) - Expect(vpcTemplate.Resources).ToNot(HaveKey("NATPrivateSubnetRouteUSWEST2A")) - Expect(vpcTemplate.Resources).ToNot(HaveKey("NATPrivateSubnetRouteUSWEST2B")) + Expect(vpcTemplate.Resources).NotTo(HaveKey("NATIP")) + Expect(vpcTemplate.Resources).NotTo(HaveKey("NATGateway")) + Expect(vpcTemplate.Resources).NotTo(HaveKey("NATPrivateSubnetRouteUSWEST2A")) + Expect(vpcTemplate.Resources).NotTo(HaveKey("NATPrivateSubnetRouteUSWEST2B")) Expect(vpcTemplate.Resources).To(HaveKey(privRouteTableA)) Expect(vpcTemplate.Resources[privRouteTableA].Properties.VpcID).To(Equal(makeRef(vpcResourceKey))) @@ -420,22 +420,22 @@ var _ = Describe("VPC Template Builder", func() { }) It("disables the nat", func() { - Expect(vpcTemplate.Resources).ToNot(HaveKey("NATIP")) - Expect(vpcTemplate.Resources).ToNot(HaveKey("NATGateway")) + Expect(vpcTemplate.Resources).NotTo(HaveKey("NATIP")) + Expect(vpcTemplate.Resources).NotTo(HaveKey("NATGateway")) }) It("does not add an internet gateway", func() { - Expect(vpcTemplate.Resources).ToNot(HaveKey(igwKey)) + Expect(vpcTemplate.Resources).NotTo(HaveKey(igwKey)) }) It("does not set public subnet resources", func() { Expect(result.SubnetDetails.Public).To(HaveLen(0)) - Expect(vpcTemplate.Resources).ToNot(HaveKey(pubSubnetRoute)) - Expect(vpcTemplate.Resources).ToNot(HaveKey(pubSubnetRoute)) - Expect(vpcTemplate.Resources).ToNot(HaveKey(publicSubnetRef1)) - Expect(vpcTemplate.Resources).ToNot(HaveKey(publicSubnetRef1)) - Expect(vpcTemplate.Resources).ToNot(HaveKey(rtaPublicA)) - Expect(vpcTemplate.Resources).ToNot(HaveKey(rtaPublicB)) + Expect(vpcTemplate.Resources).NotTo(HaveKey(pubSubnetRoute)) + Expect(vpcTemplate.Resources).NotTo(HaveKey(pubSubnetRoute)) + Expect(vpcTemplate.Resources).NotTo(HaveKey(publicSubnetRef1)) + Expect(vpcTemplate.Resources).NotTo(HaveKey(publicSubnetRef1)) + Expect(vpcTemplate.Resources).NotTo(HaveKey(rtaPublicA)) + Expect(vpcTemplate.Resources).NotTo(HaveKey(rtaPublicB)) Expect(result.SubnetDetails.Private).To(HaveLen(2)) Expect(vpcTemplate.Resources).To(HaveKey(privRouteTableA)) diff --git a/pkg/cfn/manager/api_test.go b/pkg/cfn/manager/api_test.go index ea00f184fe..c05c5c0925 100644 --- a/pkg/cfn/manager/api_test.go +++ b/pkg/cfn/manager/api_test.go @@ -53,7 +53,7 @@ var _ = Describe("StackCollection", func() { TemplateData: TemplateBody(""), Wait: true, }) - Expect(err).ToNot(HaveOccurred()) + Expect(err).NotTo(HaveOccurred()) }) }) @@ -118,7 +118,7 @@ var _ = Describe("StackCollection", func() { TemplateData: TemplateBody(""), Wait: true, }) - Expect(err).ToNot(HaveOccurred()) + Expect(err).NotTo(HaveOccurred()) // Second is CreateChangeSet() call which we are interested in args := p.MockCloudFormation().Calls[1].Arguments.Get(0) @@ -177,7 +177,7 @@ var _ = Describe("StackCollection", func() { TemplateData: TemplateBody(""), Wait: false, }) - Expect(err).ToNot(HaveOccurred()) + Expect(err).NotTo(HaveOccurred()) // Second is CreateChangeSet() call which we are interested in args := p.MockCloudFormation().Calls[1].Arguments.Get(0) diff --git a/pkg/cfn/manager/nodegroup_test.go b/pkg/cfn/manager/nodegroup_test.go index d644706673..963d62271e 100644 --- a/pkg/cfn/manager/nodegroup_test.go +++ b/pkg/cfn/manager/nodegroup_test.go @@ -162,7 +162,7 @@ var _ = Describe("StackCollection NodeGroup", func() { }) It("should not error", func() { - Expect(err).ToNot(HaveOccurred()) + Expect(err).NotTo(HaveOccurred()) }) It("should not have called AWS CloudFormation GetTemplate", func() { @@ -226,7 +226,7 @@ var _ = Describe("StackCollection NodeGroup", func() { if expectedType == "" { Expect(err).To(HaveOccurred()) } else { - Expect(err).ToNot(HaveOccurred()) + Expect(err).NotTo(HaveOccurred()) Expect(ngType).To(Equal(expectedType)) } }, @@ -272,7 +272,7 @@ var _ = Describe("StackCollection NodeGroup", func() { if expectedType == "" { Expect(err).To(HaveOccurred()) } else { - Expect(err).ToNot(HaveOccurred()) + Expect(err).NotTo(HaveOccurred()) Expect(ngType).To(Equal(expectedType)) } }, diff --git a/pkg/cfn/template/api_test.go b/pkg/cfn/template/api_test.go index 2a472f049c..e072f2f38d 100644 --- a/pkg/cfn/template/api_test.go +++ b/pkg/cfn/template/api_test.go @@ -34,7 +34,7 @@ var _ = Describe("CloudFormation template", func() { } jsRoleRef, err := roleRef.MarshalJSON() - Expect(err).ToNot(HaveOccurred()) + Expect(err).NotTo(HaveOccurred()) Expect(jsRoleRef).To(MatchJSON(`{"Ref": "aRole"}`)) policyRef := t.NewResource("aPolicy", &IAMPolicy{ @@ -43,11 +43,11 @@ var _ = Describe("CloudFormation template", func() { }) jsPolicyRef, err := policyRef.MarshalJSON() - Expect(err).ToNot(HaveOccurred()) + Expect(err).NotTo(HaveOccurred()) Expect(jsPolicyRef).To(MatchJSON(`{"Ref": "aPolicy"}`)) js, err := t.RenderJSON() - Expect(err).ToNot(HaveOccurred()) + Expect(err).NotTo(HaveOccurred()) Expect(js).To(MatchJSON([]byte(templateExample1))) }) @@ -65,24 +65,24 @@ var _ = Describe("CloudFormation template", func() { Expect(t).To(HaveResourceWithPropertyValue("aRole", "RoleName", `"foo"`)) - Expect(t).ToNot(HaveResourceWithPropertyValue("aRole", "RoleName", `"bar"`)) - Expect(t).ToNot(HaveResource("aRole", "AWS::Foo::Bar")) - Expect(t).ToNot(HaveResource("foo", "*")) + Expect(t).NotTo(HaveResourceWithPropertyValue("aRole", "RoleName", `"bar"`)) + Expect(t).NotTo(HaveResource("aRole", "AWS::Foo::Bar")) + Expect(t).NotTo(HaveResource("foo", "*")) Expect(t).To(HaveOutputs("aRole")) - Expect(t).ToNot(HaveOutputs("foo", "bar")) + Expect(t).NotTo(HaveOutputs("foo", "bar")) Expect(t).To(HaveOutputWithValue("aRole", `{ "Fn::GetAtt": "aRole.Arn" }`)) Expect(t).To(HaveOutputExportedAs("aRole", `{ "Fn::Sub": "${AWS::StackName}::aRole" }`)) - Expect(t).ToNot(HaveOutputExportedAs("aRole", `{}`)) - Expect(t).ToNot(HaveOutputExportedAs("aRole", `{ "Fn::GetAtt": "aRole.Arn" }`)) - Expect(t).ToNot(HaveOutputExportedAs("foo", `{ "Fn::Sub": "${AWS::StackName}::aRole" }`)) + Expect(t).NotTo(HaveOutputExportedAs("aRole", `{}`)) + Expect(t).NotTo(HaveOutputExportedAs("aRole", `{ "Fn::GetAtt": "aRole.Arn" }`)) + Expect(t).NotTo(HaveOutputExportedAs("foo", `{ "Fn::Sub": "${AWS::StackName}::aRole" }`)) }) It("can load multiple real templates", func() { examples, err := filepath.Glob("testdata/*.json") - Expect(err).ToNot(HaveOccurred()) + Expect(err).NotTo(HaveOccurred()) for _, example := range examples { Expect(NewTemplate()).To(LoadFileWithoutErrors(example)) } diff --git a/pkg/connector/connector_test.go b/pkg/connector/connector_test.go index c71fb48043..9e73f5a991 100644 --- a/pkg/connector/connector_test.go +++ b/pkg/connector/connector_test.go @@ -83,7 +83,7 @@ var _ = Describe("EKS Connector", func() { } manifestTemplate, err := cc.getManifestTemplate() - Expect(err).ToNot(HaveOccurred()) + Expect(err).NotTo(HaveOccurred()) c := connector.EKSConnector{ Provider: mockProvider, @@ -97,11 +97,11 @@ var _ = Describe("EKS Connector", func() { return } - Expect(err).ToNot(HaveOccurred()) + Expect(err).NotTo(HaveOccurred()) assertManifestEquals := func(m connector.ManifestFile, expectedFile string) { expected, err := os.ReadFile(path.Join("testdata", expectedFile)) - Expect(err).ToNot(HaveOccurred()) + Expect(err).NotTo(HaveOccurred()) Expect(m.Data).To(Equal(expected), m.Filename) } diff --git a/pkg/connector/manifest_test.go b/pkg/connector/manifest_test.go index acf92565d9..b2913e84a9 100644 --- a/pkg/connector/manifest_test.go +++ b/pkg/connector/manifest_test.go @@ -10,10 +10,10 @@ var _ = Describe("Manifest template", func() { Context("GetManifestTemplate", func() { It("should fetch the template", func() { template, err := connector.GetManifestTemplate() - Expect(err).ToNot(HaveOccurred()) + Expect(err).NotTo(HaveOccurred()) assertManifestFile := func(m connector.ManifestFile, expectedFilename string) { - Expect(m.Data).ToNot(BeEmpty()) + Expect(m.Data).NotTo(BeEmpty()) Expect(m.Filename).To(Equal(expectedFilename)) } assertManifestFile(template.Connector, "eks-connector.yaml") diff --git a/pkg/connector/resources_test.go b/pkg/connector/resources_test.go index c6da1c0d1e..10e107b0cc 100644 --- a/pkg/connector/resources_test.go +++ b/pkg/connector/resources_test.go @@ -30,13 +30,13 @@ var _ = Describe("Writing manifests", func() { }, } err := connector.WriteResources(fs, manifestList) - Expect(err).ToNot(HaveOccurred()) + Expect(err).NotTo(HaveOccurred()) wd, err := os.Getwd() - Expect(err).ToNot(HaveOccurred()) + Expect(err).NotTo(HaveOccurred()) files, err := afero.ReadDir(fs, wd) - Expect(err).ToNot(HaveOccurred()) + Expect(err).NotTo(HaveOccurred()) Expect(files).To(HaveLen(3)) filenameData := map[string][]byte{} @@ -50,7 +50,7 @@ var _ = Describe("Writing manifests", func() { Fail(fmt.Sprintf("unexpected filename %q", file.Name())) } file, err := afero.ReadFile(fs, path.Join(wd, file.Name())) - Expect(err).ToNot(HaveOccurred()) + Expect(err).NotTo(HaveOccurred()) Expect(file).To(Equal(data)) } }) diff --git a/pkg/credentials/filecache_test.go b/pkg/credentials/filecache_test.go index 99a5a053ca..f871fa77e6 100644 --- a/pkg/credentials/filecache_test.go +++ b/pkg/credentials/filecache_test.go @@ -47,7 +47,7 @@ var _ = Describe("filecache", func() { ) BeforeEach(func() { tmp, err = os.MkdirTemp("", "filecache") - Expect(err).ToNot(HaveOccurred()) + Expect(err).NotTo(HaveOccurred()) _ = os.Setenv(EksctlCacheFilenameEnvName, filepath.Join(tmp, "credentials.yaml")) }) AfterEach(func() { @@ -67,15 +67,15 @@ var _ = Describe("filecache", func() { fakeClock := &fakes.FakeClock{} fakeClock.NowReturns(time.Date(1981, 1, 1, 1, 1, 1, 1, time.UTC)) p, err := NewFileCacheProvider("profile", c, fakeClock) - Expect(err).ToNot(HaveOccurred()) + Expect(err).NotTo(HaveOccurred()) value, err := p.Retrieve() - Expect(err).ToNot(HaveOccurred()) + Expect(err).NotTo(HaveOccurred()) Expect(value.AccessKeyID).To(Equal("id")) Expect(value.SecretAccessKey).To(Equal("secret")) Expect(value.SessionToken).To(Equal("token")) Expect(p.IsExpired()).NotTo(BeTrue()) content, err := os.ReadFile(filepath.Join(tmp, "credentials.yaml")) - Expect(err).ToNot(HaveOccurred()) + Expect(err).NotTo(HaveOccurred()) Expect(string(content)).To(Equal(`profiles: profile: credential: @@ -101,7 +101,7 @@ var _ = Describe("filecache", func() { fakeClock := &fakes.FakeClock{} fakeClock.NowReturns(time.Date(9999, 1, 1, 1, 1, 1, 1, time.UTC)) p, err := NewFileCacheProvider("profile", c, fakeClock) - Expect(err).ToNot(HaveOccurred()) + Expect(err).NotTo(HaveOccurred()) Expect(p.IsExpired()).To(BeTrue()) }) }) @@ -117,13 +117,13 @@ var _ = Describe("filecache", func() { expiration: 0001-01-01T00:00:00Z `) err := os.WriteFile(filepath.Join(tmp, "credentials.yaml"), content, 0700) - Expect(err).ToNot(HaveOccurred()) + Expect(err).NotTo(HaveOccurred()) c := credentials.NewCredentials(&stubProviderExpirer{}) fakeClock := &fakes.FakeClock{} p, err := NewFileCacheProvider("profile", c, fakeClock) - Expect(err).ToNot(HaveOccurred()) + Expect(err).NotTo(HaveOccurred()) creds, err := p.Retrieve() - Expect(err).ToNot(HaveOccurred()) + Expect(err).NotTo(HaveOccurred()) Expect(creds.AccessKeyID).To(Equal("storedID")) Expect(creds.SecretAccessKey).To(Equal("storedSecret")) Expect(creds.SessionToken).To(Equal("storedToken")) @@ -141,9 +141,9 @@ var _ = Describe("filecache", func() { fakeClock := &fakes.FakeClock{} fakeClock.NowReturns(time.Date(9999, 1, 1, 1, 1, 1, 1, time.UTC)) p, err := NewFileCacheProvider("profile", credentials.NewStaticCredentials("id", "secret", "token"), fakeClock) - Expect(err).ToNot(HaveOccurred()) + Expect(err).NotTo(HaveOccurred()) _, err = p.Retrieve() - Expect(err).ToNot(HaveOccurred()) + Expect(err).NotTo(HaveOccurred()) _, err = os.Stat(filepath.Join(tmp, "credentials.yaml")) Expect(os.IsNotExist(err)).To(BeTrue()) }) @@ -153,7 +153,7 @@ var _ = Describe("filecache", func() { It("will refuse to use that file", func() { content := []byte(`test:`) err := os.WriteFile(filepath.Join(tmp, "credentials.yaml"), content, 0777) - Expect(err).ToNot(HaveOccurred()) + Expect(err).NotTo(HaveOccurred()) c := credentials.NewCredentials(&stubProviderExpirer{}) fakeClock := &fakes.FakeClock{} _, err = NewFileCacheProvider("profile", c, fakeClock) @@ -164,7 +164,7 @@ var _ = Describe("filecache", func() { It("will return an appropriate error", func() { content := []byte(`not valid yaml`) err := os.WriteFile(filepath.Join(tmp, "credentials.yaml"), content, 0600) - Expect(err).ToNot(HaveOccurred()) + Expect(err).NotTo(HaveOccurred()) c := credentials.NewCredentials(&stubProviderExpirer{}) fakeClock := &fakes.FakeClock{} _, err = NewFileCacheProvider("profile", c, fakeClock) diff --git a/pkg/ctl/cmdutils/configfile_test.go b/pkg/ctl/cmdutils/configfile_test.go index 6afd08c98c..59c075c6e9 100644 --- a/pkg/ctl/cmdutils/configfile_test.go +++ b/pkg/ctl/cmdutils/configfile_test.go @@ -35,7 +35,7 @@ var _ = Describe("cmdutils configfile", func() { } err := NewMetadataLoader(cmd).Load() - Expect(err).ToNot(HaveOccurred()) + Expect(err).NotTo(HaveOccurred()) Expect(cfg.Metadata.Name).To(Equal("foo-1")) } @@ -96,7 +96,7 @@ var _ = Describe("cmdutils configfile", func() { l.flagsIncompatibleWithConfigFile.Delete("name") err := l.Load() - Expect(err).ToNot(HaveOccurred()) + Expect(err).NotTo(HaveOccurred()) }) }) When("given as positional argument", func() { @@ -113,7 +113,7 @@ var _ = Describe("cmdutils configfile", func() { l.flagsIncompatibleWithConfigFile.Delete("name") err := l.Load() - Expect(err).ToNot(HaveOccurred()) + Expect(err).NotTo(HaveOccurred()) }) }) }) @@ -144,9 +144,9 @@ var _ = Describe("cmdutils configfile", func() { It("load all of example file", func() { examples, err := filepath.Glob(examplesDir + "*.yaml") - Expect(err).ToNot(HaveOccurred()) + Expect(err).NotTo(HaveOccurred()) - Expect(examples).ToNot(BeEmpty()) + Expect(examples).NotTo(BeEmpty()) for _, example := range examples { cmd := &Cmd{ CobraCommand: newCmd(), @@ -158,9 +158,9 @@ var _ = Describe("cmdutils configfile", func() { err := NewMetadataLoader(cmd).Load() cfg := cmd.ClusterConfig - Expect(err).ToNot(HaveOccurred()) - Expect(cfg.Metadata.Name).ToNot(BeEmpty()) - Expect(cfg.Metadata.Region).ToNot(BeEmpty()) + Expect(err).NotTo(HaveOccurred()) + Expect(cfg.Metadata.Name).NotTo(BeEmpty()) + Expect(cfg.Metadata.Region).NotTo(BeEmpty()) Expect(cfg.Metadata.Region).To(Equal(cmd.ProviderConfig.Region)) } }) diff --git a/pkg/ctl/cmdutils/filter/filter_test.go b/pkg/ctl/cmdutils/filter/filter_test.go index 4095326e61..a264415aeb 100644 --- a/pkg/ctl/cmdutils/filter/filter_test.go +++ b/pkg/ctl/cmdutils/filter/filter_test.go @@ -43,7 +43,7 @@ var _ = Describe("filter", func() { It("should match include filter", func() { filter.AppendIncludeNames("banana") err := filter.doAppendIncludeGlobs(allItems, "fruits", "*apple", "*berry") - Expect(err).ToNot(HaveOccurred()) + Expect(err).NotTo(HaveOccurred()) Expect(filter.Match("a1")).To(BeFalse()) Expect(filter.Match("a2")).To(BeFalse()) @@ -65,7 +65,7 @@ var _ = Describe("filter", func() { It("should match exclude filter with names and globs", func() { filter.AppendExcludeNames("banana") err := filter.AppendExcludeGlobs("*apple", "*berry") - Expect(err).ToNot(HaveOccurred()) + Expect(err).NotTo(HaveOccurred()) Expect(filter.Match("a1")).To(BeTrue()) Expect(filter.Match("a2")).To(BeTrue()) @@ -87,10 +87,10 @@ var _ = Describe("filter", func() { It("should include an item when it exists as an inclusion name overwrite", func() { filter.AppendIncludeNames("raspberry") err := filter.doAppendIncludeGlobs(allItems, "fruit", "a?", "b?") - Expect(err).ToNot(HaveOccurred()) + Expect(err).NotTo(HaveOccurred()) err = filter.AppendExcludeGlobs("*apple", "*berry") - Expect(err).ToNot(HaveOccurred()) + Expect(err).NotTo(HaveOccurred()) included, excluded := filter.doMatchAll(allItems) Expect(included).To(HaveLen(5)) @@ -101,7 +101,7 @@ var _ = Describe("filter", func() { It("should not include an item when it exists as an exclusion name overwrite", func() { err := filter.doAppendIncludeGlobs(allItems, "fruit", "a?", "b?") - Expect(err).ToNot(HaveOccurred()) + Expect(err).NotTo(HaveOccurred()) filter.AppendExcludeNames("a2") @@ -115,11 +115,11 @@ var _ = Describe("filter", func() { It("when a name is in both inclusion and exclusion overwrites the exclusion takes precedence", func() { filter.AppendIncludeNames("raspberry") err := filter.doAppendIncludeGlobs(allItems, "fruit", "a?", "b?") - Expect(err).ToNot(HaveOccurred()) + Expect(err).NotTo(HaveOccurred()) filter.AppendExcludeNames("raspberry") err = filter.AppendExcludeGlobs("*apple", "*berry") - Expect(err).ToNot(HaveOccurred()) + Expect(err).NotTo(HaveOccurred()) included, excluded := filter.doMatchAll(allItems) Expect(included).To(HaveLen(4)) @@ -130,10 +130,10 @@ var _ = Describe("filter", func() { It("when an item matches inclusion and exclusion globs exclusion takes precedence", func() { err := filter.doAppendIncludeGlobs(allItems, "fruit", "*berry", "*apple") - Expect(err).ToNot(HaveOccurred()) + Expect(err).NotTo(HaveOccurred()) err = filter.AppendExcludeGlobs("?aspberry", "a?") - Expect(err).ToNot(HaveOccurred()) + Expect(err).NotTo(HaveOccurred()) included, excluded := filter.doMatchAll(allItems) Expect(included).To(HaveLen(3)) diff --git a/pkg/ctl/cmdutils/filter/iamserviceaccount_filter_test.go b/pkg/ctl/cmdutils/filter/iamserviceaccount_filter_test.go index c98e01e3fd..074abd3159 100644 --- a/pkg/ctl/cmdutils/filter/iamserviceaccount_filter_test.go +++ b/pkg/ctl/cmdutils/filter/iamserviceaccount_filter_test.go @@ -48,7 +48,7 @@ var _ = Describe("iamserviceaccount filter", func() { "kube-system/aws-node", ) err := filter.SetDeleteFilter(mockLister, true, cfg) - Expect(err).ToNot(HaveOccurred()) + Expect(err).NotTo(HaveOccurred()) included, excluded := filter.MatchAll(cfg.IAM.ServiceAccounts) Expect(included).To(HaveLen(2)) @@ -76,7 +76,7 @@ var _ = Describe("iamserviceaccount filter", func() { "sa/only-remote-2", ) err := filter.SetExcludeExistingFilter(mockLister, clientSet, cfg.IAM.ServiceAccounts, true) - Expect(err).ToNot(HaveOccurred()) + Expect(err).NotTo(HaveOccurred()) included, excluded := filter.MatchAll(cfg.IAM.ServiceAccounts) Expect(included).To(HaveLen(3)) @@ -110,12 +110,12 @@ var _ = Describe("iamserviceaccount filter", func() { sa2 := metav1.ObjectMeta{Name: "role-only", Namespace: "sa"} err := kubernetes.MaybeCreateServiceAccountOrUpdateMetadata(clientSet, sa1) - Expect(err).ToNot(HaveOccurred()) + Expect(err).NotTo(HaveOccurred()) err = kubernetes.MaybeCreateServiceAccountOrUpdateMetadata(clientSet, sa2) - Expect(err).ToNot(HaveOccurred()) + Expect(err).NotTo(HaveOccurred()) err = filter.SetExcludeExistingFilter(mockLister, clientSet, cfg.IAM.ServiceAccounts, false) - Expect(err).ToNot(HaveOccurred()) + Expect(err).NotTo(HaveOccurred()) included, excluded := filter.MatchAll(cfg.IAM.ServiceAccounts) Expect(included).To(HaveLen(3)) diff --git a/pkg/ctl/cmdutils/filter/nodegroup_filter_test.go b/pkg/ctl/cmdutils/filter/nodegroup_filter_test.go index aa3608c352..100744ed38 100644 --- a/pkg/ctl/cmdutils/filter/nodegroup_filter_test.go +++ b/pkg/ctl/cmdutils/filter/nodegroup_filter_test.go @@ -51,7 +51,7 @@ var _ = Describe("nodegroup filter", func() { cfg.NodeGroups = append(cfg.NodeGroups, nonExistentNg) err := filter.AppendIncludeGlobs(getNodeGroupNames(cfg), "test-ng1?") - Expect(err).ToNot(HaveOccurred()) + Expect(err).NotTo(HaveOccurred()) Expect(filter.Match("test-ng3x")).To(BeFalse()) Expect(filter.Match("test-ng3b")).To(BeFalse()) @@ -80,7 +80,7 @@ var _ = Describe("nodegroup filter", func() { "non-existing-in-cfg-2", ) err := filter.SetOnlyRemote(mockProvider.EKS(), mockLister, cfg) - Expect(err).ToNot(HaveOccurred()) + Expect(err).NotTo(HaveOccurred()) included, excluded := filter.matchAll(filter.collectNames(cfg.NodeGroups)) Expect(included).To(HaveLen(2)) @@ -98,7 +98,7 @@ var _ = Describe("nodegroup filter", func() { It("should match only local nodegroups", func() { err := filter.AppendIncludeGlobs(getNodeGroupNames(cfg), "test-ng1?") - Expect(err).ToNot(HaveOccurred()) + Expect(err).NotTo(HaveOccurred()) mockLister := newMockStackLister( "test-ng1a", @@ -106,7 +106,7 @@ var _ = Describe("nodegroup filter", func() { "test-ng3a", ) err = filter.SetOnlyLocal(mockProvider.EKS(), mockLister, cfg) - Expect(err).ToNot(HaveOccurred()) + Expect(err).NotTo(HaveOccurred()) included, excluded := filter.matchAll(filter.collectNames(cfg.NodeGroups)) Expect(included).To(HaveLen(1)) @@ -117,7 +117,7 @@ var _ = Describe("nodegroup filter", func() { It("should match only local nodegroups with exclude and include rules", func() { err := filter.AppendIncludeGlobs(getNodeGroupNames(cfg), "test-ng?a", "test-ng?b") - Expect(err).ToNot(HaveOccurred()) + Expect(err).NotTo(HaveOccurred()) mockLister := newMockStackLister( "test-ng2a", @@ -125,10 +125,10 @@ var _ = Describe("nodegroup filter", func() { "test-ng2b", ) err = filter.SetOnlyLocal(mockProvider.EKS(), mockLister, cfg) - Expect(err).ToNot(HaveOccurred()) + Expect(err).NotTo(HaveOccurred()) err = filter.AppendExcludeGlobs("test-ng1a", "test-ng2?") - Expect(err).ToNot(HaveOccurred()) + Expect(err).NotTo(HaveOccurred()) included, excluded := filter.matchAll(filter.collectNames(cfg.NodeGroups)) Expect(included).To(HaveLen(2)) @@ -152,17 +152,17 @@ var _ = Describe("nodegroup filter", func() { err := filter.ForEach(cfg.NodeGroups, func(i int, nodeGroup *api.NodeGroup) error { api.SetNodeGroupDefaults(nodeGroup, cfg.Metadata) err := api.ValidateNodeGroup(i, nodeGroup) - Expect(err).ToNot(HaveOccurred()) + Expect(err).NotTo(HaveOccurred()) return nil }) - Expect(err).ToNot(HaveOccurred()) + Expect(err).NotTo(HaveOccurred()) err = filter.ForEach(cfg.NodeGroups, func(i int, nodeGroup *api.NodeGroup) error { Expect(nodeGroup).To(Equal(cfg.NodeGroups[i])) names = append(names, nodeGroup.Name) return nil }) - Expect(err).ToNot(HaveOccurred()) + Expect(err).NotTo(HaveOccurred()) Expect(names).To(Equal([]string{"test-ng1a", "test-ng2a", "test-ng3a", "test-ng1b", "test-ng2b", "test-ng3b"})) w := &bytes.Buffer{} @@ -183,17 +183,17 @@ var _ = Describe("nodegroup filter", func() { err := filter.ForEach(cfg.NodeGroups, func(i int, nodeGroup *api.NodeGroup) error { api.SetNodeGroupDefaults(nodeGroup, cfg.Metadata) err := api.ValidateNodeGroup(i, nodeGroup) - Expect(err).ToNot(HaveOccurred()) + Expect(err).NotTo(HaveOccurred()) return nil }) - Expect(err).ToNot(HaveOccurred()) + Expect(err).NotTo(HaveOccurred()) callback := false err = filter.ForEach(cfg.NodeGroups, func(_ int, _ *api.NodeGroup) error { callback = true return nil }) - Expect(err).ToNot(HaveOccurred()) + Expect(err).NotTo(HaveOccurred()) Expect(callback).To(BeFalse()) }) @@ -209,7 +209,7 @@ var _ = Describe("nodegroup filter", func() { names = append(names, nodeGroup.Name) return nil }) - Expect(err).ToNot(HaveOccurred()) + Expect(err).NotTo(HaveOccurred()) Expect(names).To(Equal([]string{"test-ng1a", "test-ng2a", "test-ng3a"})) names = []string{} @@ -222,7 +222,7 @@ var _ = Describe("nodegroup filter", func() { names = append(names, nodeGroup.Name) return nil }) - Expect(err).ToNot(HaveOccurred()) + Expect(err).NotTo(HaveOccurred()) Expect(names).To(Equal([]string{"ng-x0", "ng-x1", "ng-x2"})) }) @@ -239,7 +239,7 @@ var _ = Describe("nodegroup filter", func() { names = append(names, nodeGroup.Name) return nil }) - Expect(err).ToNot(HaveOccurred()) + Expect(err).NotTo(HaveOccurred()) Expect(names).To(Equal([]string{"test-ng1a", "test-ng2a", "test-ng3a", "test-ng1b", "test-ng2b", "test-ng3b"})) names = []string{} @@ -249,13 +249,13 @@ var _ = Describe("nodegroup filter", func() { Expect(err.Error()).To(Equal(`no nodegroups match include glob filter specification: "t?xyz?,ab*z123?"`)) err = filter.AppendIncludeGlobs(getNodeGroupNames(cfg), "test-ng1?", "te*-ng3?") - Expect(err).ToNot(HaveOccurred()) + Expect(err).NotTo(HaveOccurred()) err = filter.ForEach(cfg.NodeGroups, func(i int, nodeGroup *api.NodeGroup) error { Expect(nodeGroup).To(Equal(cfg.NodeGroups[i])) names = append(names, nodeGroup.Name) return nil }) - Expect(err).ToNot(HaveOccurred()) + Expect(err).NotTo(HaveOccurred()) Expect(names).To(Equal([]string{"test-ng1a", "test-ng3a", "test-ng1b", "test-ng3b"})) }) }) diff --git a/pkg/ctl/cmdutils/scale_test.go b/pkg/ctl/cmdutils/scale_test.go index ae4602c636..ce36263449 100644 --- a/pkg/ctl/cmdutils/scale_test.go +++ b/pkg/ctl/cmdutils/scale_test.go @@ -52,7 +52,7 @@ var _ = Describe("scale node group config file loader", func() { if params.minSize != nil { Expect(ng.MinSize).To(Equal(params.minSize)) } - Expect(err).ToNot(HaveOccurred()) + Expect(err).NotTo(HaveOccurred()) } }, Entry("one node group matched", scaleNodeGroupCase{ @@ -113,7 +113,7 @@ var _ = Describe("scale node group config file loader", func() { if params.minSize != nil { Expect(ng.MinSize).To(Equal(params.minSize)) } - Expect(err).ToNot(HaveOccurred()) + Expect(err).NotTo(HaveOccurred()) } }, Entry("only specifying min-nodes", scaleNodeGroupCLICase{ diff --git a/pkg/ctl/completion/completion_test.go b/pkg/ctl/completion/completion_test.go index 4089f0a70e..2073cd0cff 100644 --- a/pkg/ctl/completion/completion_test.go +++ b/pkg/ctl/completion/completion_test.go @@ -14,14 +14,14 @@ var _ = Describe("completion", func() { It("with bash", func() { cmd := newMockCmd("bash") out, err := cmd.execute() - Expect(err).ToNot(HaveOccurred()) + Expect(err).NotTo(HaveOccurred()) Expect(out).To(ContainSubstring("bash completion for eksctl")) }) It("with zsh", func() { cmd := newMockCmd("zsh") out, err := cmd.execute() - Expect(err).ToNot(HaveOccurred()) + Expect(err).NotTo(HaveOccurred()) Expect(out).To(ContainSubstring("#compdef _eksctl eksctl")) }) diff --git a/pkg/ctl/create/cluster_test.go b/pkg/ctl/create/cluster_test.go index 2802ceec97..06fc0bbd7d 100644 --- a/pkg/ctl/create/cluster_test.go +++ b/pkg/ctl/create/cluster_test.go @@ -39,7 +39,7 @@ var _ = Describe("create cluster", func() { }) }) _, err := cmd.execute() - Expect(err).ToNot(HaveOccurred()) + Expect(err).NotTo(HaveOccurred()) Expect(count).To(Equal(1)) }, Entry("without cluster name", ""), diff --git a/pkg/ctl/enable/flux_test.go b/pkg/ctl/enable/flux_test.go index 5855dc9be3..aefd36f98b 100644 --- a/pkg/ctl/enable/flux_test.go +++ b/pkg/ctl/enable/flux_test.go @@ -79,10 +79,10 @@ var _ = Describe("enable flux", func() { }) It("succeeds with the basic configuration", func() { - Expect(err).ToNot(HaveOccurred()) + Expect(err).NotTo(HaveOccurred()) fluxCfg := cmd.Cmd.ClusterConfig.GitOps.Flux - Expect(fluxCfg).ToNot(BeNil()) + Expect(fluxCfg).NotTo(BeNil()) Expect(fluxCfg.GitProvider).To(Equal("github")) }) diff --git a/pkg/ctl/enable/profile_test.go b/pkg/ctl/enable/profile_test.go index 2bc5d7a2cc..5f6ff71837 100644 --- a/pkg/ctl/enable/profile_test.go +++ b/pkg/ctl/enable/profile_test.go @@ -22,22 +22,22 @@ var _ = Describe("enable profile", func() { It("should accept a name argument", func() { cmd := newMockEnableProfileCmd("profile", "--cluster", "clus-1", "--region", "eu-north-1", "--git-url", "git@example.com:repo.git", "--git-email", "user@example.com", "app-dev") _, err := cmd.Execute() - Expect(err).ToNot(HaveOccurred()) + Expect(err).NotTo(HaveOccurred()) cfg := cmd.Cmd.ClusterConfig - Expect(cfg.Git.BootstrapProfile).ToNot(BeNil()) + Expect(cfg.Git.BootstrapProfile).NotTo(BeNil()) Expect(cfg.Git.BootstrapProfile.Source).To(Equal("app-dev")) }) It("should accept a --profile-source flag", func() { cmd := newMockEnableProfileCmd("profile", "--cluster", "clus-1", "--region", "eu-north-1", "--git-url", "git@example.com:repo.git", "--git-email", "user@example.com", "--profile-source", "app-dev") _, err := cmd.Execute() - Expect(err).ToNot(HaveOccurred()) + Expect(err).NotTo(HaveOccurred()) cfg := cmd.Cmd.ClusterConfig - Expect(cfg.Git.BootstrapProfile).ToNot(BeNil()) + Expect(cfg.Git.BootstrapProfile).NotTo(BeNil()) Expect(cfg.Git.BootstrapProfile.Source).To(Equal("app-dev")) }) @@ -107,20 +107,20 @@ var _ = Describe("enable profile", func() { "--profile-revision", "branch-2", ) _, err := cmd.Execute() - Expect(err).ToNot(HaveOccurred()) + Expect(err).NotTo(HaveOccurred()) cfg := cmd.Cmd.ClusterConfig Expect(cfg.Metadata.Name).To(Equal("clus-1")) Expect(cfg.Metadata.Region).To(Equal("us-west-2")) - Expect(cfg.Git).ToNot(BeNil()) - Expect(cfg.Git.Repo).ToNot(BeNil()) + Expect(cfg.Git).NotTo(BeNil()) + Expect(cfg.Git.Repo).NotTo(BeNil()) Expect(cfg.Git.Repo.URL).To(Equal("git@example.com:repo.git")) Expect(cfg.Git.Repo.Email).To(Equal("user@example.com")) Expect(cfg.Git.Repo.Branch).To(Equal("master")) Expect(cfg.Git.Repo.User).To(Equal("user1")) Expect(cfg.Git.Repo.PrivateSSHKeyPath).To(Equal("./profile_test.go")) - Expect(cfg.Git.BootstrapProfile).ToNot(BeNil()) + Expect(cfg.Git.BootstrapProfile).NotTo(BeNil()) Expect(cfg.Git.BootstrapProfile.Source).To(Equal("app-dev")) Expect(cfg.Git.BootstrapProfile.Revision).To(Equal("branch-2")) }) @@ -159,7 +159,7 @@ var _ = Describe("enable profile", func() { cmd := newMockEnableProfileCmd("profile", "-f", configFile) _, err := cmd.Execute() - Expect(err).ToNot(HaveOccurred()) + Expect(err).NotTo(HaveOccurred()) }) It("loads the correct defaults", func() { @@ -167,10 +167,10 @@ var _ = Describe("enable profile", func() { cmd := newMockEnableProfileCmd("profile", "-f", configFile) _, err := cmd.Execute() - Expect(err).ToNot(HaveOccurred()) + Expect(err).NotTo(HaveOccurred()) gitCfg := cmd.Cmd.ClusterConfig.Git - Expect(gitCfg).ToNot(BeNil()) + Expect(gitCfg).NotTo(BeNil()) Expect(gitCfg.Repo.Branch).To(Equal("master")) Expect(gitCfg.Repo.User).To(Equal("Flux")) Expect(gitCfg.Repo.FluxPath).To(Equal("flux/")) @@ -179,7 +179,7 @@ var _ = Describe("enable profile", func() { Expect(gitCfg.Operator.Namespace).To(Equal("flux")) Expect(gitCfg.Operator.Label).To(Equal("flux")) - Expect(gitCfg.Operator.WithHelm).ToNot(BeNil()) + Expect(gitCfg.Operator.WithHelm).NotTo(BeNil()) Expect(*gitCfg.Operator.WithHelm).To(BeTrue()) Expect(gitCfg.BootstrapProfile.Revision).To(Equal("")) diff --git a/pkg/ctl/enable/repo_test.go b/pkg/ctl/enable/repo_test.go index 8db3416a10..0b48033e9e 100644 --- a/pkg/ctl/enable/repo_test.go +++ b/pkg/ctl/enable/repo_test.go @@ -85,13 +85,13 @@ var _ = Describe("enable repo", func() { "--additional-helm-operator-args", "--log-format=json,--workers=4", ) _, err := cmd.Execute() - Expect(err).ToNot(HaveOccurred()) + Expect(err).NotTo(HaveOccurred()) cfg := cmd.Cmd.ClusterConfig Expect(cfg.Metadata.Name).To(Equal("clus-1")) Expect(cfg.Metadata.Region).To(Equal("us-west-2")) - Expect(cfg.Git).ToNot(BeNil()) - Expect(cfg.Git.Repo).ToNot(BeNil()) + Expect(cfg.Git).NotTo(BeNil()) + Expect(cfg.Git.Repo).NotTo(BeNil()) Expect(cfg.Git.Repo.URL).To(Equal("git@example.com:repo.git")) Expect(cfg.Git.Repo.Email).To(Equal("user@example.com")) Expect(cfg.Git.Repo.Branch).To(Equal("master")) @@ -100,7 +100,7 @@ var _ = Describe("enable repo", func() { Expect(cfg.Git.Repo.Paths).To(ConsistOf("base", "flux", "upgrades")) Expect(cfg.Git.Repo.FluxPath).To(Equal("flux-dir/")) - Expect(cfg.Git.Operator).ToNot(BeNil()) + Expect(cfg.Git.Operator).NotTo(BeNil()) Expect(cfg.Git.Operator.Label).To(Equal("flux2")) Expect(cfg.Git.Operator.Namespace).To(Equal("gitops")) Expect(*cfg.Git.Operator.WithHelm).To(BeTrue()) @@ -118,18 +118,18 @@ var _ = Describe("enable repo", func() { "--git-email", "user@example.com", ) _, err := cmd.Execute() - Expect(err).ToNot(HaveOccurred()) + Expect(err).NotTo(HaveOccurred()) cfg := cmd.Cmd.ClusterConfig - Expect(cfg.Git).ToNot(BeNil()) - Expect(cfg.Git.Repo).ToNot(BeNil()) + Expect(cfg.Git).NotTo(BeNil()) + Expect(cfg.Git.Repo).NotTo(BeNil()) Expect(cfg.Git.Repo.Branch).To(Equal("master")) Expect(cfg.Git.Repo.User).To(Equal("Flux")) Expect(cfg.Git.Repo.PrivateSSHKeyPath).To(Equal("")) Expect(cfg.Git.Repo.Paths).To(BeEmpty()) Expect(cfg.Git.Repo.FluxPath).To(Equal("flux/")) - Expect(cfg.Git.Operator).ToNot(BeNil()) + Expect(cfg.Git.Operator).NotTo(BeNil()) Expect(cfg.Git.Operator.Label).To(Equal("flux")) Expect(cfg.Git.Operator.Namespace).To(Equal("flux")) Expect(*cfg.Git.Operator.WithHelm).To(BeTrue()) @@ -173,7 +173,7 @@ var _ = Describe("enable repo", func() { cmd := newMockEnableRepoCmd("repo", "-f", configFile) _, err := cmd.Execute() - Expect(err).ToNot(HaveOccurred()) + Expect(err).NotTo(HaveOccurred()) }) It("fails without a cluster name", func() { @@ -241,10 +241,10 @@ var _ = Describe("enable repo", func() { cmd := newMockEnableRepoCmd("repo", "-f", configFile) _, err := cmd.Execute() - Expect(err).ToNot(HaveOccurred()) + Expect(err).NotTo(HaveOccurred()) gitCfg := cmd.Cmd.ClusterConfig.Git - Expect(gitCfg).ToNot(BeNil()) + Expect(gitCfg).NotTo(BeNil()) Expect(gitCfg.Repo.Branch).To(Equal("master")) Expect(gitCfg.Repo.User).To(Equal("Flux")) Expect(gitCfg.Repo.FluxPath).To(Equal("flux/")) @@ -253,7 +253,7 @@ var _ = Describe("enable repo", func() { Expect(gitCfg.Operator.Namespace).To(Equal("flux")) Expect(gitCfg.Operator.Label).To(Equal("flux")) - Expect(gitCfg.Operator.WithHelm).ToNot(BeNil()) + Expect(gitCfg.Operator.WithHelm).NotTo(BeNil()) Expect(*gitCfg.Operator.WithHelm).To(BeTrue()) Expect(gitCfg.Operator.ReadOnly).To(BeFalse()) Expect(*gitCfg.Operator.CommitOperatorManifests).To(BeTrue()) diff --git a/pkg/ctl/generate/profile_test.go b/pkg/ctl/generate/profile_test.go index 938a38a708..b7c0529634 100644 --- a/pkg/ctl/generate/profile_test.go +++ b/pkg/ctl/generate/profile_test.go @@ -21,22 +21,22 @@ var _ = Describe("generate profile", func() { It("should accept a name argument", func() { cmd := newMockGenerateProfileCmd("profile", "--cluster", "clus-1", "--region", "eu-north-1", "app-dev") _, err := cmd.Execute() - Expect(err).ToNot(HaveOccurred()) + Expect(err).NotTo(HaveOccurred()) cfg := cmd.Cmd.ClusterConfig - Expect(cfg.Git.BootstrapProfile).ToNot(BeNil()) + Expect(cfg.Git.BootstrapProfile).NotTo(BeNil()) Expect(cfg.Git.BootstrapProfile.Source).To(Equal("app-dev")) }) It("should accept --profile-source flag", func() { cmd := newMockGenerateProfileCmd("profile", "--cluster", "clus-1", "--region", "eu-north-1", "--profile-source", "app-dev") _, err := cmd.Execute() - Expect(err).ToNot(HaveOccurred()) + Expect(err).NotTo(HaveOccurred()) cfg := cmd.Cmd.ClusterConfig - Expect(cfg.Git.BootstrapProfile).ToNot(BeNil()) + Expect(cfg.Git.BootstrapProfile).NotTo(BeNil()) Expect(cfg.Git.BootstrapProfile.Source).To(Equal("app-dev")) }) @@ -78,14 +78,14 @@ var _ = Describe("generate profile", func() { "--region", "us-west-2", ) _, err := cmd.Execute() - Expect(err).ToNot(HaveOccurred()) + Expect(err).NotTo(HaveOccurred()) cfg := cmd.Cmd.ClusterConfig Expect(cfg.Metadata.Name).To(Equal("clus-1")) Expect(cfg.Metadata.Region).To(Equal("us-west-2")) - Expect(cfg.Git).ToNot(BeNil()) + Expect(cfg.Git).NotTo(BeNil()) - Expect(cfg.Git.BootstrapProfile).ToNot(BeNil()) + Expect(cfg.Git.BootstrapProfile).NotTo(BeNil()) Expect(cfg.Git.BootstrapProfile.Source).To(Equal("app-dev")) Expect(cfg.Git.BootstrapProfile.Revision).To(Equal("branch-2")) Expect(cfg.Git.BootstrapProfile.OutputPath).To(Equal("test-output-dir/dir2")) @@ -99,11 +99,11 @@ var _ = Describe("generate profile", func() { "--region", "us-west-2", ) _, err := cmd.Execute() - Expect(err).ToNot(HaveOccurred()) + Expect(err).NotTo(HaveOccurred()) cfg := cmd.Cmd.ClusterConfig - Expect(cfg.Git.BootstrapProfile).ToNot(BeNil()) + Expect(cfg.Git.BootstrapProfile).NotTo(BeNil()) Expect(cfg.Git.BootstrapProfile.OutputPath).To(Equal("./app-dev")) }) @@ -115,11 +115,11 @@ var _ = Describe("generate profile", func() { "--region", "us-west-2", ) _, err := cmd.Execute() - Expect(err).ToNot(HaveOccurred()) + Expect(err).NotTo(HaveOccurred()) cfg := cmd.Cmd.ClusterConfig - Expect(cfg.Git.BootstrapProfile).ToNot(BeNil()) + Expect(cfg.Git.BootstrapProfile).NotTo(BeNil()) Expect(cfg.Git.BootstrapProfile.OutputPath).To(Equal("./eks-quickstart-app-dev")) }) @@ -152,7 +152,7 @@ var _ = Describe("generate profile", func() { cmd := newMockGenerateProfileCmd("profile", "-f", configFile) _, err := cmd.Execute() - Expect(err).ToNot(HaveOccurred()) + Expect(err).NotTo(HaveOccurred()) }) It("fails without a cluster name", func() { @@ -200,11 +200,11 @@ var _ = Describe("generate profile", func() { cmd := newMockGenerateProfileCmd("profile", "-f", configFile) _, err := cmd.Execute() - Expect(err).ToNot(HaveOccurred()) + Expect(err).NotTo(HaveOccurred()) cfg := cmd.Cmd.ClusterConfig - Expect(cfg.Git.BootstrapProfile).ToNot(BeNil()) + Expect(cfg.Git.BootstrapProfile).NotTo(BeNil()) Expect(cfg.Git.BootstrapProfile.OutputPath).To(Equal("./app-dev")) }) @@ -214,11 +214,11 @@ var _ = Describe("generate profile", func() { cmd := newMockGenerateProfileCmd("profile", "-f", configFile) _, err := cmd.Execute() - Expect(err).ToNot(HaveOccurred()) + Expect(err).NotTo(HaveOccurred()) cfg := cmd.Cmd.ClusterConfig - Expect(cfg.Git.BootstrapProfile).ToNot(BeNil()) + Expect(cfg.Git.BootstrapProfile).NotTo(BeNil()) Expect(cfg.Git.BootstrapProfile.OutputPath).To(Equal("./some-repo")) }) }) diff --git a/pkg/ctl/upgrade/cluster_test.go b/pkg/ctl/upgrade/cluster_test.go index 701a87a75f..d1280e4d9f 100644 --- a/pkg/ctl/upgrade/cluster_test.go +++ b/pkg/ctl/upgrade/cluster_test.go @@ -22,30 +22,30 @@ var _ = Describe("upgrade cluster", func() { It("should accept a name argument", func() { cmd := newMockUpgradeClusterCmd("cluster", "clus-1") _, err := cmd.Execute() - Expect(err).ToNot(HaveOccurred()) + Expect(err).NotTo(HaveOccurred()) }) It("should accept a --name flag", func() { cmd := newMockUpgradeClusterCmd("cluster", "--name", "clus-1") _, err := cmd.Execute() - Expect(err).ToNot(HaveOccurred()) + Expect(err).NotTo(HaveOccurred()) }) It("should accept the --region flag", func() { cmd := newMockUpgradeClusterCmd("cluster", "--name", "clus-1", "--region", "eu-north-1") _, err := cmd.Execute() - Expect(err).ToNot(HaveOccurred()) + Expect(err).NotTo(HaveOccurred()) }) It("should accept the --version flag", func() { cmd := newMockUpgradeClusterCmd("cluster", "--name", "clus-1", "--region", "eu-north-1", "--version", "1.16") _, err := cmd.Execute() - Expect(err).ToNot(HaveOccurred()) + Expect(err).NotTo(HaveOccurred()) }) It("accepts --approve flag", func() { cmd := newMockUpgradeClusterCmd("cluster", "--name", "clus-1", "--approve") _, err := cmd.Execute() - Expect(err).ToNot(HaveOccurred()) + Expect(err).NotTo(HaveOccurred()) }) It("loads all flags correctly", func() { @@ -56,7 +56,7 @@ var _ = Describe("upgrade cluster", func() { "--approve", ) _, err := cmd.Execute() - Expect(err).ToNot(HaveOccurred()) + Expect(err).NotTo(HaveOccurred()) cfg := cmd.Cmd.ClusterConfig Expect(cfg.Metadata.Name).To(Equal("clus-1")) @@ -99,14 +99,14 @@ var _ = Describe("upgrade cluster", func() { cmd := newMockUpgradeClusterCmd("cluster", "-f", configFile) _, err := cmd.Execute() - Expect(err).ToNot(HaveOccurred()) + Expect(err).NotTo(HaveOccurred()) }) It("accepts --approve flag with the config file", func() { configFile = ctltest.CreateConfigFile(cfg) cmd := newMockUpgradeClusterCmd("cluster", "--config-file", configFile, "--approve") _, err := cmd.Execute() - Expect(err).ToNot(HaveOccurred()) + Expect(err).NotTo(HaveOccurred()) }) It("fails without a cluster name", func() { diff --git a/pkg/eks/api_test.go b/pkg/eks/api_test.go index d08618c2d3..f05e32995c 100644 --- a/pkg/eks/api_test.go +++ b/pkg/eks/api_test.go @@ -21,19 +21,19 @@ var _ = Describe("eksctl API", func() { BeforeEach(func() { err := api.Register() - Expect(err).ToNot(HaveOccurred()) + Expect(err).NotTo(HaveOccurred()) }) It("should load a valid YAML config without error", func() { cfg, err := LoadConfigFromFile("../../examples/01-simple-cluster.yaml") - Expect(err).ToNot(HaveOccurred()) + Expect(err).NotTo(HaveOccurred()) Expect(cfg.Metadata.Name).To(Equal("cluster-1")) Expect(cfg.NodeGroups).To(HaveLen(1)) }) It("should load a valid JSON config without error", func() { cfg, err := LoadConfigFromFile("testdata/example.json") - Expect(err).ToNot(HaveOccurred()) + Expect(err).NotTo(HaveOccurred()) Expect(cfg.Metadata.Name).To(Equal("cluster-1")) Expect(cfg.NodeGroups).To(HaveLen(1)) }) @@ -94,7 +94,7 @@ var _ = Describe("eksctl API", func() { testEnsureAMI := func(matcher gomegatypes.GomegaMatcher) { err := ResolveAMI(provider, "1.14", ng) - ExpectWithOffset(1, err).ToNot(HaveOccurred()) + ExpectWithOffset(1, err).NotTo(HaveOccurred()) ExpectWithOffset(1, ng.AMI).To(matcher) } diff --git a/pkg/eks/eks_test.go b/pkg/eks/eks_test.go index bd032876dd..44335371ae 100644 --- a/pkg/eks/eks_test.go +++ b/pkg/eks/eks_test.go @@ -332,8 +332,8 @@ var _ = Describe("EKS API wrapper", func() { p.MockCloudFormation().On("ListStacksPages", mock.Anything, mock.Anything).Return(nil) clusters, err := c.ListClusters(chunkSize, false) - Expect(err).ToNot(HaveOccurred()) - Expect(clusters).ToNot(BeNil()) + Expect(err).NotTo(HaveOccurred()) + Expect(clusters).NotTo(BeNil()) Expect(len(clusters)).To(Equal(0)) }) }) @@ -628,7 +628,7 @@ var _ = Describe("EKS API wrapper", func() { Expect(err).To(HaveOccurred()) Expect(err.Error()).To(ContainSubstring(k.errSubstr)) } else { - Expect(err).ToNot(HaveOccurred()) + Expect(err).NotTo(HaveOccurred()) } }, Entry("Invalid ARN", kmsSupportCase{ diff --git a/pkg/eks/nodegroup_service_test.go b/pkg/eks/nodegroup_service_test.go index 81cf45d975..202e607508 100644 --- a/pkg/eks/nodegroup_service_test.go +++ b/pkg/eks/nodegroup_service_test.go @@ -47,7 +47,7 @@ var _ = Describe("Instance Selector", func() { Expect(*instanceSelectorFake.FilterArgsForCall(i).AvailabilityZones).To(Equal(isc.expectedAZs)) } - Expect(err).ToNot(HaveOccurred()) + Expect(err).NotTo(HaveOccurred()) for _, np := range isc.nodeGroups { switch ng := np.(type) { case *api.NodeGroup: diff --git a/pkg/eks/update_test.go b/pkg/eks/update_test.go index e97b9af156..68c0738c14 100644 --- a/pkg/eks/update_test.go +++ b/pkg/eks/update_test.go @@ -37,7 +37,7 @@ var _ = Describe("EKS API wrapper", func() { updateClusterTagsOutput := &awseks.TagResourceOutput{} p.MockEKS().On("TagResource", mock.MatchedBy(func(input *awseks.TagResourceInput) bool { - Expect(input.Tags).ToNot(BeEmpty()) + Expect(input.Tags).NotTo(BeEmpty()) sentTags = utilsstrings.ToValuesMap(input.Tags) @@ -111,10 +111,10 @@ var _ = Describe("EKS API wrapper", func() { })).Return(describeClusterOutput, nil) p.MockEKS().On("UpdateClusterConfig", mock.MatchedBy(func(input *awseks.UpdateClusterConfigInput) bool { - Expect(input.Logging).ToNot(BeNil()) + Expect(input.Logging).NotTo(BeNil()) - Expect(input.Logging.ClusterLogging[0].Enabled).ToNot(BeNil()) - Expect(input.Logging.ClusterLogging[1].Enabled).ToNot(BeNil()) + Expect(input.Logging.ClusterLogging[0].Enabled).NotTo(BeNil()) + Expect(input.Logging.ClusterLogging[1].Enabled).NotTo(BeNil()) Expect(*input.Logging.ClusterLogging[0].Enabled).To(BeTrue()) Expect(*input.Logging.ClusterLogging[1].Enabled).To(BeFalse()) @@ -162,7 +162,7 @@ var _ = Describe("EKS API wrapper", func() { Expect(sentClusterLogging[0].Types).To(BeEmpty()) - Expect(sentClusterLogging[1].Types).ToNot(BeEmpty()) + Expect(sentClusterLogging[1].Types).NotTo(BeEmpty()) Expect(sentClusterLogging[1].Types).To(Equal(aws.StringSlice(api.SupportedCloudWatchClusterLogTypes()))) }) @@ -178,7 +178,7 @@ var _ = Describe("EKS API wrapper", func() { err = ctl.UpdateClusterConfigForLogging(cfg) Expect(err).NotTo(HaveOccurred()) - Expect(sentClusterLogging[0].Types).ToNot(BeEmpty()) + Expect(sentClusterLogging[0].Types).NotTo(BeEmpty()) Expect(sentClusterLogging[0].Types).To(Equal(aws.StringSlice(cfg.CloudWatch.ClusterLogging.EnableTypes))) Expect(sentClusterLogging[1].Types).To(BeEmpty()) @@ -196,10 +196,10 @@ var _ = Describe("EKS API wrapper", func() { err = ctl.UpdateClusterConfigForLogging(cfg) Expect(err).NotTo(HaveOccurred()) - Expect(sentClusterLogging[0].Types).ToNot(BeEmpty()) + Expect(sentClusterLogging[0].Types).NotTo(BeEmpty()) Expect(sentClusterLogging[0].Types).To(Equal(aws.StringSlice(cfg.CloudWatch.ClusterLogging.EnableTypes))) - Expect(sentClusterLogging[1].Types).ToNot(BeEmpty()) + Expect(sentClusterLogging[1].Types).NotTo(BeEmpty()) Expect(sentClusterLogging[1].Types).To(Equal(aws.StringSlice([]string{"api", "audit", "scheduler"}))) }) }) diff --git a/pkg/git/git_test.go b/pkg/git/git_test.go index 87c22710f8..09ed54f73f 100644 --- a/pkg/git/git_test.go +++ b/pkg/git/git_test.go @@ -52,12 +52,12 @@ var _ = Describe("git", func() { // The directory was created _, err = os.Stat(tempCloneDir) - Expect(err).ToNot(HaveOccurred()) + Expect(err).NotTo(HaveOccurred()) // It can delete it err = gitClient.DeleteLocalRepo() - Expect(err).ToNot(HaveOccurred()) + Expect(err).NotTo(HaveOccurred()) _, err = os.Stat(tempCloneDir) Expect(err).To(HaveOccurred()) Expect(os.IsNotExist(err)).To(BeTrue()) @@ -114,19 +114,19 @@ var _ = Describe("git", func() { Describe("RepoName", func() { It("can parse the repository name from a URL", func() { name, err := git.RepoName("git@github.com:weaveworks/eksctl.git") - Expect(err).ToNot(HaveOccurred()) + Expect(err).NotTo(HaveOccurred()) Expect(name).To(Equal("eksctl")) name, err = git.RepoName("git@github.com:weaveworks/sock-shop.git") - Expect(err).ToNot(HaveOccurred()) + Expect(err).NotTo(HaveOccurred()) Expect(name).To(Equal("sock-shop")) name, err = git.RepoName("https://example.com/department1/team1/some-repo-name.git") - Expect(err).ToNot(HaveOccurred()) + Expect(err).NotTo(HaveOccurred()) Expect(name).To(Equal("some-repo-name")) name, err = git.RepoName("https://github.com/department1/team2/another-repo-name") - Expect(err).ToNot(HaveOccurred()) + Expect(err).NotTo(HaveOccurred()) Expect(name).To(Equal("another-repo-name")) }) }) diff --git a/pkg/gitops/profile_test.go b/pkg/gitops/profile_test.go index 798df75b36..2f98300c77 100644 --- a/pkg/gitops/profile_test.go +++ b/pkg/gitops/profile_test.go @@ -74,23 +74,23 @@ var _ = Describe("gitops profile", func() { Revision: "master", OutputPath: outputDir}) - Expect(err).ToNot(HaveOccurred()) + Expect(err).NotTo(HaveOccurred()) template1, err := io.ReadFile(filepath.Join(outputDir, "a/good-template1.yaml")) - Expect(err).ToNot(HaveOccurred()) + Expect(err).NotTo(HaveOccurred()) Expect(template1).To(MatchYAML([]byte("cluster: test-cluster"))) template2, err := io.ReadFile(filepath.Join(outputDir, "a/b/good-template2.yaml")) - Expect(err).ToNot(HaveOccurred()) + Expect(err).NotTo(HaveOccurred()) Expect(template2).To(MatchYAML([]byte("name: test-cluster"))) }) It("can load files and ignore .git/ files", func() { err := profile.ignoreFiles(testDir) - Expect(err).ToNot(HaveOccurred()) + Expect(err).NotTo(HaveOccurred()) files, err := profile.loadFiles(testDir) - Expect(err).ToNot(HaveOccurred()) + Expect(err).NotTo(HaveOccurred()) Expect(files).To(HaveLen(4)) Expect(files).To(ConsistOf( fileprocessor.File{ @@ -150,7 +150,7 @@ metadata: files, err := profile.processFiles(inputFiles, "dir0") - Expect(err).ToNot(HaveOccurred()) + Expect(err).NotTo(HaveOccurred()) Expect(files).To(HaveLen(4)) Expect(files).To(ConsistOf( fileprocessor.File{ diff --git a/pkg/iam/arn_test.go b/pkg/iam/arn_test.go index b38c840ed0..5d294aafa6 100644 --- a/pkg/iam/arn_test.go +++ b/pkg/iam/arn_test.go @@ -10,7 +10,7 @@ var _ = Describe("iam", func() { It("determines if it is a user", func() { role := "arn:aws:iam::123456:role/testing" arn, err := Parse(role) - Expect(err).ToNot(HaveOccurred()) + Expect(err).NotTo(HaveOccurred()) Expect(arn.IsUser()).To(BeFalse()) Expect(arn.IsRole()).To(BeTrue()) @@ -18,7 +18,7 @@ var _ = Describe("iam", func() { It("determines if it is a role", func() { user := "arn:aws:iam::123456:user/testing" arn, err := Parse(user) - Expect(err).ToNot(HaveOccurred()) + Expect(err).NotTo(HaveOccurred()) Expect(arn.IsUser()).To(BeTrue()) Expect(arn.IsRole()).To(BeFalse()) diff --git a/pkg/iam/oidc/api_test.go b/pkg/iam/oidc/api_test.go index 6a2585a3cf..b17a7ebae5 100644 --- a/pkg/iam/oidc/api_test.go +++ b/pkg/iam/oidc/api_test.go @@ -107,7 +107,7 @@ var _ = Describe("EKS/IAM API wrapper", func() { Expect(srv.close()).To(Succeed()) Expect(err).NotTo(HaveOccurred()) - Expect(oidc.issuerCAThumbprint).ToNot(BeEmpty()) + Expect(oidc.issuerCAThumbprint).NotTo(BeEmpty()) Expect(oidc.issuerCAThumbprint).To(Equal(thumbprint)) }) @@ -128,7 +128,7 @@ var _ = Describe("EKS/IAM API wrapper", func() { Expect(srv.close()).To(Succeed()) Expect(err).NotTo(HaveOccurred()) - Expect(oidc.issuerCAThumbprint).ToNot(BeEmpty()) + Expect(oidc.issuerCAThumbprint).NotTo(BeEmpty()) Expect(oidc.issuerCAThumbprint).To(Equal(thumbprint)) }) }) @@ -231,7 +231,7 @@ var _ = Describe("EKS/IAM API wrapper", func() { Expect(exists).To(BeTrue()) document := oidc.MakeAssumeRolePolicyDocumentWithServiceAccountConditions("test-ns1", "test-sa1") - Expect(document).ToNot(BeEmpty()) + Expect(document).NotTo(BeEmpty()) expected := `{ "Version": "2012-10-17", @@ -263,7 +263,7 @@ var _ = Describe("EKS/IAM API wrapper", func() { Expect(exists).To(BeTrue()) document := oidc.MakeAssumeRolePolicyDocument() - Expect(document).ToNot(BeEmpty()) + Expect(document).NotTo(BeEmpty()) expected := `{ "Version": "2012-10-17", @@ -315,7 +315,7 @@ var _ = Describe("EKS/IAM API wrapper", func() { "cluster": "oidc", "resource": "oidc-provider", }) - Expect(err).ToNot(HaveOccurred()) + Expect(err).NotTo(HaveOccurred()) oidc.insecureSkipVerify = true var tagsInput []*awsiam.Tag @@ -374,7 +374,7 @@ var _ = Describe("EKS/IAM API wrapper", func() { oidc, err := NewOpenIDConnectManager(provider.IAM(), "12345", "https://localhost:10028/", partition, nil) oidc.insecureSkipVerify = true - Expect(err).ToNot(HaveOccurred()) + Expect(err).NotTo(HaveOccurred()) Expect(oidc.CreateProvider()).To(Succeed()) document := oidc.MakeAssumeRolePolicyDocumentWithServiceAccountConditions("test-ns", "test-sa") @@ -398,7 +398,7 @@ var _ = Describe("EKS/IAM API wrapper", func() { }`, fmt.Sprintf("arn:%s:iam::12345:oidc-provider/localhost/", partition), expectedAudience) actual, err := json.Marshal(document) - Expect(err).ToNot(HaveOccurred()) + Expect(err).NotTo(HaveOccurred()) Expect(actual).To(MatchJSON(expected)) }, Entry("Default AWS partition", "aws", "sts.amazonaws.com"), diff --git a/pkg/info/info_test.go b/pkg/info/info_test.go index df1539086a..c9917f5805 100644 --- a/pkg/info/info_test.go +++ b/pkg/info/info_test.go @@ -14,9 +14,9 @@ var _ = Describe("Info", func() { It("returns the eksctl and kubectl versions, and the host os", func() { result := GetInfo() - Expect(result.EksctlVersion).ToNot(Equal("")) - Expect(result.KubectlVersion).ToNot(Equal("")) - Expect(result.OS).ToNot(Equal("")) + Expect(result.EksctlVersion).NotTo(Equal("")) + Expect(result.KubectlVersion).NotTo(Equal("")) + Expect(result.OS).NotTo(Equal("")) _, err := semver.NewVersion(strings.TrimSpace(result.EksctlVersion)) Expect(err).NotTo(HaveOccurred()) @@ -37,9 +37,9 @@ var _ = Describe("Info", func() { err := json.Unmarshal([]byte(result), &infos) Expect(err).NotTo(HaveOccurred()) - Expect(infos.EksctlVersion).ToNot(Equal("")) - Expect(infos.KubectlVersion).ToNot(Equal("")) - Expect(infos.OS).ToNot(Equal("")) + Expect(infos.EksctlVersion).NotTo(Equal("")) + Expect(infos.KubectlVersion).NotTo(Equal("")) + Expect(infos.OS).NotTo(Equal("")) }) }) diff --git a/pkg/kubernetes/client_test.go b/pkg/kubernetes/client_test.go index aa037e04ef..631072c372 100644 --- a/pkg/kubernetes/client_test.go +++ b/pkg/kubernetes/client_test.go @@ -23,20 +23,20 @@ var _ = Describe("Kubernetes client wrappers", func() { rc, track := testutils.NewFakeRawResource(item, false, false, ct) exists, err := rc.Exists() - Expect(err).ToNot(HaveOccurred()) + Expect(err).NotTo(HaveOccurred()) Expect(exists).To(BeTrue()) // The Kubernetes resource already exists. _, err = rc.CreateOrReplace(false) - Expect(err).ToNot(HaveOccurred()) - Expect(track).ToNot(BeNil()) + Expect(err).NotTo(HaveOccurred()) + Expect(track).NotTo(BeNil()) Expect(track.Methods()).To(Equal([]string{"GET", "GET", "GET", "PUT"})) exists, err = rc.Exists() - Expect(err).ToNot(HaveOccurred()) + Expect(err).NotTo(HaveOccurred()) Expect(exists).To(BeTrue()) // The Kubernetes resource still exists. } - Expect(ct.Updated()).ToNot(BeEmpty()) + Expect(ct.Updated()).NotTo(BeEmpty()) Expect(ct.UpdatedItems()).To(HaveLen(10)) Expect(ct.Created()).To(BeEmpty()) Expect(ct.CreatedItems()).To(BeEmpty()) @@ -50,20 +50,20 @@ var _ = Describe("Kubernetes client wrappers", func() { rc, track := testutils.NewFakeRawResource(item, false, false, ct) exists, err := rc.Exists() - Expect(err).ToNot(HaveOccurred()) + Expect(err).NotTo(HaveOccurred()) Expect(exists).To(BeTrue()) // The Kubernetes resource already exists. _, err = rc.CreateOrReplace(false) - Expect(err).ToNot(HaveOccurred()) - Expect(track).ToNot(BeNil()) + Expect(err).NotTo(HaveOccurred()) + Expect(track).NotTo(BeNil()) Expect(track.Methods()).To(Equal([]string{"GET", "GET", "GET", "PUT"})) exists, err = rc.Exists() - Expect(err).ToNot(HaveOccurred()) + Expect(err).NotTo(HaveOccurred()) Expect(exists).To(BeTrue()) // The Kubernetes resource still exists. } - Expect(ct.Updated()).ToNot(BeEmpty()) + Expect(ct.Updated()).NotTo(BeEmpty()) Expect(ct.UpdatedItems()).To(HaveLen(10)) Expect(ct.Created()).To(BeEmpty()) Expect(ct.CreatedItems()).To(BeEmpty()) @@ -77,20 +77,20 @@ var _ = Describe("Kubernetes client wrappers", func() { rc, track := testutils.NewFakeRawResource(item, true, false, ct) exists, err := rc.Exists() - Expect(err).ToNot(HaveOccurred()) + Expect(err).NotTo(HaveOccurred()) Expect(exists).To(BeFalse()) // The Kubernetes resource has not been created yet. _, err = rc.CreateOrReplace(false) - Expect(err).ToNot(HaveOccurred()) - Expect(track).ToNot(BeNil()) + Expect(err).NotTo(HaveOccurred()) + Expect(track).NotTo(BeNil()) Expect(track.Methods()).To(Equal([]string{"GET", "GET", "POST"})) exists, err = rc.Exists() - Expect(err).ToNot(HaveOccurred()) + Expect(err).NotTo(HaveOccurred()) Expect(exists).To(BeTrue()) // The Kubernetes resource has not been created yet. } - Expect(ct.Created()).ToNot(BeEmpty()) + Expect(ct.Created()).NotTo(BeEmpty()) Expect(ct.CreatedItems()).To(HaveLen(10)) Expect(ct.Updated()).To(BeEmpty()) Expect(ct.UpdatedItems()).To(BeEmpty()) @@ -104,20 +104,20 @@ var _ = Describe("Kubernetes client wrappers", func() { rc, track := testutils.NewFakeRawResource(item, false, false, ct) exists, err := rc.Exists() - Expect(err).ToNot(HaveOccurred()) + Expect(err).NotTo(HaveOccurred()) Expect(exists).To(BeTrue()) // The Kubernetes resource already exists. _, err = rc.CreateOrReplace(false) - Expect(err).ToNot(HaveOccurred()) - Expect(track).ToNot(BeNil()) + Expect(err).NotTo(HaveOccurred()) + Expect(track).NotTo(BeNil()) Expect(track.Methods()).To(Equal([]string{"GET", "GET", "GET", "PUT"})) exists, err = rc.Exists() - Expect(err).ToNot(HaveOccurred()) + Expect(err).NotTo(HaveOccurred()) Expect(exists).To(BeTrue()) // The Kubernetes resource still exists. } - Expect(ct.Updated()).ToNot(BeEmpty()) + Expect(ct.Updated()).NotTo(BeEmpty()) Expect(ct.UpdatedItems()).To(HaveLen(10)) Expect(ct.Created()).To(BeEmpty()) Expect(ct.CreatedItems()).To(BeEmpty()) @@ -132,24 +132,24 @@ var _ = Describe("Kubernetes client wrappers", func() { for _, item := range sampleAddons { rc, err := rawClient.NewRawResource(item) - Expect(err).ToNot(HaveOccurred()) + Expect(err).NotTo(HaveOccurred()) _, err = rc.CreateOrReplace(false) - Expect(err).ToNot(HaveOccurred()) + Expect(err).NotTo(HaveOccurred()) } ct := rawClient.Collection - Expect(ct.Created()).ToNot(BeEmpty()) + Expect(ct.Created()).NotTo(BeEmpty()) Expect(ct.CreatedItems()).To(HaveLen(10)) Expect(ct.Updated()).To(BeEmpty()) Expect(ct.UpdatedItems()).To(BeEmpty()) dsl, err := rawClient.ClientSet().AppsV1().DaemonSets(metav1.NamespaceSystem).List(context.TODO(), metav1.ListOptions{}) - Expect(err).ToNot(HaveOccurred()) + Expect(err).NotTo(HaveOccurred()) Expect(dsl.Items).To(HaveLen(2)) awsNode, err := rawClient.ClientSet().AppsV1().DaemonSets(metav1.NamespaceSystem).Get(context.TODO(), "aws-node", metav1.GetOptions{}) - Expect(err).ToNot(HaveOccurred()) + Expect(err).NotTo(HaveOccurred()) Expect(awsNode.Spec.Template.Spec.Containers).To(HaveLen(1)) Expect(awsNode.Spec.Template.Spec.Containers[0].Image).To( Equal("602401143452.dkr.ecr.eu-west-1.amazonaws.com/amazon-k8s-cni:v1.5.7"), @@ -191,27 +191,27 @@ var _ = Describe("Kubernetes client wrappers", func() { for _, item := range []runtime.Object{saTest1, saTest2a, saTest2b} { rc, err := rawClient.NewRawResource(item) - Expect(err).ToNot(HaveOccurred()) + Expect(err).NotTo(HaveOccurred()) _, err = rc.CreateOrReplace(false) - Expect(err).ToNot(HaveOccurred()) + Expect(err).NotTo(HaveOccurred()) } - Expect(ct.Created()).ToNot(BeEmpty()) + Expect(ct.Created()).NotTo(BeEmpty()) Expect(ct.CreatedItems()).To(HaveLen(10 + 2)) - Expect(ct.UpdatedItems()).ToNot(BeEmpty()) + Expect(ct.UpdatedItems()).NotTo(BeEmpty()) Expect(ct.UpdatedItems()).To(HaveLen(1)) _, err = rawClient.ClientSet().CoreV1().ServiceAccounts(metav1.NamespaceDefault).Get(context.TODO(), "test1", metav1.GetOptions{}) - Expect(err).ToNot(HaveOccurred()) + Expect(err).NotTo(HaveOccurred()) _, err = rawClient.ClientSet().CoreV1().ServiceAccounts(metav1.NamespaceDefault).Get(context.TODO(), "test2", metav1.GetOptions{}) - Expect(err).ToNot(HaveOccurred()) + Expect(err).NotTo(HaveOccurred()) _, err = rawClient.ClientSet().CoreV1().ServiceAccounts(metav1.NamespaceDefault).Create(context.TODO(), saTest1, metav1.CreateOptions{}) Expect(err).To(HaveOccurred()) err = rawClient.ClientSet().CoreV1().ServiceAccounts(metav1.NamespaceDefault).Delete(context.TODO(), "test1", metav1.DeleteOptions{}) - Expect(err).ToNot(HaveOccurred()) + Expect(err).NotTo(HaveOccurred()) // saving a clientset instance results in objects being trackable, // but only as far as the clientset instance is concerned @@ -219,15 +219,15 @@ var _ = Describe("Kubernetes client wrappers", func() { // this limitation c := rawClient.ClientSet().CoreV1().ServiceAccounts(metav1.NamespaceDefault) err = c.Delete(context.TODO(), "test1", metav1.DeleteOptions{}) - Expect(err).ToNot(HaveOccurred()) + Expect(err).NotTo(HaveOccurred()) err = c.Delete(context.TODO(), "test1", metav1.DeleteOptions{}) Expect(err).To(HaveOccurred()) // however deletions of raw resources are trackable rc, err := rawClient.NewRawResource(saTest1) - Expect(err).ToNot(HaveOccurred()) + Expect(err).NotTo(HaveOccurred()) _, err = rc.Helper.Delete(rc.Info.Namespace, rc.Info.Name) - Expect(err).ToNot(HaveOccurred()) + Expect(err).NotTo(HaveOccurred()) _, err = rawClient.ClientSet().CoreV1().ServiceAccounts(metav1.NamespaceDefault).Get(context.TODO(), "test1", metav1.GetOptions{}) Expect(err).To(HaveOccurred()) }) @@ -240,17 +240,17 @@ var _ = Describe("Kubernetes client wrappers", func() { rc, track := testutils.NewFakeRawResource(item, false, false, ct) exists, err := rc.Exists() - Expect(err).ToNot(HaveOccurred()) + Expect(err).NotTo(HaveOccurred()) Expect(exists).To(BeTrue()) // The Kubernetes resource already exists. status, err := rc.DeleteSync() - Expect(err).ToNot(HaveOccurred()) + Expect(err).NotTo(HaveOccurred()) Expect(status).To(Equal(fmt.Sprintf("deleted %q", rc))) - Expect(track).ToNot(BeNil()) + Expect(track).NotTo(BeNil()) Expect(track.Methods()).To(Equal([]string{"GET", "GET", "DELETE", "GET"})) exists, err = rc.Exists() - Expect(err).ToNot(HaveOccurred()) + Expect(err).NotTo(HaveOccurred()) Expect(exists).To(BeFalse()) // The Kubernetes resource no longer exists. } @@ -258,7 +258,7 @@ var _ = Describe("Kubernetes client wrappers", func() { Expect(ct.CreatedItems()).To(BeEmpty()) Expect(ct.Updated()).To(BeEmpty()) Expect(ct.UpdatedItems()).To(BeEmpty()) - Expect(ct.Deleted()).ToNot(BeEmpty()) + Expect(ct.Deleted()).NotTo(BeEmpty()) Expect(ct.DeletedItems()).To(HaveLen(10)) }) }) diff --git a/pkg/kubernetes/manifests_test.go b/pkg/kubernetes/manifests_test.go index 5ce36de663..a16040507e 100644 --- a/pkg/kubernetes/manifests_test.go +++ b/pkg/kubernetes/manifests_test.go @@ -19,8 +19,8 @@ var _ = Describe("Kubernetes client toolkit", func() { Expect(err).To(Not(HaveOccurred())) list, err := NewList(jb) - Expect(err).ToNot(HaveOccurred()) - Expect(list).ToNot(BeNil()) + Expect(err).NotTo(HaveOccurred()) + Expect(list).NotTo(BeNil()) Expect(list.Items).To(HaveLen(6)) }) }) @@ -31,8 +31,8 @@ var _ = Describe("Kubernetes client toolkit", func() { Expect(err).To(Not(HaveOccurred())) list, err := NewList(jb) - Expect(err).ToNot(HaveOccurred()) - Expect(list).ToNot(BeNil()) + Expect(err).NotTo(HaveOccurred()) + Expect(list).NotTo(BeNil()) Expect(list.Items).To(HaveLen(0)) }) }) @@ -43,8 +43,8 @@ var _ = Describe("Kubernetes client toolkit", func() { Expect(err).To(Not(HaveOccurred())) list, err := NewList(yb) - Expect(err).ToNot(HaveOccurred()) - Expect(list).ToNot(BeNil()) + Expect(err).NotTo(HaveOccurred()) + Expect(list).NotTo(BeNil()) Expect(list.Items).To(HaveLen(0)) }) }) @@ -56,8 +56,8 @@ var _ = Describe("Kubernetes client toolkit", func() { Expect(err).To(Not(HaveOccurred())) list, err := NewList(yb) - Expect(err).ToNot(HaveOccurred()) - Expect(list).ToNot(BeNil()) + Expect(err).NotTo(HaveOccurred()) + Expect(list).NotTo(BeNil()) Expect(list.Items).To(HaveLen(0)) }) }) @@ -68,8 +68,8 @@ var _ = Describe("Kubernetes client toolkit", func() { Expect(err).To(Not(HaveOccurred())) list, err := NewList(yb) - Expect(err).ToNot(HaveOccurred()) - Expect(list).ToNot(BeNil()) + Expect(err).NotTo(HaveOccurred()) + Expect(list).NotTo(BeNil()) Expect(list.Items).To(HaveLen(4)) }) }) @@ -77,10 +77,10 @@ var _ = Describe("Kubernetes client toolkit", func() { Context("can handle comment nodes", func() { It("should be able to parse lists with comment nodes", func() { bytes, err := os.ReadFile("testdata/list-with-comment-nodes.yaml") - Expect(err).ToNot(HaveOccurred()) + Expect(err).NotTo(HaveOccurred()) list, err := NewList(bytes) - Expect(err).ToNot(HaveOccurred()) - Expect(list).ToNot(BeNil()) + Expect(err).NotTo(HaveOccurred()) + Expect(list).NotTo(BeNil()) Expect(list.Items).To(HaveLen(4)) }) }) diff --git a/pkg/kubernetes/namespace_test.go b/pkg/kubernetes/namespace_test.go index 1dd6e71246..f4a449a1b5 100644 --- a/pkg/kubernetes/namespace_test.go +++ b/pkg/kubernetes/namespace_test.go @@ -33,7 +33,7 @@ var _ = Describe("Kubernetes namespace object helpers", func() { Expect(ns.Labels).To(BeEmpty()) js, err := json.Marshal(ns) - Expect(err).ToNot(HaveOccurred()) + Expect(err).NotTo(HaveOccurred()) expected := `{ "apiVersion": "v1", @@ -54,7 +54,7 @@ var _ = Describe("Kubernetes namespace object helpers", func() { err = yaml.Unmarshal(ys, ns) - Expect(err).ToNot(HaveOccurred()) + Expect(err).NotTo(HaveOccurred()) Expect(ns.APIVersion).To(Equal("v1")) Expect(ns.Kind).To(Equal("Namespace")) @@ -65,10 +65,10 @@ var _ = Describe("Kubernetes namespace object helpers", func() { It("can create namespace using fake client and check confirm that it exists", func() { err = MaybeCreateNamespace(clientSet, "ns-1") - Expect(err).ToNot(HaveOccurred()) + Expect(err).NotTo(HaveOccurred()) ok, err := CheckNamespaceExists(clientSet, "ns-1") - Expect(err).ToNot(HaveOccurred()) + Expect(err).NotTo(HaveOccurred()) Expect(ok).To(BeTrue()) }) }) diff --git a/pkg/kubernetes/nodegroup_test.go b/pkg/kubernetes/nodegroup_test.go index f73679e150..7dfb19b7fa 100644 --- a/pkg/kubernetes/nodegroup_test.go +++ b/pkg/kubernetes/nodegroup_test.go @@ -41,7 +41,7 @@ var _ = Describe("NodeGroup", func() { return } - Expect(err).ToNot(HaveOccurred()) + Expect(err).NotTo(HaveOccurred()) Expect(version).To(Equal(t.expectedVersion)) }, diff --git a/pkg/kubernetes/serviceaccount_test.go b/pkg/kubernetes/serviceaccount_test.go index ce3ed30518..db736ec53e 100644 --- a/pkg/kubernetes/serviceaccount_test.go +++ b/pkg/kubernetes/serviceaccount_test.go @@ -34,7 +34,7 @@ var _ = Describe("Kubernetes serviceaccount object helpers", func() { Expect(sa.Labels).To(BeEmpty()) js, err := json.Marshal(sa) - Expect(err).ToNot(HaveOccurred()) + Expect(err).NotTo(HaveOccurred()) expected := `{ "apiVersion": "v1", @@ -52,19 +52,19 @@ var _ = Describe("Kubernetes serviceaccount object helpers", func() { sa := metav1.ObjectMeta{Name: "sa-1", Namespace: "ns-1"} err = MaybeCreateServiceAccountOrUpdateMetadata(clientSet, sa) - Expect(err).ToNot(HaveOccurred()) + Expect(err).NotTo(HaveOccurred()) ok, err := CheckNamespaceExists(clientSet, sa.Namespace) - Expect(err).ToNot(HaveOccurred()) + Expect(err).NotTo(HaveOccurred()) Expect(ok).To(BeTrue()) ok, err = CheckServiceAccountExists(clientSet, sa) - Expect(err).ToNot(HaveOccurred()) + Expect(err).NotTo(HaveOccurred()) Expect(ok).To(BeTrue()) { resp, err := clientSet.CoreV1().ServiceAccounts(sa.Namespace).Get(context.TODO(), sa.Name, metav1.GetOptions{}) - Expect(err).ToNot(HaveOccurred()) + Expect(err).NotTo(HaveOccurred()) Expect(resp.Labels).To(BeEmpty()) Expect(resp.Annotations).To(BeEmpty()) @@ -78,11 +78,11 @@ var _ = Describe("Kubernetes serviceaccount object helpers", func() { } err = MaybeCreateServiceAccountOrUpdateMetadata(clientSet, sa) - Expect(err).ToNot(HaveOccurred()) + Expect(err).NotTo(HaveOccurred()) { resp, err := clientSet.CoreV1().ServiceAccounts(sa.Namespace).Get(context.TODO(), sa.Name, metav1.GetOptions{}) - Expect(err).ToNot(HaveOccurred()) + Expect(err).NotTo(HaveOccurred()) Expect(resp.Labels).To(HaveKey("foo")) Expect(resp.Annotations).To(HaveKeyWithValue("test", "1")) @@ -92,11 +92,11 @@ var _ = Describe("Kubernetes serviceaccount object helpers", func() { sa.Annotations["test"] = "2" err = MaybeCreateServiceAccountOrUpdateMetadata(clientSet, sa) - Expect(err).ToNot(HaveOccurred()) + Expect(err).NotTo(HaveOccurred()) { resp, err := clientSet.CoreV1().ServiceAccounts(sa.Namespace).Get(context.TODO(), sa.Name, metav1.GetOptions{}) - Expect(err).ToNot(HaveOccurred()) + Expect(err).NotTo(HaveOccurred()) Expect(resp.Labels).To(HaveKey("foo")) Expect(resp.Annotations).To(HaveKeyWithValue("test", "2")) @@ -107,26 +107,26 @@ var _ = Describe("Kubernetes serviceaccount object helpers", func() { sa := metav1.ObjectMeta{Name: "sa-2", Namespace: "ns-2"} err = MaybeCreateServiceAccountOrUpdateMetadata(clientSet, sa) - Expect(err).ToNot(HaveOccurred()) + Expect(err).NotTo(HaveOccurred()) ok, err := CheckServiceAccountExists(clientSet, sa) - Expect(err).ToNot(HaveOccurred()) + Expect(err).NotTo(HaveOccurred()) Expect(ok).To(BeTrue()) // should delete it err = MaybeDeleteServiceAccount(clientSet, sa) - Expect(err).ToNot(HaveOccurred()) + Expect(err).NotTo(HaveOccurred()) ok, err = CheckServiceAccountExists(clientSet, sa) - Expect(err).ToNot(HaveOccurred()) + Expect(err).NotTo(HaveOccurred()) Expect(ok).To(BeFalse()) // shouldn't fail if it doesn't exist err = MaybeDeleteServiceAccount(clientSet, sa) - Expect(err).ToNot(HaveOccurred()) + Expect(err).NotTo(HaveOccurred()) ok, err = CheckServiceAccountExists(clientSet, sa) - Expect(err).ToNot(HaveOccurred()) + Expect(err).NotTo(HaveOccurred()) Expect(ok).To(BeFalse()) }) }) diff --git a/pkg/managed/release_version_test.go b/pkg/managed/release_version_test.go index 23d6bffdf2..2d01dc1508 100644 --- a/pkg/managed/release_version_test.go +++ b/pkg/managed/release_version_test.go @@ -33,7 +33,7 @@ var _ = Describe("AMI Release Version", func() { Expect(err.Error()).To(ContainSubstring(vc.errMsg)) return } - Expect(err).ToNot(HaveOccurred()) + Expect(err).NotTo(HaveOccurred()) Expect(cmp).To(Equal(vc.cmp)) }, Entry("Equal", versionCase{ diff --git a/pkg/nodebootstrap/al2_test.go b/pkg/nodebootstrap/al2_test.go index ef371e4d0f..4d7ff935b4 100644 --- a/pkg/nodebootstrap/al2_test.go +++ b/pkg/nodebootstrap/al2_test.go @@ -46,7 +46,7 @@ var _ = Describe("AmazonLinux2 User Data", func() { for _, f := range cloudCfg.WriteFiles { paths = append(paths, f.Path) } - Expect(paths).ToNot(ContainElement("/var/lib/cloud/scripts/eksctl/install-ssm.al2.sh")) + Expect(paths).NotTo(ContainElement("/var/lib/cloud/scripts/eksctl/install-ssm.al2.sh")) }) }) @@ -82,7 +82,7 @@ var _ = Describe("AmazonLinux2 User Data", func() { be.ng.AMIFamily = "AmazonLinux2" bootstrapper := newBootstrapper(be.clusterConfig, be.ng) userData, err := bootstrapper.UserData() - Expect(err).ToNot(HaveOccurred()) + Expect(err).NotTo(HaveOccurred()) cloudCfg := decode(userData) file := cloudCfg.WriteFiles[1] Expect(file.Path).To(Equal("/etc/eksctl/kubelet.env")) diff --git a/pkg/nodebootstrap/bottlerocket_test.go b/pkg/nodebootstrap/bottlerocket_test.go index 0828a1e65f..e1a060c0cb 100644 --- a/pkg/nodebootstrap/bottlerocket_test.go +++ b/pkg/nodebootstrap/bottlerocket_test.go @@ -40,25 +40,25 @@ var _ = Describe("Bottlerocket", func() { It("produces standard TOML userdata", func() { bootstrapper := newBootstrapper(clusterConfig, ng) userdata, err := bootstrapper.UserData() - Expect(err).ToNot(HaveOccurred()) - Expect(userdata).ToNot(Equal("")) + Expect(err).NotTo(HaveOccurred()) + Expect(userdata).NotTo(Equal("")) settings, parseErr := userdataTOML(userdata) - Expect(parseErr).ToNot(HaveOccurred()) + Expect(parseErr).NotTo(HaveOccurred()) Expect(settings.Has("settings.kubernetes.cluster-name")).To(BeTrue()) }) It("leaves settings.host-containers.admin.enabled commented", func() { bootstrapper := newBootstrapper(clusterConfig, ng) userdata, err := bootstrapper.UserData() - Expect(err).ToNot(HaveOccurred()) - Expect(userdata).ToNot(Equal("")) + Expect(err).NotTo(HaveOccurred()) + Expect(userdata).NotTo(Equal("")) settings, parseErr := userdataTOML(userdata) - Expect(parseErr).ToNot(HaveOccurred()) + Expect(parseErr).NotTo(HaveOccurred()) Expect(settings.Has("settings.host-containers.admin.enabled")).To(BeFalse()) tomlStr, err := settings.ToTomlString() - Expect(err).ToNot(HaveOccurred()) + Expect(err).NotTo(HaveOccurred()) // Generated TOML should contain a section (with the enabled // key=value) for the unset, commented out setting. Expect(tomlStr).To(ContainSubstring("[settings.host-containers.admin]")) @@ -83,11 +83,11 @@ var _ = Describe("Bottlerocket", func() { bootstrapper := newBootstrapper(clusterConfig, ng) userdata, err := bootstrapper.UserData() - Expect(err).ToNot(HaveOccurred()) - Expect(userdata).ToNot(Equal("")) + Expect(err).NotTo(HaveOccurred()) + Expect(userdata).NotTo(Equal("")) tree, parseErr := userdataTOML(userdata) - Expect(parseErr).ToNot(HaveOccurred()) + Expect(parseErr).NotTo(HaveOccurred()) // Verify the keys made it to where they were // supposed to and that nothing happened to // make them appear as dotted/split key names. @@ -109,11 +109,11 @@ var _ = Describe("Bottlerocket", func() { It("sets it on the userdata", func() { bootstrapper := newBootstrapper(clusterConfig, ng) userdata, err := bootstrapper.UserData() - Expect(err).ToNot(HaveOccurred()) - Expect(userdata).ToNot(Equal("")) + Expect(err).NotTo(HaveOccurred()) + Expect(userdata).NotTo(Equal("")) settings, parseErr := userdataTOML(userdata) - Expect(parseErr).ToNot(HaveOccurred()) + Expect(parseErr).NotTo(HaveOccurred()) Expect(settings.Has("settings.host-containers.example.enabled")).To(BeTrue()) }) }) @@ -126,11 +126,11 @@ var _ = Describe("Bottlerocket", func() { It("enables admin container on the userdata", func() { bootstrapper := newBootstrapper(clusterConfig, ng) userdata, err := bootstrapper.UserData() - Expect(err).ToNot(HaveOccurred()) - Expect(userdata).ToNot(Equal("")) + Expect(err).NotTo(HaveOccurred()) + Expect(userdata).NotTo(Equal("")) settings, parseErr := userdataTOML(userdata) - Expect(parseErr).ToNot(HaveOccurred()) + Expect(parseErr).NotTo(HaveOccurred()) Expect(settings.Has("settings.host-containers.admin.enabled")).To(BeTrue()) val, ok := settings.Get("settings.host-containers.admin.enabled").(bool) Expect(ok).To(BeTrue()) @@ -144,11 +144,11 @@ var _ = Describe("Bottlerocket", func() { providedSettings["host-containers"].(map[string]interface{})["admin"] = map[string]string{"enabled": "user-val"} bootstrapper := newBootstrapper(clusterConfig, ng) userdata, err := bootstrapper.UserData() - Expect(err).ToNot(HaveOccurred()) - Expect(userdata).ToNot(Equal("")) + Expect(err).NotTo(HaveOccurred()) + Expect(userdata).NotTo(Equal("")) settings, parseErr := userdataTOML(userdata) - Expect(parseErr).ToNot(HaveOccurred()) + Expect(parseErr).NotTo(HaveOccurred()) // Check that the value specified in config is // set, not the higher level toggle. Expect(settings.Has("settings.host-containers.admin.enabled")).To(BeTrue()) @@ -175,11 +175,11 @@ var _ = Describe("Bottlerocket", func() { It("adds the labels to the userdata", func() { bootstrapper := newBootstrapper(clusterConfig, ng) userdata, err := bootstrapper.UserData() - Expect(err).ToNot(HaveOccurred()) - Expect(userdata).ToNot(Equal("")) + Expect(err).NotTo(HaveOccurred()) + Expect(userdata).NotTo(Equal("")) tree, parseErr := userdataTOML(userdata) - Expect(parseErr).ToNot(HaveOccurred()) + Expect(parseErr).NotTo(HaveOccurred()) Expect(tree.HasPath(append(labelsPath, "foo"))).To(BeTrue()) Expect(tree.GetPath(append(labelsPath, "foo"))).To(Equal("bar")) @@ -200,11 +200,11 @@ var _ = Describe("Bottlerocket", func() { It("adds the taints to the userdata", func() { bootstrapper := newBootstrapper(clusterConfig, ng) userdata, err := bootstrapper.UserData() - Expect(err).ToNot(HaveOccurred()) - Expect(userdata).ToNot(Equal("")) + Expect(err).NotTo(HaveOccurred()) + Expect(userdata).NotTo(Equal("")) tree, parseErr := userdataTOML(userdata) - Expect(parseErr).ToNot(HaveOccurred()) + Expect(parseErr).NotTo(HaveOccurred()) Expect(tree.HasPath(append(taintsPath, "foo"))).To(BeTrue()) Expect(tree.GetPath(append(taintsPath, "foo"))).To(Equal("bar:NoExecute")) @@ -217,11 +217,11 @@ var _ = Describe("Bottlerocket", func() { bootstrapper := newBootstrapper(clusterConfig, ng) userdata, err := bootstrapper.UserData() - Expect(err).ToNot(HaveOccurred()) - Expect(userdata).ToNot(Equal("")) + Expect(err).NotTo(HaveOccurred()) + Expect(userdata).NotTo(Equal("")) tree, parseErr := userdataTOML(userdata) - Expect(parseErr).ToNot(HaveOccurred()) + Expect(parseErr).NotTo(HaveOccurred()) Expect(tree.HasPath(clusterDNSIPPath)).To(BeTrue()) Expect(tree.GetPath(clusterDNSIPPath)).To(Equal(ng.ClusterDNS)) @@ -234,11 +234,11 @@ var _ = Describe("Bottlerocket", func() { bootstrapper := newBootstrapper(clusterConfig, ng) userdata, err := bootstrapper.UserData() - Expect(err).ToNot(HaveOccurred()) - Expect(userdata).ToNot(Equal("")) + Expect(err).NotTo(HaveOccurred()) + Expect(userdata).NotTo(Equal("")) tree, parseErr := userdataTOML(userdata) - Expect(parseErr).ToNot(HaveOccurred()) + Expect(parseErr).NotTo(HaveOccurred()) Expect(tree.HasPath(maxPodsPath)).To(BeTrue()) Expect(tree.GetPath(maxPodsPath)).To(Equal(int64(ng.MaxPodsPerNode))) @@ -247,11 +247,11 @@ var _ = Describe("Bottlerocket", func() { It("does not add MaxPodsPerNode when not set", func() { bootstrapper := newBootstrapper(clusterConfig, ng) userdata, err := bootstrapper.UserData() - Expect(err).ToNot(HaveOccurred()) - Expect(userdata).ToNot(Equal("")) + Expect(err).NotTo(HaveOccurred()) + Expect(userdata).NotTo(Equal("")) tree, parseErr := userdataTOML(userdata) - Expect(parseErr).ToNot(HaveOccurred()) + Expect(parseErr).NotTo(HaveOccurred()) Expect(tree.HasPath(maxPodsPath)).To(BeFalse()) }) diff --git a/pkg/nodebootstrap/cluster_dns_test.go b/pkg/nodebootstrap/cluster_dns_test.go index b77133bbbd..c017bef9df 100644 --- a/pkg/nodebootstrap/cluster_dns_test.go +++ b/pkg/nodebootstrap/cluster_dns_test.go @@ -21,7 +21,7 @@ var _ = DescribeTable("Cluster DNS", func(c clusterDNSEntry) { Expect(err).To(MatchError(ContainSubstring(c.expectedErr))) return } - Expect(err).ToNot(HaveOccurred()) + Expect(err).NotTo(HaveOccurred()) Expect(clusterDNS).To(Equal(c.expectedClusterDNS)) }, diff --git a/pkg/nodebootstrap/legacy/userdata_test.go b/pkg/nodebootstrap/legacy/userdata_test.go index 350b028ecf..16379d36cc 100644 --- a/pkg/nodebootstrap/legacy/userdata_test.go +++ b/pkg/nodebootstrap/legacy/userdata_test.go @@ -21,7 +21,7 @@ var _ = Describe("User data", func() { parts := strings.Split(line, " ") Expect(parts[0]).To(MatchRegexp(`[a-zA-Z][a-zA-Z0-9]*\.[a-zA-Z0-9]+`)) _, err := strconv.Atoi(parts[1]) - Expect(err).ToNot(HaveOccurred()) + Expect(err).NotTo(HaveOccurred()) } }) }) @@ -40,33 +40,33 @@ var _ = Describe("User data", func() { It("the kubelet is serialized with the correct format", func() { data, err := makeKubeletConfigYAML(clusterConfig, ng) - Expect(err).ToNot(HaveOccurred()) + Expect(err).NotTo(HaveOccurred()) kubelet := &kubeletapi.KubeletConfiguration{} errUnmarshal := yaml.UnmarshalStrict(data, kubelet) - Expect(errUnmarshal).ToNot(HaveOccurred()) + Expect(errUnmarshal).NotTo(HaveOccurred()) }) It("does not contain default kube reservations for unknown instances", func() { ng.InstanceType = "dne.small" data, err := makeKubeletConfigYAML(clusterConfig, ng) - Expect(err).ToNot(HaveOccurred()) + Expect(err).NotTo(HaveOccurred()) kubelet := kubeletapi.KubeletConfiguration{} err = yaml.UnmarshalStrict(data, &kubelet) - Expect(err).ToNot(HaveOccurred()) + Expect(err).NotTo(HaveOccurred()) Expect(kubelet.KubeReserved).To(BeNil()) }) It("contains default kube reservations", func() { ng.InstanceType = "i3.metal" data, err := makeKubeletConfigYAML(clusterConfig, ng) - Expect(err).ToNot(HaveOccurred()) + Expect(err).NotTo(HaveOccurred()) kubelet := kubeletapi.KubeletConfiguration{} err = yaml.UnmarshalStrict(data, &kubelet) - Expect(err).ToNot(HaveOccurred()) + Expect(err).NotTo(HaveOccurred()) Expect(kubelet.KubeReserved).To(Equal(map[string]string{ "ephemeral-storage": "1Gi", "cpu": "250m", @@ -85,11 +85,11 @@ var _ = Describe("User data", func() { Expect(instanceTypeExists(ng.InstancesDistribution.InstanceTypes[1])).To(Equal(true)) Expect(instanceTypeExists(ng.InstancesDistribution.InstanceTypes[2])).To(Equal(true)) data, err := makeKubeletConfigYAML(clusterConfig, ng) - Expect(err).ToNot(HaveOccurred()) + Expect(err).NotTo(HaveOccurred()) kubelet := kubeletapi.KubeletConfiguration{} err = yaml.UnmarshalStrict(data, &kubelet) - Expect(err).ToNot(HaveOccurred()) + Expect(err).NotTo(HaveOccurred()) Expect(kubelet.KubeReserved).To(Equal(map[string]string{ "ephemeral-storage": "1Gi", "cpu": "80m", @@ -108,11 +108,11 @@ var _ = Describe("User data", func() { Expect(instanceTypeExists(ng.InstancesDistribution.InstanceTypes[1])).To(Equal(false)) Expect(instanceTypeExists(ng.InstancesDistribution.InstanceTypes[2])).To(Equal(false)) data, err := makeKubeletConfigYAML(clusterConfig, ng) - Expect(err).ToNot(HaveOccurred()) + Expect(err).NotTo(HaveOccurred()) kubelet := kubeletapi.KubeletConfiguration{} err = yaml.UnmarshalStrict(data, &kubelet) - Expect(err).ToNot(HaveOccurred()) + Expect(err).NotTo(HaveOccurred()) Expect(kubelet.KubeReserved).To(Equal(map[string]string{ "ephemeral-storage": "1Gi", "cpu": "80m", @@ -133,14 +133,14 @@ var _ = Describe("User data", func() { }, } data, err := makeKubeletConfigYAML(clusterConfig, ng) - Expect(err).ToNot(HaveOccurred()) + Expect(err).NotTo(HaveOccurred()) kubelet := &kubeletapi.KubeletConfiguration{} errUnmarshal := yaml.UnmarshalStrict(data, kubelet) - Expect(errUnmarshal).ToNot(HaveOccurred()) + Expect(errUnmarshal).NotTo(HaveOccurred()) - Expect(kubelet.KubeReserved).ToNot(BeNil()) + Expect(kubelet.KubeReserved).NotTo(BeNil()) Expect(kubelet.KubeReserved["cpu"]).To(Equal("300m")) Expect(kubelet.KubeReserved["memory"]).To(Equal("300Mi")) Expect(kubelet.KubeReserved["ephemeral-storage"]).To(Equal("1Gi")) @@ -171,14 +171,14 @@ var _ = Describe("User data", func() { Expect(instanceTypeExists(ng.InstancesDistribution.InstanceTypes[1])).To(Equal(true)) Expect(instanceTypeExists(ng.InstancesDistribution.InstanceTypes[2])).To(Equal(true)) data, err := makeKubeletConfigYAML(clusterConfig, ng) - Expect(err).ToNot(HaveOccurred()) + Expect(err).NotTo(HaveOccurred()) kubelet := &kubeletapi.KubeletConfiguration{} errUnmarshal := yaml.UnmarshalStrict(data, kubelet) - Expect(errUnmarshal).ToNot(HaveOccurred()) + Expect(errUnmarshal).NotTo(HaveOccurred()) - Expect(kubelet.KubeReserved).ToNot(BeNil()) + Expect(kubelet.KubeReserved).NotTo(BeNil()) Expect(kubelet.KubeReserved["cpu"]).To(Equal("300m")) Expect(kubelet.KubeReserved["memory"]).To(Equal("300Mi")) Expect(kubelet.KubeReserved["ephemeral-storage"]).To(Equal("1Gi")) diff --git a/pkg/nodebootstrap/managed_al2_test.go b/pkg/nodebootstrap/managed_al2_test.go index 2f1819c9e7..d4f8b55490 100644 --- a/pkg/nodebootstrap/managed_al2_test.go +++ b/pkg/nodebootstrap/managed_al2_test.go @@ -24,9 +24,9 @@ var _ = DescribeTable("Managed AL2", func(e managedEntry) { bootstrapper.UserDataMimeBoundary = "//" userData, err := bootstrapper.UserData() - Expect(err).ToNot(HaveOccurred()) + Expect(err).NotTo(HaveOccurred()) decoded, err := base64.StdEncoding.DecodeString(userData) - Expect(err).ToNot(HaveOccurred()) + Expect(err).NotTo(HaveOccurred()) actual := strings.ReplaceAll(string(decoded), "\r\n", "\n") Expect(actual).To(Equal(e.expectedUserData)) }, diff --git a/pkg/nodebootstrap/managed_bottlerocket_test.go b/pkg/nodebootstrap/managed_bottlerocket_test.go index 38baca28a9..b529e964a9 100644 --- a/pkg/nodebootstrap/managed_bottlerocket_test.go +++ b/pkg/nodebootstrap/managed_bottlerocket_test.go @@ -44,9 +44,9 @@ var _ = Describe("Managed Bottlerocket", func() { return } - Expect(err).ToNot(HaveOccurred()) + Expect(err).NotTo(HaveOccurred()) actual, err := base64.StdEncoding.DecodeString(userData) - Expect(err).ToNot(HaveOccurred()) + Expect(err).NotTo(HaveOccurred()) Expect(string(actual)).To(Equal(e.expectedUserData)) }, Entry("no settings", bottlerocketEntry{ diff --git a/pkg/nodebootstrap/nodebootstrap_suite_test.go b/pkg/nodebootstrap/nodebootstrap_suite_test.go index 7fb3dc8d17..399e32b5de 100644 --- a/pkg/nodebootstrap/nodebootstrap_suite_test.go +++ b/pkg/nodebootstrap/nodebootstrap_suite_test.go @@ -24,6 +24,6 @@ func decode(userData string) *cloudconfig.CloudConfig { func newBootstrapper(clusterConfig *api.ClusterConfig, ng *api.NodeGroup) nodebootstrap.Bootstrapper { bootstrapper, err := nodebootstrap.NewBootstrapper(clusterConfig, ng) - Expect(err).ToNot(HaveOccurred()) + Expect(err).NotTo(HaveOccurred()) return bootstrapper } diff --git a/pkg/nodebootstrap/windows_test.go b/pkg/nodebootstrap/windows_test.go index d744da601b..9c688484a5 100644 --- a/pkg/nodebootstrap/windows_test.go +++ b/pkg/nodebootstrap/windows_test.go @@ -37,7 +37,7 @@ var _ = Describe("Windows", func() { bootstrapper := nodebootstrap.NewWindowsBootstrapper(clusterConfig, ng) userData, err := bootstrapper.UserData() - Expect(err).ToNot(HaveOccurred()) + Expect(err).NotTo(HaveOccurred()) Expect(decodeData(userData)).To(Equal(strings.TrimSpace(e.expectedUserData))) }, @@ -138,10 +138,10 @@ start /wait msiexec.exe /qb /i "amazon-cloudwatch-agent.msi" func decodeData(userdata string) string { decodedBytes, err := base64.StdEncoding.DecodeString(userdata) - Expect(err).ToNot(HaveOccurred()) + Expect(err).NotTo(HaveOccurred()) decodedString := string(decodedBytes) - Expect(decodedString).ToNot(Equal("")) + Expect(decodedString).NotTo(Equal("")) return decodedString } diff --git a/pkg/ssh/client/ssh_test.go b/pkg/ssh/client/ssh_test.go index bc78a8fdc2..ff2520c683 100644 --- a/pkg/ssh/client/ssh_test.go +++ b/pkg/ssh/client/ssh_test.go @@ -34,7 +34,7 @@ var _ = Describe("ssh public key", func() { keyName, err := LoadKeyFromFile("assets/id_rsa_tests1.pub", clusterName, ngName, mockEC2) - Expect(err).ToNot(HaveOccurred()) + Expect(err).NotTo(HaveOccurred()) Expect(keyName).To(Equal("eksctl-sshtestcluster-nodegroup-ng1-f5:d9:01:88:1e:fb:40:fb:e1:ca:69:fe:2e:31:03:6c")) mockEC2.AssertCalled(GinkgoT(), "ImportKeyPair", @@ -50,7 +50,7 @@ var _ = Describe("ssh public key", func() { keyName, err := LoadKeyFromFile("assets/id_rsa_tests1.pub", clusterName, ngName, mockEC2) - Expect(err).ToNot(HaveOccurred()) + Expect(err).NotTo(HaveOccurred()) Expect(keyName).To(Equal("eksctl-sshtestcluster-nodegroup-ng1-f5:d9:01:88:1e:fb:40:fb:e1:ca:69:fe:2e:31:03:6c")) mockEC2.AssertNotCalled(GinkgoT(), "ImportKeyPair", mock.Anything) }) @@ -80,7 +80,7 @@ var _ = Describe("ssh public key", func() { keyName, err := LoadKeyByContent(&key, clusterName, ngName, mockEC2) - Expect(err).ToNot(HaveOccurred()) + Expect(err).NotTo(HaveOccurred()) Expect(keyName).To(Equal("eksctl-sshtestcluster-nodegroup-ng1-f5:d9:01:88:1e:fb:40:fb:e1:ca:69:fe:2e:31:03:6c")) mockEC2.AssertCalled(GinkgoT(), "ImportKeyPair", @@ -96,7 +96,7 @@ var _ = Describe("ssh public key", func() { keyName, err := LoadKeyByContent(&key, clusterName, ngName, mockEC2) - Expect(err).ToNot(HaveOccurred()) + Expect(err).NotTo(HaveOccurred()) Expect(keyName).To(Equal("eksctl-sshtestcluster-nodegroup-ng1-f5:d9:01:88:1e:fb:40:fb:e1:ca:69:fe:2e:31:03:6c")) mockEC2.AssertNotCalled(GinkgoT(), "ImportKeyPair", mock.Anything) }) @@ -150,7 +150,7 @@ var _ = Describe("ssh public key", func() { err := CheckKeyExistsInEC2(keyName, mockEC2) - Expect(err).ToNot(HaveOccurred()) + Expect(err).NotTo(HaveOccurred()) }) It("should fail when key does not exist", func() { diff --git a/pkg/testutils/client.go b/pkg/testutils/client.go index 6a38dc04d3..753fadade5 100644 --- a/pkg/testutils/client.go +++ b/pkg/testutils/client.go @@ -29,10 +29,10 @@ func LoadSamples(manifest string) []runtime.Object { ) samplesData, err := os.ReadFile(manifest) - Expect(err).ToNot(HaveOccurred()) + Expect(err).NotTo(HaveOccurred()) samplesList, err := kubernetes.NewList(samplesData) - Expect(err).ToNot(HaveOccurred()) - Expect(samplesList).ToNot(BeNil()) + Expect(err).NotTo(HaveOccurred()) + Expect(samplesList).NotTo(BeNil()) for _, item := range samplesList.Items { kind := item.Object.GetObjectKind().GroupVersionKind().Kind diff --git a/pkg/utils/kubeconfig/kubeconfig_test.go b/pkg/utils/kubeconfig/kubeconfig_test.go index 7000eb9ac4..f84ddd8557 100644 --- a/pkg/utils/kubeconfig/kubeconfig_test.go +++ b/pkg/utils/kubeconfig/kubeconfig_test.go @@ -74,7 +74,7 @@ var _ = Describe("Kubeconfig", func() { tempDir, _ := os.MkdirTemp("", "") filename, err := kubeconfig.Write(path.Join(tempDir, "nonexistentdir", "kubeconfig"), testConfig, false) Expect(err).To(BeNil()) - Expect(filename).ToNot(BeEmpty()) + Expect(filename).NotTo(BeEmpty()) }) It("sets new Kubeconfig context", func() { diff --git a/pkg/vpc/vpc_test.go b/pkg/vpc/vpc_test.go index dd7253e099..b10010ac6e 100644 --- a/pkg/vpc/vpc_test.go +++ b/pkg/vpc/vpc_test.go @@ -709,7 +709,7 @@ var _ = Describe("VPC", func() { if e.error != nil { Expect(err).To(MatchError(e.error.Error())) } else { - Expect(err).ToNot(HaveOccurred()) + Expect(err).NotTo(HaveOccurred()) Expect(*e.cfg.VPC.Subnets).To(Equal(e.expected)) } }, @@ -923,7 +923,7 @@ var _ = Describe("VPC", func() { DescribeTable("select subnets", func(e selectSubnetsCase) { ids, err := SelectNodeGroupSubnets(e.nodegroupAZs, e.nodegroupSubnets, e.subnets, nil, "") - Expect(err).ToNot(HaveOccurred()) + Expect(err).NotTo(HaveOccurred()) Expect(ids).To(ConsistOf(e.expectIDs)) }, Entry("one subnet", selectSubnetsCase{ @@ -999,7 +999,7 @@ var _ = Describe("VPC", func() { }, }, nil) ids, err := SelectNodeGroupSubnets([]string{az}, []string{subnetID}, api.AZSubnetMappingFromMap(azMap), mockEC2, vpcID) - Expect(err).ToNot(HaveOccurred()) + Expect(err).NotTo(HaveOccurred()) Expect(ids).To(ConsistOf("id-1", "id-2", subnetID)) }) }) From 8dc14168dcadbe9d55ce37b3403db8965e554a16 Mon Sep 17 00:00:00 2001 From: Chetan Patwal Date: Mon, 8 Nov 2021 19:38:52 +0530 Subject: [PATCH 069/124] Avoid writing temp ClusterConfig file (#4397) This changelist passes the ClusterConfig file via stdin using an io.Reader, instead of writing a temp file to disk and cleaning it up later. --- integration/tests/gitops/flux_test.go | 31 +++++++++++---------------- 1 file changed, 13 insertions(+), 18 deletions(-) diff --git a/integration/tests/gitops/flux_test.go b/integration/tests/gitops/flux_test.go index dfb72ee677..fb4e8148c3 100644 --- a/integration/tests/gitops/flux_test.go +++ b/integration/tests/gitops/flux_test.go @@ -4,14 +4,13 @@ package integration_test import ( - "encoding/json" - "os" + "fmt" "testing" . "github.com/weaveworks/eksctl/integration/matchers" - "github.com/weaveworks/eksctl/integration/runner" . "github.com/weaveworks/eksctl/integration/runner" "github.com/weaveworks/eksctl/integration/tests" + clusterutils "github.com/weaveworks/eksctl/integration/utilities/cluster" "github.com/weaveworks/eksctl/integration/utilities/git" api "github.com/weaveworks/eksctl/pkg/apis/eksctl.io/v1alpha5" "github.com/weaveworks/eksctl/pkg/testutils" @@ -58,10 +57,9 @@ var _ = AfterSuite(func() { var _ = Describe("Enable GitOps", func() { var ( - branch string - cmd runner.Cmd - configFile *os.File - localRepo string + branch string + clusterConfig *api.ClusterConfig + localRepo string ) BeforeEach(func() { @@ -69,7 +67,7 @@ var _ = Describe("Enable GitOps", func() { branch = namer.RandomName() } - cfg := &api.ClusterConfig{ + clusterConfig = &api.ClusterConfig{ TypeMeta: api.ClusterConfigTypeMeta(), Metadata: &api.ClusterMeta{ Version: api.DefaultVersion, @@ -87,25 +85,22 @@ var _ = Describe("Enable GitOps", func() { }, }, } - configData, err := json.Marshal(&cfg) - Expect(err).NotTo(HaveOccurred()) - configFile, err = os.CreateTemp("", "") - Expect(err).NotTo(HaveOccurred()) - Expect(os.WriteFile(configFile.Name(), configData, 0755)).To(Succeed()) }) AfterEach(func() { - _ = git.CleanupBranchAndRepo(branch, localRepo) - Expect(os.RemoveAll(configFile.Name())).To(Succeed()) + if err := git.CleanupBranchAndRepo(branch, localRepo); err != nil { + fmt.Fprintf(GinkgoWriter, "error cleaning up branch and repo: %v", err) + } }) Context("enable flux", func() { It("should deploy Flux v2 components to the cluster", func() { AssertFluxPodsAbsentInKubernetes(params.KubeconfigPath, "flux-system") - cmd = params.EksctlEnableCmd.WithArgs( + cmd := params.EksctlEnableCmd.WithArgs( "flux", - "--config-file", configFile.Name(), - ) + "--config-file", "-", + ).WithStdin(clusterutils.Reader(clusterConfig)) + Expect(cmd).To(RunSuccessfully()) AssertFlux2PodsPresentInKubernetes(params.KubeconfigPath) }) From 0ff1fffb6758b165d23c8b0a886a085b51ac891c Mon Sep 17 00:00:00 2001 From: Yuuki Ebihara Date: Tue, 9 Nov 2021 22:04:24 +0900 Subject: [PATCH 070/124] Bump GoReleaser to 0.184.0 (#4422) * bump goreleaser to 0.184.0 * bump goreleaser to 0.184.0 * bump goreleaser to 0.184.0 * bump goreleaser to 0.184.0 Co-authored-by: Jake Klein --- build/docker/build_image_manifest | 2 +- go.mod | 7 +++++-- go.sum | 9 +++++++++ 3 files changed, 15 insertions(+), 3 deletions(-) diff --git a/build/docker/build_image_manifest b/build/docker/build_image_manifest index 83999a3391..e3bb37641c 100644 --- a/build/docker/build_image_manifest +++ b/build/docker/build_image_manifest @@ -2,7 +2,7 @@ "github.com/cloudflare/cfssl v1.6.1" "github.com/cloudflare/cfssl v1.6.1" "github.com/golangci/golangci-lint v1.42.0" -"github.com/goreleaser/goreleaser v0.182.1" +"github.com/goreleaser/goreleaser v0.184.0" "github.com/onsi/ginkgo v1.16.4" "github.com/vektra/mockery v1.1.2" "github.com/github-release/github-release v0.10.0" diff --git a/go.mod b/go.mod index 8bcbf286e0..c23d76c2ed 100644 --- a/go.mod +++ b/go.mod @@ -132,7 +132,7 @@ require ( github.com/google/go-cmp v0.5.6 // indirect github.com/google/go-github/v32 v32.1.0 // indirect github.com/google/go-github/v35 v35.3.0 // indirect - github.com/google/go-querystring v1.0.0 // indirect + github.com/google/go-querystring v1.1.0 // indirect github.com/google/gofuzz v1.2.0 // indirect github.com/google/rpmpack v0.0.0-20210410105602-e20c988a6f5a // indirect github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 // indirect @@ -144,7 +144,7 @@ require ( github.com/gordonklaus/ineffassign v0.0.0-20210225214923-2e10b2664254 // indirect github.com/goreleaser/chglog v0.1.2 // indirect github.com/goreleaser/fileglob v1.2.0 // indirect - github.com/goreleaser/goreleaser v0.182.1 + github.com/goreleaser/goreleaser v0.184.0 github.com/goreleaser/nfpm/v2 v2.6.0 // indirect github.com/gorilla/websocket v1.4.2 // indirect github.com/gostaticanalysis/analysisutil v0.4.1 // indirect @@ -368,6 +368,7 @@ require ( github.com/DisgoOrg/disgohook v1.4.3 // indirect github.com/DisgoOrg/log v1.1.0 // indirect github.com/DisgoOrg/restclient v1.2.7 // indirect + github.com/alecthomas/jsonschema v0.0.0-20211022214203-8b29eab41725 // indirect github.com/atc0005/go-teams-notify/v2 v2.6.0 // indirect github.com/aws/aws-sdk-go-v2 v1.9.0 // indirect github.com/aws/aws-sdk-go-v2/config v1.7.0 // indirect @@ -389,6 +390,8 @@ require ( github.com/fullstorydev/grpcurl v1.8.1 // indirect github.com/go-telegram-bot-api/telegram-bot-api v4.6.4+incompatible // indirect github.com/golang-jwt/jwt/v4 v4.0.0 // indirect + github.com/google/go-github/v39 v39.2.0 // indirect + github.com/iancoleman/orderedmap v0.0.0-20190318233801-ac98e3ecb4b0 // indirect github.com/jhump/protoreflect v1.8.2 // indirect github.com/rivo/uniseg v0.2.0 // indirect github.com/slack-go/slack v0.9.4 // indirect diff --git a/go.sum b/go.sum index 6d46eca2e6..f75ef42798 100644 --- a/go.sum +++ b/go.sum @@ -255,6 +255,8 @@ github.com/akavel/rsrc v0.8.0/go.mod h1:uLoCtb9J+EyAqh+26kdrTgmzRBFPGOolLWKpdxkK github.com/alcortesm/tgz v0.0.0-20161220082320-9c5fe88206d7 h1:uSoVVbwJiQipAclBbw+8quDsfcvFjOpI5iCf4p/cqCs= github.com/alcortesm/tgz v0.0.0-20161220082320-9c5fe88206d7/go.mod h1:6zEj6s6u/ghQa61ZWa/C2Aw3RkjiTBOix7dkqa1VLIs= github.com/alecthomas/jsonschema v0.0.0-20210526225647-edb03dcab7bc/go.mod h1:/n6+1/DWPltRLWL/VKyUxg6tzsl5kHUCcraimt4vr60= +github.com/alecthomas/jsonschema v0.0.0-20211022214203-8b29eab41725 h1:NjwIgLQlD46o79bheVG4SCdRnnOz4XtgUN1WABX5DLA= +github.com/alecthomas/jsonschema v0.0.0-20211022214203-8b29eab41725/go.mod h1:/n6+1/DWPltRLWL/VKyUxg6tzsl5kHUCcraimt4vr60= github.com/alecthomas/kingpin v2.2.6+incompatible/go.mod h1:59OFYbFVLKQKq+mqrL6Rw5bR0c3ACQaawgXx0QYndlE= github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= @@ -908,9 +910,13 @@ github.com/google/go-github/v32 v32.1.0 h1:GWkQOdXqviCPx7Q7Fj+KyPoGm4SwHRh8rheoP github.com/google/go-github/v32 v32.1.0/go.mod h1:rIEpZD9CTDQwDK9GDrtMTycQNA4JU3qBsCizh3q2WCI= github.com/google/go-github/v35 v35.3.0 h1:fU+WBzuukn0VssbayTT+Zo3/ESKX9JYWjbZTLOTEyho= github.com/google/go-github/v35 v35.3.0/go.mod h1:yWB7uCcVWaUbUP74Aq3whuMySRMatyRmq5U9FTNlbio= +github.com/google/go-github/v39 v39.2.0 h1:rNNM311XtPOz5rDdsJXAp2o8F67X9FnROXTvto3aSnQ= +github.com/google/go-github/v39 v39.2.0/go.mod h1:C1s8C5aCC9L+JXIYpJM5GYytdX52vC1bLvHEF1IhBrE= github.com/google/go-licenses v0.0.0-20210329231322-ce1d9163b77d/go.mod h1:+TYOmkVoJOpwnS0wfdsJCV9CoD5nJYsHoFk/0CrTK4M= github.com/google/go-querystring v1.0.0 h1:Xkwi/a1rcvNg1PPYe5vI8GbeBY/jrVuDX5ASuANWTrk= github.com/google/go-querystring v1.0.0/go.mod h1:odCYkC5MyYFN7vkCjXpyrEuKhc/BUO6wN/zVPAxq5ck= +github.com/google/go-querystring v1.1.0 h1:AnCroh3fv4ZBgVIf1Iwtovgjaw/GiKJo8M8yD/fhyJ8= +github.com/google/go-querystring v1.1.0/go.mod h1:Kcdr2DB4koayq7X8pmAG4sNG59So17icRSOU623lUBU= github.com/google/go-replayers/grpcreplay v0.1.0/go.mod h1:8Ig2Idjpr6gifRd6pNVggX6TC1Zw6Jx74AKp7QNH2QE= github.com/google/go-replayers/grpcreplay v1.1.0 h1:S5+I3zYyZ+GQz68OfbURDdt/+cSMqCK1wrvNx7WBzTE= github.com/google/go-replayers/grpcreplay v1.1.0/go.mod h1:qzAvJ8/wi57zq7gWqaE6AwLM6miiXUQwP1S+I9icmhk= @@ -996,6 +1002,8 @@ github.com/goreleaser/fileglob v1.2.0/go.mod h1:rFyb2pXaK3YdnYnSjn6lifw0h2Q6s8Of github.com/goreleaser/goreleaser v0.134.0/go.mod h1:ZT6Y2rSYa6NxQzIsdfWWNWAlYGXGbreo66NmE+3X3WQ= github.com/goreleaser/goreleaser v0.182.1 h1:cKRlHfbMxejiyMCNACsl82slFXEW+k9RggADv6/Akqg= github.com/goreleaser/goreleaser v0.182.1/go.mod h1:DDAKfIsyz8N8HTGYxGT9OvLW2XMLaS5Gr8/O3fSasKw= +github.com/goreleaser/goreleaser v0.184.0 h1:j9tP9sKIVm67TjCEdbinlRxw/Jc06oALg9gEzBt+14o= +github.com/goreleaser/goreleaser v0.184.0/go.mod h1:OnFh7NZGcdGqyznqKLHS+O/CRTTYMGjluCWqnfSm+OA= github.com/goreleaser/nfpm v1.2.1 h1:AEnu9XVmupRDTR930Z2rAs31Mj6sLIPxFcR9ESYvgDA= github.com/goreleaser/nfpm v1.2.1/go.mod h1:TtWrABZozuLOttX2uDlYyECfQX7x5XYkVxhjYcR6G9w= github.com/goreleaser/nfpm/v2 v2.6.0 h1:bwDU9o4/CVTSpqASJA7+r+rkqpTGamQKYHMRH3wDlRE= @@ -1125,6 +1133,7 @@ github.com/huandu/xstrings v1.3.1/go.mod h1:y5/lhBue+AyNmUVz9RLU9xbLR0o4KIIExikq github.com/huandu/xstrings v1.3.2 h1:L18LIDzqlW6xN2rEkpdV8+oL/IXWJ1APd+vsdYy4Wdw= github.com/huandu/xstrings v1.3.2/go.mod h1:y5/lhBue+AyNmUVz9RLU9xbLR0o4KIIExikq4ovT0aE= github.com/hudl/fargo v1.3.0/go.mod h1:y3CKSmjA+wD2gak7sUSXTAoopbhU08POFhmITJgmKTg= +github.com/iancoleman/orderedmap v0.0.0-20190318233801-ac98e3ecb4b0 h1:i462o439ZjprVSFSZLZxcsoAe592sZB1rci2Z8j4wdk= github.com/iancoleman/orderedmap v0.0.0-20190318233801-ac98e3ecb4b0/go.mod h1:N0Wam8K1arqPXNWjMo21EXnBPOPp36vB07FNRdD2geA= github.com/iancoleman/strcase v0.0.0-20180726023541-3605ed457bf7/go.mod h1:SK73tn/9oHe+/Y0h39VT4UCxmurVJkR5NA7kMEAOgSE= github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= From 5fba7d68c17764a8d1596ded48895739165508dd Mon Sep 17 00:00:00 2001 From: Jake Klein Date: Tue, 9 Nov 2021 14:40:06 +0000 Subject: [PATCH 071/124] update build image (#4435) --- .github/workflows/ci.yaml | 2 +- .github/workflows/release-candidate.yaml | 2 +- .github/workflows/release.yaml | 2 +- .github/workflows/tag-release.yaml | 2 +- .github/workflows/update-generated.yaml | 2 +- Dockerfile | 2 +- build/docker/image_tag | 2 +- 7 files changed, 7 insertions(+), 7 deletions(-) diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index c47f415353..cc9cc4e23e 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -10,7 +10,7 @@ jobs: lint: name: Lint runs-on: ubuntu-latest - container: weaveworks/eksctl-build:83999a3391d78ed18a2e6093328d1122c927956f + container: weaveworks/eksctl-build:e3bb37641cdc03bcb95e88727d5d4ee2654ba888 steps: - name: Checkout uses: actions/checkout@v2 diff --git a/.github/workflows/release-candidate.yaml b/.github/workflows/release-candidate.yaml index 762e2fc4a9..c599b7bee5 100644 --- a/.github/workflows/release-candidate.yaml +++ b/.github/workflows/release-candidate.yaml @@ -7,7 +7,7 @@ jobs: rc: name: Trigger release candidate build runs-on: ubuntu-latest - container: weaveworks/eksctl-build:83999a3391d78ed18a2e6093328d1122c927956f + container: weaveworks/eksctl-build:e3bb37641cdc03bcb95e88727d5d4ee2654ba888 steps: - name: Checkout uses: actions/checkout@v2 diff --git a/.github/workflows/release.yaml b/.github/workflows/release.yaml index b334ecf2eb..7165a64e6b 100644 --- a/.github/workflows/release.yaml +++ b/.github/workflows/release.yaml @@ -7,7 +7,7 @@ jobs: rc: name: Trigger release build runs-on: ubuntu-latest - container: weaveworks/eksctl-build:83999a3391d78ed18a2e6093328d1122c927956f + container: weaveworks/eksctl-build:e3bb37641cdc03bcb95e88727d5d4ee2654ba888 steps: - name: Checkout uses: actions/checkout@v2 diff --git a/.github/workflows/tag-release.yaml b/.github/workflows/tag-release.yaml index 5f77d3ed0b..af33c2ad73 100644 --- a/.github/workflows/tag-release.yaml +++ b/.github/workflows/tag-release.yaml @@ -18,7 +18,7 @@ jobs: name: Tag release from version environment: release runs-on: ubuntu-latest - container: weaveworks/eksctl-build:83999a3391d78ed18a2e6093328d1122c927956f + container: weaveworks/eksctl-build:e3bb37641cdc03bcb95e88727d5d4ee2654ba888 steps: - name: Checkout uses: actions/checkout@v2 diff --git a/.github/workflows/update-generated.yaml b/.github/workflows/update-generated.yaml index fa9bbaaacb..cc4608791e 100644 --- a/.github/workflows/update-generated.yaml +++ b/.github/workflows/update-generated.yaml @@ -55,7 +55,7 @@ jobs: update_aws_node: name: Update aws-node and open PR runs-on: ubuntu-latest - container: weaveworks/eksctl-build:83999a3391d78ed18a2e6093328d1122c927956f + container: weaveworks/eksctl-build:e3bb37641cdc03bcb95e88727d5d4ee2654ba888 env: UPDATE_BRANCH: update-aws-node GOPRIVATE: "" diff --git a/Dockerfile b/Dockerfile index 60427db242..496e7d5056 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,4 +1,4 @@ -ARG BUILD_IMAGE=/weaveworks/eksctl-build:83999a3391d78ed18a2e6093328d1122c927956f +ARG BUILD_IMAGE=/weaveworks/eksctl-build:e3bb37641cdc03bcb95e88727d5d4ee2654ba888 FROM $BUILD_IMAGE as build WORKDIR /src diff --git a/build/docker/image_tag b/build/docker/image_tag index 387232386a..33ab05df56 100644 --- a/build/docker/image_tag +++ b/build/docker/image_tag @@ -1 +1 @@ -83999a3391d78ed18a2e6093328d1122c927956f +e3bb37641cdc03bcb95e88727d5d4ee2654ba888 From bcfd397dbeee3ef790b935834e3d3202eb8d76cb Mon Sep 17 00:00:00 2001 From: cpu1 Date: Tue, 9 Nov 2021 19:04:21 +0530 Subject: [PATCH 072/124] Set volume size in data volume for Bottlerocket The volume size was being set for the OS volume, instead of the data volume for Bottlerocket nodegroups. --- pkg/ami/api.go | 14 +- pkg/apis/eksctl.io/v1alpha5/defaults.go | 11 ++ pkg/cfn/builder/block_device_mapping.go | 2 +- .../builder/managed_launch_template_test.go | 12 ++ pkg/cfn/builder/nodegroup_test.go | 3 +- .../launch_template/bottlerocket_volume.json | 178 ++++++++++++++++++ 6 files changed, 206 insertions(+), 14 deletions(-) create mode 100644 pkg/cfn/builder/testdata/launch_template/bottlerocket_volume.json diff --git a/pkg/ami/api.go b/pkg/ami/api.go index 365eb055f2..38c9cece51 100644 --- a/pkg/ami/api.go +++ b/pkg/ami/api.go @@ -21,13 +21,6 @@ const ( ImageClassARM ) -const ( - // used by kubelet - bottlerocketDataDisk = "/dev/xvdb" - // used by OS - bottlerocketOSDisk = "/dev/xvda" -) - // ImageClasses is a list of image class names var ImageClasses = []string{ "ImageClassGeneral", @@ -59,12 +52,9 @@ func Use(ec2api ec2iface.EC2API, ng *api.NodeGroupBase) error { return fmt.Errorf("%q is an instance-store AMI and EBS block device mappings are not supported for instance-store AMIs", ng.AMI) case "ebs": - if !api.IsSetAndNonEmptyString(ng.VolumeName) { + if ng.AMIFamily != api.NodeImageFamilyBottlerocket && !api.IsSetAndNonEmptyString(ng.VolumeName) { + // Volume name is preset for Bottlerocket. ng.VolumeName = image.RootDeviceName - if ng.AMIFamily == api.NodeImageFamilyBottlerocket { - ng.VolumeName = aws.String(bottlerocketDataDisk) - ng.AdditionalEncryptedVolume = bottlerocketOSDisk - } } rootDeviceMapping, err := findRootDeviceMapping(image) if err != nil { diff --git a/pkg/apis/eksctl.io/v1alpha5/defaults.go b/pkg/apis/eksctl.io/v1alpha5/defaults.go index 1bd25fd46b..9978eadf84 100644 --- a/pkg/apis/eksctl.io/v1alpha5/defaults.go +++ b/pkg/apis/eksctl.io/v1alpha5/defaults.go @@ -15,6 +15,13 @@ const ( IAMPolicyAmazonEKSCNIPolicy = "AmazonEKS_CNI_Policy" ) +const ( + // Data volume, used by kubelet + bottlerocketDataDisk = "/dev/xvdb" + // OS volume + bottlerocketOSDisk = "/dev/xvda" +) + var ( AWSNodeMeta = ClusterIAMMeta{ Name: "aws-node", @@ -189,6 +196,10 @@ func setVolumeDefaults(ng *NodeGroupBase, template *LaunchTemplate) { if *ng.VolumeType == NodeVolumeTypeIO1 && ng.VolumeIOPS == nil { ng.VolumeIOPS = aws.Int(DefaultNodeVolumeIO1IOPS) } + if ng.AMIFamily == NodeImageFamilyBottlerocket && !IsSetAndNonEmptyString(ng.VolumeName) { + ng.AdditionalEncryptedVolume = bottlerocketOSDisk + ng.VolumeName = aws.String(bottlerocketDataDisk) + } } func setContainerRuntimeDefault(ng *NodeGroup) { diff --git a/pkg/cfn/builder/block_device_mapping.go b/pkg/cfn/builder/block_device_mapping.go index 1854f150dd..cd4de3e45e 100644 --- a/pkg/cfn/builder/block_device_mapping.go +++ b/pkg/cfn/builder/block_device_mapping.go @@ -43,7 +43,7 @@ func makeBlockDeviceMappings(ng *api.NodeGroupBase) []gfnec2.LaunchTemplate_Bloc mappings := []gfnec2.LaunchTemplate_BlockDeviceMapping{mapping} - if ng.AdditionalEncryptedVolume != "" { + if api.IsEnabled(ng.VolumeEncrypted) && ng.AdditionalEncryptedVolume != "" { mappings = append(mappings, gfnec2.LaunchTemplate_BlockDeviceMapping{ DeviceName: gfnt.NewString(ng.AdditionalEncryptedVolume), Ebs: &gfnec2.LaunchTemplate_Ebs{ diff --git a/pkg/cfn/builder/managed_launch_template_test.go b/pkg/cfn/builder/managed_launch_template_test.go index ca69084b35..7a7e6096b1 100644 --- a/pkg/cfn/builder/managed_launch_template_test.go +++ b/pkg/cfn/builder/managed_launch_template_test.go @@ -269,6 +269,18 @@ API_SERVER_URL=https://test.com }), resourcesFilename: "lt_instance_types.json", }), + + Entry("Bottlerocket with volumeSize set", &mngCase{ + ng: &api.ManagedNodeGroup{ + NodeGroupBase: &api.NodeGroupBase{ + Name: "bottlerocket-volume", + AMIFamily: api.NodeImageFamilyBottlerocket, + InstanceType: "m5.xlarge", + VolumeSize: aws.Int(142), + }, + }, + resourcesFilename: "bottlerocket_volume.json", + }), ) }) diff --git a/pkg/cfn/builder/nodegroup_test.go b/pkg/cfn/builder/nodegroup_test.go index 0d5d564c38..da8e3c2d63 100644 --- a/pkg/cfn/builder/nodegroup_test.go +++ b/pkg/cfn/builder/nodegroup_test.go @@ -994,13 +994,14 @@ var _ = Describe("Unmanaged NodeGroup Template Builder", func() { Context("ng.AdditionalEncryptedVolume is set", func() { BeforeEach(func() { ng.AdditionalEncryptedVolume = "/foo/bar" + ng.VolumeEncrypted = aws.Bool(true) }) It("the volume is added to the launch template block device mappings", func() { Expect(ngTemplate.Resources["NodeGroupLaunchTemplate"].Properties.LaunchTemplateData.BlockDeviceMappings).To(HaveLen(2)) mapping := ngTemplate.Resources["NodeGroupLaunchTemplate"].Properties.LaunchTemplateData.BlockDeviceMappings[1] Expect(mapping.DeviceName).To(Equal("/foo/bar")) - Expect(mapping.Ebs["Encrypted"]).To(Equal(false)) + Expect(mapping.Ebs["Encrypted"]).To(Equal(true)) }) }) }) diff --git a/pkg/cfn/builder/testdata/launch_template/bottlerocket_volume.json b/pkg/cfn/builder/testdata/launch_template/bottlerocket_volume.json new file mode 100644 index 0000000000..3424088669 --- /dev/null +++ b/pkg/cfn/builder/testdata/launch_template/bottlerocket_volume.json @@ -0,0 +1,178 @@ +{ + "LaunchTemplate": { + "Type": "AWS::EC2::LaunchTemplate", + "Properties": { + "LaunchTemplateData": { + "BlockDeviceMappings": [ + { + "DeviceName": "/dev/xvdb", + "Ebs": { + "Iops": 3000, + "Throughput": 125, + "VolumeSize": 142, + "VolumeType": "gp3" + } + } + ], + "MetadataOptions": { + "HttpPutResponseHopLimit": 2, + "HttpTokens": "optional" + }, + "SecurityGroupIds": [ + { + "Fn::ImportValue": "eksctl-lt::ClusterSecurityGroupId" + } + ], + "TagSpecifications": [ + { + "ResourceType": "instance", + "Tags": [ + { + "Key": "Name", + "Value": "lt-bottlerocket-volume-Node" + }, + { + "Key": "alpha.eksctl.io/nodegroup-name", + "Value": "bottlerocket-volume" + }, + { + "Key": "alpha.eksctl.io/nodegroup-type", + "Value": "managed" + } + ] + }, + { + "ResourceType": "volume", + "Tags": [ + { + "Key": "Name", + "Value": "lt-bottlerocket-volume-Node" + }, + { + "Key": "alpha.eksctl.io/nodegroup-name", + "Value": "bottlerocket-volume" + }, + { + "Key": "alpha.eksctl.io/nodegroup-type", + "Value": "managed" + } + ] + }, + { + "ResourceType": "network-interface", + "Tags": [ + { + "Key": "Name", + "Value": "lt-bottlerocket-volume-Node" + }, + { + "Key": "alpha.eksctl.io/nodegroup-name", + "Value": "bottlerocket-volume" + }, + { + "Key": "alpha.eksctl.io/nodegroup-type", + "Value": "managed" + } + ] + } + ] + }, + "LaunchTemplateName": { + "Fn::Sub": "${AWS::StackName}" + } + } + }, + "ManagedNodeGroup": { + "Type": "AWS::EKS::Nodegroup", + "Properties": { + "AmiType": "BOTTLEROCKET_x86_64", + "ClusterName": "lt", + "Labels": { + "alpha.eksctl.io/cluster-name": "lt", + "alpha.eksctl.io/nodegroup-name": "bottlerocket-volume" + }, + "InstanceTypes": ["m5.xlarge"], + "NodeRole": { + "Fn::GetAtt": [ + "NodeInstanceRole", + "Arn" + ] + }, + "NodegroupName": "bottlerocket-volume", + "ScalingConfig": { + "DesiredSize": 2, + "MaxSize": 2, + "MinSize": 2 + }, + "Subnets": { + "Fn::Split": [ + ",", + { + "Fn::ImportValue": "eksctl-lt::SubnetsPublic" + } + ] + }, + "Tags": { + "alpha.eksctl.io/nodegroup-name": "bottlerocket-volume", + "alpha.eksctl.io/nodegroup-type": "managed" + }, + "LaunchTemplate": { + "Id": { + "Ref": "LaunchTemplate" + } + } + } + }, + "NodeInstanceRole": { + "Type": "AWS::IAM::Role", + "Properties": { + "AssumeRolePolicyDocument": { + "Statement": [ + { + "Action": [ + "sts:AssumeRole" + ], + "Effect": "Allow", + "Principal": { + "Service": [ + { + "Fn::FindInMap": [ + "ServicePrincipalPartitionMap", + { + "Ref": "AWS::Partition" + }, + "EC2" + ] + } + ] + } + } + ], + "Version": "2012-10-17" + }, + "ManagedPolicyArns": [ + { + "Fn::Sub": "arn:${AWS::Partition}:iam::aws:policy/AmazonEC2ContainerRegistryReadOnly" + }, + { + "Fn::Sub": "arn:${AWS::Partition}:iam::aws:policy/AmazonEKSWorkerNodePolicy" + }, + { + "Fn::Sub": "arn:${AWS::Partition}:iam::aws:policy/AmazonEKS_CNI_Policy" + }, + { + "Fn::Sub": "arn:${AWS::Partition}:iam::aws:policy/AmazonSSMManagedInstanceCore" + } + ], + "Path": "/", + "Tags": [ + { + "Key": "Name", + "Value": { + "Fn::Sub": "${AWS::StackName}/NodeInstanceRole" + } + } + ] + } + } +} From 4dcb03375e9869dc7e63d12eda755c7a9cfc656b Mon Sep 17 00:00:00 2001 From: cpu1 Date: Tue, 9 Nov 2021 19:39:12 +0530 Subject: [PATCH 073/124] Add test for standard Bottlerocket nodegroup --- .../builder/managed_launch_template_test.go | 12 ++ .../launch_template/bottlerocket.json | 178 ++++++++++++++++++ 2 files changed, 190 insertions(+) create mode 100644 pkg/cfn/builder/testdata/launch_template/bottlerocket.json diff --git a/pkg/cfn/builder/managed_launch_template_test.go b/pkg/cfn/builder/managed_launch_template_test.go index 7a7e6096b1..04f27621ba 100644 --- a/pkg/cfn/builder/managed_launch_template_test.go +++ b/pkg/cfn/builder/managed_launch_template_test.go @@ -9,6 +9,7 @@ import ( "github.com/aws/aws-sdk-go/aws" "github.com/aws/aws-sdk-go/service/ec2" + . "github.com/benjamintf1/unmarshalledmatchers" . "github.com/onsi/ginkgo" . "github.com/onsi/ginkgo/extensions/table" @@ -270,6 +271,17 @@ API_SERVER_URL=https://test.com resourcesFilename: "lt_instance_types.json", }), + Entry("Bottlerocket AMI Family with defaults", &mngCase{ + ng: &api.ManagedNodeGroup{ + NodeGroupBase: &api.NodeGroupBase{ + Name: "bottlerocket", + AMIFamily: api.NodeImageFamilyBottlerocket, + InstanceType: "m5.xlarge", + }, + }, + resourcesFilename: "bottlerocket.json", + }), + Entry("Bottlerocket with volumeSize set", &mngCase{ ng: &api.ManagedNodeGroup{ NodeGroupBase: &api.NodeGroupBase{ diff --git a/pkg/cfn/builder/testdata/launch_template/bottlerocket.json b/pkg/cfn/builder/testdata/launch_template/bottlerocket.json new file mode 100644 index 0000000000..a2be309f83 --- /dev/null +++ b/pkg/cfn/builder/testdata/launch_template/bottlerocket.json @@ -0,0 +1,178 @@ +{ + "LaunchTemplate": { + "Type": "AWS::EC2::LaunchTemplate", + "Properties": { + "LaunchTemplateData": { + "BlockDeviceMappings": [ + { + "DeviceName": "/dev/xvdb", + "Ebs": { + "Iops": 3000, + "Throughput": 125, + "VolumeSize": 80, + "VolumeType": "gp3" + } + } + ], + "MetadataOptions": { + "HttpPutResponseHopLimit": 2, + "HttpTokens": "optional" + }, + "SecurityGroupIds": [ + { + "Fn::ImportValue": "eksctl-lt::ClusterSecurityGroupId" + } + ], + "TagSpecifications": [ + { + "ResourceType": "instance", + "Tags": [ + { + "Key": "Name", + "Value": "lt-bottlerocket-Node" + }, + { + "Key": "alpha.eksctl.io/nodegroup-name", + "Value": "bottlerocket" + }, + { + "Key": "alpha.eksctl.io/nodegroup-type", + "Value": "managed" + } + ] + }, + { + "ResourceType": "volume", + "Tags": [ + { + "Key": "Name", + "Value": "lt-bottlerocket-Node" + }, + { + "Key": "alpha.eksctl.io/nodegroup-name", + "Value": "bottlerocket" + }, + { + "Key": "alpha.eksctl.io/nodegroup-type", + "Value": "managed" + } + ] + }, + { + "ResourceType": "network-interface", + "Tags": [ + { + "Key": "Name", + "Value": "lt-bottlerocket-Node" + }, + { + "Key": "alpha.eksctl.io/nodegroup-name", + "Value": "bottlerocket" + }, + { + "Key": "alpha.eksctl.io/nodegroup-type", + "Value": "managed" + } + ] + } + ] + }, + "LaunchTemplateName": { + "Fn::Sub": "${AWS::StackName}" + } + } + }, + "ManagedNodeGroup": { + "Type": "AWS::EKS::Nodegroup", + "Properties": { + "AmiType": "BOTTLEROCKET_x86_64", + "ClusterName": "lt", + "Labels": { + "alpha.eksctl.io/cluster-name": "lt", + "alpha.eksctl.io/nodegroup-name": "bottlerocket" + }, + "InstanceTypes": ["m5.xlarge"], + "NodeRole": { + "Fn::GetAtt": [ + "NodeInstanceRole", + "Arn" + ] + }, + "NodegroupName": "bottlerocket", + "ScalingConfig": { + "DesiredSize": 2, + "MaxSize": 2, + "MinSize": 2 + }, + "Subnets": { + "Fn::Split": [ + ",", + { + "Fn::ImportValue": "eksctl-lt::SubnetsPublic" + } + ] + }, + "Tags": { + "alpha.eksctl.io/nodegroup-name": "bottlerocket", + "alpha.eksctl.io/nodegroup-type": "managed" + }, + "LaunchTemplate": { + "Id": { + "Ref": "LaunchTemplate" + } + } + } + }, + "NodeInstanceRole": { + "Type": "AWS::IAM::Role", + "Properties": { + "AssumeRolePolicyDocument": { + "Statement": [ + { + "Action": [ + "sts:AssumeRole" + ], + "Effect": "Allow", + "Principal": { + "Service": [ + { + "Fn::FindInMap": [ + "ServicePrincipalPartitionMap", + { + "Ref": "AWS::Partition" + }, + "EC2" + ] + } + ] + } + } + ], + "Version": "2012-10-17" + }, + "ManagedPolicyArns": [ + { + "Fn::Sub": "arn:${AWS::Partition}:iam::aws:policy/AmazonEC2ContainerRegistryReadOnly" + }, + { + "Fn::Sub": "arn:${AWS::Partition}:iam::aws:policy/AmazonEKSWorkerNodePolicy" + }, + { + "Fn::Sub": "arn:${AWS::Partition}:iam::aws:policy/AmazonEKS_CNI_Policy" + }, + { + "Fn::Sub": "arn:${AWS::Partition}:iam::aws:policy/AmazonSSMManagedInstanceCore" + } + ], + "Path": "/", + "Tags": [ + { + "Key": "Name", + "Value": { + "Fn::Sub": "${AWS::StackName}/NodeInstanceRole" + } + } + ] + } + } +} From 1155bc549ba496ab21fbaf62fe04276bfc3cfc3c Mon Sep 17 00:00:00 2001 From: cpu1 Date: Tue, 9 Nov 2021 20:16:23 +0530 Subject: [PATCH 074/124] Fix unit tests for ami.Use --- pkg/ami/ami_test.go | 38 ++++++++++++++++++++++---------------- 1 file changed, 22 insertions(+), 16 deletions(-) diff --git a/pkg/ami/ami_test.go b/pkg/ami/ami_test.go index 2bbd3e2173..ffd68ef562 100644 --- a/pkg/ami/ami_test.go +++ b/pkg/ami/ami_test.go @@ -17,11 +17,12 @@ func TestUseAMI(t *testing.T) { amiTests := []struct { blockDeviceMappings []*ec2.BlockDeviceMapping rootDeviceName string - description string - volumeName string amiFamily string + volumeName string + description string - encrypted bool + expectedVolumeName string + expectedEncrypted bool }{ { description: "Root device mapping not at index 0 (Windows AMIs in some regions)", @@ -43,8 +44,8 @@ func TestUseAMI(t *testing.T) { }, }, - encrypted: true, - volumeName: "/dev/sda1", + expectedEncrypted: true, + expectedVolumeName: "/dev/sda1", }, { description: "Only one device mapping (AL2 AMIs)", @@ -58,8 +59,8 @@ func TestUseAMI(t *testing.T) { }, }, - encrypted: true, - volumeName: "/dev/sda1", + expectedEncrypted: true, + expectedVolumeName: "/dev/sda1", }, { description: "Different root device name", @@ -81,13 +82,14 @@ func TestUseAMI(t *testing.T) { }, }, - encrypted: false, - volumeName: "/dev/xvda", + expectedEncrypted: false, + expectedVolumeName: "/dev/xvda", }, { - description: "uses /dev/xvdb disk for bottlerocket images", + description: "volumeName for Bottlerocket is not modified", rootDeviceName: "/dev/xvda", amiFamily: api.NodeImageFamilyBottlerocket, + volumeName: "/dev/xvdb", blockDeviceMappings: []*ec2.BlockDeviceMapping{ { DeviceName: aws.String("/dev/xvda"), @@ -97,8 +99,8 @@ func TestUseAMI(t *testing.T) { }, }, - encrypted: false, - volumeName: "/dev/xvdb", + expectedEncrypted: false, + expectedVolumeName: "/dev/xvdb", }, } @@ -111,18 +113,22 @@ func TestUseAMI(t *testing.T) { AMIFamily: tt.amiFamily, }, } + if tt.volumeName != "" { + ng.VolumeName = aws.String(tt.volumeName) + } + err := ami.Use(mockProvider.MockEC2(), ng.NodeGroupBase) if err != nil { t.Errorf("unexpected error: %v", err) } - if *ng.VolumeEncrypted != tt.encrypted { - t.Errorf("expected VolumeEncrypted to be %v", tt.encrypted) + if *ng.VolumeEncrypted != tt.expectedEncrypted { + t.Errorf("expected VolumeEncrypted to be %v", tt.expectedEncrypted) } - if *ng.VolumeName != tt.volumeName { - t.Errorf("expected VolumeName to be %v", tt.volumeName) + if *ng.VolumeName != tt.expectedVolumeName { + t.Errorf("expected VolumeName to be %v", tt.expectedVolumeName) } }) } From a14740c550864a467b9dfa4279cfb2646d16e8c5 Mon Sep 17 00:00:00 2001 From: cpu1 Date: Wed, 10 Nov 2021 17:28:00 +0530 Subject: [PATCH 075/124] Unpend and fix Windows integration tests The workload being deployed is not compatible with WindowsServer20H2CoreContainer and that was preventing the pod from starting. --- integration/tests/windows/windows_test.go | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/integration/tests/windows/windows_test.go b/integration/tests/windows/windows_test.go index 75a5bdb7c7..ba1f95fd56 100644 --- a/integration/tests/windows/windows_test.go +++ b/integration/tests/windows/windows_test.go @@ -52,12 +52,6 @@ var _ = Describe("(Integration) [Windows Nodegroups]", func() { AMIFamily: api.NodeImageFamilyWindowsServer2019FullContainer, }, }, - { - NodeGroupBase: &api.NodeGroupBase{ - Name: "windows20h2", - AMIFamily: api.NodeImageFamilyWindowsServer20H2CoreContainer, - }, - }, } clusterConfig.ManagedNodeGroups = []*api.ManagedNodeGroup{ { @@ -97,8 +91,8 @@ var _ = Describe("(Integration) [Windows Nodegroups]", func() { createCluster(withOIDC) runWindowsPod() }, - PEntry("when withOIDC is disabled", false), - PEntry("when withOIDC is enabled", true), + Entry("when withOIDC is disabled", false), + Entry("when withOIDC is enabled", true), ) }) From 7211bb3d777fb1274b59d491b195769bcabbecaa Mon Sep 17 00:00:00 2001 From: cpu1 Date: Thu, 21 Oct 2021 16:31:07 +0530 Subject: [PATCH 076/124] Add support for Windows IPAM --- examples/14-windows-nodes.yaml | 4 +- integration/tests/windows/windows_test.go | 1 - pkg/apis/eksctl.io/v1alpha5/nodegroups.go | 10 +++ pkg/ctl/create/cluster.go | 13 ++- pkg/eks/tasks.go | 43 ++++++++-- pkg/windows/ipam.go | 86 +++++++++++++++++++ pkg/windows/ipam_test.go | 97 ++++++++++++++++++++++ userdocs/src/usage/windows-worker-nodes.md | 16 ++-- 8 files changed, 253 insertions(+), 17 deletions(-) create mode 100644 pkg/windows/ipam.go create mode 100644 pkg/windows/ipam_test.go diff --git a/examples/14-windows-nodes.yaml b/examples/14-windows-nodes.yaml index 59dcb25f5f..698247685c 100644 --- a/examples/14-windows-nodes.yaml +++ b/examples/14-windows-nodes.yaml @@ -1,5 +1,5 @@ # An example of ClusterConfig containing Windows and Linux node groups to support Windows workloads -# This example should be run with `eksctl create cluster -f 14-windows-nodes.yaml --install-vpc-controllers` +# This example should be run with `eksctl create cluster -f 14-windows-nodes.yaml` --- apiVersion: eksctl.io/v1alpha5 kind: ClusterConfig @@ -13,6 +13,8 @@ nodeGroups: amiFamily: WindowsServer2019FullContainer minSize: 2 maxSize: 3 + +managedNodeGroups: - name: linux-ng instanceType: t2.large minSize: 2 diff --git a/integration/tests/windows/windows_test.go b/integration/tests/windows/windows_test.go index ba1f95fd56..3984c66d74 100644 --- a/integration/tests/windows/windows_test.go +++ b/integration/tests/windows/windows_test.go @@ -70,7 +70,6 @@ var _ = Describe("(Integration) [Windows Nodegroups]", func() { "--config-file", "-", "--verbose", "4", "--kubeconfig", params.KubeconfigPath, - "--install-vpc-controllers", ). WithoutArg("--region", params.Region). WithStdin(bytes.NewReader(data)) diff --git a/pkg/apis/eksctl.io/v1alpha5/nodegroups.go b/pkg/apis/eksctl.io/v1alpha5/nodegroups.go index 51de68cebb..94956bc626 100644 --- a/pkg/apis/eksctl.io/v1alpha5/nodegroups.go +++ b/pkg/apis/eksctl.io/v1alpha5/nodegroups.go @@ -94,3 +94,13 @@ func (c *ClusterConfig) AllNodeGroups() []*NodeGroupBase { } return baseNodeGroups } + +// HasWindowsNodeGroup returns true if an unmanaged Windows nodegroup exists. +func (c *ClusterConfig) HasWindowsNodeGroup() bool { + for _, ng := range c.NodeGroups { + if IsWindowsImage(ng.AMIFamily) { + return true + } + } + return false +} diff --git a/pkg/ctl/create/cluster.go b/pkg/ctl/create/cluster.go index f3d96d66f1..a25cd5057f 100644 --- a/pkg/ctl/create/cluster.go +++ b/pkg/ctl/create/cluster.go @@ -32,6 +32,14 @@ import ( "github.com/weaveworks/eksctl/pkg/vpc" ) +const ( + vpcControllerInfoMessage = "you no longer need to install the VPC resource controller on Linux worker nodes to run " + + "Windows workloads in EKS clusters created after Oct 22, 2021. You can enable Windows IP address management on the EKS control plane via " + + "a ConfigMap setting (see https://docs.aws.amazon.com/eks/latest/userguide/windows-support.html for details). eksctl will automatically patch the ConfigMap to enable " + + "Windows IP address management when a Windows nodegroup is created. For existing clusters, you can enable it manually " + + "and run `eksctl utils install-vpc-controllers` with the --delete flag to remove the worker node installation of the VPC resource controller" +) + func createClusterCmd(cmd *cmdutils.Cmd) { createClusterCmdWithRunFunc(cmd, func(cmd *cmdutils.Cmd, ngFilter *filter.NodeGroupFilter, params *cmdutils.CreateClusterCmdParams) error { return doCreateCluster(cmd, ngFilter, params) @@ -71,6 +79,8 @@ func createClusterCmdWithRunFunc(cmd *cmdutils.Cmd, runFunc func(cmd *cmdutils.C fs.BoolVarP(¶ms.InstallWindowsVPCController, "install-vpc-controllers", "", false, "Install VPC controller that's required for Windows workloads") fs.BoolVarP(¶ms.Fargate, "fargate", "", false, "Create a Fargate profile scheduling pods in the default and kube-system namespaces onto Fargate") fs.BoolVarP(¶ms.DryRun, "dry-run", "", false, "Dry-run mode that skips cluster creation and outputs a ClusterConfig") + + _ = fs.MarkDeprecated("install-vpc-controllers", vpcControllerInfoMessage) }) cmd.FlagSetGroup.InFlagSet("Initial nodegroup", func(fs *pflag.FlagSet) { @@ -190,6 +200,7 @@ func doCreateCluster(cmd *cmdutils.Cmd, ngFilter *filter.NodeGroupFilter, params if !eks.SupportsWindowsWorkloads(kubeNodeGroups) { return errors.New("running Windows workloads requires having both Windows and Linux (AmazonLinux2) node groups") } + logger.Warning(vpcControllerInfoMessage) } else { eks.LogWindowsCompatibility(kubeNodeGroups, cfg.Metadata) } @@ -248,7 +259,7 @@ func doCreateCluster(cmd *cmdutils.Cmd, ngFilter *filter.NodeGroupFilter, params if err != nil { return err } - postClusterCreationTasks := ctl.CreateExtraClusterConfigTasks(cfg, params.InstallWindowsVPCController) + postClusterCreationTasks := ctl.CreateExtraClusterConfigTasks(cfg) supported, err := utils.IsMinVersion(api.Version1_18, cfg.Metadata.Version) if err != nil { diff --git a/pkg/eks/tasks.go b/pkg/eks/tasks.go index 0d10e45c16..2cd5491360 100644 --- a/pkg/eks/tasks.go +++ b/pkg/eks/tasks.go @@ -9,17 +9,18 @@ import ( "github.com/aws/aws-sdk-go/service/cloudwatchlogs" "github.com/weaveworks/eksctl/pkg/actions/identityproviders" - "github.com/weaveworks/eksctl/pkg/actions/irsa" + "github.com/weaveworks/eksctl/pkg/windows" "github.com/kris-nova/logger" "github.com/pkg/errors" - "github.com/weaveworks/eksctl/pkg/cfn/manager" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" "k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/types" + "github.com/weaveworks/eksctl/pkg/actions/irsa" "github.com/weaveworks/eksctl/pkg/addons" + "github.com/weaveworks/eksctl/pkg/cfn/manager" "github.com/weaveworks/eksctl/pkg/fargate" iamoidc "github.com/weaveworks/eksctl/pkg/iam/oidc" instanceutils "github.com/weaveworks/eksctl/pkg/utils/instance" @@ -43,6 +44,31 @@ func (t *clusterConfigTask) Do(errs chan error) error { return err } +// WindowsIPAMTask is a task for enabling Windows IPAM. +type WindowsIPAMTask struct { + Info string + ClientsetFunc func() (kubernetes.Interface, error) +} + +// Do implements Task. +func (w *WindowsIPAMTask) Do(errCh chan error) error { + defer close(errCh) + + clientset, err := w.ClientsetFunc() + if err != nil { + return err + } + windowsIPAM := windows.IPAM{ + Clientset: clientset, + } + return windowsIPAM.Enable(context.TODO()) +} + +// Describe implements Task. +func (w *WindowsIPAMTask) Describe() string { + return w.Info +} + // VPCControllerTask represents a task to install the VPC controller type VPCControllerTask struct { Info string @@ -191,7 +217,7 @@ func (t *restartDaemonsetTask) Do(errCh chan error) error { } // CreateExtraClusterConfigTasks returns all tasks for updating cluster configuration not depending on the control plane availability -func (c *ClusterProvider) CreateExtraClusterConfigTasks(cfg *api.ClusterConfig, installVPCController bool) *tasks.TaskTree { +func (c *ClusterProvider) CreateExtraClusterConfigTasks(cfg *api.ClusterConfig) *tasks.TaskTree { newTasks := &tasks.TaskTree{ Parallel: false, IsSubTask: true, @@ -277,11 +303,12 @@ func (c *ClusterProvider) CreateExtraClusterConfigTasks(cfg *api.ClusterConfig, newTasks.Append(identityproviders.NewAssociateProvidersTask(*cfg.Metadata, cfg.IdentityProviders, c.Provider.EKS())) } - if installVPCController { - newTasks.Append(&VPCControllerTask{ - Info: "install Windows VPC controller", - ClusterConfig: cfg, - ClusterProvider: c, + if cfg.HasWindowsNodeGroup() { + newTasks.Append(&WindowsIPAMTask{ + Info: "enable Windows IP address management", + ClientsetFunc: func() (kubernetes.Interface, error) { + return c.NewStdClientSet(cfg) + }, }) } diff --git a/pkg/windows/ipam.go b/pkg/windows/ipam.go new file mode 100644 index 0000000000..a2390e0028 --- /dev/null +++ b/pkg/windows/ipam.go @@ -0,0 +1,86 @@ +package windows + +import ( + "context" + "encoding/json" + + jsonpatch "github.com/evanphx/json-patch/v5" + "github.com/kris-nova/logger" + "github.com/pkg/errors" + corev1 "k8s.io/api/core/v1" + apierrors "k8s.io/apimachinery/pkg/api/errors" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/types" + "k8s.io/client-go/kubernetes" + corev1client "k8s.io/client-go/kubernetes/typed/core/v1" +) + +const ( + vpcCNIName = "amazon-vpc-cni" + vpcCNINamespace = metav1.NamespaceSystem + windowsIPAMField = "enable-windows-ipam" +) + +// IPAM enables Windows IPAM in the VPC CNI ConfigMap. +type IPAM struct { + Clientset kubernetes.Interface +} + +// Enable enables Windows IPAM in the VPC CNI ConfigMap. +func (w *IPAM) Enable(ctx context.Context) error { + configMaps := w.Clientset.CoreV1().ConfigMaps(metav1.NamespaceSystem) + vpcCNIConfig, err := configMaps.Get(ctx, vpcCNIName, metav1.GetOptions{}) + if err != nil { + if !apierrors.IsNotFound(err) { + return errors.Wrapf(err, "error getting ConfigMap %q", vpcCNIName) + } + return createConfigMap(ctx, configMaps) + } + + if val, ok := vpcCNIConfig.Data[windowsIPAMField]; ok && val == "true" { + logger.Info("Windows IPAM is already enabled") + return nil + } + + patch, err := createPatch(vpcCNIConfig) + if err != nil { + return errors.Wrap(err, "error creating merge patch") + } + + _, err = configMaps.Patch(ctx, vpcCNIName, types.StrategicMergePatchType, patch, metav1.PatchOptions{}) + if err != nil { + return errors.Wrapf(err, "failed to patch resource %q", vpcCNIName) + } + return nil +} + +func createPatch(cm *corev1.ConfigMap) ([]byte, error) { + oldData, err := json.Marshal(cm) + if err != nil { + return nil, err + } + cm.Data[windowsIPAMField] = "true" + modifiedData, err := json.Marshal(cm) + if err != nil { + return nil, err + } + return jsonpatch.CreateMergePatch(oldData, modifiedData) +} + +func createConfigMap(ctx context.Context, configMaps corev1client.ConfigMapInterface) error { + cm := &corev1.ConfigMap{ + TypeMeta: metav1.TypeMeta{ + Kind: "ConfigMap", + APIVersion: "v1", + }, + ObjectMeta: metav1.ObjectMeta{ + Name: vpcCNIName, + Namespace: vpcCNINamespace, + }, + Data: map[string]string{ + windowsIPAMField: "true", + }, + } + _, err := configMaps.Create(ctx, cm, metav1.CreateOptions{}) + return err +} diff --git a/pkg/windows/ipam_test.go b/pkg/windows/ipam_test.go new file mode 100644 index 0000000000..97ced2e57c --- /dev/null +++ b/pkg/windows/ipam_test.go @@ -0,0 +1,97 @@ +package windows_test + +import ( + "context" + + v1 "k8s.io/api/core/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + + . "github.com/onsi/gomega" + + . "github.com/onsi/ginkgo/extensions/table" + "github.com/weaveworks/eksctl/pkg/windows" + "k8s.io/client-go/kubernetes/fake" +) + +type ipamEntry struct { + existingConfigMapData map[string]string + + expectedConfigMapData map[string]string +} + +var _ = DescribeTable("Windows IPAM", func(e ipamEntry) { + var clientset *fake.Clientset + if e.existingConfigMapData != nil { + clientset = fake.NewSimpleClientset(&v1.ConfigMap{ + TypeMeta: metav1.TypeMeta{ + Kind: "ConfigMap", + APIVersion: "v1", + }, + ObjectMeta: metav1.ObjectMeta{ + Name: "amazon-vpc-cni", + Namespace: "kube-system", + }, + Data: e.existingConfigMapData, + }) + } else { + clientset = fake.NewSimpleClientset() + } + + ipam := &windows.IPAM{ + Clientset: clientset, + } + ctx := context.Background() + err := ipam.Enable(ctx) + Expect(err).ToNot(HaveOccurred()) + + cm, err := clientset.CoreV1().ConfigMaps("kube-system").Get(ctx, "amazon-vpc-cni", metav1.GetOptions{}) + Expect(err).ToNot(HaveOccurred()) + Expect(cm.Data).To(Equal(e.expectedConfigMapData)) + +}, + Entry("VPC CNI ConfigMap is missing", ipamEntry{ + expectedConfigMapData: map[string]string{ + "enable-windows-ipam": "true", + }, + }), + + Entry("VPC CNI ConfigMap has data", ipamEntry{ + existingConfigMapData: map[string]string{ + "VPC_CNI_1": "yes", + "VPC_CNI_2": "no", + "other": "true", + }, + expectedConfigMapData: map[string]string{ + "VPC_CNI_1": "yes", + "VPC_CNI_2": "no", + "other": "true", + "enable-windows-ipam": "true", + }, + }), + + Entry("VPC CNI ConfigMap has Windows IPAM already enabled", ipamEntry{ + existingConfigMapData: map[string]string{ + "VPC_CNI_1": "yes", + "VPC_CNI_2": "no", + "enable-windows-ipam": "true", + }, + expectedConfigMapData: map[string]string{ + "VPC_CNI_1": "yes", + "VPC_CNI_2": "no", + "enable-windows-ipam": "true", + }, + }), + + Entry("VPC CNI ConfigMap has Windows IPAM explicitly disabled", ipamEntry{ + existingConfigMapData: map[string]string{ + "VPC_CNI_1": "yes", + "VPC_CNI_2": "no", + "enable-windows-ipam": "false", + }, + expectedConfigMapData: map[string]string{ + "VPC_CNI_1": "yes", + "VPC_CNI_2": "no", + "enable-windows-ipam": "true", + }, + }), +) diff --git a/userdocs/src/usage/windows-worker-nodes.md b/userdocs/src/usage/windows-worker-nodes.md index e9c28aeee0..01aa7874c4 100644 --- a/userdocs/src/usage/windows-worker-nodes.md +++ b/userdocs/src/usage/windows-worker-nodes.md @@ -1,10 +1,14 @@ # Windows Worker Nodes From version 1.14, Amazon EKS supports [Windows Nodes][eks-user-guide] that allow running Windows containers. -In addition to having Windows nodes, a Linux node in the cluster is required to run the VPC resource controller and CoreDNS, as Microsoft doesn't support host-networking mode yet. Thus, a Windows EKS cluster will be a mixed-mode cluster containing Windows nodes and at least one Linux node. +In addition to having Windows nodes, a Linux node in the cluster is required to run CoreDNS, as Microsoft doesn't support host-networking mode yet. Thus, a Windows EKS cluster will be a mixture of Windows nodes and at least one Linux node. The Linux nodes are critical to the functioning of the cluster, and thus, for a production-grade cluster, it's recommended to have at least two `t2.large` Linux nodes for HA. -`eksctl` provides a flag to install the VPC resource controller as part of cluster creation, and a command to install it after a cluster has been created. +!!!note + You no longer need to install the VPC resource controller on Linux worker nodes to run Windows workloads in EKS clusters + created after October 22, 2021. + You can enable Windows IP address management on the EKS control plane via a ConfigMap setting (see https://docs.aws.amazon.com/eks/latest/userguide/windows-support.html for details). + eksctl will automatically patch the ConfigMap to enable Windows IP address management when a Windows nodegroup is created. ## Creating a new Windows cluster @@ -26,6 +30,8 @@ nodeGroups: amiFamily: WindowsServer2019FullContainer minSize: 2 maxSize: 3 + +managedNodeGroups: - name: linux-ng instanceType: t2.large minSize: 2 @@ -33,7 +39,7 @@ nodeGroups: ``` ```console -eksctl create cluster -f cluster.yaml --install-vpc-controllers +eksctl create cluster -f cluster.yaml ``` @@ -42,7 +48,6 @@ To create a new cluster without using a config file, issue the following command ```console eksctl create cluster --managed=false --name=windows-cluster --node-ami-family=WindowsServer2019CoreContainer eksctl create nodegroup --cluster=windows-cluster --node-ami-family=AmazonLinux2 --nodes-min=2 --node-type=t2.large -eksctl utils install-vpc-controllers --cluster=windows-cluster --approve ``` !!!note @@ -50,11 +55,10 @@ eksctl utils install-vpc-controllers --cluster=windows-cluster --approve ## Adding Windows support to an existing Linux cluster -To enable running Windows workloads on an existing cluster with Linux nodes (`AmazonLinux2` AMI family), you need to add a Windows node group and install the Windows VPC controller: +To enable running Windows workloads on an existing cluster with Linux nodes (`AmazonLinux2` AMI family), you need to add a Windows nodegroup. ```console eksctl create nodegroup --managed=false --cluster=existing-cluster --node-ami-family=WindowsServer2019CoreContainer -eksctl utils install-vpc-controllers --cluster=existing-cluster --approve ``` To ensure workloads are scheduled on the right OS, they must have a `nodeSelector` targeting the OS it must run on: From cb0eb38ad46a172df1314202f1a4c9729453d87b Mon Sep 17 00:00:00 2001 From: cpu1 Date: Wed, 10 Nov 2021 20:13:32 +0530 Subject: [PATCH 077/124] Add release notes for 0.74 --- docs/release_notes/0.74.0.md | 14 ++++++++++++++ 1 file changed, 14 insertions(+) create mode 100644 docs/release_notes/0.74.0.md diff --git a/docs/release_notes/0.74.0.md b/docs/release_notes/0.74.0.md new file mode 100644 index 0000000000..8bc8762559 --- /dev/null +++ b/docs/release_notes/0.74.0.md @@ -0,0 +1,14 @@ +# Release 0.74.0 + +## Features + +- Add support for Windows IPAM (#4356) + +## Bug Fixes + +- Unpend and fix Windows integration tests (#4442) +- Set volume size in data volume for Bottlerocket (#4436) + +## Acknowledgments +Weaveworks would like to sincerely thank: +@silverskyvicto From 3ae83bbf64729c4c83e6ac3193c1ae1e11afd44e Mon Sep 17 00:00:00 2001 From: weaveworksbot Date: Wed, 10 Nov 2021 17:33:58 +0000 Subject: [PATCH 078/124] Prepare for next development iteration --- pkg/version/release.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkg/version/release.go b/pkg/version/release.go index afdba68c74..213afd934f 100644 --- a/pkg/version/release.go +++ b/pkg/version/release.go @@ -3,7 +3,7 @@ package version // This file was generated by release_generate.go; DO NOT EDIT. // Version is the version number in semver format X.Y.Z -var Version = "0.74.0" +var Version = "0.75.0" // PreReleaseID can be empty for releases, "rc.X" for release candidates and "dev" for snapshots var PreReleaseID = "dev" From c99f731ab8719ce8f520087ec5a089f52bb41c23 Mon Sep 17 00:00:00 2001 From: cpu1 Date: Fri, 12 Nov 2021 13:40:43 +0530 Subject: [PATCH 079/124] Document logs:PutRetentionPolicy in IAM policies doc --- userdocs/src/usage/minimum-iam-policies.md | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/userdocs/src/usage/minimum-iam-policies.md b/userdocs/src/usage/minimum-iam-policies.md index d2f65c6e31..40052b3e67 100644 --- a/userdocs/src/usage/minimum-iam-policies.md +++ b/userdocs/src/usage/minimum-iam-policies.md @@ -99,7 +99,14 @@ EksAllAccess ], "Resource": "*", "Effect": "Allow" - } + }, + { + "Action": [ + "logs:PutRetentionPolicy" + ], + "Resource": "*", + "Effect": "Allow" + } ] } ``` From c5f6d0ef7c8bc7275f43748c51041a371b7ed854 Mon Sep 17 00:00:00 2001 From: Gergely Brautigam <182850+Skarlso@users.noreply.github.com> Date: Mon, 15 Nov 2021 19:37:57 +0100 Subject: [PATCH 080/124] Fix update logic in iam service account (#4460) --- pkg/kubernetes/serviceaccount.go | 2 +- pkg/kubernetes/serviceaccount_test.go | 60 +++++++++++++++++++++++++++ 2 files changed, 61 insertions(+), 1 deletion(-) diff --git a/pkg/kubernetes/serviceaccount.go b/pkg/kubernetes/serviceaccount.go index 9447ddf97b..4584793df4 100644 --- a/pkg/kubernetes/serviceaccount.go +++ b/pkg/kubernetes/serviceaccount.go @@ -70,7 +70,7 @@ func MaybeCreateServiceAccountOrUpdateMetadata(clientSet Interface, meta metav1. mergeMetadata := func(src, dst map[string]string) { for key, value := range src { currentValue, ok := dst[key] - updateRequired = !ok || ok && currentValue != value + updateRequired = updateRequired || !ok || (ok && currentValue != value) dst[key] = value } } diff --git a/pkg/kubernetes/serviceaccount_test.go b/pkg/kubernetes/serviceaccount_test.go index db736ec53e..d15e97e159 100644 --- a/pkg/kubernetes/serviceaccount_test.go +++ b/pkg/kubernetes/serviceaccount_test.go @@ -103,6 +103,66 @@ var _ = Describe("Kubernetes serviceaccount object helpers", func() { } }) + It("can update in different variations", func() { + sa := metav1.ObjectMeta{ + Name: "sa-1", + Namespace: "ns-1", + Annotations: map[string]string{ + "foo": "bar", + }, + Labels: map[string]string{ + "label": "value", + }, + } + + err = MaybeCreateServiceAccountOrUpdateMetadata(clientSet, sa) + Expect(err).NotTo(HaveOccurred()) + + ok, err := CheckNamespaceExists(clientSet, sa.Namespace) + Expect(err).NotTo(HaveOccurred()) + Expect(ok).To(BeTrue()) + + ok, err = CheckServiceAccountExists(clientSet, sa) + Expect(err).NotTo(HaveOccurred()) + Expect(ok).To(BeTrue()) + + By("changing an existing value and not touching labels") + sa.Annotations["foo"] = "new" + err = MaybeCreateServiceAccountOrUpdateMetadata(clientSet, sa) + Expect(err).NotTo(HaveOccurred()) + + resp, err := clientSet.CoreV1().ServiceAccounts(sa.Namespace).Get(context.TODO(), sa.Name, metav1.GetOptions{}) + Expect(err).NotTo(HaveOccurred()) + + Expect(resp.Labels).To(HaveKeyWithValue("label", "value")) + Expect(resp.Annotations).To(HaveKeyWithValue("foo", "new")) + + By("adding a new value and not touching labels") + sa.Annotations["new"] = "value" + err = MaybeCreateServiceAccountOrUpdateMetadata(clientSet, sa) + Expect(err).NotTo(HaveOccurred()) + + resp, err = clientSet.CoreV1().ServiceAccounts(sa.Namespace).Get(context.TODO(), sa.Name, metav1.GetOptions{}) + Expect(err).NotTo(HaveOccurred()) + + Expect(resp.Labels).To(HaveKeyWithValue("label", "value")) + Expect(resp.Annotations).To(HaveKeyWithValue("foo", "new")) + Expect(resp.Annotations).To(HaveKeyWithValue("new", "value")) + + By("updating the labels value") + sa.Labels["new"] = "value" + err = MaybeCreateServiceAccountOrUpdateMetadata(clientSet, sa) + Expect(err).NotTo(HaveOccurred()) + + resp, err = clientSet.CoreV1().ServiceAccounts(sa.Namespace).Get(context.TODO(), sa.Name, metav1.GetOptions{}) + Expect(err).NotTo(HaveOccurred()) + + Expect(resp.Labels).To(HaveKeyWithValue("label", "value")) + Expect(resp.Labels).To(HaveKeyWithValue("new", "value")) + Expect(resp.Annotations).To(HaveKeyWithValue("foo", "new")) + Expect(resp.Annotations).To(HaveKeyWithValue("new", "value")) + }) + It("can delete existsing service account, and doesn't fail if it doesn't exist", func() { sa := metav1.ObjectMeta{Name: "sa-2", Namespace: "ns-2"} From 026bc14e139857cf3455ddb53a2aac00b4f65942 Mon Sep 17 00:00:00 2001 From: Gergely Brautigam <182850+Skarlso@users.noreply.github.com> Date: Tue, 16 Nov 2021 16:01:59 +0100 Subject: [PATCH 081/124] Add option to skip endpoint creation completely (#4457) --- .../eksctl.io/v1alpha5/assets/schema.json | 7 +++ pkg/apis/eksctl.io/v1alpha5/types.go | 4 ++ pkg/apis/eksctl.io/v1alpha5/validation.go | 4 +- .../eksctl.io/v1alpha5/validation_test.go | 59 +++++++++++++++++++ pkg/cfn/builder/cluster.go | 2 +- pkg/cfn/builder/cluster_test.go | 11 ++++ .../cmdutils/filter/nodegroup_filter_test.go | 3 +- pkg/windows/ipam_test.go | 4 +- userdocs/src/usage/eks-private-cluster.md | 15 +++++ 9 files changed, 104 insertions(+), 5 deletions(-) diff --git a/pkg/apis/eksctl.io/v1alpha5/assets/schema.json b/pkg/apis/eksctl.io/v1alpha5/assets/schema.json index e70b80cea8..cf31b49124 100755 --- a/pkg/apis/eksctl.io/v1alpha5/assets/schema.json +++ b/pkg/apis/eksctl.io/v1alpha5/assets/schema.json @@ -1947,10 +1947,17 @@ "description": "enables creation of a fully-private cluster", "x-intellij-html-description": "enables creation of a fully-private cluster", "default": "false" + }, + "skipEndpointCreation": { + "type": "boolean", + "description": "skips the creation process for endpoints completely. This is only used in case of an already provided VPC and if the user decided to set it to true.", + "x-intellij-html-description": "skips the creation process for endpoints completely. This is only used in case of an already provided VPC and if the user decided to set it to true.", + "default": "false" } }, "preferredOrder": [ "enabled", + "skipEndpointCreation", "additionalEndpointServices" ], "additionalProperties": false, diff --git a/pkg/apis/eksctl.io/v1alpha5/types.go b/pkg/apis/eksctl.io/v1alpha5/types.go index 99bf3ba3f1..12a8733cf9 100644 --- a/pkg/apis/eksctl.io/v1alpha5/types.go +++ b/pkg/apis/eksctl.io/v1alpha5/types.go @@ -1578,6 +1578,10 @@ type PrivateCluster struct { // Enabled enables creation of a fully-private cluster Enabled bool `json:"enabled"` + // SkipEndpointCreation skips the creation process for endpoints completely. This is only used in case of an already + // provided VPC and if the user decided to set it to true. + SkipEndpointCreation bool `json:"skipEndpointCreation"` + // AdditionalEndpointServices specifies additional endpoint services that // must be enabled for private access. // Valid entries are `AdditionalEndpointServices` constants diff --git a/pkg/apis/eksctl.io/v1alpha5/validation.go b/pkg/apis/eksctl.io/v1alpha5/validation.go index bc39962e4a..26a8688455 100644 --- a/pkg/apis/eksctl.io/v1alpha5/validation.go +++ b/pkg/apis/eksctl.io/v1alpha5/validation.go @@ -201,7 +201,9 @@ func (c *ClusterConfig) ValidatePrivateCluster() error { if c.VPC != nil && c.VPC.ID != "" && len(c.VPC.Subnets.Private) == 0 { return errors.New("vpc.subnets.private must be specified in a fully-private cluster when a pre-existing VPC is supplied") } - if additionalEndpoints := c.PrivateCluster.AdditionalEndpointServices; len(additionalEndpoints) > 0 { + if additionalEndpoints := c.PrivateCluster.AdditionalEndpointServices; len(additionalEndpoints) > 0 && c.PrivateCluster.SkipEndpointCreation { + return fmt.Errorf("additionalEndpoints cannot be defined together with skipEndpointCreation set to true") + } else if len(additionalEndpoints) > 0 { if err := ValidateAdditionalEndpointServices(additionalEndpoints); err != nil { return errors.Wrap(err, "invalid value in privateCluster.additionalEndpointServices") } diff --git a/pkg/apis/eksctl.io/v1alpha5/validation_test.go b/pkg/apis/eksctl.io/v1alpha5/validation_test.go index 7f02e021ba..2ac9ae6216 100644 --- a/pkg/apis/eksctl.io/v1alpha5/validation_test.go +++ b/pkg/apis/eksctl.io/v1alpha5/validation_test.go @@ -563,6 +563,65 @@ var _ = Describe("ClusterConfig validation", func() { }) }) + Describe("ValidatePrivateCluster", func() { + var ( + cfg *api.ClusterConfig + vpc *api.ClusterVPC + ) + + BeforeEach(func() { + cfg = api.NewClusterConfig() + vpc = api.NewClusterVPC() + cfg.VPC = vpc + cfg.PrivateCluster = &api.PrivateCluster{ + Enabled: true, + } + }) + When("private cluster is enabled", func() { + It("validates the config", func() { + err := cfg.ValidatePrivateCluster() + Expect(err).NotTo(HaveOccurred()) + }) + }) + When("vpc is provided but no private subnets", func() { + It("fails the validation", func() { + cfg.VPC.Subnets = &api.ClusterSubnets{} + cfg.VPC.ID = "id" + err := cfg.ValidatePrivateCluster() + Expect(err).To(MatchError(ContainSubstring("vpc.subnets.private must be specified in a fully-private cluster when a pre-existing VPC is supplied"))) + }) + }) + When("additional endpoints are defined with skip endpoints", func() { + It("fails the validation", func() { + cfg.PrivateCluster.AdditionalEndpointServices = []string{api.EndpointServiceCloudFormation} + cfg.PrivateCluster.SkipEndpointCreation = true + err := cfg.ValidatePrivateCluster() + Expect(err).To(MatchError(ContainSubstring("additionalEndpoints cannot be defined together with skipEndpointCreation set to true"))) + }) + }) + When("additional endpoints are defined", func() { + It("validates the endpoint configuration", func() { + cfg.PrivateCluster.AdditionalEndpointServices = []string{api.EndpointServiceCloudFormation} + err := cfg.ValidatePrivateCluster() + Expect(err).NotTo(HaveOccurred()) + }) + }) + When("additional endpoints are defined incorrectly", func() { + It("fails the endpoint validation", func() { + cfg.PrivateCluster.AdditionalEndpointServices = []string{"unknown"} + err := cfg.ValidatePrivateCluster() + Expect(err).To(MatchError(ContainSubstring("invalid value in privateCluster.additionalEndpointServices"))) + }) + }) + When("private cluster is enabled with skip endpoints", func() { + It("does not fail the validation", func() { + cfg.PrivateCluster.SkipEndpointCreation = true + err := cfg.ValidatePrivateCluster() + Expect(err).NotTo(HaveOccurred()) + }) + }) + }) + Describe("cpuCredits", func() { var ng *api.NodeGroup BeforeEach(func() { diff --git a/pkg/cfn/builder/cluster.go b/pkg/cfn/builder/cluster.go index e8b9a4d045..20d16c9bfd 100644 --- a/pkg/cfn/builder/cluster.go +++ b/pkg/cfn/builder/cluster.go @@ -58,7 +58,7 @@ func (c *ClusterResourceSet) AddAllResources() error { c.vpcResourceSet.AddOutputs() clusterSG := c.addResourcesForSecurityGroups(vpcResource) - if privateCluster := c.spec.PrivateCluster; privateCluster.Enabled { + if privateCluster := c.spec.PrivateCluster; privateCluster.Enabled && !privateCluster.SkipEndpointCreation { vpcEndpointResourceSet := NewVPCEndpointResourceSet(c.ec2API, c.region, c.rs, c.spec, vpcResource.VPC, vpcResource.SubnetDetails.Private, clusterSG.ClusterSharedNode) if err := vpcEndpointResourceSet.AddResources(); err != nil { diff --git a/pkg/cfn/builder/cluster_test.go b/pkg/cfn/builder/cluster_test.go index 9955fa42a4..397a816e65 100644 --- a/pkg/cfn/builder/cluster_test.go +++ b/pkg/cfn/builder/cluster_test.go @@ -310,6 +310,17 @@ var _ = Describe("Cluster Template Builder", func() { Expect(clusterTemplate.Resources).NotTo(HaveKey("PublicSubnetRoute")) Expect(clusterTemplate.Resources).To(HaveKey(ContainSubstring("PrivateRouteTable"))) }) + When("skip endpoint creation is set", func() { + BeforeEach(func() { + cfg.PrivateCluster = &api.PrivateCluster{ + Enabled: true, + SkipEndpointCreation: true, + } + }) + It("will skip creating all of the endpoints", func() { + Expect(clusterTemplate.Resources).NotTo(HaveKey(ContainSubstring("VPCEndpoint"))) + }) + }) }) Context("when adding vpc endpoint resources fails", func() { diff --git a/pkg/ctl/cmdutils/filter/nodegroup_filter_test.go b/pkg/ctl/cmdutils/filter/nodegroup_filter_test.go index 100744ed38..35fcc64fab 100644 --- a/pkg/ctl/cmdutils/filter/nodegroup_filter_test.go +++ b/pkg/ctl/cmdutils/filter/nodegroup_filter_test.go @@ -357,7 +357,8 @@ const expected = ` "clusterLogging": {} }, "privateCluster": { - "enabled": false + "enabled": false, + "skipEndpointCreation": false }, "nodeGroups": [ { diff --git a/pkg/windows/ipam_test.go b/pkg/windows/ipam_test.go index 97ced2e57c..6041d52a53 100644 --- a/pkg/windows/ipam_test.go +++ b/pkg/windows/ipam_test.go @@ -42,10 +42,10 @@ var _ = DescribeTable("Windows IPAM", func(e ipamEntry) { } ctx := context.Background() err := ipam.Enable(ctx) - Expect(err).ToNot(HaveOccurred()) + Expect(err).NotTo(HaveOccurred()) cm, err := clientset.CoreV1().ConfigMaps("kube-system").Get(ctx, "amazon-vpc-cni", metav1.GetOptions{}) - Expect(err).ToNot(HaveOccurred()) + Expect(err).NotTo(HaveOccurred()) Expect(cm.Data).To(Equal(e.expectedConfigMapData)) }, diff --git a/userdocs/src/usage/eks-private-cluster.md b/userdocs/src/usage/eks-private-cluster.md index fb31a990f6..77b67a0df7 100644 --- a/userdocs/src/usage/eks-private-cluster.md +++ b/userdocs/src/usage/eks-private-cluster.md @@ -60,6 +60,21 @@ privateCluster: The endpoints supported in `additionalEndpointServices` are `autoscaling`, `cloudformation` and `logs`. +### Skipping endpoint creations + +If a VPC has already been created with the necessary AWS endpoints set up and linked to the subnets described in the EKS documentation, +`eksctl` can skip creating them by providing the option `skipEndpointCreation` like this: + +```yaml +privateCluster: + enabled: true + skipEndpointCreation: true +``` + +_Note_: this setting cannot be used together with `additionalEndpointServices`. It will skip all endpoint creation. Also, this setting is +only recommended if the endpoint <-> subnet topology is correctly set up. I.e.: subnet ids are correct, `vpce` routing is set up with prefix addresses, +all the necessary EKS endpoints are created and linked to the provided VPC. `eksctl` will not alter any of these resources. + ## Nodegroups Only private nodegroups (both managed and self-managed) are supported in a fully-private cluster because the cluster's VPC is created without any public subnets. The `privateNetworking` field (`nodeGroup[*].privateNetworking` and `managedNodeGroup[*].privateNetworking`) must be From ff8e61d64cd03b8067830e4a0814f7eac80fe9ea Mon Sep 17 00:00:00 2001 From: Gergely Brautigam <182850+Skarlso@users.noreply.github.com> Date: Wed, 17 Nov 2021 12:23:05 +0100 Subject: [PATCH 082/124] Add config-file option to get nodegroup (#4465) --- pkg/ctl/get/nodegroup.go | 4 +++ pkg/ctl/get/nodegroup_test.go | 58 ++++++++++++++++++++++++++++++----- 2 files changed, 55 insertions(+), 7 deletions(-) diff --git a/pkg/ctl/get/nodegroup.go b/pkg/ctl/get/nodegroup.go index 7bfa1be2e8..725feb6c0c 100644 --- a/pkg/ctl/get/nodegroup.go +++ b/pkg/ctl/get/nodegroup.go @@ -38,12 +38,16 @@ func getNodeGroupCmd(cmd *cmdutils.Cmd) { cmdutils.AddRegionFlag(fs, &cmd.ProviderConfig) cmdutils.AddCommonFlagsForGetCmd(fs, ¶ms.chunkSize, ¶ms.output) cmdutils.AddTimeoutFlag(fs, &cmd.ProviderConfig.WaitTimeout) + cmdutils.AddConfigFileFlag(fs, &cmd.ClusterConfigFile) }) cmdutils.AddCommonFlagsForAWS(cmd.FlagSetGroup, &cmd.ProviderConfig, false) } func doGetNodeGroup(cmd *cmdutils.Cmd, ng *api.NodeGroup, params *getCmdParams) error { + if err := cmdutils.NewMetadataLoader(cmd).Load(); err != nil { + return err + } cfg := cmd.ClusterConfig // TODO: move this into a loader when --config-file gets added to this command diff --git a/pkg/ctl/get/nodegroup_test.go b/pkg/ctl/get/nodegroup_test.go index 1259f542a9..6d43e75247 100644 --- a/pkg/ctl/get/nodegroup_test.go +++ b/pkg/ctl/get/nodegroup_test.go @@ -1,6 +1,8 @@ package get import ( + "os" + . "github.com/onsi/ginkgo" . "github.com/onsi/gomega" ) @@ -10,22 +12,64 @@ var _ = Describe("get", func() { It("missing required flag --cluster", func() { cmd := newMockCmd("nodegroup") _, err := cmd.execute() - Expect(err).To(HaveOccurred()) - Expect(err.Error()).To(ContainSubstring("Error: --cluster must be set")) + Expect(err).To(MatchError(ContainSubstring("Error: --cluster must be set"))) }) It("setting --name and argument at the same time", func() { - cmd := newMockCmd("nodegroup", "ng", "--cluster", "dummy", "--name", "ng") + cmd := newMockCmd("nodegroup", "ng", "--name", "ng") + _, err := cmd.execute() + Expect(err).To(MatchError(ContainSubstring("Error: --name=ng and argument ng cannot be used at the same time"))) + }) + + It("setting --cluster and argument at the same time", func() { + cmd := newMockCmd("nodegroup", "ng", "--cluster", "name") _, err := cmd.execute() - Expect(err).To(HaveOccurred()) - Expect(err.Error()).To(ContainSubstring("Error: --name=ng and argument ng cannot be used at the same time")) + Expect(err).To(MatchError(ContainSubstring("Error: --cluster=name and argument ng cannot be used at the same time"))) + }) + + It("setting --name and --config-file at the same time", func() { + f, err := os.CreateTemp("", "configfile") + Expect(err).NotTo(HaveOccurred()) + _, err = f.WriteString(configFile) + Expect(err).NotTo(HaveOccurred()) + cmd := newMockCmd("nodegroup", "--name", "name", "--config-file", f.Name()) + _, err = cmd.execute() + Expect(err).To(MatchError(ContainSubstring("Error: cannot use --name when --config-file/-f is set"))) + }) + + It("setting --cluster and --config-file at the same time", func() { + f, err := os.CreateTemp("", "configfile") + Expect(err).NotTo(HaveOccurred()) + _, err = f.WriteString(configFile) + Expect(err).NotTo(HaveOccurred()) + cmd := newMockCmd("nodegroup", "--cluster", "name", "--config-file", f.Name()) + _, err = cmd.execute() + Expect(err).To(MatchError(ContainSubstring("Error: cannot use --cluster when --config-file/-f is set"))) }) It("invalid flag", func() { cmd := newMockCmd("nodegroup", "--invalid", "dummy") _, err := cmd.execute() - Expect(err).To(HaveOccurred()) - Expect(err.Error()).To(ContainSubstring("Error: unknown flag: --invalid")) + Expect(err).To(MatchError(ContainSubstring("Error: unknown flag: --invalid"))) }) }) }) + +var configFile = `apiVersion: eksctl.io/v1alpha5 +kind: ClusterConfig + +metadata: + name: test-nodegroup-cluster-config + region: us-west-2 + version: '1.20' + +managedNodeGroups: + - name: managed-ng-1 + minSize: 1 + maxSize: 2 + desiredCapacity: 1 + - name: managed-ng-2 + minSize: 1 + maxSize: 2 + desiredCapacity: 1 +` From 84b95164d42ff2402f2a26f7e56ac8d373765265 Mon Sep 17 00:00:00 2001 From: Jake Date: Wed, 15 Sep 2021 16:19:42 +0100 Subject: [PATCH 083/124] set default csi driver policies when creating the addon --- pkg/actions/addon/create.go | 45 ++++++++++---------- pkg/actions/addon/create_test.go | 70 ++++++++++++++++++++++---------- 2 files changed, 73 insertions(+), 42 deletions(-) diff --git a/pkg/actions/addon/create.go b/pkg/actions/addon/create.go index 1570aa1a82..8be10538b1 100644 --- a/pkg/actions/addon/create.go +++ b/pkg/actions/addon/create.go @@ -23,6 +23,7 @@ import ( const ( kubeSystemNamespace = "kube-system" vpcCNIName = "vpc-cni" + ebsCSIDriverName = "aws-ebs-csi-driver" ) func (a *Manager) Create(addon *api.Addon, wait bool) error { @@ -67,27 +68,20 @@ func (a *Manager) Create(addon *api.Addon, wait bool) error { return err } createAddonInput.ServiceAccountRoleArn = &outputRole - } else { - policies := a.getRecommendedPolicies(addon) - if len(policies) != 0 { - logger.Info("creating role using recommended policies") - addon.AttachPolicyARNs = policies - resourceSet := builder.NewIAMRoleResourceSetWithAttachPolicyARNs(addon.Name, namespace, serviceAccount, addon.PermissionsBoundary, addon.AttachPolicyARNs, a.oidcManager) - if err := resourceSet.AddAllResources(); err != nil { - return err - } - err := a.createStack(resourceSet, addon) - if err != nil { - return err - } - createAddonInput.ServiceAccountRoleArn = &resourceSet.OutputRole - } else { - logger.Info("no recommended policies found, proceeding without any IAM") + } else if a.hasRecommendedPolicies(addon) { + logger.Info("creating role using recommended policies") + a.setRecommendedPolicies(addon) + outputRole, err := a.createRole(addon, namespace, serviceAccount) + if err != nil { + return err } + createAddonInput.ServiceAccountRoleArn = &outputRole + } else { + logger.Info("no recommended policies found, proceeding without any IAM") } } else { //if any sort of policy is set or could be set, log a warning - if addon.ServiceAccountRoleARN != "" || hasPoliciesSet(addon) || len(a.getRecommendedPolicies(addon)) != 0 { + if addon.ServiceAccountRoleARN != "" || hasPoliciesSet(addon) || a.hasRecommendedPolicies(addon) { logger.Warning("OIDC is disabled but policies are required/specified for this addon. Users are responsible for attaching the policies to all nodegroup roles") } } @@ -179,13 +173,22 @@ func (a *Manager) patchAWSNodeDaemonSet() error { return nil } -func (a *Manager) getRecommendedPolicies(addon *api.Addon) []string { + +func (a *Manager) hasRecommendedPolicies(addon *api.Addon) bool { + updatedAddon := addon.DeepCopy() + a.setRecommendedPolicies(updatedAddon) + return hasPoliciesSet(updatedAddon) +} + +func (a *Manager) setRecommendedPolicies(addon *api.Addon) { // API isn't case sensitive switch addon.CanonicalName() { case vpcCNIName: - return []string{fmt.Sprintf("arn:%s:iam::aws:policy/%s", api.Partition(a.clusterConfig.Metadata.Region), api.IAMPolicyAmazonEKSCNIPolicy)} - default: - return []string{} + addon.AttachPolicyARNs = []string{fmt.Sprintf("arn:%s:iam::aws:policy/%s", api.Partition(a.clusterConfig.Metadata.Region), api.IAMPolicyAmazonEKSCNIPolicy)} + case ebsCSIDriverName: + addon.WellKnownPolicies = api.WellKnownPolicies{ + EBSCSIController: true, + } } } diff --git a/pkg/actions/addon/create_test.go b/pkg/actions/addon/create_test.go index d63a1acf20..a438630b2f 100644 --- a/pkg/actions/addon/create_test.go +++ b/pkg/actions/addon/create_test.go @@ -392,28 +392,56 @@ var _ = Describe("Create", func() { } }) - It("creates a role with the recommended policies and attaches it to the addon", func() { - err := manager.Create(&api.Addon{ - Name: "vpc-cni", - Version: "v1.0.0-eksbuild.1", - }, false) - Expect(err).NotTo(HaveOccurred()) - Expect(fakeStackManager.CreateStackCallCount()).To(Equal(1)) - name, resourceSet, tags, _, _ := fakeStackManager.CreateStackArgsForCall(0) - Expect(name).To(Equal("eksctl-my-cluster-addon-vpc-cni")) - Expect(resourceSet).NotTo(BeNil()) - Expect(tags).To(Equal(map[string]string{ - api.AddonNameTag: "vpc-cni", - })) - output, err := resourceSet.RenderJSON() - Expect(err).NotTo(HaveOccurred()) - Expect(string(output)).To(ContainSubstring("arn:aws:iam::aws:policy/AmazonEKS_CNI_Policy")) - Expect(string(output)).To(ContainSubstring(":sub\":\"system:serviceaccount:kube-system:aws-node")) - Expect(*createAddonInput.ClusterName).To(Equal("my-cluster")) - Expect(*createAddonInput.AddonName).To(Equal("vpc-cni")) - Expect(*createAddonInput.AddonVersion).To(Equal("v1.0.0-eksbuild.1")) - Expect(*createAddonInput.ServiceAccountRoleArn).To(Equal("role-arn")) + When("its the vpc-cni addon", func() { + It("creates a role with the recommended policies and attaches it to the addon", func() { + err := manager.Create(&api.Addon{ + Name: "vpc-cni", + Version: "v1.0.0-eksbuild.1", + }, false) + Expect(err).NotTo(HaveOccurred()) + + Expect(fakeStackManager.CreateStackCallCount()).To(Equal(1)) + name, resourceSet, tags, _, _ := fakeStackManager.CreateStackArgsForCall(0) + Expect(name).To(Equal("eksctl-my-cluster-addon-vpc-cni")) + Expect(resourceSet).NotTo(BeNil()) + Expect(tags).To(Equal(map[string]string{ + api.AddonNameTag: "vpc-cni", + })) + output, err := resourceSet.RenderJSON() + Expect(err).NotTo(HaveOccurred()) + Expect(string(output)).To(ContainSubstring("arn:aws:iam::aws:policy/AmazonEKS_CNI_Policy")) + Expect(string(output)).To(ContainSubstring(":sub\":\"system:serviceaccount:kube-system:aws-node")) + Expect(*createAddonInput.ClusterName).To(Equal("my-cluster")) + Expect(*createAddonInput.AddonName).To(Equal("vpc-cni")) + Expect(*createAddonInput.AddonVersion).To(Equal("v1.0.0-eksbuild.1")) + Expect(*createAddonInput.ServiceAccountRoleArn).To(Equal("role-arn")) + }) + }) + + When("its the aws-ebs-csi-driver addon", func() { + It("creates a role with the recommended policies and attaches it to the addon", func() { + err := manager.Create(&api.Addon{ + Name: "aws-ebs-csi-driver", + Version: "v1.0.0-eksbuild.1", + }, false) + Expect(err).NotTo(HaveOccurred()) + + Expect(fakeStackManager.CreateStackCallCount()).To(Equal(1)) + name, resourceSet, tags, _, _ := fakeStackManager.CreateStackArgsForCall(0) + Expect(name).To(Equal("eksctl-my-cluster-addon-aws-ebs-csi-driver")) + Expect(resourceSet).NotTo(BeNil()) + Expect(tags).To(Equal(map[string]string{ + api.AddonNameTag: "aws-ebs-csi-driver", + })) + output, err := resourceSet.RenderJSON() + Expect(err).NotTo(HaveOccurred()) + Expect(string(output)).To(ContainSubstring("PolicyEBSCSIController")) + Expect(*createAddonInput.ClusterName).To(Equal("my-cluster")) + Expect(*createAddonInput.AddonName).To(Equal("aws-ebs-csi-driver")) + Expect(*createAddonInput.AddonVersion).To(Equal("v1.0.0-eksbuild.1")) + Expect(*createAddonInput.ServiceAccountRoleArn).To(Equal("role-arn")) + }) }) }) }) From 664ee7cc1e8d1591a4dbd9d5c730af72baae3acd Mon Sep 17 00:00:00 2001 From: Jake Klein Date: Wed, 17 Nov 2021 12:03:54 +0000 Subject: [PATCH 084/124] Improve kube-proxy updating to always get the latest version&build #4344 (#4440) query EKS API to discover latest kube-proxy version --- .../tests/update/update_cluster_test.go | 2 +- pkg/actions/nodegroup/create.go | 2 +- pkg/addons/default/addons.go | 37 +- pkg/addons/default/assets_test.go | 4 +- pkg/addons/default/aws_node.go | 21 +- pkg/addons/default/aws_node_test.go | 249 +++--- pkg/addons/default/coredns.go | 23 +- pkg/addons/default/coredns_test.go | 17 +- pkg/addons/default/helpers.go | 16 - pkg/addons/default/helpers_test.go | 36 - pkg/addons/default/kube_proxy.go | 125 ++- pkg/addons/default/kube_proxy_test.go | 243 +++++- .../testdata/sample-1.15-eksbuild.1.json | 798 ++++++++++++++++++ .../testdata/sample-1.15-invalid-image.json | 798 ++++++++++++++++++ pkg/ctl/utils/update_aws_node.go | 5 +- pkg/ctl/utils/update_coredns.go | 7 +- pkg/ctl/utils/update_kube_proxy.go | 7 +- pkg/testutils/client.go | 11 + 18 files changed, 2145 insertions(+), 256 deletions(-) delete mode 100644 pkg/addons/default/helpers.go delete mode 100644 pkg/addons/default/helpers_test.go create mode 100644 pkg/addons/default/testdata/sample-1.15-eksbuild.1.json create mode 100644 pkg/addons/default/testdata/sample-1.15-invalid-image.json diff --git a/integration/tests/update/update_cluster_test.go b/integration/tests/update/update_cluster_test.go index 7634ced6c1..1121a40ce0 100644 --- a/integration/tests/update/update_cluster_test.go +++ b/integration/tests/update/update_cluster_test.go @@ -170,7 +170,7 @@ var _ = Describe("(Integration) Update addons", func() { kubeProxyVersion, err := addons.ImageTag(daemonSet.Spec.Template.Spec.Containers[0].Image) Expect(err).NotTo(HaveOccurred()) return kubeProxyVersion - }, k8sUpdatePollTimeout, k8sUpdatePollInterval).Should(Equal(fmt.Sprintf("v%s-eksbuild.1", kubernetesVersion))) + }, k8sUpdatePollTimeout, k8sUpdatePollInterval).Should(ContainSubstring(fmt.Sprintf("v%s-eksbuild.", kubernetesVersion))) }) It("should upgrade aws-node", func() { diff --git a/pkg/actions/nodegroup/create.go b/pkg/actions/nodegroup/create.go index 3bd92939f6..3623d76a4f 100644 --- a/pkg/actions/nodegroup/create.go +++ b/pkg/actions/nodegroup/create.go @@ -279,7 +279,7 @@ func (m *Manager) checkARMSupport(ctl *eks.ClusterProvider, clientSet kubernetes return err } if api.ClusterHasInstanceType(cfg, instanceutils.IsARMInstanceType) { - upToDate, err := defaultaddons.DoAddonsSupportMultiArch(clientSet, rawClient, kubernetesVersion, ctl.Provider.Region()) + upToDate, err := defaultaddons.DoAddonsSupportMultiArch(ctl.Provider.EKS(), rawClient, kubernetesVersion, ctl.Provider.Region()) if err != nil { return err } diff --git a/pkg/addons/default/addons.go b/pkg/addons/default/addons.go index 945062ab6d..3a7e6ae7b0 100644 --- a/pkg/addons/default/addons.go +++ b/pkg/addons/default/addons.go @@ -1,11 +1,31 @@ package defaultaddons import ( + "github.com/aws/aws-sdk-go/service/eks/eksiface" + "github.com/pkg/errors" "github.com/weaveworks/eksctl/pkg/kubernetes" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" ) -func DoAddonsSupportMultiArch(clientSet kubernetes.Interface, rawClient kubernetes.RawClientInterface, controlPlaneVersion string, region string) (bool, error) { - kubeProxyUpToDate, err := IsKubeProxyUpToDate(clientSet, controlPlaneVersion) +type AddonInput struct { + RawClient kubernetes.RawClientInterface + EKSAPI eksiface.EKSAPI + ControlPlaneVersion string + Region string +} + +// DoAddonsSupportMultiArch checks if the coredns/kubeproxy/awsnode support multi arch nodegroups +// We know that AWS node requires 1.6.3+ to work, so we check for that +// Kubeproxy/coredns we don't know what version adds support, so we just ensure its up-to-date before proceeding. +// TODO: we should know what versions of kubeproxy/coredns added support, rather than always erroring if they are out of date +func DoAddonsSupportMultiArch(eksAPI eksiface.EKSAPI, rawClient kubernetes.RawClientInterface, controlPlaneVersion string, region string) (bool, error) { + input := AddonInput{ + RawClient: rawClient, + ControlPlaneVersion: controlPlaneVersion, + Region: region, + EKSAPI: eksAPI, + } + kubeProxyUpToDate, err := IsKubeProxyUpToDate(input) if err != nil { return true, err } @@ -13,7 +33,7 @@ func DoAddonsSupportMultiArch(clientSet kubernetes.Interface, rawClient kubernet return false, nil } - awsNodeUpToDate, err := DoesAWSNodeSupportMultiArch(rawClient, region) + awsNodeUpToDate, err := DoesAWSNodeSupportMultiArch(input) if err != nil { return true, err } @@ -21,9 +41,18 @@ func DoAddonsSupportMultiArch(clientSet kubernetes.Interface, rawClient kubernet return false, nil } - coreDNSUpToDate, err := IsCoreDNSUpToDate(rawClient, region, controlPlaneVersion) + coreDNSUpToDate, err := IsCoreDNSUpToDate(input) if err != nil { return true, err } return coreDNSUpToDate, nil } + +// LoadAsset return embedded manifest as a runtime.Object +func newList(data []byte) (*metav1.List, error) { + list, err := kubernetes.NewList(data) + if err != nil { + return nil, errors.Wrapf(err, "loading individual resources from manifest") + } + return list, nil +} diff --git a/pkg/addons/default/assets_test.go b/pkg/addons/default/assets_test.go index c3dcbb4cc9..7cd43cc904 100644 --- a/pkg/addons/default/assets_test.go +++ b/pkg/addons/default/assets_test.go @@ -8,7 +8,7 @@ func init() { // we must patch the manifest until we can use fake // clientset that supports CRDs - awsNode := string(awsNodeYaml) + awsNode := string(latestAWSNodeYaml) awsNodeParts := strings.Split(awsNode, "---\n") nonCRDs := []string{} @@ -21,5 +21,5 @@ func init() { awsNode = strings.Join(nonCRDs, "---\n") - awsNodeYaml = []byte(awsNode) + latestAWSNodeYaml = []byte(awsNode) } diff --git a/pkg/addons/default/aws_node.go b/pkg/addons/default/aws_node.go index 87784f41ce..84c1a11396 100644 --- a/pkg/addons/default/aws_node.go +++ b/pkg/addons/default/aws_node.go @@ -13,7 +13,6 @@ import ( metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "github.com/weaveworks/eksctl/pkg/addons" - "github.com/weaveworks/eksctl/pkg/kubernetes" // For go:embed _ "embed" @@ -28,11 +27,11 @@ const ( ) //go:embed assets/aws-node.yaml -var awsNodeYaml []byte +var latestAWSNodeYaml []byte // DoesAWSNodeSupportMultiArch makes sure awsnode supports ARM nodes -func DoesAWSNodeSupportMultiArch(rawClient kubernetes.RawClientInterface, region string) (bool, error) { - clusterDaemonSet, err := rawClient.ClientSet().AppsV1().DaemonSets(metav1.NamespaceSystem).Get(context.TODO(), AWSNode, metav1.GetOptions{}) +func DoesAWSNodeSupportMultiArch(input AddonInput) (bool, error) { + clusterDaemonSet, err := input.RawClient.ClientSet().AppsV1().DaemonSets(metav1.NamespaceSystem).Get(context.TODO(), AWSNode, metav1.GetOptions{}) if err != nil { if apierrs.IsNotFound(err) { logger.Warning("%q was not found", AWSNode) @@ -71,8 +70,8 @@ func DoesAWSNodeSupportMultiArch(rawClient kubernetes.RawClientInterface, region // UpdateAWSNode will update the `aws-node` add-on and returns true // if an update is available. -func UpdateAWSNode(rawClient kubernetes.RawClientInterface, region string, plan bool) (bool, error) { - clusterDaemonSet, err := rawClient.ClientSet().AppsV1().DaemonSets(metav1.NamespaceSystem).Get(context.TODO(), AWSNode, metav1.GetOptions{}) +func UpdateAWSNode(input AddonInput, plan bool) (bool, error) { + clusterDaemonSet, err := input.RawClient.ClientSet().AppsV1().DaemonSets(metav1.NamespaceSystem).Get(context.TODO(), AWSNode, metav1.GetOptions{}) if err != nil { if apierrs.IsNotFound(err) { logger.Warning("%q was not found", AWSNode) @@ -81,18 +80,18 @@ func UpdateAWSNode(rawClient kubernetes.RawClientInterface, region string, plan return false, errors.Wrapf(err, "getting %q", AWSNode) } - // if DaemonSets is present, go through our list of assets - list, err := newList(awsNodeYaml) + resourceList, err := newList(latestAWSNodeYaml) if err != nil { return false, err } tagMismatch := true - for _, rawObj := range list.Items { - resource, err := rawClient.NewRawResource(rawObj.Object) + for _, rawObj := range resourceList.Items { + resource, err := input.RawClient.NewRawResource(rawObj.Object) if err != nil { return false, err } + switch resource.GVK.Kind { case "DaemonSet": daemonSet, ok := resource.Info.Object.(*appsv1.DaemonSet) @@ -108,7 +107,7 @@ func UpdateAWSNode(rawClient kubernetes.RawClientInterface, region string, plan container.Image = awsNodeImageFormatPrefix + ":" + imageParts[1] initContainer.Image = awsNodeInitImageFormatPrefix + ":" + imageParts[1] - if err := addons.UseRegionalImage(&daemonSet.Spec.Template, region); err != nil { + if err := addons.UseRegionalImage(&daemonSet.Spec.Template, input.Region); err != nil { return false, err } diff --git a/pkg/addons/default/aws_node_test.go b/pkg/addons/default/aws_node_test.go index 2aeb90d008..f3365a277f 100644 --- a/pkg/addons/default/aws_node_test.go +++ b/pkg/addons/default/aws_node_test.go @@ -5,183 +5,158 @@ import ( . "github.com/onsi/ginkgo" . "github.com/onsi/gomega" - . "github.com/onsi/gomega/gstruct" - . "github.com/weaveworks/eksctl/pkg/addons/default" + da "github.com/weaveworks/eksctl/pkg/addons/default" "github.com/weaveworks/eksctl/pkg/testutils" + v1 "k8s.io/api/apps/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" ) -var _ = Describe("default addons - aws-node", func() { - Describe("properly checks for multi-architecture support", func() { - var ( - rawClient *testutils.FakeRawClient - ct *testutils.CollectionTracker - ) - loadSample := func(f string) { - sampleAddons := testutils.LoadSamples(f) - - rawClient = testutils.NewFakeRawClient() - - rawClient.AssumeObjectsMissing = true - - for _, item := range sampleAddons { - rc, err := rawClient.NewRawResource(item) - Expect(err).NotTo(HaveOccurred()) - _, err = rc.CreateOrReplace(false) - Expect(err).NotTo(HaveOccurred()) - } - - ct = rawClient.Collection - - Expect(ct.Updated()).To(BeEmpty()) - Expect(ct.Created()).NotTo(BeEmpty()) - Expect(ct.CreatedItems()).To(HaveLen(10)) +var _ = Describe("AWS Node", func() { + var ( + input da.AddonInput + rawClient *testutils.FakeRawClient + ) + + BeforeEach(func() { + rawClient = testutils.NewFakeRawClient() + input = da.AddonInput{ + RawClient: rawClient, + ControlPlaneVersion: "1.16.0", + Region: "eu-west-1", } + }) + + Describe("DoesAWSNodeSupportMultiArch", func() { It("reports that 1.15 sample needs an update", func() { - loadSample("testdata/sample-1.15.json") + loadSamples(rawClient, "testdata/sample-1.15.json") + input.ControlPlaneVersion = "1.15.0" rawClient.AssumeObjectsMissing = false - needsUpdate, err := DoesAWSNodeSupportMultiArch(rawClient, "eu-west-1") + needsUpdate, err := da.DoesAWSNodeSupportMultiArch(input) Expect(err).NotTo(HaveOccurred()) Expect(needsUpdate).To(BeFalse()) }) + It("reports that sample with 1.6.3-eksbuild.1 doesn't need an update", func() { - loadSample("testdata/sample-1.16-eksbuild.1.json") + loadSamples(rawClient, "testdata/sample-1.16-eksbuild.1.json") rawClient.AssumeObjectsMissing = false - needsUpdate, err := DoesAWSNodeSupportMultiArch(rawClient, "eu-west-1") + needsUpdate, err := da.DoesAWSNodeSupportMultiArch(input) Expect(err).NotTo(HaveOccurred()) Expect(needsUpdate).To(BeTrue()) }) + It("reports that sample with 1.7.6 doesn't need an update", func() { - loadSample("testdata/sample-1.16-v1.7.json") + loadSamples(rawClient, "testdata/sample-1.16-v1.7.json") rawClient.AssumeObjectsMissing = false - needsUpdate, err := DoesAWSNodeSupportMultiArch(rawClient, "eu-west-1") + needsUpdate, err := da.DoesAWSNodeSupportMultiArch(input) Expect(err).NotTo(HaveOccurred()) Expect(needsUpdate).To(BeTrue()) }) }) - Describe("can update aws-node add-on to multi-architecture images", func() { - var ( - rawClient *testutils.FakeRawClient - ct *testutils.CollectionTracker - ) - - It("can load sample for 1.15 and create objects that don't exist", func() { - sampleAddons := testutils.LoadSamples("testdata/sample-1.15.json") - - rawClient = testutils.NewFakeRawClient() - - rawClient.AssumeObjectsMissing = true - - for _, item := range sampleAddons { - rc, err := rawClient.NewRawResource(item) - Expect(err).NotTo(HaveOccurred()) - _, err = rc.CreateOrReplace(false) - Expect(err).NotTo(HaveOccurred()) - } - - ct = rawClient.Collection - - Expect(ct.Updated()).To(BeEmpty()) - Expect(ct.Created()).NotTo(BeEmpty()) - Expect(ct.CreatedItems()).To(HaveLen(10)) - }) - - It("has newly created objects", func() { - rawClient.ClientSetUseUpdatedObjects = false // must be set for initial verification, and for subsequent UpdateAWSNode - - awsNode, err := rawClient.ClientSet().AppsV1().DaemonSets(metav1.NamespaceSystem).Get(context.TODO(), AWSNode, metav1.GetOptions{}) - Expect(err).NotTo(HaveOccurred()) - Expect(awsNode.Spec.Template.Spec.Containers).To(HaveLen(1)) - Expect(awsNode.Spec.Template.Spec.Containers[0].Image).To( - Equal("602401143452.dkr.ecr.eu-west-1.amazonaws.com/amazon-k8s-cni:v1.5.7"), - ) - - }) - - It("can update 1.15 sample to latest multi-architecture image", func() { - rawClient.AssumeObjectsMissing = false - - preUpdateAwsNode, err := rawClient.ClientSet().AppsV1().DaemonSets(metav1.NamespaceSystem).Get(context.TODO(), AWSNode, metav1.GetOptions{}) - Expect(err).NotTo(HaveOccurred()) - _, err = UpdateAWSNode(rawClient, "eu-west-1", false) - Expect(err).NotTo(HaveOccurred()) - Expect(rawClient.Collection.UpdatedItems()).To(HaveLen(3)) - Expect(rawClient.Collection.UpdatedItems()).NotTo(ContainElement(PointTo(MatchFields(IgnoreMissing|IgnoreExtras, Fields{ - "TypeMeta": MatchFields(IgnoreMissing|IgnoreExtras, Fields{"Kind": Equal("ServiceAccount")}), - })))) - Expect(rawClient.Collection.CreatedItems()).To(HaveLen(10)) - - rawClient.ClientSetUseUpdatedObjects = true // for verification of updated objects + Describe("UpdateAWSNode", func() { + var preUpdateAwsNode *v1.DaemonSet + BeforeEach(func() { + loadSamples(rawClient, "testdata/sample-1.15.json") - awsNode, err := rawClient.ClientSet().AppsV1().DaemonSets(metav1.NamespaceSystem).Get(context.TODO(), AWSNode, metav1.GetOptions{}) + var err error + preUpdateAwsNode, err = rawClient.ClientSet().AppsV1().DaemonSets(metav1.NamespaceSystem).Get(context.TODO(), da.AWSNode, metav1.GetOptions{}) Expect(err).NotTo(HaveOccurred()) - Expect(awsNode.Spec.Template.Spec.Containers).To(HaveLen(1)) - Expect(awsNode.Spec.Template.Spec.Containers[0].Image).NotTo( - Equal(preUpdateAwsNode.Spec.Template.Spec.Containers[0].Image), - ) - Expect(awsNode.Spec.Template.Spec.InitContainers).To(HaveLen(1)) - Expect(awsNode.Spec.Template.Spec.InitContainers[0].Image).To( - HavePrefix("602401143452.dkr.ecr.eu-west-1.amazonaws.com/amazon-k8s-cni-init"), - ) - rawClient.ClearUpdated() }) - It("can update 1.15 sample for different region to multi-architecture image", func() { - rawClient.ClientSetUseUpdatedObjects = false // must be set for subsequent UpdateAWSNode - - preUpdateAwsNode, err := rawClient.ClientSet().AppsV1().DaemonSets(metav1.NamespaceSystem).Get(context.TODO(), AWSNode, metav1.GetOptions{}) - Expect(err).NotTo(HaveOccurred()) - _, err = UpdateAWSNode(rawClient, "us-east-1", false) - Expect(err).NotTo(HaveOccurred()) + When("it is out of date", func() { + It("updates it", func() { + input.Region = "us-east-1" - rawClient.ClientSetUseUpdatedObjects = true // for verification of updated objects + _, err := da.UpdateAWSNode(input, false) + Expect(err).NotTo(HaveOccurred()) - awsNode, err := rawClient.ClientSet().AppsV1().DaemonSets(metav1.NamespaceSystem).Get(context.TODO(), AWSNode, metav1.GetOptions{}) - Expect(err).NotTo(HaveOccurred()) - Expect(awsNode.Spec.Template.Spec.Containers).To(HaveLen(1)) - Expect(awsNode.Spec.Template.Spec.Containers[0].Image).NotTo( - Equal(preUpdateAwsNode.Spec.Template.Spec.Containers[0].Image), - ) - Expect(awsNode.Spec.Template.Spec.InitContainers).To(HaveLen(1)) - Expect(awsNode.Spec.Template.Spec.InitContainers[0].Image).To( - HavePrefix("602401143452.dkr.ecr.us-east-1.amazonaws.com/amazon-k8s-cni-init"), - ) + awsNode, err := rawClient.ClientSet().AppsV1().DaemonSets(metav1.NamespaceSystem).Get(context.TODO(), da.AWSNode, metav1.GetOptions{}) + Expect(err).NotTo(HaveOccurred()) + Expect(awsNode.Spec.Template.Spec.Containers).To(HaveLen(1)) + Expect(awsNode.Spec.Template.Spec.Containers[0].Image).To( + Equal("602401143452.dkr.ecr.us-east-1.amazonaws.com/amazon-k8s-cni:v1.9.3"), + ) + Expect(awsNode.Spec.Template.Spec.InitContainers).To(HaveLen(1)) + Expect(awsNode.Spec.Template.Spec.InitContainers[0].Image).To( + Equal("602401143452.dkr.ecr.us-east-1.amazonaws.com/amazon-k8s-cni-init:v1.9.3"), + ) + }) }) - It("can update 1.15 sample for china region to multi-architecture image", func() { - rawClient.ClientSetUseUpdatedObjects = false // must be set for subsequent UpdateAWSNode - - preUpdateAwsNode, err := rawClient.ClientSet().AppsV1().DaemonSets(metav1.NamespaceSystem).Get(context.TODO(), AWSNode, metav1.GetOptions{}) - Expect(err).NotTo(HaveOccurred()) - _, err = UpdateAWSNode(rawClient, "cn-northwest-1", false) - Expect(err).NotTo(HaveOccurred()) + When("using a chinese region", func() { + It("updates it and uses the amazonaws.com.cn address", func() { + input.Region = "cn-northwest-1" - rawClient.ClientSetUseUpdatedObjects = true // for verification of updated objects + _, err := da.UpdateAWSNode(input, false) + Expect(err).NotTo(HaveOccurred()) - awsNode, err := rawClient.ClientSet().AppsV1().DaemonSets(metav1.NamespaceSystem).Get(context.TODO(), AWSNode, metav1.GetOptions{}) - Expect(err).NotTo(HaveOccurred()) - Expect(awsNode.Spec.Template.Spec.Containers).To(HaveLen(1)) - Expect(awsNode.Spec.Template.Spec.Containers[0].Image).NotTo( - Equal(preUpdateAwsNode.Spec.Template.Spec.Containers[0].Image), - ) - Expect(awsNode.Spec.Template.Spec.InitContainers).To(HaveLen(1)) - Expect(awsNode.Spec.Template.Spec.InitContainers[0].Image).To( - HavePrefix("961992271922.dkr.ecr.cn-northwest-1.amazonaws.com.cn/amazon-k8s-cni-init"), - ) + awsNode, err := rawClient.ClientSet().AppsV1().DaemonSets(metav1.NamespaceSystem).Get(context.TODO(), da.AWSNode, metav1.GetOptions{}) + Expect(err).NotTo(HaveOccurred()) + Expect(awsNode.Spec.Template.Spec.Containers).To(HaveLen(1)) + Expect(awsNode.Spec.Template.Spec.Containers[0].Image).To( + Equal("961992271922.dkr.ecr.cn-northwest-1.amazonaws.com.cn/amazon-k8s-cni:v1.9.3"), + ) + Expect(awsNode.Spec.Template.Spec.InitContainers).To(HaveLen(1)) + Expect(awsNode.Spec.Template.Spec.InitContainers[0].Image).To( + Equal("961992271922.dkr.ecr.cn-northwest-1.amazonaws.com.cn/amazon-k8s-cni-init:v1.9.3"), + ) + }) }) - It("detects matching image version when determining plan", func() { - // updating from latest to latest needs no updating - needsUpdate, err := UpdateAWSNode(rawClient, "eu-west-2", true) - Expect(err).NotTo(HaveOccurred()) - Expect(needsUpdate).To(BeFalse()) + When("dry run is true", func() { + When("it needs an update", func() { + It("returns true", func() { + needsUpdate, err := da.UpdateAWSNode(input, true) + Expect(err).NotTo(HaveOccurred()) + Expect(needsUpdate).To(BeTrue()) + + awsNode, err := rawClient.ClientSet().AppsV1().DaemonSets(metav1.NamespaceSystem).Get(context.TODO(), da.AWSNode, metav1.GetOptions{}) + Expect(err).NotTo(HaveOccurred()) + //should be unchanged + Expect(awsNode.Spec).To(Equal(preUpdateAwsNode.Spec)) + }) + }) + + When("it doesn't need an update", func() { + BeforeEach(func() { + rawClient = testutils.NewFakeRawClient() + input.RawClient = rawClient + loadSamples(rawClient, "assets/aws-node.yaml") + + var err error + preUpdateAwsNode, err = rawClient.ClientSet().AppsV1().DaemonSets(metav1.NamespaceSystem).Get(context.TODO(), da.AWSNode, metav1.GetOptions{}) + Expect(err).NotTo(HaveOccurred()) + }) + + It("returns false", func() { + needsUpdate, err := da.UpdateAWSNode(input, true) + Expect(err).NotTo(HaveOccurred()) + Expect(needsUpdate).To(BeFalse()) + + awsNode, err := rawClient.ClientSet().AppsV1().DaemonSets(metav1.NamespaceSystem).Get(context.TODO(), da.AWSNode, metav1.GetOptions{}) + Expect(err).NotTo(HaveOccurred()) + //should be unchanged + Expect(awsNode.Spec).To(Equal(preUpdateAwsNode.Spec)) + }) + }) }) }) }) + +func loadSamples(rawClient *testutils.FakeRawClient, samplesPath string) { + sampleAddons := testutils.LoadSamples(samplesPath) + rawClient.AssumeObjectsMissing = true + + for _, item := range sampleAddons { + rc, err := rawClient.NewRawResource(item) + Expect(err).NotTo(HaveOccurred()) + _, err = rc.CreateOrReplace(false) + Expect(err).NotTo(HaveOccurred()) + } +} diff --git a/pkg/addons/default/coredns.go b/pkg/addons/default/coredns.go index 204f65639b..7f8a367f43 100644 --- a/pkg/addons/default/coredns.go +++ b/pkg/addons/default/coredns.go @@ -16,7 +16,6 @@ import ( api "github.com/weaveworks/eksctl/pkg/apis/eksctl.io/v1alpha5" "github.com/weaveworks/eksctl/pkg/fargate/coredns" - "github.com/weaveworks/eksctl/pkg/kubernetes" // For go:embed _ "embed" @@ -32,8 +31,8 @@ const ( //go:embed assets/coredns*.json var coreDNSDir embed.FS -func IsCoreDNSUpToDate(rawClient kubernetes.RawClientInterface, region, controlPlaneVersion string) (bool, error) { - kubeDNSDeployment, err := rawClient.ClientSet().AppsV1().Deployments(metav1.NamespaceSystem).Get(context.TODO(), CoreDNS, metav1.GetOptions{}) +func IsCoreDNSUpToDate(input AddonInput) (bool, error) { + kubeDNSDeployment, err := input.RawClient.ClientSet().AppsV1().Deployments(metav1.NamespaceSystem).Get(context.TODO(), CoreDNS, metav1.GetOptions{}) if err != nil { if apierrs.IsNotFound(err) { logger.Warning("%q was not found", CoreDNS) @@ -43,13 +42,13 @@ func IsCoreDNSUpToDate(rawClient kubernetes.RawClientInterface, region, controlP } // if Deployment is present, go through our list of assets - list, err := loadAssetCoreDNS(controlPlaneVersion) + list, err := loadAssetCoreDNS(input.ControlPlaneVersion) if err != nil { return false, err } for _, rawObj := range list.Items { - resource, err := rawClient.NewRawResource(rawObj.Object) + resource, err := input.RawClient.NewRawResource(rawObj.Object) if err != nil { return false, err } @@ -63,7 +62,7 @@ func IsCoreDNSUpToDate(rawClient kubernetes.RawClientInterface, region, controlP if !ok { return false, fmt.Errorf("expected type %T; got %T", &appsv1.Deployment{}, resource.Info.Object) } - if err := addons.UseRegionalImage(&deployment.Spec.Template, region); err != nil { + if err := addons.UseRegionalImage(&deployment.Spec.Template, input.Region); err != nil { return false, err } if computeType, ok := kubeDNSDeployment.Spec.Template.Annotations[coredns.ComputeTypeAnnotationKey]; ok { @@ -83,8 +82,8 @@ func IsCoreDNSUpToDate(rawClient kubernetes.RawClientInterface, region, controlP // UpdateCoreDNS will update the `coredns` add-on and returns true // if an update is available -func UpdateCoreDNS(rawClient kubernetes.RawClientInterface, region, controlPlaneVersion string, plan bool) (bool, error) { - kubeDNSSevice, err := rawClient.ClientSet().CoreV1().Services(metav1.NamespaceSystem).Get(context.TODO(), KubeDNS, metav1.GetOptions{}) +func UpdateCoreDNS(input AddonInput, plan bool) (bool, error) { + kubeDNSSevice, err := input.RawClient.ClientSet().CoreV1().Services(metav1.NamespaceSystem).Get(context.TODO(), KubeDNS, metav1.GetOptions{}) if err != nil { if apierrs.IsNotFound(err) { logger.Warning("%q service was not found", KubeDNS) @@ -93,7 +92,7 @@ func UpdateCoreDNS(rawClient kubernetes.RawClientInterface, region, controlPlane return false, errors.Wrapf(err, "getting %q service", KubeDNS) } - kubeDNSDeployment, err := rawClient.ClientSet().AppsV1().Deployments(metav1.NamespaceSystem).Get(context.TODO(), CoreDNS, metav1.GetOptions{}) + kubeDNSDeployment, err := input.RawClient.ClientSet().AppsV1().Deployments(metav1.NamespaceSystem).Get(context.TODO(), CoreDNS, metav1.GetOptions{}) if err != nil { if apierrs.IsNotFound(err) { logger.Warning("%q was not found", CoreDNS) @@ -103,14 +102,14 @@ func UpdateCoreDNS(rawClient kubernetes.RawClientInterface, region, controlPlane } // if Deployment is present, go through our list of assets - list, err := loadAssetCoreDNS(controlPlaneVersion) + list, err := loadAssetCoreDNS(input.ControlPlaneVersion) if err != nil { return false, err } tagMismatch := true for _, rawObj := range list.Items { - resource, err := rawClient.NewRawResource(rawObj.Object) + resource, err := input.RawClient.NewRawResource(rawObj.Object) if err != nil { return false, err } @@ -124,7 +123,7 @@ func UpdateCoreDNS(rawClient kubernetes.RawClientInterface, region, controlPlane return false, fmt.Errorf("expected type %T; got %T", &appsv1.Deployment{}, resource.Info.Object) } template := &deployment.Spec.Template - if err := addons.UseRegionalImage(template, region); err != nil { + if err := addons.UseRegionalImage(template, input.Region); err != nil { return false, err } if computeType, ok := kubeDNSDeployment.Spec.Template.Annotations[coredns.ComputeTypeAnnotationKey]; ok { diff --git a/pkg/addons/default/coredns_test.go b/pkg/addons/default/coredns_test.go index 5ff1bcc296..94a2922341 100644 --- a/pkg/addons/default/coredns_test.go +++ b/pkg/addons/default/coredns_test.go @@ -16,6 +16,7 @@ var _ = Describe("default addons - coredns", func() { var ( rawClient *testutils.FakeRawClient ct *testutils.CollectionTracker + input da.AddonInput region string controlPlaneVersion string kubernetesVersion string @@ -28,6 +29,12 @@ var _ = Describe("default addons - coredns", func() { region = "eu-west-2" controlPlaneVersion = "1.17.x" kubernetesVersion = "1.16" + + input = da.AddonInput{ + RawClient: rawClient, + ControlPlaneVersion: controlPlaneVersion, + Region: region, + } }) Context("UpdateCoreDNS", func() { @@ -41,7 +48,7 @@ var _ = Describe("default addons - coredns", func() { }) It("updates coredns to the correct version", func() { - _, err := da.UpdateCoreDNS(rawClient, region, controlPlaneVersion, false) + _, err := da.UpdateCoreDNS(input, false) Expect(err).NotTo(HaveOccurred()) updateReqs := []string{ @@ -67,17 +74,17 @@ var _ = Describe("default addons - coredns", func() { Context("IsCoreDNSUpToDate", func() { BeforeEach(func() { createCoreDNSFromTestSample(rawClient, ct, kubernetesVersion) - _, err := da.UpdateCoreDNS(rawClient, region, controlPlaneVersion, false) + _, err := da.UpdateCoreDNS(input, false) Expect(err).NotTo(HaveOccurred()) }) Context("when CoreDNS is NOT up to date", func() { BeforeEach(func() { - controlPlaneVersion = "1.18.x" + input.ControlPlaneVersion = "1.18.x" }) It("reports 'false'", func() { - isUpToDate, err := da.IsCoreDNSUpToDate(rawClient, region, controlPlaneVersion) + isUpToDate, err := da.IsCoreDNSUpToDate(input) Expect(err).NotTo(HaveOccurred()) Expect(isUpToDate).To(Equal(false)) }) @@ -85,7 +92,7 @@ var _ = Describe("default addons - coredns", func() { Context("when CoreDNS is up to date", func() { It("reports 'true'", func() { - isUpToDate, err := da.IsCoreDNSUpToDate(rawClient, region, controlPlaneVersion) + isUpToDate, err := da.IsCoreDNSUpToDate(input) Expect(err).NotTo(HaveOccurred()) Expect(isUpToDate).To(Equal(true)) }) diff --git a/pkg/addons/default/helpers.go b/pkg/addons/default/helpers.go deleted file mode 100644 index 3f1e1fefaa..0000000000 --- a/pkg/addons/default/helpers.go +++ /dev/null @@ -1,16 +0,0 @@ -package defaultaddons - -import ( - "github.com/pkg/errors" - "github.com/weaveworks/eksctl/pkg/kubernetes" - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" -) - -// LoadAsset return embedded manifest as a runtime.Object -func newList(data []byte) (*metav1.List, error) { - list, err := kubernetes.NewList(data) - if err != nil { - return nil, errors.Wrapf(err, "loading individual resources from manifest") - } - return list, nil -} diff --git a/pkg/addons/default/helpers_test.go b/pkg/addons/default/helpers_test.go deleted file mode 100644 index 5aff765cf9..0000000000 --- a/pkg/addons/default/helpers_test.go +++ /dev/null @@ -1,36 +0,0 @@ -package defaultaddons_test - -import ( - "context" - - . "github.com/onsi/ginkgo" - . "github.com/onsi/gomega" - - . "github.com/weaveworks/eksctl/pkg/addons/default" - - "github.com/weaveworks/eksctl/pkg/testutils" - - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" -) - -var _ = Describe("default addons", func() { - Describe("can load a set of resources and create a fake client", func() { - It("can create the fake client and verify objects get loaded client", func() { - clientSet, _ := testutils.NewFakeClientSetWithSamples("testdata/sample-1.16.json") - - nsl, err := clientSet.CoreV1().Namespaces().List(context.TODO(), metav1.ListOptions{}) - Expect(err).NotTo(HaveOccurred()) - Expect(nsl.Items).To(HaveLen(0)) - - dl, err := clientSet.AppsV1().Deployments(metav1.NamespaceAll).List(context.TODO(), metav1.ListOptions{}) - Expect(err).NotTo(HaveOccurred()) - Expect(dl.Items).To(HaveLen(1)) - Expect(dl.Items[0].Spec.Template.Spec.Containers).To(HaveLen(1)) - - kubeProxy, err := clientSet.AppsV1().DaemonSets(metav1.NamespaceSystem).Get(context.TODO(), KubeProxy, metav1.GetOptions{}) - Expect(err).NotTo(HaveOccurred()) - Expect(kubeProxy).NotTo(BeNil()) - Expect(kubeProxy.Spec.Template.Spec.Containers).To(HaveLen(1)) - }) - }) -}) diff --git a/pkg/addons/default/kube_proxy.go b/pkg/addons/default/kube_proxy.go index 7e04bb9b72..c53a2faed1 100644 --- a/pkg/addons/default/kube_proxy.go +++ b/pkg/addons/default/kube_proxy.go @@ -3,13 +3,18 @@ package defaultaddons import ( "context" "fmt" + "sort" "strings" v1 "k8s.io/api/apps/v1" + "github.com/aws/aws-sdk-go/aws" + "github.com/aws/aws-sdk-go/service/eks" + "github.com/aws/aws-sdk-go/service/eks/eksiface" "github.com/kris-nova/logger" "github.com/pkg/errors" + "github.com/hashicorp/go-version" "github.com/weaveworks/eksctl/pkg/addons" "github.com/weaveworks/eksctl/pkg/printers" @@ -18,7 +23,6 @@ import ( metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "github.com/weaveworks/eksctl/pkg/utils" - "k8s.io/client-go/kubernetes" ) const ( @@ -28,8 +32,8 @@ const ( ArchLabel = "kubernetes.io/arch" ) -func IsKubeProxyUpToDate(clientSet kubernetes.Interface, controlPlaneVersion string) (bool, error) { - d, err := clientSet.AppsV1().DaemonSets(metav1.NamespaceSystem).Get(context.TODO(), KubeProxy, metav1.GetOptions{}) +func IsKubeProxyUpToDate(input AddonInput) (bool, error) { + d, err := input.RawClient.ClientSet().AppsV1().DaemonSets(metav1.NamespaceSystem).Get(context.TODO(), KubeProxy, metav1.GetOptions{}) if err != nil { if apierrs.IsNotFound(err) { logger.Warning("%q was not found", KubeProxy) @@ -41,7 +45,12 @@ func IsKubeProxyUpToDate(clientSet kubernetes.Interface, controlPlaneVersion str return false, fmt.Errorf("%s has %d containers, expected at least 1", KubeProxy, numContainers) } - desiredTag, err := kubeProxyImageTag(controlPlaneVersion) + greaterThanOrEqualTo1_18, err := utils.IsMinVersion(api.Version1_18, input.ControlPlaneVersion) + if err != nil { + return false, err + } + + desiredTag, err := getLatestKubeProxyImage(input, greaterThanOrEqualTo1_18) if err != nil { return false, err } @@ -53,11 +62,11 @@ func IsKubeProxyUpToDate(clientSet kubernetes.Interface, controlPlaneVersion str return desiredTag == imageTag, nil } -// UpdateKubeProxy updates image tag for kube-system:daemonset/kube-proxy based to match controlPlaneVersion -func UpdateKubeProxy(clientSet kubernetes.Interface, controlPlaneVersion string, plan bool) (bool, error) { +// UpdateKubeProxy updates image tag for kube-system:daemonset/kube-proxy based to match ControlPlaneVersion +func UpdateKubeProxy(input AddonInput, plan bool) (bool, error) { printer := printers.NewJSONPrinter() - d, err := clientSet.AppsV1().DaemonSets(metav1.NamespaceSystem).Get(context.TODO(), KubeProxy, metav1.GetOptions{}) + d, err := input.RawClient.ClientSet().AppsV1().DaemonSets(metav1.NamespaceSystem).Get(context.TODO(), KubeProxy, metav1.GetOptions{}) if err != nil { if apierrs.IsNotFound(err) { logger.Warning("%q was not found", KubeProxy) @@ -67,11 +76,11 @@ func UpdateKubeProxy(clientSet kubernetes.Interface, controlPlaneVersion string, } archLabel := ArchLabel - isMinVersion, err := utils.IsMinVersion(api.Version1_18, controlPlaneVersion) + greaterThanOrEqualTo1_18, err := utils.IsMinVersion(api.Version1_18, input.ControlPlaneVersion) if err != nil { return false, err } - if !isMinVersion { + if !greaterThanOrEqualTo1_18 { archLabel = ArchBetaLabel } @@ -95,11 +104,10 @@ func UpdateKubeProxy(clientSet kubernetes.Interface, controlPlaneVersion string, return false, fmt.Errorf("unexpected image format %q for %q", *image, KubeProxy) } - desiredTag, err := kubeProxyImageTag(controlPlaneVersion) + desiredTag, err := getLatestKubeProxyImage(input, greaterThanOrEqualTo1_18) if err != nil { return false, err } - if imageParts[1] == desiredTag && hasArm64NodeSelector { logger.Debug("imageParts = %v, desiredTag = %s", imageParts, desiredTag) logger.Info("%q is already up-to-date", KubeProxy) @@ -122,7 +130,7 @@ func UpdateKubeProxy(clientSet kubernetes.Interface, controlPlaneVersion string, addArm64NodeSelector(d, archLabel) } - if _, err := clientSet.AppsV1().DaemonSets(metav1.NamespaceSystem).Update(context.TODO(), d, metav1.UpdateOptions{}); err != nil { + if _, err := input.RawClient.ClientSet().AppsV1().DaemonSets(metav1.NamespaceSystem).Update(context.TODO(), d, metav1.UpdateOptions{}); err != nil { return false, err } @@ -161,6 +169,95 @@ func addArm64NodeSelector(daemonSet *v1.DaemonSet, archLabel string) { } } -func kubeProxyImageTag(controlPlaneVersion string) (string, error) { - return fmt.Sprintf("v%s-eksbuild.1", controlPlaneVersion), nil +func getLatestKubeProxyImage(input AddonInput, greaterThanOrEqualTo1_18 bool) (string, error) { + defaultClusterVersion := generateImageVersionFromClusterVersion(input.ControlPlaneVersion) + // EKS Addons API only works for 1.18 and above + if !greaterThanOrEqualTo1_18 { + return defaultClusterVersion, nil + } + + latestEKSReportedVersion, err := getLatestImageVersionFromEKS(input.EKSAPI, input.ControlPlaneVersion) + if err != nil { + return "", err + } + + // Sometimes the EKS API is ahead, sometimes behind. Pick whichever is latest + eksVersionIsGreaterThanDefaultVersion, err := versionGreaterThan(latestEKSReportedVersion, defaultClusterVersion) + if err != nil { + return "", err + } + + if eksVersionIsGreaterThanDefaultVersion { + return latestEKSReportedVersion, nil + } + + return defaultClusterVersion, nil +} + +func versionGreaterThan(v1, v2 string) (bool, error) { + v1Version, err := parseVersion(v1) + if err != nil { + return false, err + } + v2Version, err := parseVersion(v2) + if err != nil { + return false, err + } + return v1Version.GreaterThan(v2Version), nil +} + +func generateImageVersionFromClusterVersion(controlPlaneVersion string) string { + return fmt.Sprintf("v%s-eksbuild.1", controlPlaneVersion) +} + +func getLatestImageVersionFromEKS(eksAPI eksiface.EKSAPI, controlPlaneVersion string) (string, error) { + controlPlaneMajorMinor, err := versionWithOnlyMajorAndMinor(controlPlaneVersion) + if err != nil { + return "", err + } + input := &eks.DescribeAddonVersionsInput{ + KubernetesVersion: &controlPlaneMajorMinor, + AddonName: aws.String(KubeProxy), + } + + addonInfos, err := eksAPI.DescribeAddonVersions(input) + if err != nil { + return "", fmt.Errorf("failed to describe addon versions: %v", err) + } + + if len(addonInfos.Addons) == 0 || len(addonInfos.Addons[0].AddonVersions) == 0 { + return "", fmt.Errorf("no versions available for %q", KubeProxy) + } + + var versions []*version.Version + for _, addonVersionInfo := range addonInfos.Addons[0].AddonVersions { + v, err := parseVersion(*addonVersionInfo.AddonVersion) + if err != nil { + return "", err + } + + versions = append(versions, v) + } + + sort.SliceStable(versions, func(i, j int) bool { + return versions[j].LessThan(versions[i]) + }) + return versions[0].Original(), nil +} + +func versionWithOnlyMajorAndMinor(v string) (string, error) { + parsedVersion, err := parseVersion(v) + if err != nil { + return "", err + } + parsedVersionSegments := parsedVersion.Segments() + return fmt.Sprintf("%d.%d", parsedVersionSegments[0], parsedVersionSegments[1]), nil +} + +func parseVersion(v string) (*version.Version, error) { + version, err := version.NewVersion(v) + if err != nil { + return nil, fmt.Errorf("failed to parse version %q: %w", v, err) + } + return version, nil } diff --git a/pkg/addons/default/kube_proxy_test.go b/pkg/addons/default/kube_proxy_test.go index c48a4aea88..131cbb0a85 100644 --- a/pkg/addons/default/kube_proxy_test.go +++ b/pkg/addons/default/kube_proxy_test.go @@ -2,44 +2,259 @@ package defaultaddons_test import ( "context" + "fmt" + "github.com/aws/aws-sdk-go/aws" . "github.com/onsi/ginkgo" . "github.com/onsi/gomega" - . "github.com/weaveworks/eksctl/pkg/addons/default" + awseks "github.com/aws/aws-sdk-go/service/eks" + da "github.com/weaveworks/eksctl/pkg/addons/default" + "github.com/weaveworks/eksctl/pkg/kubernetes" "github.com/weaveworks/eksctl/pkg/testutils" + "github.com/weaveworks/eksctl/pkg/testutils/mockprovider" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - "k8s.io/client-go/kubernetes/fake" ) -var _ = Describe("default addons - kube-proxy", func() { - Context("UpdateKubeProxyImageTag", func() { - var ( - clientSet *fake.Clientset - ) +var _ = Describe("KubeProxy", func() { + var ( + clientSet kubernetes.Interface + input da.AddonInput + mockProvider *mockprovider.MockProvider + ) + Context("IsKubeProxyUpToDate", func() { BeforeEach(func() { - clientSet, _ = testutils.NewFakeClientSetWithSamples("testdata/sample-1.15.json") + mockProvider = mockprovider.NewMockProvider() + input = da.AddonInput{ + Region: "eu-west-1", + EKSAPI: mockProvider.EKS(), + ControlPlaneVersion: "1.15.11", + } + }) + When("its not up-to-date", func() { + BeforeEach(func() { + rawClient := testutils.NewFakeRawClientWithSamples("testdata/sample-1.16-eksbuild.1.json") + input.RawClient = rawClient + clientSet = rawClient.ClientSet() + + }) + + It("returns false", func() { + needsUpdating, err := da.IsKubeProxyUpToDate(input) + Expect(err).NotTo(HaveOccurred()) + Expect(needsUpdating).To(BeFalse()) + }) + }) + + When("when its up-to-date", func() { + BeforeEach(func() { + //1.15.11 image tag + rawClient := testutils.NewFakeRawClientWithSamples("testdata/sample-1.15-eksbuild.1.json") + input.RawClient = rawClient + clientSet = rawClient.ClientSet() + }) + + It("returns true", func() { + needsUpdating, err := da.IsKubeProxyUpToDate(input) + Expect(err).NotTo(HaveOccurred()) + Expect(needsUpdating).To(BeTrue()) + }) + }) + + When("it doesn't exist", func() { + BeforeEach(func() { + rawClient := testutils.NewFakeRawClient() + input.RawClient = rawClient + clientSet = rawClient.ClientSet() + }) + + // if it doesn't exist it doesn't need updating, so its up to date ¯\_(ツ)_/¯ according to #2667 + It("returns true", func() { + needsUpdating, err := da.IsKubeProxyUpToDate(input) + Expect(err).NotTo(HaveOccurred()) + Expect(needsUpdating).To(BeTrue()) + }) + }) + + When("it has an existing invalid image tag", func() { + BeforeEach(func() { + rawClient := testutils.NewFakeRawClientWithSamples("testdata/sample-1.15-invalid-image.json") + input.RawClient = rawClient + clientSet = rawClient.ClientSet() + }) + It("errors", func() { + _, err := da.IsKubeProxyUpToDate(input) + Expect(err).To(HaveOccurred()) + }) + }) + }) + + Context("UpdateKubeProxyImageTag", func() { + BeforeEach(func() { + rawClient := testutils.NewFakeRawClientWithSamples("testdata/sample-1.15.json") + clientSet = rawClient.ClientSet() + mockProvider = mockprovider.NewMockProvider() + input = da.AddonInput{ + RawClient: rawClient, + ControlPlaneVersion: "1.16.0", + Region: "eu-west-1", + EKSAPI: mockProvider.EKS(), + } }) It("can update to multi-architecture image based on control plane version", func() { - _, err := UpdateKubeProxy(clientSet, "1.16.0", false) + _, err := da.UpdateKubeProxy(input, false) Expect(err).NotTo(HaveOccurred()) Expect(kubeProxyImage(clientSet)).To(Equal("602401143452.dkr.ecr.eu-west-1.amazonaws.com/eks/kube-proxy:v1.16.0-eksbuild.1")) Expect(kubeProxyNodeSelectorValues(clientSet)).To(ConsistOf("amd64", "arm64")) }) It("can dry-run update based on control plane version", func() { - _, err := UpdateKubeProxy(clientSet, "1.16.1", true) + input.ControlPlaneVersion = "1.16.1" + _, err := da.UpdateKubeProxy(input, true) Expect(err).NotTo(HaveOccurred()) Expect(kubeProxyImage(clientSet)).To(Equal("602401143452.dkr.ecr.eu-west-1.amazonaws.com/eks/kube-proxy:v1.15.11")) }) + + When("the cluster version is 1.18 or newer", func() { + BeforeEach(func() { + input.ControlPlaneVersion = "1.18.1" + }) + + When("the version reported by EKS API is more up-to-date than the default cluster version", func() { + BeforeEach(func() { + mockProvider.MockEKS().On("DescribeAddonVersions", &awseks.DescribeAddonVersionsInput{ + AddonName: aws.String("kube-proxy"), + KubernetesVersion: aws.String("1.18"), + }).Return(&awseks.DescribeAddonVersionsOutput{ + Addons: []*awseks.AddonInfo{ + { + AddonName: aws.String("kube-proxy"), + AddonVersions: []*awseks.AddonVersionInfo{ + { + AddonVersion: aws.String("v1.17.0-eksbuild.1"), + }, + { + //latest, unordered list to ensure we sort correctly + AddonVersion: aws.String("v1.18.1-eksbuild.2"), + }, + { + AddonVersion: aws.String("v1.18.1-eksbuild.1"), + }, + }, + }, + }, + }, nil) + }) + + It("uses the image version from the EKS api", func() { + _, err := da.UpdateKubeProxy(input, false) + Expect(err).NotTo(HaveOccurred()) + Expect(kubeProxyImage(clientSet)).To(Equal("602401143452.dkr.ecr.eu-west-1.amazonaws.com/eks/kube-proxy:v1.18.1-eksbuild.2")) + }) + }) + + When("the version reported by EKS API is behind the default cluster version", func() { + BeforeEach(func() { + mockProvider.MockEKS().On("DescribeAddonVersions", &awseks.DescribeAddonVersionsInput{ + AddonName: aws.String("kube-proxy"), + KubernetesVersion: aws.String("1.18"), + }).Return(&awseks.DescribeAddonVersionsOutput{ + Addons: []*awseks.AddonInfo{ + { + AddonName: aws.String("kube-proxy"), + AddonVersions: []*awseks.AddonVersionInfo{ + { + AddonVersion: aws.String("v1.17.0-eksbuild.1"), + }, + { + //latest, unordered list to ensure we sort correctly + //behind the default-cluster version 1.18.1-eksbuild.1 + AddonVersion: aws.String("v1.18.0-eksbuild.2"), + }, + { + AddonVersion: aws.String("v1.18.0-eksbuild.1"), + }, + }, + }, + }, + }, nil) + }) + + It("uses the default cluster version", func() { + _, err := da.UpdateKubeProxy(input, false) + Expect(err).NotTo(HaveOccurred()) + Expect(kubeProxyImage(clientSet)).To(Equal("602401143452.dkr.ecr.eu-west-1.amazonaws.com/eks/kube-proxy:v1.18.1-eksbuild.1")) + }) + }) + + When("there are no versions returned", func() { + BeforeEach(func() { + mockProvider.MockEKS().On("DescribeAddonVersions", &awseks.DescribeAddonVersionsInput{ + AddonName: aws.String("kube-proxy"), + KubernetesVersion: aws.String("1.18"), + }).Return(&awseks.DescribeAddonVersionsOutput{ + Addons: []*awseks.AddonInfo{ + { + AddonName: aws.String("kube-proxy"), + AddonVersions: []*awseks.AddonVersionInfo{}, + }, + }, + }, nil) + }) + + It("returns an error", func() { + _, err := da.UpdateKubeProxy(input, false) + Expect(err).To(MatchError(ContainSubstring("no versions available for \"kube-proxy\""))) + }) + }) + + When("there are no valid versions returned", func() { + BeforeEach(func() { + mockProvider.MockEKS().On("DescribeAddonVersions", &awseks.DescribeAddonVersionsInput{ + AddonName: aws.String("kube-proxy"), + KubernetesVersion: aws.String("1.18"), + }).Return(&awseks.DescribeAddonVersionsOutput{ + Addons: []*awseks.AddonInfo{ + { + AddonName: aws.String("kube-proxy"), + AddonVersions: []*awseks.AddonVersionInfo{ + { + AddonVersion: aws.String("not-a.1valid-version!?"), + }, + }, + }, + }, + }, nil) + }) + + It("returns an error", func() { + _, err := da.UpdateKubeProxy(input, false) + Expect(err).To(MatchError(ContainSubstring("failed to parse version"))) + }) + }) + + When("describing the addon errors", func() { + BeforeEach(func() { + mockProvider.MockEKS().On("DescribeAddonVersions", &awseks.DescribeAddonVersionsInput{ + AddonName: aws.String("kube-proxy"), + KubernetesVersion: aws.String("1.18"), + }).Return(&awseks.DescribeAddonVersionsOutput{}, fmt.Errorf("foo")) + }) + + It("returns an error", func() { + _, err := da.UpdateKubeProxy(input, false) + Expect(err).To(MatchError(ContainSubstring("failed to describe addon versions: foo"))) + }) + }) + }) }) }) -func kubeProxyImage(clientSet *fake.Clientset) string { - kubeProxy, err := clientSet.AppsV1().DaemonSets(metav1.NamespaceSystem).Get(context.TODO(), KubeProxy, metav1.GetOptions{}) +func kubeProxyImage(clientSet kubernetes.Interface) string { + kubeProxy, err := clientSet.AppsV1().DaemonSets(metav1.NamespaceSystem).Get(context.TODO(), da.KubeProxy, metav1.GetOptions{}) Expect(err).NotTo(HaveOccurred()) Expect(kubeProxy).NotTo(BeNil()) @@ -48,8 +263,8 @@ func kubeProxyImage(clientSet *fake.Clientset) string { return kubeProxy.Spec.Template.Spec.Containers[0].Image } -func kubeProxyNodeSelectorValues(clientSet *fake.Clientset) []string { - kubeProxy, err := clientSet.AppsV1().DaemonSets(metav1.NamespaceSystem).Get(context.TODO(), KubeProxy, metav1.GetOptions{}) +func kubeProxyNodeSelectorValues(clientSet kubernetes.Interface) []string { + kubeProxy, err := clientSet.AppsV1().DaemonSets(metav1.NamespaceSystem).Get(context.TODO(), da.KubeProxy, metav1.GetOptions{}) Expect(err).NotTo(HaveOccurred()) Expect(kubeProxy).NotTo(BeNil()) diff --git a/pkg/addons/default/testdata/sample-1.15-eksbuild.1.json b/pkg/addons/default/testdata/sample-1.15-eksbuild.1.json new file mode 100644 index 0000000000..b83bd89915 --- /dev/null +++ b/pkg/addons/default/testdata/sample-1.15-eksbuild.1.json @@ -0,0 +1,798 @@ +{ + "apiVersion": "v1", + "items": [ + { + "apiVersion": "apps/v1", + "kind": "DaemonSet", + "metadata": { + "annotations": { + "deprecated.daemonset.template.generation": "1" + }, + "labels": { + "eks.amazonaws.com/component": "kube-proxy", + "k8s-app": "kube-proxy" + }, + "name": "kube-proxy", + "namespace": "kube-system" + }, + "spec": { + "revisionHistoryLimit": 10, + "selector": { + "matchLabels": { + "k8s-app": "kube-proxy" + } + }, + "template": { + "metadata": { + "creationTimestamp": null, + "labels": { + "k8s-app": "kube-proxy" + } + }, + "spec": { + "affinity": { + "nodeAffinity": { + "requiredDuringSchedulingIgnoredDuringExecution": { + "nodeSelectorTerms": [ + { + "matchExpressions": [ + { + "key": "beta.kubernetes.io/os", + "operator": "In", + "values": [ + "linux" + ] + }, + { + "key": "beta.kubernetes.io/arch", + "operator": "In", + "values": [ + "amd64" + ] + }, + { + "key": "eks.amazonaws.com/compute-type", + "operator": "NotIn", + "values": [ + "fargate" + ] + } + ] + } + ] + } + } + }, + "containers": [ + { + "command": [ + "kube-proxy", + "--v=2", + "--config=/var/lib/kube-proxy-config/config" + ], + "image": "602401143452.dkr.ecr.eu-west-1.amazonaws.com/eks/kube-proxy:v1.15.11-eksbuild.1", + "imagePullPolicy": "IfNotPresent", + "name": "kube-proxy", + "resources": { + "requests": { + "cpu": "100m" + } + }, + "securityContext": { + "privileged": true + }, + "terminationMessagePath": "/dev/termination-log", + "terminationMessagePolicy": "File", + "volumeMounts": [ + { + "mountPath": "/var/log", + "name": "varlog" + }, + { + "mountPath": "/run/xtables.lock", + "name": "xtables-lock" + }, + { + "mountPath": "/lib/modules", + "name": "lib-modules", + "readOnly": true + }, + { + "mountPath": "/var/lib/kube-proxy/", + "name": "kubeconfig" + }, + { + "mountPath": "/var/lib/kube-proxy-config/", + "name": "config" + } + ] + } + ], + "dnsPolicy": "ClusterFirst", + "hostNetwork": true, + "priorityClassName": "system-node-critical", + "restartPolicy": "Always", + "schedulerName": "default-scheduler", + "securityContext": {}, + "serviceAccount": "kube-proxy", + "serviceAccountName": "kube-proxy", + "terminationGracePeriodSeconds": 30, + "tolerations": [ + { + "operator": "Exists" + } + ], + "volumes": [ + { + "hostPath": { + "path": "/var/log", + "type": "" + }, + "name": "varlog" + }, + { + "hostPath": { + "path": "/run/xtables.lock", + "type": "FileOrCreate" + }, + "name": "xtables-lock" + }, + { + "hostPath": { + "path": "/lib/modules", + "type": "" + }, + "name": "lib-modules" + }, + { + "configMap": { + "defaultMode": 420, + "name": "kube-proxy" + }, + "name": "kubeconfig" + }, + { + "configMap": { + "defaultMode": 420, + "name": "kube-proxy-config" + }, + "name": "config" + } + ] + } + }, + "updateStrategy": { + "rollingUpdate": { + "maxUnavailable": "10%" + }, + "type": "RollingUpdate" + } + } + }, + { + "apiVersion": "v1", + "kind": "Service", + "metadata": { + "annotations": { + "prometheus.io/port": "9153", + "prometheus.io/scrape": "true" + }, + "labels": { + "eks.amazonaws.com/component": "kube-dns", + "k8s-app": "kube-dns", + "kubernetes.io/cluster-service": "true", + "kubernetes.io/name": "CoreDNS" + }, + "name": "kube-dns", + "namespace": "kube-system" + }, + "spec": { + "clusterIP": "10.100.0.10", + "ports": [ + { + "name": "dns", + "port": 53, + "protocol": "UDP", + "targetPort": 53 + }, + { + "name": "dns-tcp", + "port": 53, + "protocol": "TCP", + "targetPort": 53 + } + ], + "selector": { + "k8s-app": "kube-dns" + }, + "sessionAffinity": "None", + "type": "ClusterIP" + } + }, + { + "apiVersion": "v1", + "kind": "ServiceAccount", + "metadata": { + "annotations": {}, + "labels": { + "eks.amazonaws.com/component": "coredns", + "k8s-app": "kube-dns" + }, + "name": "coredns", + "namespace": "kube-system" + } + }, + { + "apiVersion": "v1", + "data": { + "Corefile": ".:53 {\n errors\n health\n kubernetes cluster.local in-addr.arpa ip6.arpa {\n pods insecure\n upstream\n fallthrough in-addr.arpa ip6.arpa\n }\n prometheus :9153\n forward . /etc/resolv.conf\n cache 30\n loop\n reload\n loadbalance\n}\n" + }, + "kind": "ConfigMap", + "metadata": { + "annotations": {}, + "labels": { + "eks.amazonaws.com/component": "coredns", + "k8s-app": "kube-dns" + }, + "name": "coredns", + "namespace": "kube-system" + } + }, + { + "apiVersion": "apps/v1", + "kind": "Deployment", + "metadata": { + "annotations": {}, + "labels": { + "eks.amazonaws.com/component": "coredns", + "k8s-app": "kube-dns", + "kubernetes.io/name": "CoreDNS" + }, + "name": "coredns", + "namespace": "kube-system" + }, + "spec": { + "progressDeadlineSeconds": 600, + "replicas": 2, + "revisionHistoryLimit": 10, + "selector": { + "matchLabels": { + "eks.amazonaws.com/component": "coredns", + "k8s-app": "kube-dns" + } + }, + "strategy": { + "rollingUpdate": { + "maxSurge": "25%", + "maxUnavailable": 1 + }, + "type": "RollingUpdate" + }, + "template": { + "metadata": { + "annotations": { + "eks.amazonaws.com/compute-type": "ec2" + }, + "creationTimestamp": null, + "labels": { + "eks.amazonaws.com/component": "coredns", + "k8s-app": "kube-dns" + } + }, + "spec": { + "affinity": { + "nodeAffinity": { + "requiredDuringSchedulingIgnoredDuringExecution": { + "nodeSelectorTerms": [ + { + "matchExpressions": [ + { + "key": "beta.kubernetes.io/os", + "operator": "In", + "values": [ + "linux" + ] + }, + { + "key": "beta.kubernetes.io/arch", + "operator": "In", + "values": [ + "amd64" + ] + } + ] + } + ] + } + }, + "podAntiAffinity": { + "preferredDuringSchedulingIgnoredDuringExecution": [ + { + "podAffinityTerm": { + "labelSelector": { + "matchExpressions": [ + { + "key": "k8s-app", + "operator": "In", + "values": [ + "kube-dns" + ] + } + ] + }, + "topologyKey": "kubernetes.io/hostname" + }, + "weight": 100 + } + ] + } + }, + "containers": [ + { + "args": [ + "-conf", + "/etc/coredns/Corefile" + ], + "image": "%s.dkr.ecr.%s.%s/eks/coredns:v1.6.6", + "imagePullPolicy": "IfNotPresent", + "livenessProbe": { + "failureThreshold": 5, + "httpGet": { + "path": "/health", + "port": 8080, + "scheme": "HTTP" + }, + "initialDelaySeconds": 60, + "periodSeconds": 10, + "successThreshold": 1, + "timeoutSeconds": 5 + }, + "name": "coredns", + "ports": [ + { + "containerPort": 53, + "name": "dns", + "protocol": "UDP" + }, + { + "containerPort": 53, + "name": "dns-tcp", + "protocol": "TCP" + }, + { + "containerPort": 9153, + "name": "metrics", + "protocol": "TCP" + } + ], + "readinessProbe": { + "failureThreshold": 3, + "httpGet": { + "path": "/health", + "port": 8080, + "scheme": "HTTP" + }, + "periodSeconds": 10, + "successThreshold": 1, + "timeoutSeconds": 1 + }, + "resources": { + "limits": { + "memory": "170Mi" + }, + "requests": { + "cpu": "100m", + "memory": "70Mi" + } + }, + "securityContext": { + "allowPrivilegeEscalation": false, + "capabilities": { + "add": [ + "NET_BIND_SERVICE" + ], + "drop": [ + "all" + ] + }, + "readOnlyRootFilesystem": true + }, + "terminationMessagePath": "/dev/termination-log", + "terminationMessagePolicy": "File", + "volumeMounts": [ + { + "mountPath": "/etc/coredns", + "name": "config-volume", + "readOnly": true + }, + { + "mountPath": "/tmp", + "name": "tmp" + } + ] + } + ], + "dnsPolicy": "Default", + "priorityClassName": "system-cluster-critical", + "restartPolicy": "Always", + "schedulerName": "default-scheduler", + "securityContext": {}, + "serviceAccount": "coredns", + "serviceAccountName": "coredns", + "terminationGracePeriodSeconds": 30, + "tolerations": [ + { + "effect": "NoSchedule", + "key": "node-role.kubernetes.io/master" + }, + { + "key": "CriticalAddonsOnly", + "operator": "Exists" + } + ], + "volumes": [ + { + "emptyDir": {}, + "name": "tmp" + }, + { + "configMap": { + "defaultMode": 420, + "items": [ + { + "key": "Corefile", + "path": "Corefile" + } + ], + "name": "coredns" + }, + "name": "config-volume" + } + ] + } + } + } + }, + { + "apiVersion": "rbac.authorization.k8s.io/v1", + "kind": "ClusterRole", + "metadata": { + "annotations": {}, + "labels": { + "eks.amazonaws.com/component": "coredns", + "k8s-app": "kube-dns", + "kubernetes.io/bootstrapping": "rbac-defaults" + }, + "name": "system:coredns" + }, + "rules": [ + { + "apiGroups": [ + "" + ], + "resources": [ + "endpoints", + "services", + "pods", + "namespaces" + ], + "verbs": [ + "list", + "watch" + ] + }, + { + "apiGroups": [ + "" + ], + "resources": [ + "nodes" + ], + "verbs": [ + "get" + ] + } + ] + }, + { + "apiVersion": "rbac.authorization.k8s.io/v1", + "kind": "ClusterRoleBinding", + "metadata": { + "annotations": { + "rbac.authorization.kubernetes.io/autoupdate": "true" + }, + "labels": { + "eks.amazonaws.com/component": "coredns", + "k8s-app": "kube-dns", + "kubernetes.io/bootstrapping": "rbac-defaults" + }, + "name": "system:coredns" + }, + "roleRef": { + "apiGroup": "rbac.authorization.k8s.io", + "kind": "ClusterRole", + "name": "system:coredns" + }, + "subjects": [ + { + "kind": "ServiceAccount", + "name": "coredns", + "namespace": "kube-system" + } + ] + }, + { + "apiVersion": "apps/v1", + "kind": "DaemonSet", + "metadata": { + "annotations": {}, + "generation": 1, + "labels": { + "k8s-app": "aws-node" + }, + "name": "aws-node", + "namespace": "kube-system" + }, + "spec": { + "revisionHistoryLimit": 10, + "selector": { + "matchLabels": { + "k8s-app": "aws-node" + } + }, + "template": { + "metadata": { + "creationTimestamp": null, + "labels": { + "k8s-app": "aws-node" + } + }, + "spec": { + "affinity": { + "nodeAffinity": { + "requiredDuringSchedulingIgnoredDuringExecution": { + "nodeSelectorTerms": [ + { + "matchExpressions": [ + { + "key": "beta.kubernetes.io/os", + "operator": "In", + "values": [ + "linux" + ] + }, + { + "key": "beta.kubernetes.io/arch", + "operator": "In", + "values": [ + "amd64" + ] + }, + { + "key": "eks.amazonaws.com/compute-type", + "operator": "NotIn", + "values": [ + "fargate" + ] + } + ] + } + ] + } + } + }, + "containers": [ + { + "env": [ + { + "name": "AWS_VPC_K8S_CNI_LOGLEVEL", + "value": "DEBUG" + }, + { + "name": "MY_NODE_NAME", + "valueFrom": { + "fieldRef": { + "apiVersion": "v1", + "fieldPath": "spec.nodeName" + } + } + } + ], + "image": "602401143452.dkr.ecr.eu-west-1.amazonaws.com/amazon-k8s-cni:v1.5.7", + "imagePullPolicy": "Always", + "name": "aws-node", + "ports": [ + { + "containerPort": 61678, + "hostPort": 61678, + "name": "metrics", + "protocol": "TCP" + } + ], + "resources": { + "requests": { + "cpu": "10m" + } + }, + "securityContext": { + "privileged": true + }, + "terminationMessagePath": "/dev/termination-log", + "terminationMessagePolicy": "File", + "volumeMounts": [ + { + "mountPath": "/host/opt/cni/bin", + "name": "cni-bin-dir" + }, + { + "mountPath": "/host/etc/cni/net.d", + "name": "cni-net-dir" + }, + { + "mountPath": "/host/var/log", + "name": "log-dir" + }, + { + "mountPath": "/var/run/docker.sock", + "name": "dockersock" + } + ] + } + ], + "dnsPolicy": "ClusterFirst", + "hostNetwork": true, + "priorityClassName": "system-node-critical", + "restartPolicy": "Always", + "schedulerName": "default-scheduler", + "securityContext": {}, + "serviceAccount": "aws-node", + "serviceAccountName": "aws-node", + "terminationGracePeriodSeconds": 30, + "tolerations": [ + { + "operator": "Exists" + } + ], + "volumes": [ + { + "hostPath": { + "path": "/opt/cni/bin", + "type": "" + }, + "name": "cni-bin-dir" + }, + { + "hostPath": { + "path": "/etc/cni/net.d", + "type": "" + }, + "name": "cni-net-dir" + }, + { + "hostPath": { + "path": "/var/log", + "type": "" + }, + "name": "log-dir" + }, + { + "hostPath": { + "path": "/var/run/docker.sock", + "type": "" + }, + "name": "dockersock" + } + ] + } + }, + "templateGeneration": 1, + "updateStrategy": { + "rollingUpdate": { + "maxUnavailable": 1 + }, + "type": "RollingUpdate" + } + } + }, + { + "apiVersion": "apiextensions.k8s.io/v1beta1", + "kind": "CustomResourceDefinition", + "metadata": { + "annotations": {}, + "name": "eniconfigs.crd.k8s.amazonaws.com" + }, + "spec": { + "conversion": { + "strategy": "None" + }, + "group": "crd.k8s.amazonaws.com", + "names": { + "kind": "ENIConfig", + "listKind": "ENIConfigList", + "plural": "eniconfigs", + "singular": "eniconfig" + }, + "preserveUnknownFields": true, + "scope": "Cluster", + "version": "v1alpha1", + "versions": [ + { + "name": "v1alpha1", + "served": true, + "storage": true + } + ] + } + }, + { + "apiVersion": "rbac.authorization.k8s.io/v1", + "kind": "ClusterRole", + "metadata": { + "annotations": {}, + "name": "aws-node" + }, + "rules": [ + { + "apiGroups": [ + "crd.k8s.amazonaws.com" + ], + "resources": [ + "*", + "namespaces" + ], + "verbs": [ + "*" + ] + }, + { + "apiGroups": [ + "" + ], + "resources": [ + "pods", + "nodes", + "namespaces" + ], + "verbs": [ + "list", + "watch", + "get" + ] + }, + { + "apiGroups": [ + "extensions" + ], + "resources": [ + "daemonsets" + ], + "verbs": [ + "list", + "watch" + ] + } + ] + }, + { + "apiVersion": "rbac.authorization.k8s.io/v1", + "kind": "ClusterRoleBinding", + "metadata": { + "annotations": {}, + "name": "aws-node" + }, + "roleRef": { + "apiGroup": "rbac.authorization.k8s.io", + "kind": "ClusterRole", + "name": "aws-node" + }, + "subjects": [ + { + "kind": "ServiceAccount", + "name": "aws-node", + "namespace": "kube-system" + } + ] + } + ], + "kind": "List" +} diff --git a/pkg/addons/default/testdata/sample-1.15-invalid-image.json b/pkg/addons/default/testdata/sample-1.15-invalid-image.json new file mode 100644 index 0000000000..3c75efd4d4 --- /dev/null +++ b/pkg/addons/default/testdata/sample-1.15-invalid-image.json @@ -0,0 +1,798 @@ +{ + "apiVersion": "v1", + "items": [ + { + "apiVersion": "apps/v1", + "kind": "DaemonSet", + "metadata": { + "annotations": { + "deprecated.daemonset.template.generation": "1" + }, + "labels": { + "eks.amazonaws.com/component": "kube-proxy", + "k8s-app": "kube-proxy" + }, + "name": "kube-proxy", + "namespace": "kube-system" + }, + "spec": { + "revisionHistoryLimit": 10, + "selector": { + "matchLabels": { + "k8s-app": "kube-proxy" + } + }, + "template": { + "metadata": { + "creationTimestamp": null, + "labels": { + "k8s-app": "kube-proxy" + } + }, + "spec": { + "affinity": { + "nodeAffinity": { + "requiredDuringSchedulingIgnoredDuringExecution": { + "nodeSelectorTerms": [ + { + "matchExpressions": [ + { + "key": "beta.kubernetes.io/os", + "operator": "In", + "values": [ + "linux" + ] + }, + { + "key": "beta.kubernetes.io/arch", + "operator": "In", + "values": [ + "amd64" + ] + }, + { + "key": "eks.amazonaws.com/compute-type", + "operator": "NotIn", + "values": [ + "fargate" + ] + } + ] + } + ] + } + } + }, + "containers": [ + { + "command": [ + "kube-proxy", + "--v=2", + "--config=/var/lib/kube-proxy-config/config" + ], + "image": "602401143452.dkr.ecr.eu-west-1.amazonaws.com/eks/kube-proxywithnotag", + "imagePullPolicy": "IfNotPresent", + "name": "kube-proxy", + "resources": { + "requests": { + "cpu": "100m" + } + }, + "securityContext": { + "privileged": true + }, + "terminationMessagePath": "/dev/termination-log", + "terminationMessagePolicy": "File", + "volumeMounts": [ + { + "mountPath": "/var/log", + "name": "varlog" + }, + { + "mountPath": "/run/xtables.lock", + "name": "xtables-lock" + }, + { + "mountPath": "/lib/modules", + "name": "lib-modules", + "readOnly": true + }, + { + "mountPath": "/var/lib/kube-proxy/", + "name": "kubeconfig" + }, + { + "mountPath": "/var/lib/kube-proxy-config/", + "name": "config" + } + ] + } + ], + "dnsPolicy": "ClusterFirst", + "hostNetwork": true, + "priorityClassName": "system-node-critical", + "restartPolicy": "Always", + "schedulerName": "default-scheduler", + "securityContext": {}, + "serviceAccount": "kube-proxy", + "serviceAccountName": "kube-proxy", + "terminationGracePeriodSeconds": 30, + "tolerations": [ + { + "operator": "Exists" + } + ], + "volumes": [ + { + "hostPath": { + "path": "/var/log", + "type": "" + }, + "name": "varlog" + }, + { + "hostPath": { + "path": "/run/xtables.lock", + "type": "FileOrCreate" + }, + "name": "xtables-lock" + }, + { + "hostPath": { + "path": "/lib/modules", + "type": "" + }, + "name": "lib-modules" + }, + { + "configMap": { + "defaultMode": 420, + "name": "kube-proxy" + }, + "name": "kubeconfig" + }, + { + "configMap": { + "defaultMode": 420, + "name": "kube-proxy-config" + }, + "name": "config" + } + ] + } + }, + "updateStrategy": { + "rollingUpdate": { + "maxUnavailable": "10%" + }, + "type": "RollingUpdate" + } + } + }, + { + "apiVersion": "v1", + "kind": "Service", + "metadata": { + "annotations": { + "prometheus.io/port": "9153", + "prometheus.io/scrape": "true" + }, + "labels": { + "eks.amazonaws.com/component": "kube-dns", + "k8s-app": "kube-dns", + "kubernetes.io/cluster-service": "true", + "kubernetes.io/name": "CoreDNS" + }, + "name": "kube-dns", + "namespace": "kube-system" + }, + "spec": { + "clusterIP": "10.100.0.10", + "ports": [ + { + "name": "dns", + "port": 53, + "protocol": "UDP", + "targetPort": 53 + }, + { + "name": "dns-tcp", + "port": 53, + "protocol": "TCP", + "targetPort": 53 + } + ], + "selector": { + "k8s-app": "kube-dns" + }, + "sessionAffinity": "None", + "type": "ClusterIP" + } + }, + { + "apiVersion": "v1", + "kind": "ServiceAccount", + "metadata": { + "annotations": {}, + "labels": { + "eks.amazonaws.com/component": "coredns", + "k8s-app": "kube-dns" + }, + "name": "coredns", + "namespace": "kube-system" + } + }, + { + "apiVersion": "v1", + "data": { + "Corefile": ".:53 {\n errors\n health\n kubernetes cluster.local in-addr.arpa ip6.arpa {\n pods insecure\n upstream\n fallthrough in-addr.arpa ip6.arpa\n }\n prometheus :9153\n forward . /etc/resolv.conf\n cache 30\n loop\n reload\n loadbalance\n}\n" + }, + "kind": "ConfigMap", + "metadata": { + "annotations": {}, + "labels": { + "eks.amazonaws.com/component": "coredns", + "k8s-app": "kube-dns" + }, + "name": "coredns", + "namespace": "kube-system" + } + }, + { + "apiVersion": "apps/v1", + "kind": "Deployment", + "metadata": { + "annotations": {}, + "labels": { + "eks.amazonaws.com/component": "coredns", + "k8s-app": "kube-dns", + "kubernetes.io/name": "CoreDNS" + }, + "name": "coredns", + "namespace": "kube-system" + }, + "spec": { + "progressDeadlineSeconds": 600, + "replicas": 2, + "revisionHistoryLimit": 10, + "selector": { + "matchLabels": { + "eks.amazonaws.com/component": "coredns", + "k8s-app": "kube-dns" + } + }, + "strategy": { + "rollingUpdate": { + "maxSurge": "25%", + "maxUnavailable": 1 + }, + "type": "RollingUpdate" + }, + "template": { + "metadata": { + "annotations": { + "eks.amazonaws.com/compute-type": "ec2" + }, + "creationTimestamp": null, + "labels": { + "eks.amazonaws.com/component": "coredns", + "k8s-app": "kube-dns" + } + }, + "spec": { + "affinity": { + "nodeAffinity": { + "requiredDuringSchedulingIgnoredDuringExecution": { + "nodeSelectorTerms": [ + { + "matchExpressions": [ + { + "key": "beta.kubernetes.io/os", + "operator": "In", + "values": [ + "linux" + ] + }, + { + "key": "beta.kubernetes.io/arch", + "operator": "In", + "values": [ + "amd64" + ] + } + ] + } + ] + } + }, + "podAntiAffinity": { + "preferredDuringSchedulingIgnoredDuringExecution": [ + { + "podAffinityTerm": { + "labelSelector": { + "matchExpressions": [ + { + "key": "k8s-app", + "operator": "In", + "values": [ + "kube-dns" + ] + } + ] + }, + "topologyKey": "kubernetes.io/hostname" + }, + "weight": 100 + } + ] + } + }, + "containers": [ + { + "args": [ + "-conf", + "/etc/coredns/Corefile" + ], + "image": "%s.dkr.ecr.%s.%s/eks/coredns:v1.6.6", + "imagePullPolicy": "IfNotPresent", + "livenessProbe": { + "failureThreshold": 5, + "httpGet": { + "path": "/health", + "port": 8080, + "scheme": "HTTP" + }, + "initialDelaySeconds": 60, + "periodSeconds": 10, + "successThreshold": 1, + "timeoutSeconds": 5 + }, + "name": "coredns", + "ports": [ + { + "containerPort": 53, + "name": "dns", + "protocol": "UDP" + }, + { + "containerPort": 53, + "name": "dns-tcp", + "protocol": "TCP" + }, + { + "containerPort": 9153, + "name": "metrics", + "protocol": "TCP" + } + ], + "readinessProbe": { + "failureThreshold": 3, + "httpGet": { + "path": "/health", + "port": 8080, + "scheme": "HTTP" + }, + "periodSeconds": 10, + "successThreshold": 1, + "timeoutSeconds": 1 + }, + "resources": { + "limits": { + "memory": "170Mi" + }, + "requests": { + "cpu": "100m", + "memory": "70Mi" + } + }, + "securityContext": { + "allowPrivilegeEscalation": false, + "capabilities": { + "add": [ + "NET_BIND_SERVICE" + ], + "drop": [ + "all" + ] + }, + "readOnlyRootFilesystem": true + }, + "terminationMessagePath": "/dev/termination-log", + "terminationMessagePolicy": "File", + "volumeMounts": [ + { + "mountPath": "/etc/coredns", + "name": "config-volume", + "readOnly": true + }, + { + "mountPath": "/tmp", + "name": "tmp" + } + ] + } + ], + "dnsPolicy": "Default", + "priorityClassName": "system-cluster-critical", + "restartPolicy": "Always", + "schedulerName": "default-scheduler", + "securityContext": {}, + "serviceAccount": "coredns", + "serviceAccountName": "coredns", + "terminationGracePeriodSeconds": 30, + "tolerations": [ + { + "effect": "NoSchedule", + "key": "node-role.kubernetes.io/master" + }, + { + "key": "CriticalAddonsOnly", + "operator": "Exists" + } + ], + "volumes": [ + { + "emptyDir": {}, + "name": "tmp" + }, + { + "configMap": { + "defaultMode": 420, + "items": [ + { + "key": "Corefile", + "path": "Corefile" + } + ], + "name": "coredns" + }, + "name": "config-volume" + } + ] + } + } + } + }, + { + "apiVersion": "rbac.authorization.k8s.io/v1", + "kind": "ClusterRole", + "metadata": { + "annotations": {}, + "labels": { + "eks.amazonaws.com/component": "coredns", + "k8s-app": "kube-dns", + "kubernetes.io/bootstrapping": "rbac-defaults" + }, + "name": "system:coredns" + }, + "rules": [ + { + "apiGroups": [ + "" + ], + "resources": [ + "endpoints", + "services", + "pods", + "namespaces" + ], + "verbs": [ + "list", + "watch" + ] + }, + { + "apiGroups": [ + "" + ], + "resources": [ + "nodes" + ], + "verbs": [ + "get" + ] + } + ] + }, + { + "apiVersion": "rbac.authorization.k8s.io/v1", + "kind": "ClusterRoleBinding", + "metadata": { + "annotations": { + "rbac.authorization.kubernetes.io/autoupdate": "true" + }, + "labels": { + "eks.amazonaws.com/component": "coredns", + "k8s-app": "kube-dns", + "kubernetes.io/bootstrapping": "rbac-defaults" + }, + "name": "system:coredns" + }, + "roleRef": { + "apiGroup": "rbac.authorization.k8s.io", + "kind": "ClusterRole", + "name": "system:coredns" + }, + "subjects": [ + { + "kind": "ServiceAccount", + "name": "coredns", + "namespace": "kube-system" + } + ] + }, + { + "apiVersion": "apps/v1", + "kind": "DaemonSet", + "metadata": { + "annotations": {}, + "generation": 1, + "labels": { + "k8s-app": "aws-node" + }, + "name": "aws-node", + "namespace": "kube-system" + }, + "spec": { + "revisionHistoryLimit": 10, + "selector": { + "matchLabels": { + "k8s-app": "aws-node" + } + }, + "template": { + "metadata": { + "creationTimestamp": null, + "labels": { + "k8s-app": "aws-node" + } + }, + "spec": { + "affinity": { + "nodeAffinity": { + "requiredDuringSchedulingIgnoredDuringExecution": { + "nodeSelectorTerms": [ + { + "matchExpressions": [ + { + "key": "beta.kubernetes.io/os", + "operator": "In", + "values": [ + "linux" + ] + }, + { + "key": "beta.kubernetes.io/arch", + "operator": "In", + "values": [ + "amd64" + ] + }, + { + "key": "eks.amazonaws.com/compute-type", + "operator": "NotIn", + "values": [ + "fargate" + ] + } + ] + } + ] + } + } + }, + "containers": [ + { + "env": [ + { + "name": "AWS_VPC_K8S_CNI_LOGLEVEL", + "value": "DEBUG" + }, + { + "name": "MY_NODE_NAME", + "valueFrom": { + "fieldRef": { + "apiVersion": "v1", + "fieldPath": "spec.nodeName" + } + } + } + ], + "image": "602401143452.dkr.ecr.eu-west-1.amazonaws.com/amazon-k8s-cni:v1.5.7", + "imagePullPolicy": "Always", + "name": "aws-node", + "ports": [ + { + "containerPort": 61678, + "hostPort": 61678, + "name": "metrics", + "protocol": "TCP" + } + ], + "resources": { + "requests": { + "cpu": "10m" + } + }, + "securityContext": { + "privileged": true + }, + "terminationMessagePath": "/dev/termination-log", + "terminationMessagePolicy": "File", + "volumeMounts": [ + { + "mountPath": "/host/opt/cni/bin", + "name": "cni-bin-dir" + }, + { + "mountPath": "/host/etc/cni/net.d", + "name": "cni-net-dir" + }, + { + "mountPath": "/host/var/log", + "name": "log-dir" + }, + { + "mountPath": "/var/run/docker.sock", + "name": "dockersock" + } + ] + } + ], + "dnsPolicy": "ClusterFirst", + "hostNetwork": true, + "priorityClassName": "system-node-critical", + "restartPolicy": "Always", + "schedulerName": "default-scheduler", + "securityContext": {}, + "serviceAccount": "aws-node", + "serviceAccountName": "aws-node", + "terminationGracePeriodSeconds": 30, + "tolerations": [ + { + "operator": "Exists" + } + ], + "volumes": [ + { + "hostPath": { + "path": "/opt/cni/bin", + "type": "" + }, + "name": "cni-bin-dir" + }, + { + "hostPath": { + "path": "/etc/cni/net.d", + "type": "" + }, + "name": "cni-net-dir" + }, + { + "hostPath": { + "path": "/var/log", + "type": "" + }, + "name": "log-dir" + }, + { + "hostPath": { + "path": "/var/run/docker.sock", + "type": "" + }, + "name": "dockersock" + } + ] + } + }, + "templateGeneration": 1, + "updateStrategy": { + "rollingUpdate": { + "maxUnavailable": 1 + }, + "type": "RollingUpdate" + } + } + }, + { + "apiVersion": "apiextensions.k8s.io/v1beta1", + "kind": "CustomResourceDefinition", + "metadata": { + "annotations": {}, + "name": "eniconfigs.crd.k8s.amazonaws.com" + }, + "spec": { + "conversion": { + "strategy": "None" + }, + "group": "crd.k8s.amazonaws.com", + "names": { + "kind": "ENIConfig", + "listKind": "ENIConfigList", + "plural": "eniconfigs", + "singular": "eniconfig" + }, + "preserveUnknownFields": true, + "scope": "Cluster", + "version": "v1alpha1", + "versions": [ + { + "name": "v1alpha1", + "served": true, + "storage": true + } + ] + } + }, + { + "apiVersion": "rbac.authorization.k8s.io/v1", + "kind": "ClusterRole", + "metadata": { + "annotations": {}, + "name": "aws-node" + }, + "rules": [ + { + "apiGroups": [ + "crd.k8s.amazonaws.com" + ], + "resources": [ + "*", + "namespaces" + ], + "verbs": [ + "*" + ] + }, + { + "apiGroups": [ + "" + ], + "resources": [ + "pods", + "nodes", + "namespaces" + ], + "verbs": [ + "list", + "watch", + "get" + ] + }, + { + "apiGroups": [ + "extensions" + ], + "resources": [ + "daemonsets" + ], + "verbs": [ + "list", + "watch" + ] + } + ] + }, + { + "apiVersion": "rbac.authorization.k8s.io/v1", + "kind": "ClusterRoleBinding", + "metadata": { + "annotations": {}, + "name": "aws-node" + }, + "roleRef": { + "apiGroup": "rbac.authorization.k8s.io", + "kind": "ClusterRole", + "name": "aws-node" + }, + "subjects": [ + { + "kind": "ServiceAccount", + "name": "aws-node", + "namespace": "kube-system" + } + ] + } + ], + "kind": "List" +} diff --git a/pkg/ctl/utils/update_aws_node.go b/pkg/ctl/utils/update_aws_node.go index cd2adc275d..fab054df4a 100644 --- a/pkg/ctl/utils/update_aws_node.go +++ b/pkg/ctl/utils/update_aws_node.go @@ -54,7 +54,10 @@ func doUpdateAWSNode(cmd *cmdutils.Cmd) error { return err } - updateRequired, err := defaultaddons.UpdateAWSNode(rawClient, meta.Region, cmd.Plan) + updateRequired, err := defaultaddons.UpdateAWSNode(defaultaddons.AddonInput{ + RawClient: rawClient, + Region: meta.Region, + }, cmd.Plan) if err != nil { return err } diff --git a/pkg/ctl/utils/update_coredns.go b/pkg/ctl/utils/update_coredns.go index fc2bac0a83..f3cee24143 100644 --- a/pkg/ctl/utils/update_coredns.go +++ b/pkg/ctl/utils/update_coredns.go @@ -59,7 +59,12 @@ func doUpdateCoreDNS(cmd *cmdutils.Cmd) error { return err } - updateRequired, err := defaultaddons.UpdateCoreDNS(rawClient, meta.Region, kubernetesVersion, cmd.Plan) + updateRequired, err := defaultaddons.UpdateCoreDNS(defaultaddons.AddonInput{ + RawClient: rawClient, + ControlPlaneVersion: kubernetesVersion, + Region: meta.Region, + }, cmd.Plan) + if err != nil { return err } diff --git a/pkg/ctl/utils/update_kube_proxy.go b/pkg/ctl/utils/update_kube_proxy.go index fe07bd51c6..fb10c6f82c 100644 --- a/pkg/ctl/utils/update_kube_proxy.go +++ b/pkg/ctl/utils/update_kube_proxy.go @@ -59,7 +59,12 @@ func doUpdateKubeProxy(cmd *cmdutils.Cmd) error { return err } - updateRequired, err := defaultaddons.UpdateKubeProxy(rawClient.ClientSet(), kubernetesVersion, cmd.Plan) + updateRequired, err := defaultaddons.UpdateKubeProxy(defaultaddons.AddonInput{ + RawClient: rawClient, + ControlPlaneVersion: kubernetesVersion, + Region: meta.Region, + EKSAPI: ctl.Provider.EKS(), + }, cmd.Plan) if err != nil { return err } diff --git a/pkg/testutils/client.go b/pkg/testutils/client.go index 753fadade5..9a3be7af33 100644 --- a/pkg/testutils/client.go +++ b/pkg/testutils/client.go @@ -266,6 +266,7 @@ func NewFakeRawResource(item runtime.Object, missing, unionised bool, ct *Collec type FakeRawClient struct { Collection *CollectionTracker + ExistingClientSet kubernetes.Interface AssumeObjectsMissing bool ClientSetUseUpdatedObjects bool UseUnionTracker bool @@ -277,7 +278,17 @@ func NewFakeRawClient() *FakeRawClient { } } +func NewFakeRawClientWithSamples(sample string) *FakeRawClient { + clientSet, _ := NewFakeClientSetWithSamples(sample) + return &FakeRawClient{ + ExistingClientSet: clientSet, + } +} + func (c *FakeRawClient) ClientSet() kubeclient.Interface { + if c.ExistingClientSet != nil { + return c.ExistingClientSet + } if c.UseUnionTracker { // TODO: try to use clientSet.Fake.Actions, clientSet.Fake.PrependReactor // or any of the other hooks to connect this clientset instance with From bb34e06be4f45f34afab52fa0688046fc2373f5f Mon Sep 17 00:00:00 2001 From: Jake Date: Wed, 17 Nov 2021 12:06:18 +0000 Subject: [PATCH 085/124] refactor set/get recommended policies --- pkg/actions/addon/create.go | 22 +++++++++++++++------- 1 file changed, 15 insertions(+), 7 deletions(-) diff --git a/pkg/actions/addon/create.go b/pkg/actions/addon/create.go index 8be10538b1..184ad4ca14 100644 --- a/pkg/actions/addon/create.go +++ b/pkg/actions/addon/create.go @@ -70,7 +70,15 @@ func (a *Manager) Create(addon *api.Addon, wait bool) error { createAddonInput.ServiceAccountRoleArn = &outputRole } else if a.hasRecommendedPolicies(addon) { logger.Info("creating role using recommended policies") - a.setRecommendedPolicies(addon) + attachPolicyARNs, wellKnownPolicies := a.getRecommendedPolicies(addon) + + if attachPolicyARNs != nil { + addon.AttachPolicyARNs = attachPolicyARNs + } + if wellKnownPolicies != nil { + addon.WellKnownPolicies = *wellKnownPolicies + } + outputRole, err := a.createRole(addon, namespace, serviceAccount) if err != nil { return err @@ -175,21 +183,21 @@ func (a *Manager) patchAWSNodeDaemonSet() error { } func (a *Manager) hasRecommendedPolicies(addon *api.Addon) bool { - updatedAddon := addon.DeepCopy() - a.setRecommendedPolicies(updatedAddon) - return hasPoliciesSet(updatedAddon) + attachPolicyARNs, wellKnownPolicies := a.getRecommendedPolicies(addon) + return attachPolicyARNs != nil || wellKnownPolicies != nil } -func (a *Manager) setRecommendedPolicies(addon *api.Addon) { +func (a *Manager) getRecommendedPolicies(addon *api.Addon) ([]string, *api.WellKnownPolicies) { // API isn't case sensitive switch addon.CanonicalName() { case vpcCNIName: - addon.AttachPolicyARNs = []string{fmt.Sprintf("arn:%s:iam::aws:policy/%s", api.Partition(a.clusterConfig.Metadata.Region), api.IAMPolicyAmazonEKSCNIPolicy)} + return []string{fmt.Sprintf("arn:%s:iam::aws:policy/%s", api.Partition(a.clusterConfig.Metadata.Region), api.IAMPolicyAmazonEKSCNIPolicy)}, nil case ebsCSIDriverName: - addon.WellKnownPolicies = api.WellKnownPolicies{ + return nil, &api.WellKnownPolicies{ EBSCSIController: true, } } + return nil, nil } func (a *Manager) getKnownServiceAccountLocation(addon *api.Addon) (string, string) { From 85528abecdb007c91e2e5b256bb1bfe620866c19 Mon Sep 17 00:00:00 2001 From: Gergely Brautigam <182850+Skarlso@users.noreply.github.com> Date: Wed, 17 Nov 2021 17:26:51 +0100 Subject: [PATCH 086/124] Add --config-flag to get labels (#4469) --- pkg/ctl/cmdutils/configfile.go | 58 ++++++++++++++++++++++++++++++++++ pkg/ctl/get/labels.go | 14 +++----- pkg/ctl/get/labels_test.go | 21 ++++++++++++ pkg/ctl/get/nodegroup.go | 20 +----------- pkg/ctl/get/nodegroup_test.go | 8 +---- 5 files changed, 85 insertions(+), 36 deletions(-) diff --git a/pkg/ctl/cmdutils/configfile.go b/pkg/ctl/cmdutils/configfile.go index 9b0dd42c71..66eca8c5e4 100644 --- a/pkg/ctl/cmdutils/configfile.go +++ b/pkg/ctl/cmdutils/configfile.go @@ -829,6 +829,64 @@ func NewUpdateNodegroupLoader(cmd *Cmd) ClusterConfigLoader { return l } +// NewGetNodegroupLoader loads config file and validates command for `eksctl get nodegroup`. +func NewGetNodegroupLoader(cmd *Cmd, ng *api.NodeGroup) ClusterConfigLoader { + l := newCommonClusterConfigLoader(cmd) + + l.validateWithoutConfigFile = func() error { + meta := cmd.ClusterConfig.Metadata + + if meta.Name != "" && cmd.NameArg != "" { + return ErrClusterFlagAndArg(cmd, meta.Name, cmd.NameArg) + } + + if meta.Name == "" { + return ErrMustBeSet(ClusterNameFlag(cmd)) + } + + if ng.Name != "" && cmd.NameArg != "" { + return ErrFlagAndArg("--name", ng.Name, cmd.NameArg) + } + + if cmd.NameArg != "" { + ng.Name = cmd.NameArg + } + + // prevent creation of invalid config object with unnamed nodegroup + if ng.Name != "" { + cmd.ClusterConfig.NodeGroups = append(cmd.ClusterConfig.NodeGroups, ng) + } + + return nil + } + + return l +} + +// NewGetLabelsLoader loads config file and validates command for `eksctl get labels`. +func NewGetLabelsLoader(cmd *Cmd, ngName string) ClusterConfigLoader { + l := newCommonClusterConfigLoader(cmd) + l.validateWithoutConfigFile = func() error { + meta := cmd.ClusterConfig.Metadata + + if meta.Name == "" { + return ErrMustBeSet(ClusterNameFlag(cmd)) + } + + if ngName == "" { + return ErrMustBeSet("--nodegroup") + } + + if cmd.NameArg != "" { + return ErrUnsupportedNameArg() + } + + return nil + } + + return l +} + // validateSupportedConfigFields parses a config file's fields, evaluates if non-empty fields are supported, // and returns an error if a field is not supported. func validateSupportedConfigFields(obj interface{}, supportedFields []string, unsupportedFields []string) ([]string, error) { diff --git a/pkg/ctl/get/labels.go b/pkg/ctl/get/labels.go index efdece8d9e..00aa9aa236 100644 --- a/pkg/ctl/get/labels.go +++ b/pkg/ctl/get/labels.go @@ -34,6 +34,7 @@ func getLabelsCmd(cmd *cmdutils.Cmd) { cmdutils.AddRegionFlag(fs, &cmd.ProviderConfig) cmdutils.AddTimeoutFlag(fs, &cmd.ProviderConfig.WaitTimeout) + cmdutils.AddConfigFileFlag(fs, &cmd.ClusterConfigFile) }) cmdutils.AddCommonFlagsForAWS(cmd.FlagSetGroup, &cmd.ProviderConfig, false) @@ -41,17 +42,10 @@ func getLabelsCmd(cmd *cmdutils.Cmd) { } func getLabels(cmd *cmdutils.Cmd, nodeGroupName string) error { - cfg := cmd.ClusterConfig - if cfg.Metadata.Name == "" { - return cmdutils.ErrMustBeSet(cmdutils.ClusterNameFlag(cmd)) - } - if nodeGroupName == "" { - return cmdutils.ErrMustBeSet("--nodegroup") - } - - if cmd.NameArg != "" { - return cmdutils.ErrUnsupportedNameArg() + if err := cmdutils.NewGetLabelsLoader(cmd, nodeGroupName).Load(); err != nil { + return err } + cfg := cmd.ClusterConfig ctl, err := cmd.NewProviderForExistingCluster() if err != nil { diff --git a/pkg/ctl/get/labels_test.go b/pkg/ctl/get/labels_test.go index 3a2ea17b7a..7c42be0b8d 100644 --- a/pkg/ctl/get/labels_test.go +++ b/pkg/ctl/get/labels_test.go @@ -1,6 +1,8 @@ package get import ( + "os" + . "github.com/onsi/ginkgo" . "github.com/onsi/gomega" ) @@ -34,5 +36,24 @@ var _ = Describe("get", func() { Expect(err).To(HaveOccurred()) Expect(err.Error()).To(ContainSubstring("Error: name argument is not supported")) }) + + It("setting --cluster and --config-file at the same time", func() { + f, err := os.CreateTemp("", "configfile") + Expect(err).NotTo(HaveOccurred()) + _, err = f.WriteString(labelsGetConfigFile) + Expect(err).NotTo(HaveOccurred()) + cmd := newMockCmd("labels", "--cluster", "name", "--nodegroup", "name", "--config-file", f.Name()) + _, err = cmd.execute() + Expect(err).To(MatchError(ContainSubstring("Error: cannot use --cluster when --config-file/-f is set"))) + }) }) }) + +var labelsGetConfigFile = `apiVersion: eksctl.io/v1alpha5 +kind: ClusterConfig + +metadata: + name: test-nodegroup-cluster-config + region: us-west-2 + version: '1.20' +` diff --git a/pkg/ctl/get/nodegroup.go b/pkg/ctl/get/nodegroup.go index 725feb6c0c..404e1cae03 100644 --- a/pkg/ctl/get/nodegroup.go +++ b/pkg/ctl/get/nodegroup.go @@ -45,29 +45,11 @@ func getNodeGroupCmd(cmd *cmdutils.Cmd) { } func doGetNodeGroup(cmd *cmdutils.Cmd, ng *api.NodeGroup, params *getCmdParams) error { - if err := cmdutils.NewMetadataLoader(cmd).Load(); err != nil { + if err := cmdutils.NewGetNodegroupLoader(cmd, ng).Load(); err != nil { return err } cfg := cmd.ClusterConfig - // TODO: move this into a loader when --config-file gets added to this command - if cfg.Metadata.Name == "" { - return cmdutils.ErrMustBeSet(cmdutils.ClusterNameFlag(cmd)) - } - - if ng.Name != "" && cmd.NameArg != "" { - return cmdutils.ErrFlagAndArg("--name", ng.Name, cmd.NameArg) - } - - if cmd.NameArg != "" { - ng.Name = cmd.NameArg - } - - // prevent creation of invalid config object with unnamed nodegroup - if ng.Name != "" { - cfg.NodeGroups = append(cfg.NodeGroups, ng) - } - ctl, err := cmd.NewProviderForExistingCluster() if err != nil { return err diff --git a/pkg/ctl/get/nodegroup_test.go b/pkg/ctl/get/nodegroup_test.go index 6d43e75247..38cbbb7737 100644 --- a/pkg/ctl/get/nodegroup_test.go +++ b/pkg/ctl/get/nodegroup_test.go @@ -15,14 +15,8 @@ var _ = Describe("get", func() { Expect(err).To(MatchError(ContainSubstring("Error: --cluster must be set"))) }) - It("setting --name and argument at the same time", func() { - cmd := newMockCmd("nodegroup", "ng", "--name", "ng") - _, err := cmd.execute() - Expect(err).To(MatchError(ContainSubstring("Error: --name=ng and argument ng cannot be used at the same time"))) - }) - It("setting --cluster and argument at the same time", func() { - cmd := newMockCmd("nodegroup", "ng", "--cluster", "name") + cmd := newMockCmd("nodegroup", "ng", "--cluster", "name", "--name", "ng") _, err := cmd.execute() Expect(err).To(MatchError(ContainSubstring("Error: --cluster=name and argument ng cannot be used at the same time"))) }) From 82aa1d4953b9b18261efc63abe70311ac741c726 Mon Sep 17 00:00:00 2001 From: nikimanoledaki <18622989+nikimanoledaki@users.noreply.github.com> Date: Wed, 17 Nov 2021 12:58:45 +0100 Subject: [PATCH 087/124] Bump goreleaser --- go.mod | 31 ++++++++++++++++--------------- go.sum | 41 +++++++++++++++++++++++++++++++++++++++++ 2 files changed, 57 insertions(+), 15 deletions(-) diff --git a/go.mod b/go.mod index c23d76c2ed..8ae7415079 100644 --- a/go.mod +++ b/go.mod @@ -10,7 +10,7 @@ require ( cloud.google.com/go v0.94.0 // indirect cloud.google.com/go/storage v1.16.1 // indirect code.gitea.io/sdk/gitea v0.15.0 // indirect - github.com/AlekSi/pointer v1.1.0 // indirect + github.com/AlekSi/pointer v1.2.0 // indirect github.com/Antonboom/errname v0.1.3 // indirect github.com/Azure/azure-pipeline-go v0.2.3 // indirect github.com/Azure/azure-sdk-for-go v57.0.0+incompatible // indirect @@ -31,7 +31,7 @@ require ( github.com/Masterminds/semver v1.5.0 // indirect github.com/Masterminds/semver/v3 v3.1.1 github.com/Masterminds/sprig v2.22.0+incompatible // indirect - github.com/Microsoft/go-winio v0.4.16 // indirect + github.com/Microsoft/go-winio v0.5.0 // indirect github.com/OpenPeeDeeP/depguard v1.0.1 // indirect github.com/ProtonMail/go-crypto v0.0.0-20210512092938-c05353c2d58c // indirect github.com/PuerkitoBio/purell v1.1.1 // indirect @@ -63,7 +63,7 @@ require ( github.com/chavacava/garif v0.0.0-20210405164556-e8a0a408d6af // indirect github.com/cloudflare/cfssl v1.6.1 github.com/coreos/go-semver v0.3.0 // indirect - github.com/cpuguy83/go-md2man/v2 v2.0.0 // indirect + github.com/cpuguy83/go-md2man/v2 v2.0.1 // indirect github.com/daixiang0/gci v0.2.9 // indirect github.com/dave/jennifer v1.4.1 github.com/davecgh/go-spew v1.1.1 // indirect @@ -93,8 +93,8 @@ require ( github.com/go-critic/go-critic v0.5.6 // indirect github.com/go-errors/errors v1.0.1 // indirect github.com/go-git/gcfg v1.5.0 // indirect - github.com/go-git/go-billy/v5 v5.1.0 // indirect - github.com/go-git/go-git/v5 v5.3.0 // indirect + github.com/go-git/go-billy/v5 v5.3.1 // indirect + github.com/go-git/go-git/v5 v5.4.2 // indirect github.com/go-ini/ini v1.62.0 // indirect github.com/go-logr/logr v0.4.0 // indirect github.com/go-openapi/jsonpointer v0.19.3 // indirect @@ -134,7 +134,7 @@ require ( github.com/google/go-github/v35 v35.3.0 // indirect github.com/google/go-querystring v1.1.0 // indirect github.com/google/gofuzz v1.2.0 // indirect - github.com/google/rpmpack v0.0.0-20210410105602-e20c988a6f5a // indirect + github.com/google/rpmpack v0.0.0-20210518075352-dc539ef4f2ea // indirect github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 // indirect github.com/google/uuid v1.3.0 github.com/google/wire v0.5.0 // indirect @@ -144,8 +144,8 @@ require ( github.com/gordonklaus/ineffassign v0.0.0-20210225214923-2e10b2664254 // indirect github.com/goreleaser/chglog v0.1.2 // indirect github.com/goreleaser/fileglob v1.2.0 // indirect - github.com/goreleaser/goreleaser v0.184.0 - github.com/goreleaser/nfpm/v2 v2.6.0 // indirect + github.com/goreleaser/goreleaser v1.0.0 + github.com/goreleaser/nfpm/v2 v2.9.2 // indirect github.com/gorilla/websocket v1.4.2 // indirect github.com/gostaticanalysis/analysisutil v0.4.1 // indirect github.com/gostaticanalysis/comment v1.4.1 // indirect @@ -209,10 +209,10 @@ require ( github.com/mbilski/exhaustivestruct v1.2.0 // indirect github.com/mgechev/dots v0.0.0-20190921121421-c36f7dcfbb81 // indirect github.com/mgechev/revive v1.1.0 // indirect - github.com/mitchellh/copystructure v1.1.2 // indirect + github.com/mitchellh/copystructure v1.2.0 // indirect github.com/mitchellh/go-homedir v1.1.0 // indirect github.com/mitchellh/mapstructure v1.4.1 // indirect - github.com/mitchellh/reflectwalk v1.0.1 // indirect + github.com/mitchellh/reflectwalk v1.0.2 // indirect github.com/mmarkdown/mmark v2.0.40+incompatible // indirect github.com/moby/spdystream v0.2.0 // indirect github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect @@ -293,7 +293,7 @@ require ( github.com/weaveworks/schemer v0.0.0-20210802122110-338b258ad2ca github.com/whilp/git-urls v0.0.0-20191001220047-6db9661140c0 github.com/xanzy/go-gitlab v0.50.3 // indirect - github.com/xanzy/ssh-agent v0.3.0 // indirect + github.com/xanzy/ssh-agent v0.3.1 // indirect github.com/xeipuuv/gojsonpointer v0.0.0-20190905194746-02993c407bfb // indirect github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415 // indirect github.com/xeipuuv/gojsonschema v1.2.0 // indirect @@ -308,12 +308,12 @@ require ( go.uber.org/multierr v1.7.0 // indirect go.uber.org/zap v1.19.0 // indirect gocloud.dev v0.24.0 // indirect - golang.org/x/crypto v0.0.0-20210817164053-32db794688a5 // indirect + golang.org/x/crypto v0.0.0-20210921155107-089bfa567519 // indirect golang.org/x/mod v0.5.0 // indirect - golang.org/x/net v0.0.0-20210825183410-e898025ed96a // indirect + golang.org/x/net v0.0.0-20211007125505-59d4e928ea9d // indirect golang.org/x/oauth2 v0.0.0-20210819190943-2bc19b11175f // indirect golang.org/x/sync v0.0.0-20210220032951-036812b2e83c // indirect - golang.org/x/sys v0.0.0-20210831042530-f4d43177bf5e // indirect + golang.org/x/sys v0.0.0-20211007075335-d3039528d8ac // indirect golang.org/x/term v0.0.0-20210220032956-6a3ed077a48d // indirect golang.org/x/text v0.3.7 // indirect golang.org/x/time v0.0.0-20210723032227-1f47c861a9ac // indirect @@ -368,6 +368,7 @@ require ( github.com/DisgoOrg/disgohook v1.4.3 // indirect github.com/DisgoOrg/log v1.1.0 // indirect github.com/DisgoOrg/restclient v1.2.7 // indirect + github.com/acomagu/bufpipe v1.0.3 // indirect github.com/alecthomas/jsonschema v0.0.0-20211022214203-8b29eab41725 // indirect github.com/atc0005/go-teams-notify/v2 v2.6.0 // indirect github.com/aws/aws-sdk-go-v2 v1.9.0 // indirect @@ -391,7 +392,7 @@ require ( github.com/go-telegram-bot-api/telegram-bot-api v4.6.4+incompatible // indirect github.com/golang-jwt/jwt/v4 v4.0.0 // indirect github.com/google/go-github/v39 v39.2.0 // indirect - github.com/iancoleman/orderedmap v0.0.0-20190318233801-ac98e3ecb4b0 // indirect + github.com/iancoleman/orderedmap v0.2.0 // indirect github.com/jhump/protoreflect v1.8.2 // indirect github.com/rivo/uniseg v0.2.0 // indirect github.com/slack-go/slack v0.9.4 // indirect diff --git a/go.sum b/go.sum index f75ef42798..5853462998 100644 --- a/go.sum +++ b/go.sum @@ -89,6 +89,8 @@ contrib.go.opencensus.io/resource v0.1.1/go.mod h1:F361eGI91LCmW1I/Saf+rX0+OFcig dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU= github.com/AlekSi/pointer v1.1.0 h1:SSDMPcXD9jSl8FPy9cRzoRaMJtm9g9ggGTxecRUbQoI= github.com/AlekSi/pointer v1.1.0/go.mod h1:y7BvfRI3wXPWKXEBhU71nbnIEEZX0QTSB2Bj48UJIZE= +github.com/AlekSi/pointer v1.2.0 h1:glcy/gc4h8HnG2Z3ZECSzZ1IX1x2JxRVuDzaJwQE0+w= +github.com/AlekSi/pointer v1.2.0/go.mod h1:gZGfd3dpW4vEc/UlyfKKi1roIqcCgwOIvb0tSNSBle0= github.com/Antonboom/errname v0.1.3 h1:qKV8gSzPzBqrG/q0dgraZXJCymWt6KuD9+Y7K7xtzN8= github.com/Antonboom/errname v0.1.3/go.mod h1:jRXo3m0E0EuCnK3wbsSVH3X55Z4iTDLl6ZfCxwFj4TM= github.com/Azure/azure-amqp-common-go/v2 v2.1.0/go.mod h1:R8rea+gJRuJR6QxTir/XuEd+YuKoUiazDC/N96FiDEU= @@ -220,6 +222,8 @@ github.com/Microsoft/go-winio v0.4.15-0.20190919025122-fc70bd9a86b5/go.mod h1:tT github.com/Microsoft/go-winio v0.4.15/go.mod h1:tTuCMEN+UleMWgg9dVx4Hu52b1bJo+59jBh3ajtinzw= github.com/Microsoft/go-winio v0.4.16 h1:FtSW/jqD+l4ba5iPBj9CODVtgfYAD8w2wS923g/cFDk= github.com/Microsoft/go-winio v0.4.16/go.mod h1:XB6nPKklQyQ7GC9LdcBEcBl8PF76WugXOPRXwdLnMv0= +github.com/Microsoft/go-winio v0.5.0 h1:Elr9Wn+sGKPlkaBvwu4mTrxtmOp3F3yV9qhaHbXGjwU= +github.com/Microsoft/go-winio v0.5.0/go.mod h1:JPGBdM1cNvN/6ISo+n8V5iA4v8pBzdOpzfwIujj1a84= github.com/Microsoft/hcsshim v0.8.7/go.mod h1:OHd7sQqRFrYd3RmSgbgji+ctCwkbq2wbEYNSzOYtcBQ= github.com/Microsoft/hcsshim v0.8.10-0.20200715222032-5eafd1556990/go.mod h1:ay/0dTb7NsG8QMDfsRfLHgZo/6xAJShLe1+ePPflihk= github.com/NYTimes/gziphandler v0.0.0-20170623195520-56545f4a5d46/go.mod h1:3wb06e3pkSAbeQ52E9H9iFoQsEEwGN64994WTCIhntQ= @@ -228,12 +232,14 @@ github.com/OneOfOne/xxhash v1.2.2 h1:KMrpdQIwFcEqXDklaen+P1axHaj9BSKzvpUUfnHldSE github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU= github.com/OpenPeeDeeP/depguard v1.0.1 h1:VlW4R6jmBIv3/u1JNlawEvJMM4J+dPORPaZasQee8Us= github.com/OpenPeeDeeP/depguard v1.0.1/go.mod h1:xsIw86fROiiwelg+jB2uM9PiKihMMmUx/1V+TNhjQvM= +github.com/ProtonMail/go-crypto v0.0.0-20210428141323-04723f9f07d7/go.mod h1:z4/9nQmJSSwwds7ejkxaJwO37dru3geImFUdJlaLzQo= github.com/ProtonMail/go-crypto v0.0.0-20210512092938-c05353c2d58c h1:bNpaLLv2Y4kslsdkdCwAYu8Bak1aGVtxwi8Z/wy4Yuo= github.com/ProtonMail/go-crypto v0.0.0-20210512092938-c05353c2d58c/go.mod h1:z4/9nQmJSSwwds7ejkxaJwO37dru3geImFUdJlaLzQo= github.com/ProtonMail/go-mime v0.0.0-20190923161245-9b5a4261663a h1:W6RrgN/sTxg1msqzFFb+G80MFmpjMw61IU+slm+wln4= github.com/ProtonMail/go-mime v0.0.0-20190923161245-9b5a4261663a/go.mod h1:NYt+V3/4rEeDuaev/zw1zCq8uqVEuPHzDPo3OZrlGJ4= github.com/ProtonMail/gopenpgp/v2 v2.2.0 h1:XLsUEY/dQhQcOg8r0ijNvMTJIKM4EBkf3K7zV+kcGj4= github.com/ProtonMail/gopenpgp/v2 v2.2.0/go.mod h1:ajUlBGvxMH1UBZnaYO3d1FSVzjiC6kK9XlZYGiDCvpM= +github.com/ProtonMail/gopenpgp/v2 v2.2.2 h1:u2m7xt+CZWj88qK1UUNBoXeJCFJwJCZ/Ff4ymGoxEXs= github.com/PuerkitoBio/purell v1.0.0/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbtSwDGJws/X0= github.com/PuerkitoBio/purell v1.1.0/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbtSwDGJws/X0= github.com/PuerkitoBio/purell v1.1.1 h1:WEQqlqaGbrPkxLJWfBwQmfEAE1Z7ONdDLqrN38tNFfI= @@ -247,6 +253,8 @@ github.com/Shopify/toxiproxy v2.1.4+incompatible/go.mod h1:OXgGpZ6Cli1/URJOF1DMx github.com/StackExchange/wmi v1.2.1/go.mod h1:rcmrprowKIVzvc+NUiLncP2uuArMWLCbu9SBzvHz7e8= github.com/Venafi/vcert/v4 v4.13.1/go.mod h1:Z3sJFoAurFNXPpoSUSHq46aIeHLiGQEMDhprfxlpofQ= github.com/VividCortex/gohistogram v1.0.0/go.mod h1:Pf5mBqqDxYaXu3hDrrU+w6nw50o/4+TcAqDqk/vUH7g= +github.com/acomagu/bufpipe v1.0.3 h1:fxAGrHZTgQ9w5QqVItgzwj235/uYZYgbXitB+dLupOk= +github.com/acomagu/bufpipe v1.0.3/go.mod h1:mxdxdup/WdsKVreO5GpW4+M/1CE2sMG4jeGJ2sYmHc4= github.com/afex/hystrix-go v0.0.0-20180502004556-fa1af6a1f4f5/go.mod h1:SkGFH1ia65gfNATL8TAiHDNxPzPdmEL5uirI2Uyuz6c= github.com/agext/levenshtein v1.2.1/go.mod h1:JEDfjyjHDjOF/1e4FlBE/PkbqA9OfWu2ki2W0IB5558= github.com/agnivade/levenshtein v1.0.1/go.mod h1:CURSv5d9Uaml+FovSIICkLbAUZ9S4RqaHDIsdSBg7lM= @@ -503,6 +511,8 @@ github.com/cpuguy83/go-md2man v1.0.10/go.mod h1:SmD6nW6nTyfqj6ABTjUi3V3JVMnlJmwc github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= github.com/cpuguy83/go-md2man/v2 v2.0.0 h1:EoUDS0afbrsXAZ9YQ9jdu/mZ2sXgT1/2yyNng4PGlyM= github.com/cpuguy83/go-md2man/v2 v2.0.0/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= +github.com/cpuguy83/go-md2man/v2 v2.0.1 h1:r/myEWzV9lfsM1tFLgDyu0atFtJ1fXn261LKYj/3DxU= +github.com/cpuguy83/go-md2man/v2 v2.0.1/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= github.com/creack/pty v1.1.7/go.mod h1:lj5s0c3V2DBrqTV7llrYr5NG6My20zk30Fl46Y7DoTY= github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= github.com/creack/pty v1.1.11/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= @@ -662,11 +672,18 @@ github.com/go-git/gcfg v1.5.0/go.mod h1:5m20vg6GwYabIxaOonVkTdrILxQMpEShl1xiMF4u github.com/go-git/go-billy/v5 v5.0.0/go.mod h1:pmpqyWchKfYfrkb/UVH4otLvyi/5gJlGI4Hb3ZqZ3W0= github.com/go-git/go-billy/v5 v5.1.0 h1:4pl5BV4o7ZG/lterP4S6WzJ6xr49Ba5ET9ygheTYahk= github.com/go-git/go-billy/v5 v5.1.0/go.mod h1:pmpqyWchKfYfrkb/UVH4otLvyi/5gJlGI4Hb3ZqZ3W0= +github.com/go-git/go-billy/v5 v5.2.0/go.mod h1:pmpqyWchKfYfrkb/UVH4otLvyi/5gJlGI4Hb3ZqZ3W0= +github.com/go-git/go-billy/v5 v5.3.1 h1:CPiOUAzKtMRvolEKw+bG1PLRpT7D3LIs3/3ey4Aiu34= +github.com/go-git/go-billy/v5 v5.3.1/go.mod h1:pmpqyWchKfYfrkb/UVH4otLvyi/5gJlGI4Hb3ZqZ3W0= github.com/go-git/go-git-fixtures/v4 v4.0.2-0.20200613231340-f56387b50c12 h1:PbKy9zOy4aAKrJ5pibIRpVO2BXnK1Tlcg+caKI7Ox5M= github.com/go-git/go-git-fixtures/v4 v4.0.2-0.20200613231340-f56387b50c12/go.mod h1:m+ICp2rF3jDhFgEZ/8yziagdT1C+ZpZcrJjappBCDSw= +github.com/go-git/go-git-fixtures/v4 v4.2.1 h1:n9gGL1Ct/yIw+nfsfr8s4+sbhT+Ncu2SubfXjIWgci8= +github.com/go-git/go-git-fixtures/v4 v4.2.1/go.mod h1:K8zd3kDUAykwTdDCr+I0per6Y6vMiRR/nnVTBtavnB0= github.com/go-git/go-git/v5 v5.2.0/go.mod h1:kh02eMX+wdqqxgNMEyq8YgwlIOsDOa9homkUq1PoTMs= github.com/go-git/go-git/v5 v5.3.0 h1:8WKMtJR2j8RntEXR/uvTKagfEt4GYlwQ7mntE4+0GWc= github.com/go-git/go-git/v5 v5.3.0/go.mod h1:xdX4bWJ48aOrdhnl2XqHYstHbbp6+LFS4r4X+lNVprw= +github.com/go-git/go-git/v5 v5.4.2 h1:BXyZu9t0VkbiHtqrsvdq39UDhGJTl1h55VW6CSC4aY4= +github.com/go-git/go-git/v5 v5.4.2/go.mod h1:gQ1kArt6d+n+BGd+/B/I74HwRTLhth2+zti4ihgckDc= github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU= github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= @@ -957,6 +974,8 @@ github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm4 github.com/google/rpmpack v0.0.0-20191226140753-aa36bfddb3a0/go.mod h1:RaTPr0KUf2K7fnZYLNDrr8rxAamWs3iNywJLtQ2AzBg= github.com/google/rpmpack v0.0.0-20210410105602-e20c988a6f5a h1:XC048Fc/OB2rUl/BxruopEl2u/EP6cJNFveVxI1cvdk= github.com/google/rpmpack v0.0.0-20210410105602-e20c988a6f5a/go.mod h1:+y9lKiqDhR4zkLl+V9h4q0rdyrYVsWWm6LLCQP33DIk= +github.com/google/rpmpack v0.0.0-20210518075352-dc539ef4f2ea h1:Fv9Ni1vIq9+Gv4Sm0Xq+NnPYcnsMbdNhJ4Cu4rkbPBM= +github.com/google/rpmpack v0.0.0-20210518075352-dc539ef4f2ea/go.mod h1:+y9lKiqDhR4zkLl+V9h4q0rdyrYVsWWm6LLCQP33DIk= 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/subcommands v1.0.1/go.mod h1:ZjhPrFU+Olkh9WazFPsl27BQ4UPiG37m3yTrtFlrHVk= @@ -1004,10 +1023,14 @@ github.com/goreleaser/goreleaser v0.182.1 h1:cKRlHfbMxejiyMCNACsl82slFXEW+k9RggA github.com/goreleaser/goreleaser v0.182.1/go.mod h1:DDAKfIsyz8N8HTGYxGT9OvLW2XMLaS5Gr8/O3fSasKw= github.com/goreleaser/goreleaser v0.184.0 h1:j9tP9sKIVm67TjCEdbinlRxw/Jc06oALg9gEzBt+14o= github.com/goreleaser/goreleaser v0.184.0/go.mod h1:OnFh7NZGcdGqyznqKLHS+O/CRTTYMGjluCWqnfSm+OA= +github.com/goreleaser/goreleaser v1.0.0 h1:83h1R0Y6K4JegTI3K4/koFoAjK14lJ716f0vS6/6ABg= +github.com/goreleaser/goreleaser v1.0.0/go.mod h1:cf++C2P5dMPOGdpoZVfNoJHbhfoK3r0Tasin0z2C0yA= github.com/goreleaser/nfpm v1.2.1 h1:AEnu9XVmupRDTR930Z2rAs31Mj6sLIPxFcR9ESYvgDA= github.com/goreleaser/nfpm v1.2.1/go.mod h1:TtWrABZozuLOttX2uDlYyECfQX7x5XYkVxhjYcR6G9w= github.com/goreleaser/nfpm/v2 v2.6.0 h1:bwDU9o4/CVTSpqASJA7+r+rkqpTGamQKYHMRH3wDlRE= github.com/goreleaser/nfpm/v2 v2.6.0/go.mod h1:qaMnjBaZz/2vInOIWx0IbuKuaZpaVB6O8oLG0u4qH1Y= +github.com/goreleaser/nfpm/v2 v2.9.2 h1:L6CnpgugnSXFuC2eYvfDiYsb6Kb4o2g9rIBxJL31hpc= +github.com/goreleaser/nfpm/v2 v2.9.2/go.mod h1:Bj/ztLvdnBnEgMae0fl/bLF6By1+yFFKeL97WiS6ZJg= github.com/gorhill/cronexpr v0.0.0-20180427100037-88b0669f7d75/go.mod h1:g2644b03hfBX9Ov0ZBDgXXens4rxSxmqFBbhvKv2yVA= github.com/gorilla/context v1.1.1/go.mod h1:kBGZzfjB9CEq2AlWe17Uuf7NDRt0dE0s8S51q0aT7Yg= github.com/gorilla/handlers v0.0.0-20150720190736-60c7bfde3e33/go.mod h1:Qkdc/uu4tH4g6mTK6auzZ766c4CA0Ng8+o/OAirnOIQ= @@ -1135,6 +1158,8 @@ github.com/huandu/xstrings v1.3.2/go.mod h1:y5/lhBue+AyNmUVz9RLU9xbLR0o4KIIExikq github.com/hudl/fargo v1.3.0/go.mod h1:y3CKSmjA+wD2gak7sUSXTAoopbhU08POFhmITJgmKTg= github.com/iancoleman/orderedmap v0.0.0-20190318233801-ac98e3ecb4b0 h1:i462o439ZjprVSFSZLZxcsoAe592sZB1rci2Z8j4wdk= github.com/iancoleman/orderedmap v0.0.0-20190318233801-ac98e3ecb4b0/go.mod h1:N0Wam8K1arqPXNWjMo21EXnBPOPp36vB07FNRdD2geA= +github.com/iancoleman/orderedmap v0.2.0 h1:sq1N/TFpYH++aViPcaKjys3bDClUEU7s5B+z6jq8pNA= +github.com/iancoleman/orderedmap v0.2.0/go.mod h1:N0Wam8K1arqPXNWjMo21EXnBPOPp36vB07FNRdD2geA= github.com/iancoleman/strcase v0.0.0-20180726023541-3605ed457bf7/go.mod h1:SK73tn/9oHe+/Y0h39VT4UCxmurVJkR5NA7kMEAOgSE= github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= @@ -1320,6 +1345,7 @@ github.com/marstr/guid v1.1.0/go.mod h1:74gB1z2wpxxInTG6yaqA7KrtM0NZ+RbrcqDvYHef github.com/marten-seemann/qtls v0.2.3/go.mod h1:xzjG7avBwGGbdZ8dTGxlBnLArsVKLvwmjgmPuiQEcYk= github.com/matoous/godox v0.0.0-20210227103229-6504466cf951 h1:pWxk9e//NbPwfxat7RXkts09K+dEBJWakUWwICVqYbA= github.com/matoous/godox v0.0.0-20210227103229-6504466cf951/go.mod h1:1BELzlh859Sh1c6+90blK8lbYy0kwQf1bYlBhBysy1s= +github.com/matryer/is v1.2.0/go.mod h1:2fLPjFQM9rhQ15aVEtbuwhJinnOqrmgXPNdZsdwlWXA= github.com/matryer/is v1.4.0 h1:sosSmIWwkYITGrxZ25ULNDeKiMNzFSr4V/eqBQP0PeE= github.com/matryer/is v1.4.0/go.mod h1:8I/i5uYgLzgsgEloJE1U6xx5HkBQpAZvepWuujKwMRU= github.com/mattbaird/jsonpatch v0.0.0-20171005235357-81af80346b1a/go.mod h1:M1qoD/MqPgTZIk0EWKB38wE28ACRfVcn+cU08jyArI0= @@ -1383,6 +1409,8 @@ github.com/mitchellh/cli v1.0.0/go.mod h1:hNIlj7HEI86fIcpObd7a0FcrxTWetlwJDGcceT github.com/mitchellh/copystructure v1.0.0/go.mod h1:SNtv71yrdKgLRyLFxmLdkAbkKEFWgYaq1OVrnRcwhnw= github.com/mitchellh/copystructure v1.1.2 h1:Th2TIvG1+6ma3e/0/bopBKohOTY7s4dA8V2q4EUcBJ0= github.com/mitchellh/copystructure v1.1.2/go.mod h1:EBArHfARyrSWO/+Wyr9zwEkc6XMFB9XyNgFNmRkZZU4= +github.com/mitchellh/copystructure v1.2.0 h1:vpKXTN4ewci03Vljg/q9QvCGUDttBOGBIa15WveJJGw= +github.com/mitchellh/copystructure v1.2.0/go.mod h1:qLl+cE2AmVv+CoeAwDPye/v+N2HKCj9FbZEVFJRxO9s= github.com/mitchellh/go-homedir v1.0.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y= github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= @@ -1405,6 +1433,8 @@ github.com/mitchellh/osext v0.0.0-20151018003038-5e2d6d41470f/go.mod h1:OkQIRizQ github.com/mitchellh/reflectwalk v1.0.0/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx0jmZXqmk4esnw= github.com/mitchellh/reflectwalk v1.0.1 h1:FVzMWA5RllMAKIdUSC8mdWo3XtwoecrH79BY70sEEpE= github.com/mitchellh/reflectwalk v1.0.1/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx0jmZXqmk4esnw= +github.com/mitchellh/reflectwalk v1.0.2 h1:G2LzWKi524PWgd3mLHV8Y5k7s6XUvT0Gef6zxSIeXaQ= +github.com/mitchellh/reflectwalk v1.0.2/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx0jmZXqmk4esnw= github.com/mmarkdown/mmark v2.0.40+incompatible h1:vMeUeDzBK3H+/mU0oMVfMuhSXJlIA+DE/DMPQNAj5C4= github.com/mmarkdown/mmark v2.0.40+incompatible/go.mod h1:Uvmoz7tvsWpr7bMVxIpqZPyN3FbOtzDmnsJDFp7ltJs= github.com/moby/ipvs v1.0.1/go.mod h1:2pngiyseZbIKXNv7hsKj3O9UEz30c53MT9005gt2hxQ= @@ -1907,6 +1937,8 @@ github.com/xanzy/go-gitlab v0.50.3/go.mod h1:Q+hQhV508bDPoBijv7YjK/Lvlb4PhVhJdKq github.com/xanzy/ssh-agent v0.2.1/go.mod h1:mLlQY/MoOhWBj+gOGMQkOeiEvkx+8pJSI+0Bx9h2kr4= github.com/xanzy/ssh-agent v0.3.0 h1:wUMzuKtKilRgBAD1sUb8gOwwRr2FGoBVumcjoOACClI= github.com/xanzy/ssh-agent v0.3.0/go.mod h1:3s9xbODqPuuhK9JV1R321M/FlMZSBvE5aY6eAcqrDh0= +github.com/xanzy/ssh-agent v0.3.1 h1:AmzO1SSWxw73zxFZPRwaMN1MohDw8UyHnmuxyceTEGo= +github.com/xanzy/ssh-agent v0.3.1/go.mod h1:QIE4lCeL7nkC25x+yA3LBIYfwCc1TFziCtG7cBAac6w= github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f/go.mod h1:N2zxlSyiKSe5eX1tZViRH5QA0qijqEDrYZiPEAiq3wU= github.com/xeipuuv/gojsonpointer v0.0.0-20190905194746-02993c407bfb h1:zGWFAtiMcyryUHoUjUJX0/lt1H2+i2Ka2n+D3DImSNo= github.com/xeipuuv/gojsonpointer v0.0.0-20190905194746-02993c407bfb/go.mod h1:N2zxlSyiKSe5eX1tZViRH5QA0qijqEDrYZiPEAiq3wU= @@ -2066,10 +2098,14 @@ golang.org/x/crypto v0.0.0-20201124201722-c8d3bf9c5392/go.mod h1:jdWPYTVW3xRLrWP golang.org/x/crypto v0.0.0-20201221181555-eec23a3978ad/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I= golang.org/x/crypto v0.0.0-20210220033148-5ea612d1eb83/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I= golang.org/x/crypto v0.0.0-20210322153248-0c34fe9e7dc2/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4= +golang.org/x/crypto v0.0.0-20210421170649-83a5a9bb288b/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4= golang.org/x/crypto v0.0.0-20210506145944-38f3c27a63bf/go.mod h1:P+XmwS30IXTQdn5tA2iutPOUgjI07+tq3H3K9MVA1s8= golang.org/x/crypto v0.0.0-20210513164829-c07d793c2f9a/go.mod h1:P+XmwS30IXTQdn5tA2iutPOUgjI07+tq3H3K9MVA1s8= +golang.org/x/crypto v0.0.0-20210711020723-a769d52b0f97/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.0.0-20210817164053-32db794688a5 h1:HWj/xjIHfjYU5nVXpTM0s39J9CbLn7Cc5a7IC5rwsMQ= golang.org/x/crypto v0.0.0-20210817164053-32db794688a5/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= +golang.org/x/crypto v0.0.0-20210921155107-089bfa567519 h1:7I4JAnoQBe7ZtJcBaYHi5UtiO8tQHbUSXxL+pnGRANg= +golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/exp v0.0.0-20180321215751-8460e604b9de/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20180807140117-3d87b88a115f/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= @@ -2193,6 +2229,8 @@ golang.org/x/net v0.0.0-20210614182718-04defd469f4e/go.mod h1:9nx3DQGgdP8bBQD5qx golang.org/x/net v0.0.0-20210726213435-c6fcb2dbf985/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20210825183410-e898025ed96a h1:bRuuGXV8wwSdGTB+CtJf+FjgO1APK1CoO39T4BN/XBw= golang.org/x/net v0.0.0-20210825183410-e898025ed96a/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= +golang.org/x/net v0.0.0-20211007125505-59d4e928ea9d h1:QWMn1lFvU/nZ58ssWqiFJMd3DKIII8NYc4sn708XgKs= +golang.org/x/net v0.0.0-20211007125505-59d4e928ea9d/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/oauth2 v0.0.0-20180227000427-d7d64896b5ff/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20181106182150-f42d05182288/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= @@ -2338,6 +2376,7 @@ golang.org/x/sys v0.0.0-20210403161142-5e06dd20ab57/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20210412220455-f1c623a9e750/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210426230700-d19ff857e887/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210502180810-71e4cd670f79/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210503080704-8803ae5d1324/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210511113859-b0526f3d8744/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= @@ -2351,6 +2390,8 @@ golang.org/x/sys v0.0.0-20210806184541-e5e7981a1069/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20210823070655-63515b42dcdf/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210831042530-f4d43177bf5e h1:XMgFehsDnnLGtjvjOfqWSUzt0alpTR1RSEuznObga2c= golang.org/x/sys v0.0.0-20210831042530-f4d43177bf5e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20211007075335-d3039528d8ac h1:oN6lz7iLW/YC7un8pq+9bOLyXrprv2+DKfkJY+2LJJw= +golang.org/x/sys v0.0.0-20211007075335-d3039528d8ac/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210220032956-6a3ed077a48d h1:SZxvLBoTP5yHO3Frd4z4vrF+DBX9vMVanchswa69toE= From 7e016ba3c78c9369bc08da2aaec649adea96ce3f Mon Sep 17 00:00:00 2001 From: nikimanoledaki <18622989+nikimanoledaki@users.noreply.github.com> Date: Wed, 17 Nov 2021 14:10:26 +0100 Subject: [PATCH 088/124] Update build image tag --- .github/workflows/ci.yaml | 2 +- .github/workflows/release-candidate.yaml | 2 +- .github/workflows/release.yaml | 2 +- .github/workflows/tag-release.yaml | 2 +- .github/workflows/update-generated.yaml | 2 +- Dockerfile | 2 +- build/docker/build_image_manifest | 2 +- build/docker/image_tag | 2 +- 8 files changed, 8 insertions(+), 8 deletions(-) diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index cc9cc4e23e..16b361c25d 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -10,7 +10,7 @@ jobs: lint: name: Lint runs-on: ubuntu-latest - container: weaveworks/eksctl-build:e3bb37641cdc03bcb95e88727d5d4ee2654ba888 + container: weaveworks/eksctl-build:3007a819ae8c7ed967da6512c24c45407dd27358 steps: - name: Checkout uses: actions/checkout@v2 diff --git a/.github/workflows/release-candidate.yaml b/.github/workflows/release-candidate.yaml index c599b7bee5..5dc0bcbad5 100644 --- a/.github/workflows/release-candidate.yaml +++ b/.github/workflows/release-candidate.yaml @@ -7,7 +7,7 @@ jobs: rc: name: Trigger release candidate build runs-on: ubuntu-latest - container: weaveworks/eksctl-build:e3bb37641cdc03bcb95e88727d5d4ee2654ba888 + container: weaveworks/eksctl-build:3007a819ae8c7ed967da6512c24c45407dd27358 steps: - name: Checkout uses: actions/checkout@v2 diff --git a/.github/workflows/release.yaml b/.github/workflows/release.yaml index 7165a64e6b..782e04089c 100644 --- a/.github/workflows/release.yaml +++ b/.github/workflows/release.yaml @@ -7,7 +7,7 @@ jobs: rc: name: Trigger release build runs-on: ubuntu-latest - container: weaveworks/eksctl-build:e3bb37641cdc03bcb95e88727d5d4ee2654ba888 + container: weaveworks/eksctl-build:3007a819ae8c7ed967da6512c24c45407dd27358 steps: - name: Checkout uses: actions/checkout@v2 diff --git a/.github/workflows/tag-release.yaml b/.github/workflows/tag-release.yaml index af33c2ad73..2edc556721 100644 --- a/.github/workflows/tag-release.yaml +++ b/.github/workflows/tag-release.yaml @@ -18,7 +18,7 @@ jobs: name: Tag release from version environment: release runs-on: ubuntu-latest - container: weaveworks/eksctl-build:e3bb37641cdc03bcb95e88727d5d4ee2654ba888 + container: weaveworks/eksctl-build:3007a819ae8c7ed967da6512c24c45407dd27358 steps: - name: Checkout uses: actions/checkout@v2 diff --git a/.github/workflows/update-generated.yaml b/.github/workflows/update-generated.yaml index cc4608791e..bca32ef8c7 100644 --- a/.github/workflows/update-generated.yaml +++ b/.github/workflows/update-generated.yaml @@ -55,7 +55,7 @@ jobs: update_aws_node: name: Update aws-node and open PR runs-on: ubuntu-latest - container: weaveworks/eksctl-build:e3bb37641cdc03bcb95e88727d5d4ee2654ba888 + container: weaveworks/eksctl-build:3007a819ae8c7ed967da6512c24c45407dd27358 env: UPDATE_BRANCH: update-aws-node GOPRIVATE: "" diff --git a/Dockerfile b/Dockerfile index 496e7d5056..752d808289 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,4 +1,4 @@ -ARG BUILD_IMAGE=/weaveworks/eksctl-build:e3bb37641cdc03bcb95e88727d5d4ee2654ba888 +ARG BUILD_IMAGE=/weaveworks/eksctl-build:3007a819ae8c7ed967da6512c24c45407dd27358 FROM $BUILD_IMAGE as build WORKDIR /src diff --git a/build/docker/build_image_manifest b/build/docker/build_image_manifest index e3bb37641c..3007a819ae 100644 --- a/build/docker/build_image_manifest +++ b/build/docker/build_image_manifest @@ -2,7 +2,7 @@ "github.com/cloudflare/cfssl v1.6.1" "github.com/cloudflare/cfssl v1.6.1" "github.com/golangci/golangci-lint v1.42.0" -"github.com/goreleaser/goreleaser v0.184.0" +"github.com/goreleaser/goreleaser v1.0.0" "github.com/onsi/ginkgo v1.16.4" "github.com/vektra/mockery v1.1.2" "github.com/github-release/github-release v0.10.0" diff --git a/build/docker/image_tag b/build/docker/image_tag index 33ab05df56..6352a33d76 100644 --- a/build/docker/image_tag +++ b/build/docker/image_tag @@ -1 +1 @@ -e3bb37641cdc03bcb95e88727d5d4ee2654ba888 +3007a819ae8c7ed967da6512c24c45407dd27358 From cef2ecbe0a07e5a344d469e3e32cab9290650bd9 Mon Sep 17 00:00:00 2001 From: Gergely Brautigam <182850+Skarlso@users.noreply.github.com> Date: Thu, 18 Nov 2021 10:41:36 +0100 Subject: [PATCH 089/124] Fixed the config naming check error (#4470) --- pkg/ctl/cmdutils/configfile.go | 4 ---- pkg/ctl/get/nodegroup_test.go | 6 +++--- 2 files changed, 3 insertions(+), 7 deletions(-) diff --git a/pkg/ctl/cmdutils/configfile.go b/pkg/ctl/cmdutils/configfile.go index 66eca8c5e4..0d10447d7f 100644 --- a/pkg/ctl/cmdutils/configfile.go +++ b/pkg/ctl/cmdutils/configfile.go @@ -836,10 +836,6 @@ func NewGetNodegroupLoader(cmd *Cmd, ng *api.NodeGroup) ClusterConfigLoader { l.validateWithoutConfigFile = func() error { meta := cmd.ClusterConfig.Metadata - if meta.Name != "" && cmd.NameArg != "" { - return ErrClusterFlagAndArg(cmd, meta.Name, cmd.NameArg) - } - if meta.Name == "" { return ErrMustBeSet(ClusterNameFlag(cmd)) } diff --git a/pkg/ctl/get/nodegroup_test.go b/pkg/ctl/get/nodegroup_test.go index 38cbbb7737..ba365dd54a 100644 --- a/pkg/ctl/get/nodegroup_test.go +++ b/pkg/ctl/get/nodegroup_test.go @@ -15,10 +15,10 @@ var _ = Describe("get", func() { Expect(err).To(MatchError(ContainSubstring("Error: --cluster must be set"))) }) - It("setting --cluster and argument at the same time", func() { - cmd := newMockCmd("nodegroup", "ng", "--cluster", "name", "--name", "ng") + It("setting --name and argument at the same time", func() { + cmd := newMockCmd("nodegroup", "ng", "--cluster", "dummy", "--name", "ng") _, err := cmd.execute() - Expect(err).To(MatchError(ContainSubstring("Error: --cluster=name and argument ng cannot be used at the same time"))) + Expect(err).To(MatchError(ContainSubstring("Error: --name=ng and argument ng cannot be used at the same time"))) }) It("setting --name and --config-file at the same time", func() { From fbd6e59ef11ecb274449cf68b626fbc620bbbcb1 Mon Sep 17 00:00:00 2001 From: Jake Date: Thu, 18 Nov 2021 09:44:57 +0000 Subject: [PATCH 090/124] remove flux1 & profiles support --- cmd/eksctl/main.go | 2 - examples/21-eks-quickstart-app-dev.yaml | 33 -- integration/matchers/flux.go | 332 ----------- .../quickstart_profiles_test.go | 127 ----- .../quickstart_profiles_gen_test.go | 107 ---- integration/utilities/git/git.go | 158 ++++- pkg/actions/cluster/owned.go | 3 +- pkg/actions/repo/enable.go | 477 ---------------- pkg/actions/repo/enable_test.go | 93 --- pkg/actions/repo/repo_suite_test.go | 14 - pkg/actions/repo/wait.go | 57 -- .../eksctl.io/v1alpha5/assets/schema.json | 183 +----- pkg/apis/eksctl.io/v1alpha5/defaults.go | 47 -- pkg/apis/eksctl.io/v1alpha5/types.go | 142 ----- .../v1alpha5/zz_generated.deepcopy.go | 105 ---- pkg/ctl/cmdutils/configfile.go | 23 - pkg/ctl/cmdutils/gitops.go | 283 --------- pkg/ctl/create/cluster.go | 25 +- pkg/ctl/enable/enable.go | 4 - pkg/ctl/enable/flux_test.go | 10 - pkg/ctl/enable/profile.go | 66 --- pkg/ctl/enable/profile_test.go | 270 --------- pkg/ctl/enable/repo.go | 88 --- pkg/ctl/enable/repo_test.go | 265 --------- pkg/ctl/generate/generate.go | 18 - pkg/ctl/generate/generate_suite_test.go | 11 - pkg/ctl/generate/generate_test.go | 61 -- pkg/ctl/generate/profile.go | 83 --- pkg/ctl/generate/profile_test.go | 226 -------- pkg/git/git.go | 250 -------- pkg/git/git_suite_test.go | 12 - pkg/git/git_test.go | 199 ------- pkg/gitops/deploykey/deploykey.go | 50 -- pkg/gitops/fileprocessor/fileprocessor.go | 13 - pkg/gitops/fileprocessor/gotemplates.go | 65 --- pkg/gitops/gitops.go | 98 +--- pkg/gitops/gitops_suite_test.go | 15 - pkg/gitops/profile.go | 272 --------- pkg/gitops/profile_test.go | 201 ------- pkg/gitops/url.go | 23 - pkg/gitops/url_test.go | 40 -- userdocs/mkdocs.yml | 1 - userdocs/src/community.md | 2 - userdocs/src/usage/gitops-v1.md | 539 ------------------ 44 files changed, 166 insertions(+), 4927 deletions(-) delete mode 100644 examples/21-eks-quickstart-app-dev.yaml delete mode 100644 integration/tests/quickstart_profiles/quickstart_profiles_test.go delete mode 100644 integration/tests/quickstart_profiles_gen/quickstart_profiles_gen_test.go delete mode 100644 pkg/actions/repo/enable.go delete mode 100644 pkg/actions/repo/enable_test.go delete mode 100644 pkg/actions/repo/repo_suite_test.go delete mode 100644 pkg/actions/repo/wait.go delete mode 100644 pkg/ctl/enable/profile.go delete mode 100644 pkg/ctl/enable/profile_test.go delete mode 100644 pkg/ctl/enable/repo.go delete mode 100644 pkg/ctl/enable/repo_test.go delete mode 100644 pkg/ctl/generate/generate.go delete mode 100644 pkg/ctl/generate/generate_suite_test.go delete mode 100644 pkg/ctl/generate/generate_test.go delete mode 100644 pkg/ctl/generate/profile.go delete mode 100644 pkg/ctl/generate/profile_test.go delete mode 100644 pkg/git/git.go delete mode 100644 pkg/git/git_suite_test.go delete mode 100644 pkg/git/git_test.go delete mode 100644 pkg/gitops/deploykey/deploykey.go delete mode 100644 pkg/gitops/fileprocessor/fileprocessor.go delete mode 100644 pkg/gitops/fileprocessor/gotemplates.go delete mode 100644 pkg/gitops/gitops_suite_test.go delete mode 100644 pkg/gitops/profile.go delete mode 100644 pkg/gitops/profile_test.go delete mode 100644 pkg/gitops/url.go delete mode 100644 pkg/gitops/url_test.go delete mode 100644 userdocs/src/usage/gitops-v1.md diff --git a/cmd/eksctl/main.go b/cmd/eksctl/main.go index 7e9b6bde0c..a72b552206 100644 --- a/cmd/eksctl/main.go +++ b/cmd/eksctl/main.go @@ -18,7 +18,6 @@ import ( "github.com/weaveworks/eksctl/pkg/ctl/disassociate" "github.com/weaveworks/eksctl/pkg/ctl/drain" "github.com/weaveworks/eksctl/pkg/ctl/enable" - "github.com/weaveworks/eksctl/pkg/ctl/generate" "github.com/weaveworks/eksctl/pkg/ctl/get" "github.com/weaveworks/eksctl/pkg/ctl/scale" "github.com/weaveworks/eksctl/pkg/ctl/set" @@ -40,7 +39,6 @@ func addCommands(rootCmd *cobra.Command, flagGrouping *cmdutils.FlagGrouping) { rootCmd.AddCommand(unset.Command(flagGrouping)) rootCmd.AddCommand(scale.Command(flagGrouping)) rootCmd.AddCommand(drain.Command(flagGrouping)) - rootCmd.AddCommand(generate.Command(flagGrouping)) rootCmd.AddCommand(enable.Command(flagGrouping)) rootCmd.AddCommand(register.Command(flagGrouping)) rootCmd.AddCommand(deregister.Command(flagGrouping)) diff --git a/examples/21-eks-quickstart-app-dev.yaml b/examples/21-eks-quickstart-app-dev.yaml deleted file mode 100644 index 682e46cb20..0000000000 --- a/examples/21-eks-quickstart-app-dev.yaml +++ /dev/null @@ -1,33 +0,0 @@ -# An example of ClusterConfig object compatible with the "app-dev" quickstart -# profile. See also: https://github.com/weaveworks/eks-quickstart-app-dev ---- -apiVersion: eksctl.io/v1alpha5 -kind: ClusterConfig - -metadata: - name: cluster-21 - region: eu-north-1 - -nodeGroups: - - name: ng-1 - instanceType: m5.large - desiredCapacity: 1 - iam: - withAddonPolicies: - albIngress: true - autoScaler: true - cloudWatch: true - -git: - repo: - url: "git@github.com:myorg/cluster-21.git" - branch: master - fluxPath: "flux/" - user: "gitops" - email: "gitops@myorg.com" - operator: - namespace: "flux" - withHelm: true - bootstrapProfile: - source: app-dev - revision: master diff --git a/integration/matchers/flux.go b/integration/matchers/flux.go index ca9a9a7f06..12a10ab866 100644 --- a/integration/matchers/flux.go +++ b/integration/matchers/flux.go @@ -4,358 +4,26 @@ package matchers import ( - "fmt" - "os" "os/exec" - "path/filepath" - . "github.com/onsi/ginkgo" . "github.com/onsi/gomega" - "github.com/weaveworks/eksctl/integration/utilities/git" - "github.com/weaveworks/eksctl/pkg/kubernetes" - appsv1 "k8s.io/api/apps/v1" corev1 "k8s.io/api/core/v1" - rbacv1beta1 "k8s.io/api/rbac/v1beta1" - apiextensionsv1beta1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1beta1" "sigs.k8s.io/yaml" ) const ( - fluxNamespace = "flux" flux2Namespace = "flux-system" ) var ( - fluxComponents = []string{"flux", "helm-operator", "memcached"} flux2Components = []string{"helm-controller", "kustomize-controller", "notification-controller", "source-controller"} ) -// AssertFluxManifestsAbsentInGit asserts expected Flux manifests are not present in Git. -func AssertFluxManifestsAbsentInGit(branch string) { - dir, err := git.GetBranch(branch) - defer os.RemoveAll(dir) - Expect(err).ShouldNot(HaveOccurred()) - assertDoesNotContainFluxDir(dir) -} - -// AssertFluxManifestsPresentInGit asserts expected Flux manifests are present in Git. -func AssertFluxManifestsPresentInGit(branch string) { - dir, err := git.GetBranch(branch) - defer os.RemoveAll(dir) - Expect(err).ShouldNot(HaveOccurred()) - assertContainsFluxDir(dir) - assertContainsFluxManifests(filepath.Join(dir, fluxNamespace)) -} - -func assertContainsFluxDir(dir string) { - fluxDirExists, err := dirExists(dir) - Expect(err).ShouldNot(HaveOccurred()) - Expect(fluxDirExists).To(BeTrue(), "flux directory could not be found in %s", dir) -} - -func assertDoesNotContainFluxDir(dir string) { - fluxDirExists, err := dirExists(dir) - Expect(err).ShouldNot(HaveOccurred()) - Expect(fluxDirExists).To(BeFalse(), "flux directory was unexpectedly found in %s", dir) -} - -func dirExists(dir string) (bool, error) { - files, err := os.ReadDir(dir) - if err != nil { - return false, err - } - for _, f := range files { - if f.Name() == fluxNamespace && f.IsDir() { - return true, nil - } - } - return false, nil -} - -func assertContainsFluxManifests(dir string) { - // We could have stricter validation by comparing objects in Kubernetes and - // in the manifests, and ensuring they are equal. However, this may not be - // very easy to achieve, especially for values which are defaulted by the - // API server. Hence, for now, we simply ensure that all files & objects - // are present, and that the main fields of these objects match expected - // values. - files, err := os.ReadDir(dir) - Expect(err).ShouldNot(HaveOccurred()) - for _, f := range files { - if f.IsDir() { - Fail(fmt.Sprintf("Unrecognized directory: %s", f.Name())) - } - filePath := filepath.Join(dir, f.Name()) - switch f.Name() { - // Flux resources: - case "flux-account.yaml": - assertValidFluxAccountManifest(filePath) - case "flux-deployment.yaml": - assertValidFluxDeploymentManifest(filePath) - case "flux-namespace.yaml": - assertValidFluxNamespaceManifest(filePath) - case "flux-secret.yaml": - assertValidFluxSecretManifest(filePath) - case "memcache-dep.yaml": - assertValidFluxMemcacheDeploymentManifest(filePath) - case "memcache-svc.yaml": - assertValidFluxMemcacheServiceManifest(filePath) - // Helm operator resources: - case "rbac.yaml": - assertValidFluxHelmOperatorAccount(filePath) - case "crds.yaml": - assertValidFluxHelmReleaseCRD(filePath) - case "deployment.yaml": - assertValidHelmOperatorDeployment(filePath) - default: - Fail(fmt.Sprintf("Unrecognized file: %s", f.Name())) - } - } -} - -func assertValidFluxAccountManifest(fileName string) { - bytes, err := os.ReadFile(fileName) - Expect(err).ShouldNot(HaveOccurred()) - list, err := kubernetes.NewRawExtensions(bytes) - Expect(err).ShouldNot(HaveOccurred()) - Expect(list).To(HaveLen(3)) - for _, item := range list { - gvk := item.Object.GetObjectKind().GroupVersionKind() - if gvk.Version == "v1" && gvk.Kind == "ServiceAccount" { - sa, ok := item.Object.(*corev1.ServiceAccount) - Expect(ok).To(BeTrue(), "Failed to convert object of type %T to %s", item.Object, gvk.Kind) - Expect(sa.Kind).To(Equal("ServiceAccount")) - Expect(sa.Namespace).To(Equal(fluxNamespace)) - Expect(sa.Name).To(Equal("flux")) - Expect(sa.Labels["name"]).To(Equal("flux")) - } else if gvk.Version == "v1beta1" && gvk.Kind == "ClusterRole" { - cr, ok := item.Object.(*rbacv1beta1.ClusterRole) - Expect(ok).To(BeTrue(), "Failed to convert object of type %T to %s", item.Object, gvk.Kind) - Expect(cr.Kind).To(Equal("ClusterRole")) - Expect(cr.Name).To(Equal("flux")) - Expect(cr.Labels["name"]).To(Equal("flux")) - } else if gvk.Version == "v1beta1" && gvk.Kind == "ClusterRoleBinding" { - crb, ok := item.Object.(*rbacv1beta1.ClusterRoleBinding) - Expect(ok).To(BeTrue(), "Failed to convert object of type %T to %s", item.Object, gvk.Kind) - Expect(crb.Kind).To(Equal("ClusterRoleBinding")) - Expect(crb.Name).To(Equal("flux")) - Expect(crb.Labels["name"]).To(Equal("flux")) - } else { - Fail(fmt.Sprintf("Unsupported Kubernetes object. Got %s object with version %s in: %s", gvk.Kind, gvk.Version, fileName)) - } - } -} - -func assertValidFluxDeploymentManifest(fileName string) { - bytes, err := os.ReadFile(fileName) - Expect(err).ShouldNot(HaveOccurred()) - list, err := kubernetes.NewRawExtensions(bytes) - Expect(err).ShouldNot(HaveOccurred()) - Expect(list).To(HaveLen(1)) - for _, item := range list { - gvk := item.Object.GetObjectKind().GroupVersionKind() - if gvk.Version == "v1" && gvk.Kind == "Deployment" { - deployment, ok := item.Object.(*appsv1.Deployment) - Expect(ok).To(BeTrue(), "Failed to convert object of type %T to %s", item.Object, gvk.Kind) - Expect(deployment.Kind).To(Equal("Deployment")) - - Expect(deployment.Namespace).To(Equal(fluxNamespace)) - Expect(deployment.Name).To(Equal("flux")) - Expect(*deployment.Spec.Replicas).To(Equal(int32(1))) - Expect(deployment.Spec.Template.Labels["name"]).To(Equal("flux")) - Expect(deployment.Spec.Template.Spec.Containers).To(HaveLen(1)) - container := deployment.Spec.Template.Spec.Containers[0] - Expect(container.Name).To(Equal("flux")) - Expect(container.Image).To(HavePrefix("docker.io/fluxcd/flux")) - } else { - Fail(fmt.Sprintf("Unsupported Kubernetes object. Got %s object with version %s in: %s", gvk.Kind, gvk.Version, fileName)) - } - } -} - -func assertValidFluxSecretManifest(fileName string) { - bytes, err := os.ReadFile(fileName) - Expect(err).ShouldNot(HaveOccurred()) - list, err := kubernetes.NewRawExtensions(bytes) - Expect(err).ShouldNot(HaveOccurred()) - Expect(list).To(HaveLen(1)) - for _, item := range list { - gvk := item.Object.GetObjectKind().GroupVersionKind() - if gvk.Version == "v1" && gvk.Kind == "Secret" { - secret, ok := item.Object.(*corev1.Secret) - Expect(ok).To(BeTrue(), "Failed to convert object of type %T to %s", item.Object, gvk.Kind) - Expect(secret.Kind).To(Equal("Secret")) - Expect(secret.Namespace).To(Equal(fluxNamespace)) - Expect(secret.Name).To(Equal("flux-git-deploy")) - Expect(secret.Type).To(Equal(corev1.SecretTypeOpaque)) - } else { - Fail(fmt.Sprintf("Unsupported Kubernetes object. Got %s object with version %s in: %s", gvk.Kind, gvk.Version, fileName)) - } - } -} - -func assertValidFluxMemcacheDeploymentManifest(fileName string) { - bytes, err := os.ReadFile(fileName) - Expect(err).ShouldNot(HaveOccurred()) - list, err := kubernetes.NewRawExtensions(bytes) - Expect(err).ShouldNot(HaveOccurred()) - Expect(list).To(HaveLen(1)) - for _, item := range list { - gvk := item.Object.GetObjectKind().GroupVersionKind() - if gvk.Version == "v1" && gvk.Kind == "Deployment" { - deployment, ok := item.Object.(*appsv1.Deployment) - Expect(ok).To(BeTrue(), "Failed to convert object of type %T to %s", item.Object, gvk.Kind) - Expect(deployment.Kind).To(Equal("Deployment")) - Expect(deployment.Namespace).To(Equal(fluxNamespace)) - Expect(deployment.Name).To(Equal("memcached")) - Expect(*deployment.Spec.Replicas).To(Equal(int32(1))) - Expect(deployment.Spec.Template.Labels["name"]).To(Equal("memcached")) - Expect(deployment.Spec.Template.Spec.Containers).To(HaveLen(1)) - container := deployment.Spec.Template.Spec.Containers[0] - Expect(container.Name).To(Equal("memcached")) - Expect(container.Image).To(Equal("memcached:1.5.20")) - Expect(container.Ports).To(HaveLen(1)) - Expect(container.Ports[0].ContainerPort).To(Equal(int32(11211))) - } else { - Fail(fmt.Sprintf("Unsupported Kubernetes object. Got %s object with version %s in: %s", gvk.Kind, gvk.Version, fileName)) - } - } -} - -func assertValidFluxMemcacheServiceManifest(fileName string) { - bytes, err := os.ReadFile(fileName) - Expect(err).ShouldNot(HaveOccurred()) - list, err := kubernetes.NewRawExtensions(bytes) - Expect(err).ShouldNot(HaveOccurred()) - Expect(list).To(HaveLen(1)) - for _, item := range list { - gvk := item.Object.GetObjectKind().GroupVersionKind() - if gvk.Version == "v1" && gvk.Kind == "Service" { - service, ok := item.Object.(*corev1.Service) - Expect(ok).To(BeTrue(), "Failed to convert object of type %T to %s", item.Object, gvk.Kind) - Expect(service.Kind).To(Equal("Service")) - - Expect(service.Namespace).To(Equal(fluxNamespace)) - Expect("memcached").To(Equal(service.Name)) - Expect(service.Spec.Ports).To(HaveLen(1)) - Expect(service.Spec.Ports[0].Name).To(Equal("memcached")) - Expect(service.Spec.Ports[0].Port).To(Equal(int32(11211))) - Expect(service.Spec.Selector).To(HaveLen(1)) - Expect(service.Spec.Selector["name"]).To(Equal("memcached")) - } else { - Fail(fmt.Sprintf("Unsupported Kubernetes object. Got %s object with version %s in: %s", gvk.Kind, gvk.Version, fileName)) - } - } -} - -func assertValidFluxNamespaceManifest(fileName string) { - bytes, err := os.ReadFile(fileName) - Expect(err).ShouldNot(HaveOccurred()) - list, err := kubernetes.NewRawExtensions(bytes) - Expect(err).ShouldNot(HaveOccurred()) - Expect(list).To(HaveLen(1)) - for _, item := range list { - gvk := item.Object.GetObjectKind().GroupVersionKind() - if gvk.Version == "v1" && gvk.Kind == "Namespace" { - ns, ok := item.Object.(*corev1.Namespace) - Expect(ok).To(BeTrue(), "Failed to convert object of type %T to %s", item.Object, gvk.Kind) - Expect(ns.Kind).To(Equal("Namespace")) - Expect(ns.Name).To(Equal(fluxNamespace)) - } else { - Fail(fmt.Sprintf("Unsupported Kubernetes object. Got %s object with version %s in: %s", gvk.Kind, gvk.Version, fileName)) - } - } -} - -func assertValidFluxHelmOperatorAccount(fileName string) { - bytes, err := os.ReadFile(fileName) - Expect(err).ShouldNot(HaveOccurred()) - list, err := kubernetes.NewRawExtensions(bytes) - Expect(err).ShouldNot(HaveOccurred()) - Expect(list).To(HaveLen(3)) - for _, item := range list { - gvk := item.Object.GetObjectKind().GroupVersionKind() - if gvk.Version == "v1" && gvk.Kind == "ServiceAccount" { - sa, ok := item.Object.(*corev1.ServiceAccount) - Expect(ok).To(BeTrue(), "Failed to convert object of type %T to %s", item.Object, gvk.Kind) - Expect(sa.Kind).To(Equal("ServiceAccount")) - Expect(sa.Namespace).To(Equal(fluxNamespace)) - Expect(sa.Name).To(Equal("helm-operator")) - Expect(sa.Labels["name"]).To(Equal("helm-operator")) - } else if gvk.Version == "v1beta1" && gvk.Kind == "ClusterRole" { - cr, ok := item.Object.(*rbacv1beta1.ClusterRole) - Expect(ok).To(BeTrue(), "Failed to convert object of type %T to %s", item.Object, gvk.Kind) - Expect(cr.Kind).To(Equal("ClusterRole")) - Expect(cr.Name).To(Equal("helm-operator")) - Expect(cr.Labels["name"]).To(Equal("helm-operator")) - } else if gvk.Version == "v1beta1" && gvk.Kind == "ClusterRoleBinding" { - crb, ok := item.Object.(*rbacv1beta1.ClusterRoleBinding) - Expect(ok).To(BeTrue(), "Failed to convert object of type %T to %s", item.Object, gvk.Kind) - Expect(crb.Kind).To(Equal("ClusterRoleBinding")) - Expect(crb.Name).To(Equal("helm-operator")) - Expect(crb.Labels["name"]).To(Equal("helm-operator")) - } else { - Fail(fmt.Sprintf("Unsupported Kubernetes object. Got %s object with version %s in: %s", gvk.Kind, gvk.Version, fileName)) - } - } -} - -func assertValidFluxHelmReleaseCRD(fileName string) { - bytes, err := os.ReadFile(fileName) - Expect(err).ShouldNot(HaveOccurred()) - list, err := kubernetes.NewRawExtensions(bytes) - Expect(err).ShouldNot(HaveOccurred()) - Expect(list).To(HaveLen(1)) - for _, item := range list { - gvk := item.Object.GetObjectKind().GroupVersionKind() - if gvk.Version == "v1beta1" && gvk.Kind == "CustomResourceDefinition" { - crd, ok := item.Object.(*apiextensionsv1beta1.CustomResourceDefinition) - Expect(ok).To(BeTrue(), "Failed to convert object of type %T to %s", item.Object, gvk.Kind) - Expect(crd.Kind).To(Equal("CustomResourceDefinition")) - Expect(crd.Name).To(Equal("helmreleases.helm.fluxcd.io")) - Expect(crd.Spec.Group).To(Equal("helm.fluxcd.io")) - Expect(crd.Spec.Names.Kind).To(Equal("HelmRelease")) - } else { - Fail(fmt.Sprintf("Unsupported Kubernetes object. Got %s object with version %s in: %s", gvk.Kind, gvk.Version, fileName)) - } - } -} - -func assertValidHelmOperatorDeployment(fileName string) { - bytes, err := os.ReadFile(fileName) - Expect(err).ShouldNot(HaveOccurred()) - list, err := kubernetes.NewRawExtensions(bytes) - Expect(err).ShouldNot(HaveOccurred()) - Expect(list).To(HaveLen(1)) - for _, item := range list { - gvk := item.Object.GetObjectKind().GroupVersionKind() - if gvk.Version == "v1" && gvk.Kind == "Deployment" { - deployment, ok := item.Object.(*appsv1.Deployment) - Expect(ok).To(BeTrue(), "Failed to convert object of type %T to %s", item.Object, gvk.Kind) - Expect(deployment.Kind).To(Equal("Deployment")) - Expect(deployment.Namespace).To(Equal(fluxNamespace)) - Expect(deployment.Name).To(Equal("helm-operator")) - Expect(*deployment.Spec.Replicas).To(Equal(int32(1))) - Expect(deployment.Spec.Template.Labels["name"]).To(Equal("helm-operator")) - Expect(deployment.Spec.Template.Spec.Containers).To(HaveLen(1)) - container := deployment.Spec.Template.Spec.Containers[0] - Expect(container.Name).To(Equal("helm-operator")) - Expect(container.Image).To(HavePrefix("docker.io/fluxcd/helm-operator")) - } else { - Fail(fmt.Sprintf("Unsupported Kubernetes object. Got %s object with version %s in: %s", gvk.Kind, gvk.Version, fileName)) - } - } -} - func AssertFluxPodsAbsentInKubernetes(kubeconfigPath, namespace string) { pods := fluxPods(kubeconfigPath, namespace) Expect(pods.Items).To(HaveLen(0)) } -func AssertFluxPodsPresentInKubernetes(kubeconfigPath string) { - assertLabelPresent(kubeconfigPath, fluxNamespace, "name", fluxComponents) -} - func AssertFlux2PodsPresentInKubernetes(kubeconfigPath string) { assertLabelPresent(kubeconfigPath, flux2Namespace, "app", flux2Components) } diff --git a/integration/tests/quickstart_profiles/quickstart_profiles_test.go b/integration/tests/quickstart_profiles/quickstart_profiles_test.go deleted file mode 100644 index 11feeaf870..0000000000 --- a/integration/tests/quickstart_profiles/quickstart_profiles_test.go +++ /dev/null @@ -1,127 +0,0 @@ -//go:build integration -// +build integration - -package integration_test - -import ( - "testing" - - . "github.com/weaveworks/eksctl/integration/matchers" - . "github.com/weaveworks/eksctl/integration/runner" - "github.com/weaveworks/eksctl/integration/tests" - "github.com/weaveworks/eksctl/integration/utilities/git" - "github.com/weaveworks/eksctl/pkg/testutils" - - "github.com/kubicorn/kubicorn/pkg/namer" - . "github.com/onsi/ginkgo" - . "github.com/onsi/gomega" -) - -var ( - params *tests.Params -) - -func init() { - // Call testing.Init() prior to tests.NewParams(), as otherwise -test.* will not be recognised. See also: https://golang.org/doc/go1.13#testing - testing.Init() - params = tests.NewParams("qstart") -} - -func TestQuickstartProfiles(t *testing.T) { - testutils.RegisterAndRun(t) -} - -var _ = BeforeSuite(func() { - if !params.SkipCreate { - cmd := params.EksctlCreateCmd.WithArgs( - "cluster", - "--name", params.ClusterName, - "--verbose", "4", - "--region", params.Region, - "--kubeconfig", params.KubeconfigPath, - ) - Expect(cmd).To(RunSuccessfully()) - } -}) - -var _ = Describe("Enable and use GitOps quickstart profiles", func() { - var ( - branch string - cloneDir string - err error - ) - - BeforeEach(func() { - if branch == "" { - branch = namer.RandomName() - cloneDir, err = git.CreateBranch(branch) - } - }) - - Context("enable repo", func() { - It("should add Flux to the repo and the cluster", func() { - Expect(err).NotTo(HaveOccurred()) // Creating the branch should have succeeded. - AssertFluxManifestsAbsentInGit(branch) - AssertFluxPodsAbsentInKubernetes(params.KubeconfigPath, "flux") - - cmd := params.EksctlCmd.WithArgs( - "enable", "repo", - "--git-url", git.Repository, - "--git-email", git.Email, - "--git-branch", branch, - "--cluster", params.ClusterName, - ) - Expect(cmd).To(RunSuccessfully()) - - AssertFluxManifestsPresentInGit(branch) - AssertFluxPodsPresentInKubernetes(params.KubeconfigPath) - }) - }) - - Context("enable repo", func() { - It("should not add Flux to the repo and the cluster if there is a flux deployment already", func() { - Expect(err).NotTo(HaveOccurred()) // Creating the branch should have succeeded. - AssertFluxPodsPresentInKubernetes(params.KubeconfigPath) - - cmd := params.EksctlCmd.WithArgs( - "enable", "repo", - "--git-url", git.Repository, - "--git-email", git.Email, - "--git-branch", branch, - "--cluster", params.ClusterName, - ) - Expect(cmd).To(RunSuccessfullyWithOutputString(ContainSubstring("Skipping installation"))) - }) - }) - - Context("enable profile", func() { - It("should add the configured quickstart profile to the repo and the cluster", func() { - Expect(err).NotTo(HaveOccurred()) // Creating the branch should have succeeded. - // Flux should have been installed by the previously run "enable repo" command: - AssertFluxManifestsPresentInGit(branch) - AssertFluxPodsPresentInKubernetes(params.KubeconfigPath) - - cmd := params.EksctlCmd.WithArgs( - "enable", "profile", - "--git-url", git.Repository, - "--git-email", git.Email, - "--git-branch", branch, - "--cluster", params.ClusterName, - "app-dev", - ) - Expect(cmd).To(RunSuccessfully()) - - AssertQuickStartComponentsPresentInGit(branch) - // Flux should still be present: - AssertFluxManifestsPresentInGit(branch) - AssertFluxPodsPresentInKubernetes(params.KubeconfigPath) - // Clean-up: - err := git.CleanupBranchAndRepo(branch, cloneDir) - Expect(err).NotTo(HaveOccurred()) // Deleting the branch should have succeeded. - }) - }) -}) - -var _ = AfterSuite(func() { - params.DeleteClusters() -}) diff --git a/integration/tests/quickstart_profiles_gen/quickstart_profiles_gen_test.go b/integration/tests/quickstart_profiles_gen/quickstart_profiles_gen_test.go deleted file mode 100644 index 13e957d6f7..0000000000 --- a/integration/tests/quickstart_profiles_gen/quickstart_profiles_gen_test.go +++ /dev/null @@ -1,107 +0,0 @@ -//go:build integration -// +build integration - -package quickstart_profiles_gen - -import ( - "fmt" - "os" - "path/filepath" - "testing" - - . "github.com/weaveworks/eksctl/integration/runner" - "github.com/weaveworks/eksctl/integration/tests" - "github.com/weaveworks/eksctl/pkg/testutils" - - . "github.com/onsi/ginkgo" - . "github.com/onsi/gomega" - "github.com/spf13/afero" -) - -var params *tests.Params - -func init() { - // Call testing.Init() prior to tests.NewParams(), as otherwise -test.* will not be recognised. See also: https://golang.org/doc/go1.13#testing - testing.Init() - params = tests.NewParams("qstartgen") -} - -func TestQuickstartProfilesGen(t *testing.T) { - testutils.RegisterAndRun(t) -} - -var _ = BeforeSuite(func() { - cmd := params.EksctlCreateCmd.WithArgs( - "cluster", - "--verbose", "4", - "--name", params.ClusterName, - "--region", params.Region, - ) - Expect(cmd).To(RunSuccessfully()) -}) - -var _ = Describe("(Integration) generate profile", func() { - - Describe("when generating a profile", func() { - It("should write the processed repo files in the supplied directory", func() { - cmd := params.EksctlCmd.WithArgs( - "generate", "profile", - "--verbose", "4", - "--cluster", params.ClusterName, - "--profile-source", "git@github.com:eksctl-bot/eksctl-profile-integration-tests.git", - "--profile-path", params.TestDirectory, - ) - Expect(cmd).To(RunSuccessfully()) - - fs := afero.Afero{ - Fs: afero.NewOsFs(), - } - - contents, err := fs.ReadFile(filepath.Join(params.TestDirectory, "workloads/namespace.yaml")) - Expect(err).NotTo(HaveOccurred()) - Expect(string(contents)).To(MatchYAML(fmt.Sprintf( - `--- -apiVersion: v1 -kind: Namespace -metadata: - labels: - name: %s-%s - name: %s -`, params.ClusterName, params.Region, params.ClusterName))) - - contents, err = fs.ReadFile(filepath.Join(params.TestDirectory, "workloads/services/service.yaml")) - Expect(err).NotTo(HaveOccurred()) - Expect(string(contents)).To(MatchYAML(fmt.Sprintf( - `--- -apiVersion: v1 -kind: Service -metadata: - name: %s-service1 -spec: - selector: - app: MyApp - ports: - - protocol: TCP - port: 80 - targetPort: 9376 -`, params.ClusterName))) - - contents, err = fs.ReadFile(filepath.Join(params.TestDirectory, "metadata.yaml")) - Expect(err).NotTo(HaveOccurred()) - Expect(string(contents)).To(MatchYAML( - `--- -somekey: - repo: eks-gitops-tests - thisFile: should not be modified by eksctl generate profile -anotherkey: - nestedKey: nestedvalue -`)) - - }) - }) -}) - -var _ = AfterSuite(func() { - params.DeleteClusters() - os.RemoveAll(params.TestDirectory) -}) diff --git a/integration/utilities/git/git.go b/integration/utilities/git/git.go index c1154cc5a9..e4f1c24037 100644 --- a/integration/utilities/git/git.go +++ b/integration/utilities/git/git.go @@ -4,7 +4,13 @@ package git import ( - "github.com/weaveworks/eksctl/pkg/git" + "fmt" + "os" + + "github.com/kris-nova/logger" + "github.com/pkg/errors" + "github.com/weaveworks/eksctl/pkg/executor" + "github.com/weaveworks/eksctl/pkg/utils/file" ) const ( @@ -16,10 +22,10 @@ const ( // CreateBranch creates the provided branch. func CreateBranch(branch string) (string, error) { - cli := git.NewGitClient(git.ClientParams{}) + cli := NewGitClient(ClientParams{}) cloneDir, err := cli.CloneRepoInTmpDir( "eksctl-install-flux-test-branch-", - git.CloneOptions{ + CloneOptions{ URL: Repository, Branch: branch, Bootstrap: true, @@ -36,7 +42,7 @@ func CreateBranch(branch string) (string, error) { // CleanupBranchAndRepo deletes the local clone used for testing Git repository, and delete the branch from "origin" as well. func CleanupBranchAndRepo(branch, cloneDir string) error { - cli := git.NewGitClient(git.ClientParams{}) + cli := NewGitClient(ClientParams{}) cli.WithDir(cloneDir) if err := cli.DeleteRemoteBranch(branch); err != nil { return err @@ -46,13 +52,153 @@ func CleanupBranchAndRepo(branch, cloneDir string) error { // GetBranch clones the testing Git repository and checks out the provided branch. func GetBranch(branch string) (string, error) { - cli := git.NewGitClient(git.ClientParams{}) + cli := NewGitClient(ClientParams{}) return cli.CloneRepoInTmpDir( "eksctl-install-flux-test-branch-", - git.CloneOptions{ + CloneOptions{ URL: Repository, Branch: branch, Bootstrap: true, }, ) } + +// TmpCloner can clone git repositories in temporary directories +type TmpCloner interface { + CloneRepoInTmpDir(cloneDirPrefix string, options CloneOptions) (string, error) +} + +// Client can perform git operations on the given directory +type Client struct { + executor executor.Executor + dir string +} + +// ClientParams groups the arguments to provide to create a new Git client. +type ClientParams struct { + PrivateSSHKeyPath string +} + +// ValidatePrivateSSHKeyPath validates the path to the (optional) private SSH +// key used to interact with the Git repository configured in this object. +func ValidatePrivateSSHKeyPath(privateSSHKeyPath string) error { + if privateSSHKeyPath != "" && !file.Exists(privateSSHKeyPath) { + return fmt.Errorf("invalid path to private SSH key: %s", privateSSHKeyPath) + } + return nil +} + +// NewGitClient returns a client that can perform git operations +func NewGitClient(params ClientParams) *Client { + return &Client{ + executor: executor.NewShellExecutor(envVars(params)), + } +} + +func envVars(params ClientParams) executor.EnvVars { + envVars := executor.EnvVars{ + "PATH": os.Getenv("PATH"), + } + if sshAuthSock, ok := os.LookupEnv("SSH_AUTH_SOCK"); ok { + envVars["SSH_AUTH_SOCK"] = sshAuthSock + } + if params.PrivateSSHKeyPath != "" { + envVars["GIT_SSH_COMMAND"] = "ssh -i " + params.PrivateSSHKeyPath + } + return envVars +} + +// NewGitClientFromExecutor returns a client that can have an executor injected. Useful for testing +func NewGitClientFromExecutor(executor executor.Executor) *Client { + return &Client{ + executor: executor, + } +} + +// CloneOptions are the options for cloning a Git repository +type CloneOptions struct { + URL string + Branch string + Bootstrap bool // create the branch if the repository is empty +} + +// WithDir directly sets the Client to use a directory, without havine to clone +// it +func (git *Client) WithDir(dir string) { + git.dir = dir +} + +// CloneRepoInTmpDir clones a repo specified in the gitURL in a temporary directory and checks out the specified branch +func (git *Client) CloneRepoInTmpDir(tmpDirPrefix string, options CloneOptions) (string, error) { + cloneDir, err := os.MkdirTemp(os.TempDir(), tmpDirPrefix) + if err != nil { + return "", fmt.Errorf("cannot create temporary directory: %s", err) + } + return cloneDir, git.cloneRepoInPath(cloneDir, options) +} + +// CloneRepoInPath behaves like CloneRepoInTmpDir but clones the repository in a specific directory +// which creates if needed +func (git *Client) CloneRepoInPath(clonePath string, options CloneOptions) error { + if err := os.MkdirAll(clonePath, 0700); err != nil { + return errors.Wrapf(err, "unable to create directory for cloning") + } + return git.cloneRepoInPath(clonePath, options) +} + +func (git *Client) cloneRepoInPath(clonePath string, options CloneOptions) error { + args := []string{"clone", options.URL, clonePath} + if err := git.runGitCmd(args...); err != nil { + return err + } + // Set the working directory to the cloned directory, but + // only do it after the clone so that it doesn't create an + // undesirable nested directory + git.dir = clonePath + + if options.Branch != "" { + // Switch to target branch + args := []string{"checkout", options.Branch} + if options.Bootstrap { + if !git.isRemoteBranch(options.Branch) { + args = []string{"checkout", "-b", options.Branch} + } + } + if err := git.runGitCmd(args...); err != nil { + return err + } + } + + return nil +} + +func (git *Client) isRemoteBranch(branch string) bool { + err := git.runGitCmd("ls-remote", "--heads", "--exit-code", "origin", branch) + return err == nil +} + +// Push pushes the changes to the origin remote +func (git Client) Push() error { + if err := git.runGitCmd("config", "push.default", "current"); err != nil { + return err + } + err := git.runGitCmd("push") + return err +} + +func (git Client) DeleteRemoteBranch(branch string) error { + return git.runGitCmd("push", "origin", "--delete", branch) +} + +// DeleteLocalRepo deletes the local copy of a repository, including the directory +func (git Client) DeleteLocalRepo() error { + if git.dir != "" { + return os.RemoveAll(git.dir) + } + return fmt.Errorf("no cloned directory to delete") +} + +func (git Client) runGitCmd(args ...string) error { + logger.Debug(fmt.Sprintf("running git %v in %s", args, git.dir)) + return git.executor.ExecInDir("git", git.dir, args...) +} diff --git a/pkg/actions/cluster/owned.go b/pkg/actions/cluster/owned.go index 41ea0c57d8..2168572b09 100644 --- a/pkg/actions/cluster/owned.go +++ b/pkg/actions/cluster/owned.go @@ -9,7 +9,6 @@ import ( "github.com/weaveworks/eksctl/pkg/cfn/manager" "github.com/weaveworks/eksctl/pkg/ctl/cmdutils" "github.com/weaveworks/eksctl/pkg/eks" - "github.com/weaveworks/eksctl/pkg/gitops" iamoidc "github.com/weaveworks/eksctl/pkg/iam/oidc" "github.com/weaveworks/eksctl/pkg/kubernetes" "github.com/weaveworks/eksctl/pkg/vpc" @@ -155,5 +154,5 @@ func (c *OwnedCluster) Delete(_ time.Duration, wait, force bool) error { logger.Success("all cluster resources were deleted") - return gitops.DeleteKey(c.cfg) + return nil } diff --git a/pkg/actions/repo/enable.go b/pkg/actions/repo/enable.go deleted file mode 100644 index ac3ae5cd90..0000000000 --- a/pkg/actions/repo/enable.go +++ /dev/null @@ -1,477 +0,0 @@ -// FLUX V1 DEPRECATION NOTICE. https://github.com/weaveworks/eksctl/issues/2963 -package repo - -import ( - "context" - "encoding/json" - "fmt" - "net/http" - "os" - "path/filepath" - "strings" - "time" - - fluxinstall "github.com/fluxcd/flux/pkg/install" - "github.com/fluxcd/go-git-providers/gitprovider" - helmopinstall "github.com/fluxcd/helm-operator/pkg/install" - portforward "github.com/justinbarrick/go-k8s-portforward" - "github.com/kris-nova/logger" - "github.com/pkg/errors" - api "github.com/weaveworks/eksctl/pkg/apis/eksctl.io/v1alpha5" - "github.com/weaveworks/eksctl/pkg/git" - "github.com/weaveworks/eksctl/pkg/gitops/deploykey" - "github.com/weaveworks/eksctl/pkg/kubernetes" - apierrs "k8s.io/apimachinery/pkg/api/errors" - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - kubeclient "k8s.io/client-go/kubernetes" - "k8s.io/client-go/rest" -) - -const ( - fluxNamespaceFileName = "flux-namespace.yaml" - fluxPrivateSSHKeyFileName = "flux-secret.yaml" - fluxPrivateSSHKeySecretName = "flux-git-deploy" - fluxHelmVersions = "v3" - portForwardingTimeout = 120 * time.Second - portForwardingRetryPeriod = 2 * time.Second -) - -type Installer struct { - Cfg *api.ClusterConfig - Opts *api.Git - Timeout time.Duration - K8sRestConfig *rest.Config - K8sClientSet kubeclient.Interface - GitClient *git.Client -} - -func New( - k8sRestConfig *rest.Config, k8sClientSet kubeclient.Interface, - cfg *api.ClusterConfig, timeout time.Duration, -) (*Installer, error) { - if cfg.Git == nil { - return nil, errors.New("expected git configuration in cluster configuration but found nil") - } - if cfg.Git.Repo == nil { - return nil, errors.New("expected git.repo in cluster configuration but found nil") - } - gitClient := git.NewGitClient(git.ClientParams{ - PrivateSSHKeyPath: cfg.Git.Repo.PrivateSSHKeyPath, - }) - installer := &Installer{ - Cfg: cfg, - Opts: cfg.Git, - K8sRestConfig: k8sRestConfig, - K8sClientSet: k8sClientSet, - GitClient: gitClient, - Timeout: timeout, - } - return installer, nil -} - -func (fi *Installer) Run() error { - fluxIsInstalled, err := fi.isFluxInstalled() - if err != nil { - // Continue with installation - logger.Warning(err.Error()) - } - - if fluxIsInstalled { - logger.Warning("found existing flux deployment in namespace %q. Skipping installation", fi.Opts.Operator.Namespace) - return nil - } - - userInstructions, err := fi.installFlux(context.Background()) - if err != nil { - logger.Critical("unable to set up gitops repo: %s", err.Error()) - return err - } - logger.Info(userInstructions) - - return nil -} - -func (fi *Installer) isFluxInstalled() (bool, error) { - _, err := fi.K8sClientSet.AppsV1().Deployments(fi.Opts.Operator.Namespace).Get(context.TODO(), "flux", metav1.GetOptions{}) - if err != nil { - if apierrs.IsNotFound(err) { - logger.Warning("flux deployment was not found") - return false, nil - } - return false, errors.Wrapf(err, "error while looking for flux pod") - } - return true, nil -} - -func (fi *Installer) installFlux(ctx context.Context) (string, error) { - logger.Info("Generating manifests") - manifests, err := fi.GetManifests() - if err != nil { - return "", err - } - - logger.Info("Cloning %s", fi.Opts.Repo.URL) - options := git.CloneOptions{ - URL: fi.Opts.Repo.URL, - Branch: fi.Opts.Repo.Branch, - Bootstrap: true, - } - cloneDir, err := fi.GitClient.CloneRepoInTmpDir("eksctl-install-flux-clone-", options) - if err != nil { - return "", errors.Wrapf(err, "cannot clone repository %s", fi.Opts.Repo.URL) - } - cleanCloneDir := false - defer func() { - if cleanCloneDir { - _ = fi.GitClient.DeleteLocalRepo() - } else { - logger.Critical("You may find the local clone of %s used by eksctl at %s", - fi.Opts.Repo.URL, - cloneDir) - } - }() - logger.Info("Writing Flux manifests") - fluxManifestDir := filepath.Join(cloneDir, fi.Opts.Repo.FluxPath) - if err := writeFluxManifests(fluxManifestDir, manifests); err != nil { - return "", err - } - - if err := fi.createFluxNamespaceIfMissing(manifests); err != nil { - return "", err - } - - logger.Info("Applying manifests") - if err := fi.applyManifests(manifests); err != nil { - return "", err - } - - if api.IsEnabled(fi.Opts.Operator.WithHelm) { - logger.Info("Waiting for Helm Operator to start") - if err := waitForHelmOpToStart(fi.Opts.Operator.Namespace, fi.Timeout, fi.K8sClientSet); err != nil { - return "", err - } - logger.Info("Helm Operator started successfully") - logger.Info("see https://docs.fluxcd.io/projects/helm-operator for details on how to use the Helm Operator") - } - - logger.Info("Waiting for Flux to start") - err = waitForFluxToStart(fi.Opts.Operator.Namespace, fi.Timeout, fi.K8sClientSet) - if err != nil { - return "", err - } - logger.Info("fetching public SSH key from Flux") - fluxSSHKey, err := getPublicKeyFromFlux(ctx, fi.Opts.Operator.Namespace, fi.Timeout, fi.K8sRestConfig, fi.K8sClientSet) - if err != nil { - return "", err - } - - logger.Info("Flux started successfully") - logger.Info("see https://docs.fluxcd.io/projects/flux for details on how to use Flux") - - if api.IsEnabled(fi.Opts.Operator.CommitOperatorManifests) { - logger.Info("Committing and pushing manifests to %s", fi.Opts.Repo.URL) - if err = fi.addFilesToRepo(); err != nil { - return "", err - } - } - cleanCloneDir = true - - logger.Info("Flux will only operate properly once it has write-access to the Git repository") - instruction := fmt.Sprintf("please configure %s so that the following Flux SSH public key has write access to it\n%s", - fi.Opts.Repo.URL, fluxSSHKey.Key) - - client, err := deploykey.GetDeployKeyClient(ctx, fi.Opts.Repo.URL) - if err != nil { - logger.Warning( - "could not find git provider implementation for url %q: %q. Skipping authorization of SSH key", - fi.Opts.Repo.URL, - err.Error(), - ) - return instruction, nil - } - - keyTitle := KeyTitle(*fi.Cfg.Metadata) - _, _, err = client.Reconcile(ctx, gitprovider.DeployKeyInfo{ - Name: keyTitle, - Key: []byte(fluxSSHKey.Key), - ReadOnly: &fi.Opts.Operator.ReadOnly, - }) - if err != nil { - return instruction, errors.Wrapf(err, "could not authorize SSH key") - } - instruction = fmt.Sprintf("Flux SSH key with name %q authorized to access the repo", keyTitle) - - return instruction, nil -} - -func (fi *Installer) addFilesToRepo() error { - if err := fi.GitClient.Add(fi.Opts.Repo.FluxPath); err != nil { - return err - } - - // Confirm there is something to commit, otherwise move on - if err := fi.GitClient.Commit("Add Initial Flux configuration", fi.Opts.Repo.User, fi.Opts.Repo.Email); err != nil { - return err - } - - // git push - if err := fi.GitClient.Push(); err != nil { - return err - } - return nil -} - -func (fi *Installer) createFluxNamespaceIfMissing(manifestsMap map[string][]byte) error { - client, err := kubernetes.NewRawClient(fi.K8sClientSet, fi.K8sRestConfig) - if err != nil { - return err - } - - // If the flux namespace needs to be created, do it first, before any other - // resource which should potentially be created within the namespace. - // Otherwise, creation of these resources will fail. - if namespace, ok := manifestsMap[fluxNamespaceFileName]; ok { - if err := client.CreateOrReplace(namespace, false); err != nil { - return err - } - delete(manifestsMap, fluxNamespaceFileName) - } - return nil -} - -func (fi *Installer) applyManifests(manifestsMap map[string][]byte) error { - client, err := kubernetes.NewRawClient(fi.K8sClientSet, fi.K8sRestConfig) - if err != nil { - return err - } - - if fluxSecret, ok := manifestsMap[fluxPrivateSSHKeyFileName]; ok { - existence, err := client.Exists(fluxSecret) - if err != nil { - return err - } - // We do NOT want to recreate the flux-git-deploy Secret object inside - // the flux-secret.yaml file, as it contains Flux's private SSH key, - // and deleting it would force the user to set Flux's permissions up - // again in their Git repository, which is not very "friendly". - if existence[fi.Opts.Operator.Namespace][fluxPrivateSSHKeySecretName] { - delete(manifestsMap, fluxPrivateSSHKeyFileName) - } - } - - // do not recreate Flux's cache if exists - for m, r := range manifestsMap { - if strings.Contains(m, "memcache") { - existence, err := client.Exists(r) - if err != nil { - return err - } - for _, found := range existence[fi.Opts.Operator.Namespace] { - if found { - delete(manifestsMap, m) - } - } - } - } - - var manifestValues [][]byte - for _, manifest := range manifestsMap { - manifestValues = append(manifestValues, manifest) - } - manifests := kubernetes.ConcatManifests(manifestValues...) - return client.CreateOrReplace(manifests, false) -} - -func writeFluxManifests(baseDir string, manifests map[string][]byte) error { - if err := os.MkdirAll(baseDir, 0700); err != nil { - return errors.Wrapf(err, "cannot create Flux manifests directory (%s)", baseDir) - } - for fileName, contents := range manifests { - fullPath := filepath.Join(baseDir, fileName) - if err := os.WriteFile(fullPath, contents, 0600); err != nil { - return errors.Wrapf(err, "failed to write Flux manifest file %s", fullPath) - } - } - return nil -} - -func (fi *Installer) GetManifests() (map[string][]byte, error) { - var manifests map[string][]byte - - // Flux - var err error - if manifests, err = getFluxManifests(fi.Opts, fi.K8sClientSet); err != nil { - return nil, err - } - - // Helm Operator - if !api.IsEnabled(fi.Opts.Operator.WithHelm) { - return manifests, nil - } - helmOpManifests, err := getHelmOpManifests(fi.Opts.Operator.Namespace, fi.Opts.Operator.AdditionalHelmOperatorArgs) - if err != nil { - return nil, err - } - manifests = mergeMaps(manifests, helmOpManifests) - - return manifests, nil -} - -func getFluxManifests(opts *api.Git, cs kubeclient.Interface) (map[string][]byte, error) { - manifests := map[string][]byte{} - fluxNSExists, err := kubernetes.CheckNamespaceExists(cs, opts.Operator.Namespace) - if err != nil { - return nil, errors.Wrapf(err, "cannot check if namespace %s exists", opts.Operator.Namespace) - } - if !fluxNSExists { - manifests[fluxNamespaceFileName] = kubernetes.NewNamespaceYAML(opts.Operator.Namespace) - } - - additionalFluxArgs := []string{"--sync-garbage-collection"} - additionalFluxArgs = append(additionalFluxArgs, opts.Operator.AdditionalFluxArgs...) - if opts.Operator.ReadOnly { - additionalFluxArgs = append(additionalFluxArgs, "--registry-disable-scanning") - } - - fluxParameters := fluxinstall.TemplateParameters{ - GitURL: opts.Repo.URL, - GitBranch: opts.Repo.Branch, - GitPaths: opts.Repo.Paths, - GitLabel: opts.Operator.Label, - GitUser: opts.Repo.User, - GitEmail: opts.Repo.Email, - GitReadOnly: opts.Operator.ReadOnly, - Namespace: opts.Operator.Namespace, - ManifestGeneration: true, - AdditionalFluxArgs: additionalFluxArgs, - } - fluxManifests, err := fluxinstall.FillInTemplates(fluxParameters) - if err != nil { - return nil, errors.Wrap(err, "failed to create Flux manifests") - } - return mergeMaps(manifests, fluxManifests), nil -} - -func getHelmOpManifests(namespace string, additionalHelmOperatorArgs []string) (map[string][]byte, error) { - helmOpParameters := helmopinstall.TemplateParameters{ - Namespace: namespace, - AdditionalArgs: additionalHelmOperatorArgs, - HelmVersions: fluxHelmVersions, - SSHSecretName: fluxPrivateSSHKeySecretName, - } - manifests, err := helmopinstall.FillInTemplates(helmOpParameters) - if err != nil { - return nil, errors.Wrap(err, "failed to create Helm Operator Manifests") - } - return manifests, nil -} - -func mergeMaps(m1 map[string][]byte, m2 map[string][]byte) map[string][]byte { - result := make(map[string][]byte, len(m1)+len(m2)) - for k, v := range m1 { - result[k] = v - } - for k, v := range m2 { - result[k] = v - } - return result -} - -// PublicKey represents a public SSH key as it is returned by flux -type PublicKey struct { - Key string `json:"key"` -} - -func getPublicKeyFromFlux( - ctx context.Context, namespace string, timeout time.Duration, restConfig *rest.Config, - cs kubeclient.Interface, -) (PublicKey, error) { - var deployKey PublicKey - try := func(rootURL string) error { - fluxURL := rootURL + "api/flux/v6/identity.pub" - req, reqErr := http.NewRequest("GET", fluxURL, nil) - if reqErr != nil { - return fmt.Errorf("failed to create request: %s", reqErr) - } - repoCtx, repoCtxCancel := context.WithTimeout(ctx, timeout) - defer repoCtxCancel() - req = req.WithContext(repoCtx) - resp, err := http.DefaultClient.Do(req) - if err != nil { - return fmt.Errorf("failed to query Flux API: %s", err) - } - if resp.Body == nil { - return fmt.Errorf("failed to fetch Flux deploy key from: %s", fluxURL) - } - defer resp.Body.Close() - - jsonErr := json.NewDecoder(resp.Body).Decode(&deployKey) - if jsonErr != nil { - return fmt.Errorf("failed to decode Flux API response: %s", jsonErr) - } - - if deployKey.Key == "" { - return fmt.Errorf("failed to fetch Flux deploy key from: %s", fluxURL) - } - return nil - } - err := portForward(namespace, "flux", 3030, "Flux", restConfig, cs, try) - return deployKey, err -} - -type tryFunc func(rootURL string) error - -func portForward( - namespace string, nameLabelValue string, port int, name string, - restConfig *rest.Config, cs kubeclient.Interface, try tryFunc, -) error { - fluxSelector := metav1.LabelSelector{ - MatchExpressions: []metav1.LabelSelectorRequirement{ - { - Key: "name", - Operator: metav1.LabelSelectorOpIn, - Values: []string{nameLabelValue}, - }, - }, - } - portforwarder := portforward.PortForward{ - Labels: fluxSelector, - Config: restConfig, - Clientset: cs, - DestinationPort: port, - Namespace: namespace, - } - podDeadline := time.Now().Add(portForwardingTimeout) - for ; time.Now().Before(podDeadline); time.Sleep(portForwardingRetryPeriod) { - err := portforwarder.Start(context.TODO()) - if err == nil { - defer portforwarder.Stop() - break - } - if !strings.Contains(err.Error(), "Could not find running pod for selector") { - logger.Warning("%s is not ready yet (%s), retrying ...", name, err) - } - } - if time.Now().After(podDeadline) { - return fmt.Errorf("timed out waiting for %s's pod to be created", name) - } - baseURL := fmt.Sprintf("http://127.0.0.1:%d/", portforwarder.ListenPort) - // Make sure it's alive - retryDeadline := time.Now().Add(30 * time.Second) - for ; time.Now().Before(retryDeadline); time.Sleep(2 * time.Second) { - err := try(baseURL) - if err == nil { - break - } - logger.Warning("%s is not ready yet (%s), retrying ...", name, err) - } - if time.Now().After(retryDeadline) { - return fmt.Errorf("timed out waiting for %s to be operative", name) - } - return nil -} - -// KeyTitle returns the title for the SSH key used to access the gitops repo -func KeyTitle(clusterMeta api.ClusterMeta) string { - return fmt.Sprintf("eksctl-flux-%s-%s", clusterMeta.Region, clusterMeta.Name) -} diff --git a/pkg/actions/repo/enable_test.go b/pkg/actions/repo/enable_test.go deleted file mode 100644 index c086d56ddd..0000000000 --- a/pkg/actions/repo/enable_test.go +++ /dev/null @@ -1,93 +0,0 @@ -// FLUX V1 DEPRECATION NOTICE. https://github.com/weaveworks/eksctl/issues/2963 -package repo_test - -import ( - "os" - - "github.com/instrumenta/kubeval/kubeval" - . "github.com/onsi/ginkgo" - . "github.com/onsi/gomega" - "k8s.io/client-go/kubernetes/fake" - - "github.com/weaveworks/eksctl/pkg/actions/repo" - api "github.com/weaveworks/eksctl/pkg/apis/eksctl.io/v1alpha5" -) - -var _ = Describe("Installer", func() { - var ( - installer *repo.Installer - tmpDir string - mockOpts *api.Git - ) - - BeforeEach(func() { - mockOpts = &api.Git{ - Repo: &api.Repo{ - URL: "git@github.com/foo/bar.git", - Branch: "gitbranch", - User: "gituser", - Email: "gitemail@example.com", - Paths: []string{"gitpath/"}, - FluxPath: "fluxpath/", - }, - Operator: api.Operator{ - Label: "gitlabel", - Namespace: "fluxnamespace", - WithHelm: api.Enabled(), - AdditionalFluxArgs: []string{"--git-poll-interval=30s"}, - AdditionalHelmOperatorArgs: []string{"--log-format=json"}, - }, - } - - installer = &repo.Installer{ - Opts: mockOpts, - K8sClientSet: fake.NewSimpleClientset(), - } - - var err error - tmpDir, err = os.MkdirTemp(os.TempDir(), "getmanifestsandsecrets") - Expect(err).NotTo(HaveOccurred()) - }) - - AfterEach(func() { - os.RemoveAll(tmpDir) - }) - - Context("GetManifests", func() { - var ( - err error - manifests map[string][]byte - ) - - BeforeEach(func() { - manifests, err = installer.GetManifests() - }) - - It("should not error", func() { - Expect(err).NotTo(HaveOccurred()) - }) - - It("should match expected lengths", func() { - Expect(len(manifests)).To(Equal(9)) - }) - - It("should not error", func() { - manifestContents := [][]byte{} - for _, manifest := range manifests { - manifestContents = append(manifestContents, manifest) - } - - config := &kubeval.Config{ - IgnoreMissingSchemas: true, - KubernetesVersion: "master", - } - for _, content := range manifestContents { - validationResults, err := kubeval.Validate(content, config) - Expect(err).NotTo(HaveOccurred()) - for _, result := range validationResults { - Expect(len(result.Errors)).To(Equal(0)) - } - } - }) - }) -}) diff --git a/pkg/actions/repo/repo_suite_test.go b/pkg/actions/repo/repo_suite_test.go deleted file mode 100644 index 66a0e55a99..0000000000 --- a/pkg/actions/repo/repo_suite_test.go +++ /dev/null @@ -1,14 +0,0 @@ -// FLUX V1 DEPRECATION NOTICE. https://github.com/weaveworks/eksctl/issues/2963 -package repo_test - -import ( - "testing" - - . "github.com/onsi/ginkgo" - . "github.com/onsi/gomega" -) - -func TestGitops(t *testing.T) { - RegisterFailHandler(Fail) - RunSpecs(t, "Gitops Repo Suite") -} diff --git a/pkg/actions/repo/wait.go b/pkg/actions/repo/wait.go deleted file mode 100644 index 9da8aba7c6..0000000000 --- a/pkg/actions/repo/wait.go +++ /dev/null @@ -1,57 +0,0 @@ -// FLUX V1 DEPRECATION NOTICE. https://github.com/weaveworks/eksctl/issues/2963 -package repo - -import ( - "context" - "fmt" - "time" - - "github.com/pkg/errors" - v1 "k8s.io/api/apps/v1" - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - "k8s.io/apimachinery/pkg/watch" - kubeclient "k8s.io/client-go/kubernetes" -) - -func waitForHelmOpToStart(namespace string, timeout time.Duration, cs kubeclient.Interface) error { - return waitForDeploymentToStart(cs, namespace, "helm-operator", timeout) -} - -func waitForFluxToStart(namespace string, timeout time.Duration, cs kubeclient.Interface) error { - return waitForDeploymentToStart(cs, namespace, "flux", timeout) -} - -func waitForDeploymentToStart(k8sClientSet kubeclient.Interface, namespace string, name string, timeout time.Duration) error { - watcher, err := k8sClientSet.AppsV1().Deployments(namespace).Watch(context.TODO(), metav1.ListOptions{ - FieldSelector: "metadata.name=" + name, - }) - if err != nil { - return err - } - - defer watcher.Stop() - - timer := time.NewTimer(timeout) - defer timer.Stop() - - for { - select { - case event, ok := <-watcher.ResultChan(): - if !ok { - return errors.Wrapf(err, "failed waiting for pod %q", name) - } - switch event.Type { - case watch.Added, watch.Modified: - deployment, ok := event.Object.(*v1.Deployment) - if !ok { - return errors.Errorf("expected event type to be %T; got %T", &v1.Deployment{}, event.Object) - } - if deployment.Status.ReadyReplicas == deployment.Status.Replicas { - return nil - } - } - case <-timer.C: - return fmt.Errorf("timed out (after %v) waiting for deployment %q", timeout, name) - } - } -} diff --git a/pkg/apis/eksctl.io/v1alpha5/assets/schema.json b/pkg/apis/eksctl.io/v1alpha5/assets/schema.json index cf31b49124..9d4c4e29c3 100755 --- a/pkg/apis/eksctl.io/v1alpha5/assets/schema.json +++ b/pkg/apis/eksctl.io/v1alpha5/assets/schema.json @@ -176,15 +176,10 @@ }, "type": "array" }, - "git": { - "$ref": "#/definitions/Git", - "description": "FLUX V1 DEPRECATION NOTICE. https://github.com/weaveworks/eksctl/issues/2963 Git exposes configuration for Flux v1 and an earlier iteration of gitops", - "x-intellij-html-description": "FLUX V1 DEPRECATION NOTICE. https://github.com/weaveworks/eksctl/issues/2963 Git exposes configuration for Flux v1 and an earlier iteration of gitops" - }, "gitops": { "$ref": "#/definitions/GitOps", - "description": "exposes configuration for Flux v2 and will continue to be used in future gitops plans, replacing the Git configuration above", - "x-intellij-html-description": "exposes configuration for Flux v2 and will continue to be used in future gitops plans, replacing the Git configuration above" + "description": "future gitops plans, replacing the Git configuration above", + "x-intellij-html-description": "future gitops plans, replacing the Git configuration above" }, "iam": { "$ref": "#/definitions/ClusterIAM" @@ -251,7 +246,6 @@ "availabilityZones", "cloudWatch", "secretsEncryption", - "git", "gitops" ], "additionalProperties": false, @@ -740,33 +734,6 @@ "x-intellij-html-description": "a map of string for passing arbitrary flags to Flux bootstrap", "default": "{}" }, - "Git": { - "properties": { - "bootstrapProfile": { - "$ref": "#/definitions/Profile", - "description": "holds options to install a BootstrapProfile on the cluster. DEPRECATED.", - "x-intellij-html-description": "holds options to install a BootstrapProfile on the cluster. DEPRECATED." - }, - "operator": { - "$ref": "#/definitions/Operator", - "description": "holds options to configure the Helm Operator in conjunction with a Flux v1 installation. DEPRECATED.", - "x-intellij-html-description": "holds options to configure the Helm Operator in conjunction with a Flux v1 installation. DEPRECATED." - }, - "repo": { - "$ref": "#/definitions/Repo", - "description": "holds options to enable Flux v1 on your cluster. DEPRECATED.", - "x-intellij-html-description": "holds options to enable Flux v1 on your cluster. DEPRECATED." - } - }, - "preferredOrder": [ - "repo", - "operator", - "bootstrapProfile" - ], - "additionalProperties": false, - "description": "groups all configuration options related to enabling GitOps on a cluster and linking it to a Git repository. [Gitops Guide](/gitops-quickstart/)", - "x-intellij-html-description": "groups all configuration options related to enabling GitOps on a cluster and linking it to a Git repository. Gitops Guide" - }, "GitOps": { "properties": { "flux": { @@ -1856,64 +1823,6 @@ "description": "holds the spec of an OIDC provider to use for EKS authzn", "x-intellij-html-description": "holds the spec of an OIDC provider to use for EKS authzn" }, - "Operator": { - "properties": { - "additionalFluxArgs": { - "items": { - "type": "string" - }, - "type": "array", - "description": "Additional command line arguments for the Flux daemon DEPRECATED", - "x-intellij-html-description": "Additional command line arguments for the Flux daemon DEPRECATED" - }, - "additionalHelmOperatorArgs": { - "items": { - "type": "string" - }, - "type": "array", - "description": "Additional command line arguments for the Helm Operator DEPRECATED", - "x-intellij-html-description": "Additional command line arguments for the Helm Operator DEPRECATED" - }, - "commitOperatorManifests": { - "type": "boolean", - "description": "Commit and push Flux manifests to the Git Repo on install DEPRECATED", - "x-intellij-html-description": "Commit and push Flux manifests to the Git Repo on install DEPRECATED" - }, - "label": { - "type": "string", - "description": "Git label to keep track of Flux's sync progress; this is equivalent to overriding --git-sync-tag and --git-notes-ref in Flux DEPRECATED", - "x-intellij-html-description": "Git label to keep track of Flux's sync progress; this is equivalent to overriding --git-sync-tag and --git-notes-ref in Flux DEPRECATED" - }, - "namespace": { - "type": "string", - "description": "Cluster namespace where to install Flux and the Helm Operator e.g. flux DEPRECATED", - "x-intellij-html-description": "Cluster namespace where to install Flux and the Helm Operator e.g. flux DEPRECATED" - }, - "readOnly": { - "type": "boolean", - "description": "Instruct Flux to read-only mode and create the deploy key as read-only DEPRECATED", - "x-intellij-html-description": "Instruct Flux to read-only mode and create the deploy key as read-only DEPRECATED", - "default": "false" - }, - "withHelm": { - "type": "boolean", - "description": "Install the Helm Operator DEPRECATED", - "x-intellij-html-description": "Install the Helm Operator DEPRECATED" - } - }, - "preferredOrder": [ - "commitOperatorManifests", - "label", - "namespace", - "withHelm", - "readOnly", - "additionalFluxArgs", - "additionalHelmOperatorArgs" - ], - "additionalProperties": false, - "description": "groups all configuration options related to the operator used to keep the cluster and the Git repository in sync.", - "x-intellij-html-description": "groups all configuration options related to the operator used to keep the cluster and the Git repository in sync." - }, "Placement": { "properties": { "groupName": { @@ -1964,94 +1873,6 @@ "description": "defines the configuration for a fully-private cluster", "x-intellij-html-description": "defines the configuration for a fully-private cluster" }, - "Profile": { - "properties": { - "outputPath": { - "type": "string", - "description": "Output directory for the processed profile templates (generate profile command)", - "x-intellij-html-description": "Output directory for the processed profile templates (generate profile command)", - "default": "./" - }, - "revision": { - "type": "string", - "description": "of the Quick Start profile. Can be a branch, tag or commit hash DEPRECATED.", - "x-intellij-html-description": "of the Quick Start profile. Can be a branch, tag or commit hash DEPRECATED." - }, - "source": { - "type": "string", - "description": "Name or URL of the Quick Start profile", - "x-intellij-html-description": "Name or URL of the Quick Start profile", - "examples": [ - "app-dev" - ] - } - }, - "preferredOrder": [ - "source", - "revision", - "outputPath" - ], - "additionalProperties": false, - "description": "groups all details on a quickstart profile to enable on the cluster and add to the Git repository.", - "x-intellij-html-description": "groups all details on a quickstart profile to enable on the cluster and add to the Git repository." - }, - "Repo": { - "properties": { - "branch": { - "type": "string", - "description": "The git branch under which cluster configuration files will be committed & pushed, e.g. master DEPRECATED", - "x-intellij-html-description": "The git branch under which cluster configuration files will be committed & pushed, e.g. master DEPRECATED" - }, - "email": { - "type": "string", - "description": "Git email which will be used to commit changes DEPRECATED", - "x-intellij-html-description": "Git email which will be used to commit changes DEPRECATED" - }, - "fluxPath": { - "type": "string", - "description": "The directory under which Flux configuration files will be written, e.g. flux/ DEPRECATED", - "x-intellij-html-description": "The directory under which Flux configuration files will be written, e.g. flux/ DEPRECATED" - }, - "paths": { - "items": { - "type": "string" - }, - "type": "array", - "description": "Relative paths within the Git repository which the GitOps operator will monitor to find Kubernetes manifests to apply, e.g. [\"kube-system\", \"base\"] DEPRECATED", - "x-intellij-html-description": "Relative paths within the Git repository which the GitOps operator will monitor to find Kubernetes manifests to apply, e.g. ["kube-system", "base"] DEPRECATED" - }, - "privateSSHKeyPath": { - "type": "string", - "description": "Path to the private SSH key to use to authenticate DEPRECATED", - "x-intellij-html-description": "Path to the private SSH key to use to authenticate DEPRECATED" - }, - "url": { - "type": "string", - "description": "The Git SSH URL to the repository which will contain the cluster configuration", - "x-intellij-html-description": "The Git SSH URL to the repository which will contain the cluster configuration", - "examples": [ - "git@github.com:org/repo" - ] - }, - "user": { - "type": "string", - "description": "Git user which will be used to commit changes DEPRECATED", - "x-intellij-html-description": "Git user which will be used to commit changes DEPRECATED" - } - }, - "preferredOrder": [ - "url", - "branch", - "paths", - "fluxPath", - "user", - "email", - "privateSSHKeyPath" - ], - "additionalProperties": false, - "description": "groups all configuration options related to a Git repository used for GitOps.", - "x-intellij-html-description": "groups all configuration options related to a Git repository used for GitOps." - }, "SecretsEncryption": { "required": [ "keyARN" diff --git a/pkg/apis/eksctl.io/v1alpha5/defaults.go b/pkg/apis/eksctl.io/v1alpha5/defaults.go index 9978eadf84..7d6311acde 100644 --- a/pkg/apis/eksctl.io/v1alpha5/defaults.go +++ b/pkg/apis/eksctl.io/v1alpha5/defaults.go @@ -7,8 +7,6 @@ import ( metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "github.com/aws/aws-sdk-go/aws" - - "github.com/weaveworks/eksctl/pkg/git" ) const ( @@ -327,48 +325,3 @@ func (c *ClusterConfig) SetDefaultFargateProfile() { }, } } - -// SetDefaultGitSettings sets the default values for the gitops repo and operator settings -func SetDefaultGitSettings(c *ClusterConfig) { - if c.Git == nil { - return - } - - if c.Git.Operator.CommitOperatorManifests == nil { - c.Git.Operator.CommitOperatorManifests = Enabled() - } - - if c.Git.Operator.Label == "" { - c.Git.Operator.Label = "flux" - } - if c.Git.Operator.Namespace == "" { - c.Git.Operator.Namespace = "flux" - } - if c.Git.Operator.WithHelm == nil { - c.Git.Operator.WithHelm = Enabled() - } - - if c.Git.Repo != nil { - repo := c.Git.Repo - if repo.FluxPath == "" { - repo.FluxPath = "flux/" - } - if repo.Branch == "" { - repo.Branch = "master" - } - if repo.User == "" { - repo.User = "Flux" - } - } - - if c.Git.BootstrapProfile != nil { - profile := c.Git.BootstrapProfile - if profile.Source != "" && profile.OutputPath == "" { - repoName, err := git.RepoName(profile.Source) - if err != nil { - profile.OutputPath = "./" - } - profile.OutputPath = "./" + repoName - } - } -} diff --git a/pkg/apis/eksctl.io/v1alpha5/types.go b/pkg/apis/eksctl.io/v1alpha5/types.go index 12a8733cf9..9b6e6f4a17 100644 --- a/pkg/apis/eksctl.io/v1alpha5/types.go +++ b/pkg/apis/eksctl.io/v1alpha5/types.go @@ -674,12 +674,6 @@ type ClusterConfig struct { Status *ClusterStatus `json:"-"` - // FLUX V1 DEPRECATION NOTICE. https://github.com/weaveworks/eksctl/issues/2963 - // Git exposes configuration for Flux v1 and an earlier iteration of gitops - // +optional - Git *Git `json:"git,omitempty"` - - // GitOps exposes configuration for Flux v2 and will continue to be used in // future gitops plans, replacing the Git configuration above // +optional GitOps *GitOps `json:"gitops,omitempty"` @@ -939,34 +933,6 @@ type GitOps struct { Flux *Flux `json:"flux,omitempty"` } -// Git groups all configuration options related to enabling GitOps on a -// cluster and linking it to a Git repository. -// [Gitops Guide](/gitops-quickstart/) -type Git struct { - // Repo holds options to enable Flux v1 on your cluster. DEPRECATED. - Repo *Repo `json:"repo,omitempty"` - - // Operator holds options to configure the Helm Operator in conjunction with - // a Flux v1 installation. DEPRECATED. - // +optional - Operator Operator `json:"operator,omitempty"` - - // BootstrapProfile holds options to install a BootstrapProfile on the cluster. - // DEPRECATED. - // +optional - BootstrapProfile *Profile `json:"bootstrapProfile,omitempty"` // one or many profiles to enable on this cluster once it is created -} - -// FLUX V1 DEPRECATION NOTICE. https://github.com/weaveworks/eksctl/issues/2963 -// NewGit returns a new empty Git configuration -func NewGit() *Git { - return &Git{ - Repo: &Repo{}, - Operator: Operator{}, - BootstrapProfile: &Profile{}, - } -} - // Flux groups all configuration options related to a Git repository used for // GitOps Toolkit (Flux v2). type Flux struct { @@ -981,116 +947,8 @@ type Flux struct { // FluxFlags is a map of string for passing arbitrary flags to Flux bootstrap type FluxFlags map[string]string -// Repo groups all configuration options related to a Git repository used for -// GitOps. -type Repo struct { - // The Git SSH URL to the repository which will contain the cluster configuration - // For example: `git@github.com:org/repo` - // DEPRECATED - URL string `json:"url,omitempty"` - - // The git branch under which cluster configuration files will be committed & pushed, e.g. master - // DEPRECATED - // +optional - Branch string `json:"branch,omitempty"` - - // Relative paths within the Git repository which the GitOps operator will monitor to find Kubernetes manifests to apply, e.g. ["kube-system", "base"] - // DEPRECATED - //+optional - Paths []string `json:"paths,omitempty"` - - // The directory under which Flux configuration files will be written, e.g. flux/ - // DEPRECATED - // +optional - FluxPath string `json:"fluxPath,omitempty"` - - // Git user which will be used to commit changes - // DEPRECATED - // +optional - User string `json:"user,omitempty"` - - // Git email which will be used to commit changes - // DEPRECATED - Email string `json:"email,omitempty"` - - // Path to the private SSH key to use to authenticate - // DEPRECATED - // +optional - PrivateSSHKeyPath string `json:"privateSSHKeyPath,omitempty"` -} - // Operator groups all configuration options related to the operator used to // keep the cluster and the Git repository in sync. -type Operator struct { - - // Commit and push Flux manifests to the Git Repo on install - // DEPRECATED - // +optional - CommitOperatorManifests *bool `json:"commitOperatorManifests,omitempty"` - - // Git label to keep track of Flux's sync progress; this is equivalent to overriding --git-sync-tag and --git-notes-ref in Flux - // DEPRECATED - // +optional - Label string `json:"label,omitempty"` - - // Cluster namespace where to install Flux and the Helm Operator e.g. flux - // DEPRECATED - // +optional - Namespace string `json:"namespace,omitempty"` - - // Install the Helm Operator - // DEPRECATED - // +optional - WithHelm *bool `json:"withHelm,omitempty"` - - // Instruct Flux to read-only mode and create the deploy key as read-only - // DEPRECATED - // +optional - ReadOnly bool `json:"readOnly,omitempty"` - - // Additional command line arguments for the Flux daemon - // DEPRECATED - // +optional - AdditionalFluxArgs []string `json:"additionalFluxArgs,omitempty"` - - // Additional command line arguments for the Helm Operator - // DEPRECATED - // +optional - AdditionalHelmOperatorArgs []string `json:"additionalHelmOperatorArgs,omitempty"` -} - -// Profile groups all details on a quickstart profile to enable on the cluster -// and add to the Git repository. -type Profile struct { - // Name or URL of the Quick Start profile - // For example: `app-dev` - // DEPRECATED. - Source string `json:"source,omitempty"` - - // Revision of the Quick Start profile. Can be a branch, tag or commit hash - // DEPRECATED. - // +optional - Revision string `json:"revision,omitempty"` - - // Output directory for the processed profile templates (generate profile command) - // Defaults to `./` - // DEPRECATED. - // +optional - OutputPath string `json:"outputPath,omitempty"` -} - -// FLUX V1 DEPRECATION NOTICE. https://github.com/weaveworks/eksctl/issues/2963 -// HasBootstrapProfile returns true if there is a profile with a source specified -func (c *ClusterConfig) HasBootstrapProfile() bool { - return c.Git != nil && c.Git.BootstrapProfile != nil && c.Git.BootstrapProfile.Source != "" -} - -// FLUX V1 DEPRECATION NOTICE. https://github.com/weaveworks/eksctl/issues/2963 -// HasGitopsRepoConfigured returns true if git.repo and git.repo.url are not nil -func (c *ClusterConfig) HasGitopsRepoConfigured() bool { - return c.Git != nil && c.Git.Repo != nil && c.Git.Repo.URL != "" -} - // HasGitOpsFluxConfigured returns true if gitops.flux configuration is not nil func (c *ClusterConfig) HasGitOpsFluxConfigured() bool { return c.GitOps != nil && c.GitOps.Flux != nil diff --git a/pkg/apis/eksctl.io/v1alpha5/zz_generated.deepcopy.go b/pkg/apis/eksctl.io/v1alpha5/zz_generated.deepcopy.go index 9273a0095c..d28167d057 100644 --- a/pkg/apis/eksctl.io/v1alpha5/zz_generated.deepcopy.go +++ b/pkg/apis/eksctl.io/v1alpha5/zz_generated.deepcopy.go @@ -239,11 +239,6 @@ func (in *ClusterConfig) DeepCopyInto(out *ClusterConfig) { *out = new(ClusterStatus) (*in).DeepCopyInto(*out) } - if in.Git != nil { - in, out := &in.Git, &out.Git - *out = new(Git) - (*in).DeepCopyInto(*out) - } if in.GitOps != nil { in, out := &in.GitOps, &out.GitOps *out = new(GitOps) @@ -740,33 +735,6 @@ func (in FluxFlags) DeepCopy() FluxFlags { return *out } -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *Git) DeepCopyInto(out *Git) { - *out = *in - if in.Repo != nil { - in, out := &in.Repo, &out.Repo - *out = new(Repo) - (*in).DeepCopyInto(*out) - } - in.Operator.DeepCopyInto(&out.Operator) - if in.BootstrapProfile != nil { - in, out := &in.BootstrapProfile, &out.BootstrapProfile - *out = new(Profile) - **out = **in - } - return -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Git. -func (in *Git) DeepCopy() *Git { - if in == nil { - return nil - } - out := new(Git) - in.DeepCopyInto(out) - return out -} - // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *GitOps) DeepCopyInto(out *GitOps) { *out = *in @@ -1492,42 +1460,6 @@ func (in *OIDCIdentityProvider) DeepCopy() *OIDCIdentityProvider { return out } -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *Operator) DeepCopyInto(out *Operator) { - *out = *in - if in.CommitOperatorManifests != nil { - in, out := &in.CommitOperatorManifests, &out.CommitOperatorManifests - *out = new(bool) - **out = **in - } - if in.WithHelm != nil { - in, out := &in.WithHelm, &out.WithHelm - *out = new(bool) - **out = **in - } - if in.AdditionalFluxArgs != nil { - in, out := &in.AdditionalFluxArgs, &out.AdditionalFluxArgs - *out = make([]string, len(*in)) - copy(*out, *in) - } - if in.AdditionalHelmOperatorArgs != nil { - in, out := &in.AdditionalHelmOperatorArgs, &out.AdditionalHelmOperatorArgs - *out = make([]string, len(*in)) - copy(*out, *in) - } - return -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Operator. -func (in *Operator) DeepCopy() *Operator { - if in == nil { - return nil - } - out := new(Operator) - in.DeepCopyInto(out) - return out -} - // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *Placement) DeepCopyInto(out *Placement) { *out = *in @@ -1565,22 +1497,6 @@ func (in *PrivateCluster) DeepCopy() *PrivateCluster { return out } -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *Profile) DeepCopyInto(out *Profile) { - *out = *in - return -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Profile. -func (in *Profile) DeepCopy() *Profile { - if in == nil { - return nil - } - out := new(Profile) - in.DeepCopyInto(out) - return out -} - // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *ProviderConfig) DeepCopyInto(out *ProviderConfig) { *out = *in @@ -1597,27 +1513,6 @@ func (in *ProviderConfig) DeepCopy() *ProviderConfig { return out } -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *Repo) DeepCopyInto(out *Repo) { - *out = *in - if in.Paths != nil { - in, out := &in.Paths, &out.Paths - *out = make([]string, len(*in)) - copy(*out, *in) - } - return -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Repo. -func (in *Repo) DeepCopy() *Repo { - if in == nil { - return nil - } - out := new(Repo) - in.DeepCopyInto(out) - return out -} - // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *ScalingConfig) DeepCopyInto(out *ScalingConfig) { *out = *in diff --git a/pkg/ctl/cmdutils/configfile.go b/pkg/ctl/cmdutils/configfile.go index 9b0dd42c71..67ce4c6c75 100644 --- a/pkg/ctl/cmdutils/configfile.go +++ b/pkg/ctl/cmdutils/configfile.go @@ -147,7 +147,6 @@ func (l *commonClusterConfigLoader) Load() error { } l.ProviderConfig.Region = meta.Region - api.SetDefaultGitSettings(l.ClusterConfig) return l.validateWithConfigFile() } @@ -261,10 +260,6 @@ func NewCreateClusterLoader(cmd *Cmd, ngFilter *filter.NodeGroupFilter, ng *api. return errors.New("vpc.subnets and availabilityZones cannot be set at the same time") } - if clusterConfig.GitOps != nil && clusterConfig.Git != nil { - return errors.New("git cannot be configured alongside gitops") - } - if clusterConfig.GitOps != nil { fluxCfg := clusterConfig.GitOps.Flux @@ -278,24 +273,6 @@ func NewCreateClusterLoader(cmd *Cmd, ngFilter *filter.NodeGroupFilter, ng *api. } } - if clusterConfig.Git != nil { - repo := clusterConfig.Git.Repo - if repo != nil { - if repo.URL == "" { - return ErrMustBeSet("git.repo.url") - } - - if repo.Email == "" { - return ErrMustBeSet("git.repo.email") - } - - profile := clusterConfig.Git.BootstrapProfile - if profile != nil && profile.Source == "" { - return ErrMustBeSet("git.bootstrapProfile.source") - } - } - } - return validateDryRun() } diff --git a/pkg/ctl/cmdutils/gitops.go b/pkg/ctl/cmdutils/gitops.go index ca66018d21..287856e231 100644 --- a/pkg/ctl/cmdutils/gitops.go +++ b/pkg/ctl/cmdutils/gitops.go @@ -1,289 +1,10 @@ package cmdutils import ( - "fmt" - - "github.com/kris-nova/logger" - "github.com/pkg/errors" - "github.com/spf13/pflag" - "k8s.io/apimachinery/pkg/util/sets" - api "github.com/weaveworks/eksctl/pkg/apis/eksctl.io/v1alpha5" "github.com/weaveworks/eksctl/pkg/eks" - "github.com/weaveworks/eksctl/pkg/git" -) - -const ( - gitURL = "git-url" - gitBranch = "git-branch" - gitUser = "git-user" - gitEmail = "git-email" - gitPrivateSSHKeyPath = "git-private-ssh-key-path" - - gitPaths = "git-paths" - gitFluxPath = "git-flux-subdir" - gitLabel = "git-label" - namespace = "namespace" - readOnly = "read-only" - withHelm = "with-helm" - additionalFluxArgs = "additional-flux-args" - additionalHelmOperatorArgs = "additional-helm-operator-args" - - commitOperatorManifests = "commit-operator-manifests" - - profileName = "profile-source" - profileRevision = "profile-revision" ) -// FLUX V1 DEPRECATION NOTICE. https://github.com/weaveworks/eksctl/issues/2963 -// AddCommonFlagsForFlux configures the flags required to install Flux on an -// EKS cluster and have it point to the specified Git repository. -func AddCommonFlagsForFlux(fs *pflag.FlagSet, opts *api.Git) { - AddCommonFlagsForGitRepo(fs, opts.Repo) - - fs.StringSliceVar(&opts.Repo.Paths, gitPaths, []string{}, - "Relative paths within the Git repo for Flux to locate Kubernetes manifests") - fs.StringVar(&opts.Operator.Label, gitLabel, "flux", - "Git label to keep track of Flux's sync progress; this is equivalent to overriding --git-sync-tag and --git-notes-ref in Flux") - fs.StringVar(&opts.Repo.FluxPath, gitFluxPath, "flux/", - "Directory within the Git repository where to commit the Flux manifests") - fs.StringVar(&opts.Operator.Namespace, namespace, "flux", - "Cluster namespace where to install Flux and the Helm Operator") - fs.BoolVar(&opts.Operator.ReadOnly, readOnly, false, - "Configure Flux in read-only mode and create the deploy key as read-only (Github only)") - opts.Operator.CommitOperatorManifests = fs.Bool(commitOperatorManifests, true, - "Commit and push Flux manifests to the Git repo on install") - opts.Operator.WithHelm = fs.Bool(withHelm, true, "Install the Helm Operator") - fs.StringSliceVar(&opts.Operator.AdditionalFluxArgs, additionalFluxArgs, []string{}, - "Additional command line arguments for the Flux daemon") - fs.StringSliceVar(&opts.Operator.AdditionalHelmOperatorArgs, additionalHelmOperatorArgs, []string{}, - "Additional command line arguments for the Helm Operator") -} - -// FLUX V1 DEPRECATION NOTICE. https://github.com/weaveworks/eksctl/issues/2963 -// AddCommonFlagsForGitRepo configures the flags required to interact with a Git -// repository. -func AddCommonFlagsForGitRepo(fs *pflag.FlagSet, repo *api.Repo) { - fs.StringVar(&repo.URL, gitURL, "", - "SSH URL of the Git repository to be used for GitOps, e.g. git@github.com:/") - fs.StringVar(&repo.Branch, gitBranch, "master", - "Git branch to be used for GitOps") - fs.StringVar(&repo.User, gitUser, "Flux", - "Username to use as Git committer") - fs.StringVar(&repo.Email, gitEmail, "", - "Email to use as Git committer") - fs.StringVar(&repo.PrivateSSHKeyPath, - gitPrivateSSHKeyPath, "", - "Optional path to the private SSH key to use with Git, e.g. ~/.ssh/id_rsa") -} - -// AddCommonFlagsForProfile configures the flags required to enable a Quick -// Start profile. -func AddCommonFlagsForProfile(fs *pflag.FlagSet, opts *api.Profile) { - fs.StringVarP(&opts.Source, profileName, "", "", "name or URL of the Quick Start profile. For example, app-dev.") - fs.StringVarP(&opts.Revision, profileRevision, "", "master", "revision of the Quick Start profile.") -} - -// FLUX V1 DEPRECATION NOTICE. https://github.com/weaveworks/eksctl/issues/2963 -// GitConfigLoader handles loading of ClusterConfigFile v.s. using CLI -// flags for Git-related commands. -type GitConfigLoader struct { - cmd *Cmd - flagsIncompatibleWithConfigFile sets.String - flagsIncompatibleWithoutConfigFile sets.String - validateWithConfigFile func() error - validateWithoutConfigFile func() error - gitConfig *api.Git -} - -// FLUX V1 DEPRECATION NOTICE. https://github.com/weaveworks/eksctl/issues/2963 -// NewGitConfigLoader creates a new ClusterConfigLoader which handles -// loading of ClusterConfigFile v.s. using CLI flags for Git-related -// commands. -func NewGitConfigLoader(cmd *Cmd, cfg *api.Git) *GitConfigLoader { - l := &GitConfigLoader{ - cmd: cmd, - flagsIncompatibleWithConfigFile: sets.NewString( - "region", - "version", - "cluster", - gitURL, - gitBranch, - gitUser, - gitEmail, - gitPrivateSSHKeyPath, - gitPaths, - gitLabel, - gitFluxPath, - namespace, - withHelm, - "amend", - profileName, - profileRevision, - additionalFluxArgs, - additionalHelmOperatorArgs, - ), - flagsIncompatibleWithoutConfigFile: sets.NewString(), - } - - l.gitConfig = cfg - - l.validateWithoutConfigFile = func() error { - meta := l.cmd.ClusterConfig.Metadata - if meta.Name == "" { - return ErrMustBeSet(ClusterNameFlag(cmd)) - } - if meta.Region == "" { - return ErrMustBeSet("--region") - } - - return nil - } - - l.validateWithConfigFile = func() error { - meta := l.cmd.ClusterConfig.Metadata - if meta.Name == "" { - return ErrMustBeSet("metadata.name") - } - - if meta.Region == "" { - return ErrMustBeSet("metadata.region") - } - - if l.cmd.ClusterConfig.Git == nil { - return nil - } - - if l.cmd.ClusterConfig.Git.Repo != nil { - if err := git.ValidatePrivateSSHKeyPath(l.cmd.ClusterConfig.Git.Repo.PrivateSSHKeyPath); err != nil { - return errors.Wrapf(err, "please supply a valid file for git.repo.privateSSHKeyPath") - } - } - - return nil - } - - return l -} - -// FLUX V1 DEPRECATION NOTICE. https://github.com/weaveworks/eksctl/issues/2963 -// WithRepoValidation adds extra validation to make sure that the git url and the email are provided as they -// are required for the commands enable profile and enable repo (but not for generate profile) -func (l *GitConfigLoader) WithRepoValidation() *GitConfigLoader { - newLoader := *l - newLoader.validateWithoutConfigFile = func() error { - if newLoader.cmd.ClusterConfig.Git.Repo.URL == "" { - return ErrMustBeSet("--git-url") - } - - if newLoader.cmd.ClusterConfig.Git.Repo.Email == "" { - return ErrMustBeSet("--git-email") - } - if err := git.ValidateURL(newLoader.cmd.ClusterConfig.Git.Repo.URL); err != nil { - return errors.Wrapf(err, "please supply a valid URL for --%s argument", gitURL) - } - - return l.validateWithoutConfigFile() - } - - newLoader.validateWithConfigFile = func() error { - repo := newLoader.cmd.ClusterConfig.Git.Repo - if repo == nil || repo.URL == "" { - return ErrMustBeSet("git.repo.url") - } - - if repo.Email == "" { - return ErrMustBeSet("git.repo.email") - } - - if l.cmd.ClusterConfig.GitOps != nil { - return errors.New("config cannot be provided for gitops alongside git") - } - - return l.validateWithConfigFile() - } - return &newLoader -} - -// FLUX V1 DEPRECATION NOTICE. https://github.com/weaveworks/eksctl/issues/2963 -// WithProfileValidation adds extra validation to make sure that the git url and the email are provided as they -// are required for the commands enable profile and enable repo (but not for generate profile) -func (l *GitConfigLoader) WithProfileValidation() *GitConfigLoader { - newLoader := *l - newLoader.validateWithoutConfigFile = func() error { - if !newLoader.cmd.ClusterConfig.HasBootstrapProfile() { - return ErrMustBeSet("--profile-source") - } - - return l.validateWithoutConfigFile() - } - - newLoader.validateWithConfigFile = func() error { - if !newLoader.cmd.ClusterConfig.HasBootstrapProfile() { - return ErrMustBeSet("git.bootstrapProfile.Source") - } - - return l.validateWithConfigFile() - } - return &newLoader -} - -// FLUX V1 DEPRECATION NOTICE. https://github.com/weaveworks/eksctl/issues/2963 -// Load ClusterConfig or use CLI flags. -func (l *GitConfigLoader) Load() error { - if err := api.Register(); err != nil { - return err - } - - logger.Warning("the `enable repo`, `enable profile` and `generate profile` commands DEPRECATED: see https://github.com/weaveworks/eksctl/issues/2963") - logger.Warning("the `git.repo`, `git.operator` and `git.bootstrapProfile` config options are DEPRECATED: see https://github.com/weaveworks/eksctl/issues/2963") - - if l.cmd.ClusterConfigFile == "" { - l.cmd.ClusterConfig.Metadata.Region = l.cmd.ProviderConfig.Region - for f := range l.flagsIncompatibleWithoutConfigFile { - if flag := l.cmd.CobraCommand.Flag(f); flag != nil && flag.Changed { - return fmt.Errorf("cannot use --%s unless a config file is specified via --config-file/-f", f) - } - } - - l.cmd.ClusterConfig.Git = l.gitConfig - if l.cmd.NameArg != "" && l.cmd.ClusterConfig.Git.BootstrapProfile.Source != "" { - return ErrFlagAndArg("--profile-source", l.cmd.ClusterConfig.Git.BootstrapProfile.Source, l.cmd.NameArg) - } - if l.cmd.NameArg != "" { - l.cmd.ClusterConfig.Git.BootstrapProfile.Source = l.cmd.NameArg - } - api.SetDefaultGitSettings(l.cmd.ClusterConfig) - return l.validateWithoutConfigFile() - } - - // The reference to ClusterConfig should only be reassigned if ClusterConfigFile is specified - // because other parts of the code store the pointer locally and access it directly instead of via - // the Cmd reference - var err error - if l.cmd.ClusterConfig, err = eks.LoadConfigFromFile(l.cmd.ClusterConfigFile); err != nil { - return err - } - - meta := l.cmd.ClusterConfig.Metadata - if meta == nil { - return ErrMustBeSet("metadata") - } - - for f := range l.flagsIncompatibleWithConfigFile { - if flag := l.cmd.CobraCommand.Flag(f); flag != nil && flag.Changed { - return ErrCannotUseWithConfigFile(fmt.Sprintf("--%s", f)) - } - } - - if meta.Region != "" { - l.cmd.ProviderConfig.Region = meta.Region - } - - api.SetDefaultGitSettings(l.cmd.ClusterConfig) - return l.validateWithConfigFile() -} - // GitOpsConfigLoader handles loading of ClusterConfigFile v.s. using CLI // flags for GitOps-related commands. type GitOpsConfigLoader struct { @@ -308,10 +29,6 @@ func NewGitOpsConfigLoader(cmd *Cmd) *GitOpsConfigLoader { return ErrMustBeSet("metadata.region") } - if l.cmd.ClusterConfig.Git != nil { - return errors.New("config cannot be provided for git.repo, git.bootstrapProfile or git.operator alongside gitops.*") - } - if l.cmd.ClusterConfig.GitOps == nil || l.cmd.ClusterConfig.GitOps.Flux == nil { return ErrMustBeSet("gitops.flux") } diff --git a/pkg/ctl/create/cluster.go b/pkg/ctl/create/cluster.go index a25cd5057f..fa19316af2 100644 --- a/pkg/ctl/create/cluster.go +++ b/pkg/ctl/create/cluster.go @@ -11,19 +11,18 @@ import ( "github.com/weaveworks/eksctl/pkg/utils" "github.com/weaveworks/eksctl/pkg/actions/addon" + "github.com/weaveworks/eksctl/pkg/actions/flux" "github.com/kris-nova/logger" "github.com/pkg/errors" "github.com/spf13/cobra" "github.com/spf13/pflag" - "k8s.io/client-go/tools/clientcmd" api "github.com/weaveworks/eksctl/pkg/apis/eksctl.io/v1alpha5" "github.com/weaveworks/eksctl/pkg/authconfigmap" "github.com/weaveworks/eksctl/pkg/ctl/cmdutils" "github.com/weaveworks/eksctl/pkg/ctl/cmdutils/filter" "github.com/weaveworks/eksctl/pkg/eks" - "github.com/weaveworks/eksctl/pkg/gitops" "github.com/weaveworks/eksctl/pkg/printers" "github.com/weaveworks/eksctl/pkg/utils/kubeconfig" "github.com/weaveworks/eksctl/pkg/utils/kubectl" @@ -355,24 +354,18 @@ func doCreateCluster(cmd *cmdutils.Cmd, ngFilter *filter.NodeGroupFilter, params } } - // FLUX V1 DEPRECATION NOTICE. https://github.com/weaveworks/eksctl/issues/2963 - if cfg.HasGitopsRepoConfigured() { - logger.Warning("git.X configuration is marked for deprecation: Please see https://github.com/weaveworks/eksctl/issues/2963") - } - if cfg.HasGitopsRepoConfigured() || cfg.HasGitOpsFluxConfigured() { - kubernetesClientConfigs, err := ctl.NewClient(cfg) - if err != nil { - return err - } - k8sConfig := kubernetesClientConfigs.Config - k8sRestConfig, err := clientcmd.NewDefaultClientConfig(*k8sConfig, &clientcmd.ConfigOverrides{}).ClientConfig() + if cfg.HasGitOpsFluxConfigured() { + installer, err := flux.New(clientSet, cfg.GitOps) + logger.Info("gitops configuration detected, setting installer to Flux v2") if err != nil { - return errors.Wrap(err, "cannot create Kubernetes client configuration") + return errors.Wrapf(err, "could not initialise Flux installer") } - err = gitops.Setup(params.KubeconfigPath, k8sRestConfig, clientSet, cfg, gitops.DefaultPodReadyTimeout) - if err != nil { + + if err := installer.Run(); err != nil { return err } + + //TODO why was it returning early before? I want to remove this line :thinking: return nil } diff --git a/pkg/ctl/enable/enable.go b/pkg/ctl/enable/enable.go index a9cb98d71e..7dc839cee7 100644 --- a/pkg/ctl/enable/enable.go +++ b/pkg/ctl/enable/enable.go @@ -11,9 +11,5 @@ func Command(flagGrouping *cmdutils.FlagGrouping) *cobra.Command { verbCmd := cmdutils.NewVerbCmd("enable", "Enable features in a cluster", "") cmdutils.AddResourceCmd(flagGrouping, verbCmd, enableFlux2) - // FLUX V1 DEPRECATION NOTICE. https://github.com/weaveworks/eksctl/issues/2963 - cmdutils.AddResourceCmd(flagGrouping, verbCmd, enableProfile) - cmdutils.AddResourceCmd(flagGrouping, verbCmd, enableRepo) - return verbCmd } diff --git a/pkg/ctl/enable/flux_test.go b/pkg/ctl/enable/flux_test.go index aefd36f98b..651bbb22b0 100644 --- a/pkg/ctl/enable/flux_test.go +++ b/pkg/ctl/enable/flux_test.go @@ -145,15 +145,5 @@ var _ = Describe("enable flux", func() { Expect(err).To(MatchError("gitops.flux.flags must be set")) }) }) - - When("deprecated git configuration is provided", func() { - BeforeEach(func() { - cfg.Git = &api.Git{Repo: &api.Repo{}} - }) - - It("fails", func() { - Expect(err).To(MatchError("config cannot be provided for git.repo, git.bootstrapProfile or git.operator alongside gitops.*")) - }) - }) }) }) diff --git a/pkg/ctl/enable/profile.go b/pkg/ctl/enable/profile.go deleted file mode 100644 index c568813af0..0000000000 --- a/pkg/ctl/enable/profile.go +++ /dev/null @@ -1,66 +0,0 @@ -// FLUX V1 DEPRECATION NOTICE. https://github.com/weaveworks/eksctl/issues/2963 -package enable - -import ( - "time" - - "github.com/spf13/cobra" - "github.com/spf13/pflag" - - api "github.com/weaveworks/eksctl/pkg/apis/eksctl.io/v1alpha5" - "github.com/weaveworks/eksctl/pkg/ctl/cmdutils" - "github.com/weaveworks/eksctl/pkg/gitops" -) - -// FLUX V1 DEPRECATION NOTICE. https://github.com/weaveworks/eksctl/issues/2963 -func enableProfile(cmd *cmdutils.Cmd) { - enableProfileWithRunFunc(cmd, doEnableProfile) -} - -func enableProfileWithRunFunc(cmd *cmdutils.Cmd, runFunc func(cmd *cmdutils.Cmd) error) { - cmd.ClusterConfig = api.NewClusterConfig() - cmd.SetDescription( - "profile", - "DEPRECATED: https://github.com/weaveworks/eksctl/issues/2963. Commits the components from the selected Quick Start profile to the destination repository.", - "", - ) - cmd.CobraCommand.Hidden = true - opts := configureProfileCmd(cmd) - cmd.CobraCommand.RunE = func(_ *cobra.Command, args []string) error { - cmd.NameArg = cmdutils.GetNameArg(args) - - if err := cmdutils.NewGitConfigLoader(cmd, opts). - WithRepoValidation(). - WithProfileValidation(). - Load(); err != nil { - return err - } - - return runFunc(cmd) - } -} - -// configureProfileCmd configures the provided command object so that it can -// process CLI options and ClusterConfig file, to prepare for the installation -// of the configured profile on the configured repository & cluster. -func configureProfileCmd(cmd *cmdutils.Cmd) *api.Git { - opts := api.NewGit() - - cmd.FlagSetGroup.InFlagSet("Enable profile", func(fs *pflag.FlagSet) { - cmdutils.AddCommonFlagsForProfile(fs, opts.BootstrapProfile) - cmdutils.AddCommonFlagsForGitRepo(fs, opts.Repo) - }) - cmd.FlagSetGroup.InFlagSet("General", func(fs *pflag.FlagSet) { - fs.StringVar(&cmd.ClusterConfig.Metadata.Name, "cluster", "", "name of the EKS cluster to enable this Quick Start profile on") - cmdutils.AddRegionFlag(fs, &cmd.ProviderConfig) - cmdutils.AddConfigFileFlag(fs, &cmd.ClusterConfigFile) - cmdutils.AddTimeoutFlagWithValue(fs, &cmd.ProviderConfig.WaitTimeout, 20*time.Second) - }) - cmdutils.AddCommonFlagsForAWS(cmd.FlagSetGroup, &cmd.ProviderConfig, false) - return opts -} - -// doEnableProfile enables the configured profile on the configured repository. -func doEnableProfile(cmd *cmdutils.Cmd) error { - return gitops.InstallProfile(cmd.ClusterConfig) -} diff --git a/pkg/ctl/enable/profile_test.go b/pkg/ctl/enable/profile_test.go deleted file mode 100644 index 5f6ff71837..0000000000 --- a/pkg/ctl/enable/profile_test.go +++ /dev/null @@ -1,270 +0,0 @@ -// FLUX V1 DEPRECATION NOTICE. https://github.com/weaveworks/eksctl/issues/2963 -package enable - -import ( - "os" - - . "github.com/onsi/ginkgo" - . "github.com/onsi/gomega" - - api "github.com/weaveworks/eksctl/pkg/apis/eksctl.io/v1alpha5" - "github.com/weaveworks/eksctl/pkg/ctl/ctltest" -) - -var _ = Describe("enable profile", func() { - - newMockEnableProfileCmd := func(args ...string) *ctltest.MockCmd { - return ctltest.NewMockCmd(enableProfileWithRunFunc, "enable", args...) - } - - Describe("without a config file", func() { - - It("should accept a name argument", func() { - cmd := newMockEnableProfileCmd("profile", "--cluster", "clus-1", "--region", "eu-north-1", "--git-url", "git@example.com:repo.git", "--git-email", "user@example.com", "app-dev") - _, err := cmd.Execute() - Expect(err).NotTo(HaveOccurred()) - - cfg := cmd.Cmd.ClusterConfig - - Expect(cfg.Git.BootstrapProfile).NotTo(BeNil()) - Expect(cfg.Git.BootstrapProfile.Source).To(Equal("app-dev")) - }) - - It("should accept a --profile-source flag", func() { - cmd := newMockEnableProfileCmd("profile", "--cluster", "clus-1", "--region", "eu-north-1", "--git-url", "git@example.com:repo.git", "--git-email", "user@example.com", "--profile-source", "app-dev") - _, err := cmd.Execute() - Expect(err).NotTo(HaveOccurred()) - - cfg := cmd.Cmd.ClusterConfig - - Expect(cfg.Git.BootstrapProfile).NotTo(BeNil()) - Expect(cfg.Git.BootstrapProfile.Source).To(Equal("app-dev")) - }) - - It("should reject name argument and --profile-source flag", func() { - cmd := newMockEnableProfileCmd("profile", "--cluster", "clus-1", "--region", "eu-north-1", "--git-url", "git@example.com:repo.git", "--git-email", "user@example.com", "--profile-source", "app-dev", "app-dev") - _, err := cmd.Execute() - Expect(err).To(HaveOccurred()) - Expect(err.Error()).To(Equal("--profile-source=app-dev and argument app-dev cannot be used at the same time")) - }) - - It("requires the --profile-source flag", func() { - cmd := newMockEnableProfileCmd("profile", "--cluster", "clus-1", "--region", "eu-north-1", "--git-url", "git@example.com:repo.git", "--git-email", "user@example.com") - out, err := cmd.Execute() - Expect(err).To(HaveOccurred()) - Expect(err.Error()).To(Equal("--profile-source must be set")) - Expect(out).To(ContainSubstring("Usage")) - }) - - It("requires the --git-email flag", func() { - cmd := newMockEnableProfileCmd("profile", "--cluster", "clus-1", "--region", "eu-north-1", "--git-url", "git@example.com:repo.git", "app-dev") - out, err := cmd.Execute() - Expect(err).To(HaveOccurred()) - Expect(err.Error()).To(Equal("--git-email must be set")) - Expect(out).To(ContainSubstring("Usage")) - }) - - It("requires the --git-url flag", func() { - cmd := newMockEnableProfileCmd("profile", "--cluster", "clus-1", "--region", "eu-north-1", "--git-email", "user@example.com", "app-dev") - out, err := cmd.Execute() - Expect(err).To(HaveOccurred()) - Expect(err.Error()).To(Equal("--git-url must be set")) - Expect(out).To(ContainSubstring("Usage")) - }) - - It("requires the --cluster flag", func() { - cmd := newMockEnableProfileCmd("profile", "--region", "eu-north-1", "--git-email", "user@example.com", "--git-url", "git@example.com:repo.git", "--git-email", "user@example.com", "app-dev") - out, err := cmd.Execute() - Expect(err).To(HaveOccurred()) - Expect(err.Error()).To(Equal("--cluster must be set")) - Expect(out).To(ContainSubstring("Usage")) - }) - It("requires the --region flag", func() { - cmd := newMockEnableProfileCmd("profile", "--cluster", "clus-1", "--git-email", "user@example.com", "--git-url", "git@example.com:repo.git", "--git-email", "user@example.com", "app-dev") - out, err := cmd.Execute() - Expect(err).To(HaveOccurred()) - Expect(err.Error()).To(Equal("--region must be set")) - Expect(out).To(ContainSubstring("Usage")) - }) - It("requires the git-private-ssh-key file to exist", func() { - cmd := newMockEnableProfileCmd("profile", "--cluster", "clus-1", "--git-email", "user@example.com", "--git-url", "git@example.com:repo.git", "--git-email", "user@example.com", "--git-private-ssh-key-path", "./inexistent-file", "app-dev") - out, err := cmd.Execute() - Expect(err).To(HaveOccurred()) - Expect(err.Error()).To(Equal("--region must be set")) - Expect(out).To(ContainSubstring("Usage")) - }) - - It("loads all flags correctly", func() { - cmd := newMockEnableProfileCmd("profile", - "--cluster", "clus-1", - "--region", "us-west-2", - "--git-url", "git@example.com:repo.git", - "--git-email", "user@example.com", - "--git-branch", "master", - "--git-user", "user1", - "--git-private-ssh-key-path", "./profile_test.go", - "--profile-source", "app-dev", - "--profile-revision", "branch-2", - ) - _, err := cmd.Execute() - Expect(err).NotTo(HaveOccurred()) - - cfg := cmd.Cmd.ClusterConfig - Expect(cfg.Metadata.Name).To(Equal("clus-1")) - Expect(cfg.Metadata.Region).To(Equal("us-west-2")) - Expect(cfg.Git).NotTo(BeNil()) - Expect(cfg.Git.Repo).NotTo(BeNil()) - Expect(cfg.Git.Repo.URL).To(Equal("git@example.com:repo.git")) - Expect(cfg.Git.Repo.Email).To(Equal("user@example.com")) - Expect(cfg.Git.Repo.Branch).To(Equal("master")) - Expect(cfg.Git.Repo.User).To(Equal("user1")) - Expect(cfg.Git.Repo.PrivateSSHKeyPath).To(Equal("./profile_test.go")) - - Expect(cfg.Git.BootstrapProfile).NotTo(BeNil()) - Expect(cfg.Git.BootstrapProfile.Source).To(Equal("app-dev")) - Expect(cfg.Git.BootstrapProfile.Revision).To(Equal("branch-2")) - }) - }) - - Describe("with a config file", func() { - var configFile string - var cfg *api.ClusterConfig - - BeforeEach(func() { - // Minimal cluster config for the command to work - cfg = &api.ClusterConfig{ - TypeMeta: api.ClusterConfigTypeMeta(), - Metadata: &api.ClusterMeta{ - Name: "cluster-1", - Region: "us-west-2", - }, - Git: &api.Git{ - Repo: &api.Repo{ - URL: "git@github.com:org/repo1", - Email: "user@example.com", - }, - BootstrapProfile: &api.Profile{Source: "app-dev"}, - }, - } - }) - - AfterEach(func() { - if configFile != "" { - os.Remove(configFile) - } - }) - - It("succeeds with the basic configuration", func() { - configFile = ctltest.CreateConfigFile(cfg) - - cmd := newMockEnableProfileCmd("profile", "-f", configFile) - _, err := cmd.Execute() - Expect(err).NotTo(HaveOccurred()) - }) - - It("loads the correct defaults", func() { - configFile = ctltest.CreateConfigFile(cfg) - - cmd := newMockEnableProfileCmd("profile", "-f", configFile) - _, err := cmd.Execute() - Expect(err).NotTo(HaveOccurred()) - - gitCfg := cmd.Cmd.ClusterConfig.Git - Expect(gitCfg).NotTo(BeNil()) - Expect(gitCfg.Repo.Branch).To(Equal("master")) - Expect(gitCfg.Repo.User).To(Equal("Flux")) - Expect(gitCfg.Repo.FluxPath).To(Equal("flux/")) - Expect(gitCfg.Repo.Paths).To(BeEmpty()) - Expect(gitCfg.Repo.PrivateSSHKeyPath).To(Equal("")) - - Expect(gitCfg.Operator.Namespace).To(Equal("flux")) - Expect(gitCfg.Operator.Label).To(Equal("flux")) - Expect(gitCfg.Operator.WithHelm).NotTo(BeNil()) - Expect(*gitCfg.Operator.WithHelm).To(BeTrue()) - - Expect(gitCfg.BootstrapProfile.Revision).To(Equal("")) - Expect(gitCfg.BootstrapProfile.OutputPath).To(Equal("./app-dev")) - }) - - It("fails without a cluster name", func() { - cfg.Metadata.Name = "" - configFile = ctltest.CreateConfigFile(cfg) - - cmd := newMockEnableProfileCmd("profile", "-f", configFile) - _, err := cmd.Execute() - Expect(err).To(HaveOccurred()) - Expect(err.Error()).To(Equal("metadata.name must be set")) - }) - - It("fails without a region", func() { - cfg.Metadata.Region = "" - configFile = ctltest.CreateConfigFile(cfg) - - cmd := newMockEnableProfileCmd("profile", "-f", configFile) - _, err := cmd.Execute() - Expect(err).To(HaveOccurred()) - Expect(err.Error()).To(Equal("metadata.region must be set")) - }) - - It("fails without a nil repo", func() { - cfg.Git.Repo = nil - configFile = ctltest.CreateConfigFile(cfg) - - cmd := newMockEnableProfileCmd("profile", "-f", configFile) - _, err := cmd.Execute() - Expect(err).To(HaveOccurred()) - Expect(err.Error()).To(Equal("git.repo.url must be set")) - }) - - It("fails without a git url", func() { - cfg.Git.Repo.URL = "" - configFile = ctltest.CreateConfigFile(cfg) - - cmd := newMockEnableProfileCmd("profile", "-f", configFile) - _, err := cmd.Execute() - Expect(err).To(HaveOccurred()) - Expect(err.Error()).To(Equal("git.repo.url must be set")) - }) - - It("fails without a user email", func() { - cfg.Git.Repo.Email = "" - configFile = ctltest.CreateConfigFile(cfg) - - cmd := newMockEnableProfileCmd("profile", "-f", configFile) - _, err := cmd.Execute() - Expect(err).To(HaveOccurred()) - Expect(err.Error()).To(Equal("git.repo.email must be set")) - }) - - It("fails when the private ssh key file does not exist", func() { - cfg.Git.Repo.PrivateSSHKeyPath = "non-existent-file" - configFile = ctltest.CreateConfigFile(cfg) - - cmd := newMockEnableProfileCmd("profile", "-f", configFile) - _, err := cmd.Execute() - Expect(err).To(HaveOccurred()) - Expect(err.Error()).To(Equal("please supply a valid file for git.repo.privateSSHKeyPath: invalid path to private SSH key: non-existent-file")) - }) - - It("fails without bootstrap profiles", func() { - cfg.Git.BootstrapProfile = nil - configFile = ctltest.CreateConfigFile(cfg) - - cmd := newMockEnableProfileCmd("profile", "-f", configFile) - _, err := cmd.Execute() - Expect(err).To(HaveOccurred()) - Expect(err.Error()).To(Equal("git.bootstrapProfile.Source must be set")) - }) - - It("fails with empty bootstrap profile", func() { - cfg.Git.BootstrapProfile = &api.Profile{} - configFile = ctltest.CreateConfigFile(cfg) - - cmd := newMockEnableProfileCmd("profile", "-f", configFile) - _, err := cmd.Execute() - Expect(err).To(HaveOccurred()) - Expect(err.Error()).To(Equal("git.bootstrapProfile.Source must be set")) - }) - }) - -}) diff --git a/pkg/ctl/enable/repo.go b/pkg/ctl/enable/repo.go deleted file mode 100644 index 5df77fe2a4..0000000000 --- a/pkg/ctl/enable/repo.go +++ /dev/null @@ -1,88 +0,0 @@ -// FLUX V1 DEPRECATION NOTICE. https://github.com/weaveworks/eksctl/issues/2963 -package enable - -import ( - "time" - - "github.com/kris-nova/logger" - "github.com/spf13/cobra" - "github.com/spf13/pflag" - "github.com/weaveworks/eksctl/pkg/actions/repo" - api "github.com/weaveworks/eksctl/pkg/apis/eksctl.io/v1alpha5" - "github.com/weaveworks/eksctl/pkg/ctl/cmdutils" - "github.com/weaveworks/eksctl/pkg/gitops" -) - -// FLUX V1 DEPRECATION NOTICE. https://github.com/weaveworks/eksctl/issues/2963 -type options struct { - cfg api.Git - timeout time.Duration -} - -func enableRepo(cmd *cmdutils.Cmd) { - enableRepoWithRunFunc(cmd, doEnableRepository) -} - -func enableRepoWithRunFunc(cmd *cmdutils.Cmd, runFunc func(cmd *cmdutils.Cmd) error) { - cmd.ClusterConfig = api.NewClusterConfig() - cmd.SetDescription( - "repo", - "DEPRECATED: https://github.com/weaveworks/eksctl/issues/2963. Set up a repo for gitops, installing Flux in the cluster and initializing its manifests in the specified Git repository", - "", - ) - cmd.CobraCommand.Hidden = true - opts := configureRepositoryCmd(cmd) - cmd.CobraCommand.RunE = func(_ *cobra.Command, args []string) error { - cmd.NameArg = cmdutils.GetNameArg(args) - - if cmd.NameArg != "" { - return cmdutils.ErrUnsupportedNameArg() - } - - if err := cmdutils.NewGitConfigLoader(cmd, &opts.cfg).WithRepoValidation().Load(); err != nil { - return err - } - - cmd.ProviderConfig.WaitTimeout = opts.timeout - return runFunc(cmd) - } -} - -// configureRepositoryCmd configures the provided command object so that it can -// process CLI options and ClusterConfig file, to prepare for the "enablement" -// of the configured repository & cluster. -func configureRepositoryCmd(cmd *cmdutils.Cmd) *options { - opts := options{ - cfg: *api.NewGit(), - } - cmd.FlagSetGroup.InFlagSet("Enable repository", func(fs *pflag.FlagSet) { - cmdutils.AddCommonFlagsForFlux(fs, &opts.cfg) - }) - cmd.FlagSetGroup.InFlagSet("General", func(fs *pflag.FlagSet) { - fs.StringVar(&cmd.ClusterConfig.Metadata.Name, "cluster", "", "name of the EKS cluster to enable gitops on") - cmdutils.AddRegionFlag(fs, &cmd.ProviderConfig) - cmdutils.AddConfigFileFlag(fs, &cmd.ClusterConfigFile) - cmdutils.AddTimeoutFlagWithValue(fs, &opts.timeout, gitops.DefaultPodReadyTimeout) - }) - cmdutils.AddCommonFlagsForAWS(cmd.FlagSetGroup, &cmd.ProviderConfig, false) - return &opts -} - -func doEnableRepository(cmd *cmdutils.Cmd) error { - k8sClientSet, k8sRestConfig, err := cmdutils.KubernetesClientAndConfigFrom(cmd) - if err != nil { - return err - } - - installer, err := repo.New(k8sRestConfig, k8sClientSet, cmd.ClusterConfig, cmd.ProviderConfig.WaitTimeout) - if err != nil { - return err - } - - if err := installer.Run(); err != nil { - logger.Critical("unable to set up gitops repo: %s", err.Error()) - return err - } - - return nil -} diff --git a/pkg/ctl/enable/repo_test.go b/pkg/ctl/enable/repo_test.go deleted file mode 100644 index 0b48033e9e..0000000000 --- a/pkg/ctl/enable/repo_test.go +++ /dev/null @@ -1,265 +0,0 @@ -// FLUX V1 DEPRECATION NOTICE. https://github.com/weaveworks/eksctl/issues/2963 -package enable - -import ( - "os" - - . "github.com/onsi/ginkgo" - . "github.com/onsi/gomega" - - api "github.com/weaveworks/eksctl/pkg/apis/eksctl.io/v1alpha5" - "github.com/weaveworks/eksctl/pkg/ctl/ctltest" -) - -var _ = Describe("enable repo", func() { - - newMockEnableRepoCmd := func(args ...string) *ctltest.MockCmd { - return ctltest.NewMockCmd(enableRepoWithRunFunc, "enable", args...) - } - - Describe("without a config file", func() { - - It("with name argument should fail", func() { - cmd := newMockEnableRepoCmd("repo", "--cluster", "clus-1", "--region", "eu-north-1", "--git-url", "git@example.com:repo.git", "--git-email", "user@example.com", "name-argument") - out, err := cmd.Execute() - Expect(err).To(HaveOccurred()) - Expect(err.Error()).To(Equal("name argument is not supported")) - Expect(out).To(ContainSubstring("Usage")) - }) - - It("requires the --git-email flag", func() { - cmd := newMockEnableRepoCmd("repo", "--cluster", "clus-1", "--region", "eu-north-1", "--git-url", "git@example.com:repo.git") - out, err := cmd.Execute() - Expect(err).To(HaveOccurred()) - Expect(err.Error()).To(Equal("--git-email must be set")) - Expect(out).To(ContainSubstring("Usage")) - }) - - It("requires the --git-url flag", func() { - cmd := newMockEnableRepoCmd("repo", "--cluster", "clus-1", "--region", "eu-north-1", "--git-email", "user@example.com") - out, err := cmd.Execute() - Expect(err).To(HaveOccurred()) - Expect(err.Error()).To(Equal("--git-url must be set")) - Expect(out).To(ContainSubstring("Usage")) - }) - - It("requires the --cluster flag", func() { - cmd := newMockEnableRepoCmd("repo", "--region", "eu-north-1", "--git-email", "user@example.com", "--git-url", "git@example.com:repo.git", "--git-email", "user@example.com") - out, err := cmd.Execute() - Expect(err).To(HaveOccurred()) - Expect(err.Error()).To(Equal("--cluster must be set")) - Expect(out).To(ContainSubstring("Usage")) - }) - It("requires the --region flag", func() { - cmd := newMockEnableRepoCmd("repo", "--cluster", "clus-1", "--git-email", "user@example.com", "--git-url", "git@example.com:repo.git", "--git-email", "user@example.com") - out, err := cmd.Execute() - Expect(err).To(HaveOccurred()) - Expect(err.Error()).To(Equal("--region must be set")) - Expect(out).To(ContainSubstring("Usage")) - }) - It("requires the git-private-ssh-key file to exist", func() { - cmd := newMockEnableRepoCmd("repo", "--cluster", "clus-1", "--git-email", "user@example.com", "--git-url", "git@example.com:repo.git", "--git-email", "user@example.com", "--git-private-ssh-key-path", "./inexistent-file") - out, err := cmd.Execute() - Expect(err).To(HaveOccurred()) - Expect(err.Error()).To(Equal("--region must be set")) - Expect(out).To(ContainSubstring("Usage")) - }) - - It("loads all flags correctly", func() { - cmd := newMockEnableRepoCmd("repo", - "--cluster", "clus-1", - "--region", "us-west-2", - "--git-url", "git@example.com:repo.git", - "--git-email", "user@example.com", - "--git-branch", "master", - "--git-user", "user1", - "--git-private-ssh-key-path", "./repo_test.go", - "--git-paths", "base,flux,upgrades", - "--git-label", "flux2", - "--git-flux-subdir", "flux-dir/", - "--namespace", "gitops", - "--with-helm", - "--read-only", - "--commit-operator-manifests=false", - "--additional-flux-args", "--git-poll-interval=30s,--git-timeout=5m", - "--additional-helm-operator-args", "--log-format=json,--workers=4", - ) - _, err := cmd.Execute() - Expect(err).NotTo(HaveOccurred()) - - cfg := cmd.Cmd.ClusterConfig - Expect(cfg.Metadata.Name).To(Equal("clus-1")) - Expect(cfg.Metadata.Region).To(Equal("us-west-2")) - Expect(cfg.Git).NotTo(BeNil()) - Expect(cfg.Git.Repo).NotTo(BeNil()) - Expect(cfg.Git.Repo.URL).To(Equal("git@example.com:repo.git")) - Expect(cfg.Git.Repo.Email).To(Equal("user@example.com")) - Expect(cfg.Git.Repo.Branch).To(Equal("master")) - Expect(cfg.Git.Repo.User).To(Equal("user1")) - Expect(cfg.Git.Repo.PrivateSSHKeyPath).To(Equal("./repo_test.go")) - Expect(cfg.Git.Repo.Paths).To(ConsistOf("base", "flux", "upgrades")) - Expect(cfg.Git.Repo.FluxPath).To(Equal("flux-dir/")) - - Expect(cfg.Git.Operator).NotTo(BeNil()) - Expect(cfg.Git.Operator.Label).To(Equal("flux2")) - Expect(cfg.Git.Operator.Namespace).To(Equal("gitops")) - Expect(*cfg.Git.Operator.WithHelm).To(BeTrue()) - Expect(cfg.Git.Operator.ReadOnly).To(BeTrue()) - Expect(*cfg.Git.Operator.CommitOperatorManifests).To(BeFalse()) - Expect(cfg.Git.Operator.AdditionalFluxArgs).To(ConsistOf("--git-poll-interval=30s", "--git-timeout=5m")) - Expect(cfg.Git.Operator.AdditionalHelmOperatorArgs).To(ConsistOf("--log-format=json", "--workers=4")) - }) - - It("loads correct defaults", func() { - cmd := newMockEnableRepoCmd("repo", - "--cluster", "clus-1", - "--region", "us-west-2", - "--git-url", "git@example.com:repo.git", - "--git-email", "user@example.com", - ) - _, err := cmd.Execute() - Expect(err).NotTo(HaveOccurred()) - - cfg := cmd.Cmd.ClusterConfig - Expect(cfg.Git).NotTo(BeNil()) - Expect(cfg.Git.Repo).NotTo(BeNil()) - Expect(cfg.Git.Repo.Branch).To(Equal("master")) - Expect(cfg.Git.Repo.User).To(Equal("Flux")) - Expect(cfg.Git.Repo.PrivateSSHKeyPath).To(Equal("")) - Expect(cfg.Git.Repo.Paths).To(BeEmpty()) - Expect(cfg.Git.Repo.FluxPath).To(Equal("flux/")) - - Expect(cfg.Git.Operator).NotTo(BeNil()) - Expect(cfg.Git.Operator.Label).To(Equal("flux")) - Expect(cfg.Git.Operator.Namespace).To(Equal("flux")) - Expect(*cfg.Git.Operator.WithHelm).To(BeTrue()) - Expect(cfg.Git.Operator.ReadOnly).To(BeFalse()) - Expect(*cfg.Git.Operator.CommitOperatorManifests).To(BeTrue()) - Expect(cfg.Git.Operator.AdditionalFluxArgs).To(BeEmpty()) - Expect(cfg.Git.Operator.AdditionalHelmOperatorArgs).To(BeEmpty()) - }) - }) - - Describe("with a config file", func() { - var configFile string - var cfg *api.ClusterConfig - - BeforeEach(func() { - // Minimal valid cluster config for the command to work - cfg = &api.ClusterConfig{ - TypeMeta: api.ClusterConfigTypeMeta(), - Metadata: &api.ClusterMeta{ - Name: "cluster-1", - Region: "us-west-2", - }, - Git: &api.Git{ - Repo: &api.Repo{ - URL: "git@github.com:org/repo1", - Email: "user@example.com", - }, - BootstrapProfile: &api.Profile{Source: "app-dev"}, - }, - } - }) - - AfterEach(func() { - if configFile != "" { - os.Remove(configFile) - } - }) - - It("succeeds with the basic configuration", func() { - configFile = ctltest.CreateConfigFile(cfg) - - cmd := newMockEnableRepoCmd("repo", "-f", configFile) - _, err := cmd.Execute() - Expect(err).NotTo(HaveOccurred()) - }) - - It("fails without a cluster name", func() { - cfg.Metadata.Name = "" - configFile = ctltest.CreateConfigFile(cfg) - - cmd := newMockEnableRepoCmd("repo", "-f", configFile) - _, err := cmd.Execute() - Expect(err).To(HaveOccurred()) - Expect(err.Error()).To(Equal("metadata.name must be set")) - }) - - It("fails without a region", func() { - cfg.Metadata.Region = "" - configFile = ctltest.CreateConfigFile(cfg) - - cmd := newMockEnableRepoCmd("repo", "-f", configFile) - _, err := cmd.Execute() - Expect(err).To(HaveOccurred()) - Expect(err.Error()).To(Equal("metadata.region must be set")) - }) - - It("fails without a git url", func() { - cfg.Git.Repo.URL = "" - configFile = ctltest.CreateConfigFile(cfg) - - cmd := newMockEnableRepoCmd("repo", "-f", configFile) - _, err := cmd.Execute() - Expect(err).To(HaveOccurred()) - Expect(err.Error()).To(Equal("git.repo.url must be set")) - }) - - It("fails without a user email", func() { - cfg.Git.Repo.Email = "" - configFile = ctltest.CreateConfigFile(cfg) - - cmd := newMockEnableRepoCmd("repo", "-f", configFile) - _, err := cmd.Execute() - Expect(err).To(HaveOccurred()) - Expect(err.Error()).To(Equal("git.repo.email must be set")) - }) - - It("fails when the private ssh key file does not exist", func() { - cfg.Git.Repo.PrivateSSHKeyPath = "non-existent-file" - configFile = ctltest.CreateConfigFile(cfg) - - cmd := newMockEnableRepoCmd("repo", "-f", configFile) - _, err := cmd.Execute() - Expect(err).To(HaveOccurred()) - Expect(err.Error()).To(Equal("please supply a valid file for git.repo.privateSSHKeyPath: invalid path to private SSH key: non-existent-file")) - }) - - It("fails with new gitops configuration", func() { - cfg.GitOps = &api.GitOps{} - configFile = ctltest.CreateConfigFile(cfg) - - cmd := newMockEnableRepoCmd("repo", "-f", configFile) - _, err := cmd.Execute() - Expect(err).To(HaveOccurred()) - Expect(err.Error()).To(Equal("config cannot be provided for gitops alongside git")) - }) - - It("loads the correct defaults", func() { - configFile = ctltest.CreateConfigFile(cfg) - - cmd := newMockEnableRepoCmd("repo", "-f", configFile) - _, err := cmd.Execute() - Expect(err).NotTo(HaveOccurred()) - - gitCfg := cmd.Cmd.ClusterConfig.Git - Expect(gitCfg).NotTo(BeNil()) - Expect(gitCfg.Repo.Branch).To(Equal("master")) - Expect(gitCfg.Repo.User).To(Equal("Flux")) - Expect(gitCfg.Repo.FluxPath).To(Equal("flux/")) - Expect(gitCfg.Repo.Paths).To(BeEmpty()) - Expect(gitCfg.Repo.PrivateSSHKeyPath).To(Equal("")) - - Expect(gitCfg.Operator.Namespace).To(Equal("flux")) - Expect(gitCfg.Operator.Label).To(Equal("flux")) - Expect(gitCfg.Operator.WithHelm).NotTo(BeNil()) - Expect(*gitCfg.Operator.WithHelm).To(BeTrue()) - Expect(gitCfg.Operator.ReadOnly).To(BeFalse()) - Expect(*gitCfg.Operator.CommitOperatorManifests).To(BeTrue()) - Expect(gitCfg.Operator.AdditionalFluxArgs).To(BeEmpty()) - Expect(gitCfg.Operator.AdditionalHelmOperatorArgs).To(BeEmpty()) - }) - - }) -}) diff --git a/pkg/ctl/generate/generate.go b/pkg/ctl/generate/generate.go deleted file mode 100644 index 011b27a5bc..0000000000 --- a/pkg/ctl/generate/generate.go +++ /dev/null @@ -1,18 +0,0 @@ -package generate - -import ( - "github.com/spf13/cobra" - - "github.com/weaveworks/eksctl/pkg/ctl/cmdutils" -) - -// Command creates `generate` commands -func Command(flagGrouping *cmdutils.FlagGrouping) *cobra.Command { - verbCmd := cmdutils.NewVerbCmd("generate", - "DEPRECATED: https://github.com/weaveworks/eksctl/issues/2963\nGenerate gitops manifests", - "", - ) - verbCmd.Hidden = true - cmdutils.AddResourceCmd(flagGrouping, verbCmd, generateProfile) - return verbCmd -} diff --git a/pkg/ctl/generate/generate_suite_test.go b/pkg/ctl/generate/generate_suite_test.go deleted file mode 100644 index 65c04dd651..0000000000 --- a/pkg/ctl/generate/generate_suite_test.go +++ /dev/null @@ -1,11 +0,0 @@ -package generate - -import ( - "testing" - - "github.com/weaveworks/eksctl/pkg/testutils" -) - -func TestCtlGenerate(t *testing.T) { - testutils.RegisterAndRun(t) -} diff --git a/pkg/ctl/generate/generate_test.go b/pkg/ctl/generate/generate_test.go deleted file mode 100644 index 8d507f5735..0000000000 --- a/pkg/ctl/generate/generate_test.go +++ /dev/null @@ -1,61 +0,0 @@ -package generate - -import ( - "bytes" - "errors" - - . "github.com/onsi/ginkgo" - . "github.com/onsi/gomega" - "github.com/spf13/cobra" - "github.com/weaveworks/eksctl/pkg/ctl/cmdutils" -) - -var _ = Describe("generate", func() { - Describe("invalid-resource", func() { - It("with no flag", func() { - cmd := newMockCmd("invalid-resource") - _, err := cmd.execute() - Expect(err).To(HaveOccurred()) - Expect(err.Error()).To(ContainSubstring("Error: unknown command \"invalid-resource\" for \"generate\"")) - Expect(err.Error()).To(ContainSubstring("usage")) - }) - It("with invalid-resource and some flag", func() { - cmd := newMockCmd("invalid-resource", "--invalid-flag", "foo") - _, err := cmd.execute() - Expect(err).To(HaveOccurred()) - Expect(err.Error()).To(ContainSubstring("Error: unknown command \"invalid-resource\" for \"generate\"")) - Expect(err.Error()).To(ContainSubstring("usage")) - }) - It("with invalid-resource and additional argument", func() { - cmd := newMockCmd("invalid-resource", "foo") - _, err := cmd.execute() - Expect(err).To(HaveOccurred()) - Expect(err.Error()).To(ContainSubstring("Error: unknown command \"invalid-resource\" for \"generate\"")) - Expect(err.Error()).To(ContainSubstring("usage")) - }) - }) -}) - -func newMockCmd(args ...string) *mockVerbCmd { - cmd := Command(cmdutils.NewGrouping()) - cmd.SetArgs(args) - return &mockVerbCmd{ - parentCmd: cmd, - } -} - -type mockVerbCmd struct { - parentCmd *cobra.Command -} - -func (c mockVerbCmd) execute() (string, error) { - outBuf := new(bytes.Buffer) - errBuf := new(bytes.Buffer) - c.parentCmd.SetOut(outBuf) - c.parentCmd.SetErr(errBuf) - err := c.parentCmd.Execute() - if err != nil { - err = errors.New(errBuf.String()) - } - return outBuf.String(), err -} diff --git a/pkg/ctl/generate/profile.go b/pkg/ctl/generate/profile.go deleted file mode 100644 index 5532cbe18e..0000000000 --- a/pkg/ctl/generate/profile.go +++ /dev/null @@ -1,83 +0,0 @@ -package generate - -import ( - "github.com/pkg/errors" - "github.com/spf13/afero" - "github.com/spf13/cobra" - "github.com/spf13/pflag" - - api "github.com/weaveworks/eksctl/pkg/apis/eksctl.io/v1alpha5" - "github.com/weaveworks/eksctl/pkg/ctl/cmdutils" - "github.com/weaveworks/eksctl/pkg/git" - "github.com/weaveworks/eksctl/pkg/gitops" - "github.com/weaveworks/eksctl/pkg/gitops/fileprocessor" -) - -// FLUX V1 DEPRECATION NOTICE. https://github.com/weaveworks/eksctl/issues/2963 -func generateProfile(cmd *cmdutils.Cmd) { - generateProfileWithRunFunc(cmd, doGenerateProfile) -} - -func generateProfileWithRunFunc(cmd *cmdutils.Cmd, runFunc func(*cmdutils.Cmd) error) { - cmd.ClusterConfig = api.NewClusterConfig() - cmd.SetDescription("profile", - "DEPRECATED: https://github.com/weaveworks/eksctl/issues/2963. Generate a gitops profile", - "", - ) - - opts := configureGenerateProfileCmd(cmd) - - cmd.CobraCommand.RunE = func(_ *cobra.Command, args []string) error { - cmd.NameArg = cmdutils.GetNameArg(args) - - if err := cmdutils.NewGitConfigLoader(cmd, opts). - WithProfileValidation().Load(); err != nil { - return err - } - - return runFunc(cmd) - } - -} - -func configureGenerateProfileCmd(cmd *cmdutils.Cmd) *api.Git { - opts := api.NewGit() - - cmd.FlagSetGroup.InFlagSet("Generate profile", func(fs *pflag.FlagSet) { - cmdutils.AddCommonFlagsForProfile(fs, opts.BootstrapProfile) - fs.StringVarP(&opts.BootstrapProfile.OutputPath, "profile-path", "", "", "path to generate the profile in. Defaults to ./") - }) - - cmd.FlagSetGroup.InFlagSet("General", func(fs *pflag.FlagSet) { - fs.StringVar(&cmd.ClusterConfig.Metadata.Name, "cluster", "", "name of the EKS cluster to enable gitops on") - cmdutils.AddRegionFlag(fs, &cmd.ProviderConfig) - cmdutils.AddConfigFileFlag(fs, &cmd.ClusterConfigFile) - }) - - cmdutils.AddCommonFlagsForAWS(cmd.FlagSetGroup, &cmd.ProviderConfig, false) - return opts -} - -func doGenerateProfile(cmd *cmdutils.Cmd) error { - // TODO move the load of the region outside of the creation of the EKS client - // currently that is done inside cmd.NewCtl() but we don't need EKS here - cmd.ClusterConfig.Metadata.Region = cmd.ProviderConfig.Region - - processor := &fileprocessor.GoTemplateProcessor{ - Params: fileprocessor.NewTemplateParameters(cmd.ClusterConfig), - } - profile := &gitops.Profile{ - Processor: processor, - ProfileCloner: git.NewGitClient(git.ClientParams{}), - FS: afero.NewOsFs(), - IO: afero.Afero{Fs: afero.NewOsFs()}, - } - - bootstrapProfile := cmd.ClusterConfig.Git.BootstrapProfile - err := profile.Generate(*bootstrapProfile) - if err != nil { - return errors.Wrap(err, "error generating profile") - } - - return nil -} diff --git a/pkg/ctl/generate/profile_test.go b/pkg/ctl/generate/profile_test.go deleted file mode 100644 index b7c0529634..0000000000 --- a/pkg/ctl/generate/profile_test.go +++ /dev/null @@ -1,226 +0,0 @@ -package generate - -import ( - "os" - - . "github.com/onsi/ginkgo" - . "github.com/onsi/gomega" - - api "github.com/weaveworks/eksctl/pkg/apis/eksctl.io/v1alpha5" - "github.com/weaveworks/eksctl/pkg/ctl/ctltest" -) - -var _ = Describe("generate profile", func() { - - newMockGenerateProfileCmd := func(args ...string) *ctltest.MockCmd { - return ctltest.NewMockCmd(generateProfileWithRunFunc, "generate", args...) - } - - Describe("without a config file", func() { - - It("should accept a name argument", func() { - cmd := newMockGenerateProfileCmd("profile", "--cluster", "clus-1", "--region", "eu-north-1", "app-dev") - _, err := cmd.Execute() - Expect(err).NotTo(HaveOccurred()) - - cfg := cmd.Cmd.ClusterConfig - - Expect(cfg.Git.BootstrapProfile).NotTo(BeNil()) - Expect(cfg.Git.BootstrapProfile.Source).To(Equal("app-dev")) - }) - - It("should accept --profile-source flag", func() { - cmd := newMockGenerateProfileCmd("profile", "--cluster", "clus-1", "--region", "eu-north-1", "--profile-source", "app-dev") - _, err := cmd.Execute() - Expect(err).NotTo(HaveOccurred()) - - cfg := cmd.Cmd.ClusterConfig - - Expect(cfg.Git.BootstrapProfile).NotTo(BeNil()) - Expect(cfg.Git.BootstrapProfile.Source).To(Equal("app-dev")) - }) - - It("should reject name argument and --profile-source flag", func() { - cmd := newMockGenerateProfileCmd("profile", "--cluster", "clus-1", "--region", "eu-north-1", "--profile-source", "app-dev", "app-dev") - _, err := cmd.Execute() - Expect(err).To(HaveOccurred()) - Expect(err.Error()).To(Equal("--profile-source=app-dev and argument app-dev cannot be used at the same time")) - }) - - It("requires the --profile-source flag", func() { - cmd := newMockGenerateProfileCmd("profile", "--cluster", "clus-1", "--region", "eu-north-1") - _, err := cmd.Execute() - Expect(err).To(HaveOccurred()) - Expect(err.Error()).To(Equal("--profile-source must be set")) - }) - - It("requires the --cluster flag", func() { - cmd := newMockGenerateProfileCmd("profile", "--region", "eu-north-1", "--profile-source", "app-dev") - out, err := cmd.Execute() - Expect(err).To(HaveOccurred()) - Expect(err.Error()).To(Equal("--cluster must be set")) - Expect(out).To(ContainSubstring("Usage")) - }) - It("requires the --region flag", func() { - cmd := newMockGenerateProfileCmd("profile", "--cluster", "clus-1", "--profile-source", "app-dev") - out, err := cmd.Execute() - Expect(err).To(HaveOccurred()) - Expect(err.Error()).To(Equal("--region must be set")) - Expect(out).To(ContainSubstring("Usage")) - }) - - It("loads all flags correctly", func() { - cmd := newMockGenerateProfileCmd("profile", - "--profile-source", "app-dev", - "--profile-revision", "branch-2", - "--profile-path", "test-output-dir/dir2", - "--cluster", "clus-1", - "--region", "us-west-2", - ) - _, err := cmd.Execute() - Expect(err).NotTo(HaveOccurred()) - - cfg := cmd.Cmd.ClusterConfig - Expect(cfg.Metadata.Name).To(Equal("clus-1")) - Expect(cfg.Metadata.Region).To(Equal("us-west-2")) - Expect(cfg.Git).NotTo(BeNil()) - - Expect(cfg.Git.BootstrapProfile).NotTo(BeNil()) - Expect(cfg.Git.BootstrapProfile.Source).To(Equal("app-dev")) - Expect(cfg.Git.BootstrapProfile.Revision).To(Equal("branch-2")) - Expect(cfg.Git.BootstrapProfile.OutputPath).To(Equal("test-output-dir/dir2")) - }) - - It("defaults the --output-path to the profile name", func() { - cmd := newMockGenerateProfileCmd("profile", - "--profile-source", "app-dev", - "--profile-revision", "branch-2", - "--cluster", "clus-1", - "--region", "us-west-2", - ) - _, err := cmd.Execute() - Expect(err).NotTo(HaveOccurred()) - - cfg := cmd.Cmd.ClusterConfig - - Expect(cfg.Git.BootstrapProfile).NotTo(BeNil()) - Expect(cfg.Git.BootstrapProfile.OutputPath).To(Equal("./app-dev")) - }) - - It("defaults the --output-path to the repo name", func() { - cmd := newMockGenerateProfileCmd("profile", - "--profile-source", "git@github.com:weaveworks/eks-quickstart-app-dev.git", - "--profile-revision", "branch-2", - "--cluster", "clus-1", - "--region", "us-west-2", - ) - _, err := cmd.Execute() - Expect(err).NotTo(HaveOccurred()) - - cfg := cmd.Cmd.ClusterConfig - - Expect(cfg.Git.BootstrapProfile).NotTo(BeNil()) - Expect(cfg.Git.BootstrapProfile.OutputPath).To(Equal("./eks-quickstart-app-dev")) - }) - - Describe("with a config file", func() { - var configFile string - var cfg *api.ClusterConfig - - BeforeEach(func() { - // Minimal cluster config for the command to work - cfg = &api.ClusterConfig{ - TypeMeta: api.ClusterConfigTypeMeta(), - Metadata: &api.ClusterMeta{ - Name: "cluster-1", - Region: "us-west-2", - }, - Git: &api.Git{ - BootstrapProfile: &api.Profile{Source: "app-dev"}, - }, - } - }) - - AfterEach(func() { - if configFile != "" { - os.Remove(configFile) - } - }) - - It("succeeds with the basic configuration", func() { - configFile = ctltest.CreateConfigFile(cfg) - - cmd := newMockGenerateProfileCmd("profile", "-f", configFile) - _, err := cmd.Execute() - Expect(err).NotTo(HaveOccurred()) - }) - - It("fails without a cluster name", func() { - cfg.Metadata.Name = "" - configFile = ctltest.CreateConfigFile(cfg) - - cmd := newMockGenerateProfileCmd("profile", "-f", configFile) - _, err := cmd.Execute() - Expect(err).To(HaveOccurred()) - Expect(err.Error()).To(Equal("metadata.name must be set")) - }) - - It("fails without a region", func() { - cfg.Metadata.Region = "" - configFile = ctltest.CreateConfigFile(cfg) - - cmd := newMockGenerateProfileCmd("profile", "-f", configFile) - _, err := cmd.Execute() - Expect(err).To(HaveOccurred()) - Expect(err.Error()).To(Equal("metadata.region must be set")) - }) - - It("fails without bootstrap profiles", func() { - cfg.Git.BootstrapProfile = nil - configFile = ctltest.CreateConfigFile(cfg) - - cmd := newMockGenerateProfileCmd("profile", "-f", configFile) - _, err := cmd.Execute() - Expect(err).To(HaveOccurred()) - Expect(err.Error()).To(Equal("git.bootstrapProfile.Source must be set")) - }) - - It("fails with empty bootstrap profile", func() { - cfg.Git.BootstrapProfile = &api.Profile{} - configFile = ctltest.CreateConfigFile(cfg) - - cmd := newMockGenerateProfileCmd("profile", "-f", configFile) - _, err := cmd.Execute() - Expect(err).To(HaveOccurred()) - Expect(err.Error()).To(Equal("git.bootstrapProfile.Source must be set")) - }) - - It("defaults the outputPath to the profile name", func() { - configFile = ctltest.CreateConfigFile(cfg) - - cmd := newMockGenerateProfileCmd("profile", "-f", configFile) - _, err := cmd.Execute() - Expect(err).NotTo(HaveOccurred()) - - cfg := cmd.Cmd.ClusterConfig - - Expect(cfg.Git.BootstrapProfile).NotTo(BeNil()) - Expect(cfg.Git.BootstrapProfile.OutputPath).To(Equal("./app-dev")) - }) - - It("defaults the outputPath to the repo name", func() { - cfg.Git.BootstrapProfile.Source = "git@github.com:some-org/some-repo.git" - configFile = ctltest.CreateConfigFile(cfg) - - cmd := newMockGenerateProfileCmd("profile", "-f", configFile) - _, err := cmd.Execute() - Expect(err).NotTo(HaveOccurred()) - - cfg := cmd.Cmd.ClusterConfig - - Expect(cfg.Git.BootstrapProfile).NotTo(BeNil()) - Expect(cfg.Git.BootstrapProfile.OutputPath).To(Equal("./some-repo")) - }) - }) - }) -}) diff --git a/pkg/git/git.go b/pkg/git/git.go deleted file mode 100644 index 33c1871a12..0000000000 --- a/pkg/git/git.go +++ /dev/null @@ -1,250 +0,0 @@ -// FLUX V1 DEPRECATION NOTICE. https://github.com/weaveworks/eksctl/issues/2963 -package git - -import ( - "fmt" - "os" - "os/exec" - "strings" - - "github.com/kris-nova/logger" - "github.com/pkg/errors" - giturls "github.com/whilp/git-urls" - - "github.com/weaveworks/eksctl/pkg/executor" - "github.com/weaveworks/eksctl/pkg/utils/file" -) - -// TmpCloner can clone git repositories in temporary directories -type TmpCloner interface { - CloneRepoInTmpDir(cloneDirPrefix string, options CloneOptions) (string, error) -} - -// Client can perform git operations on the given directory -type Client struct { - executor executor.Executor - dir string -} - -// ClientParams groups the arguments to provide to create a new Git client. -type ClientParams struct { - PrivateSSHKeyPath string -} - -// ValidatePrivateSSHKeyPath validates the path to the (optional) private SSH -// key used to interact with the Git repository configured in this object. -func ValidatePrivateSSHKeyPath(privateSSHKeyPath string) error { - if privateSSHKeyPath != "" && !file.Exists(privateSSHKeyPath) { - return fmt.Errorf("invalid path to private SSH key: %s", privateSSHKeyPath) - } - return nil -} - -// NewGitClient returns a client that can perform git operations -func NewGitClient(params ClientParams) *Client { - return &Client{ - executor: executor.NewShellExecutor(envVars(params)), - } -} - -func envVars(params ClientParams) executor.EnvVars { - envVars := executor.EnvVars{ - "PATH": os.Getenv("PATH"), - } - if sshAuthSock, ok := os.LookupEnv("SSH_AUTH_SOCK"); ok { - envVars["SSH_AUTH_SOCK"] = sshAuthSock - } - if params.PrivateSSHKeyPath != "" { - envVars["GIT_SSH_COMMAND"] = "ssh -i " + params.PrivateSSHKeyPath - } - return envVars -} - -// NewGitClientFromExecutor returns a client that can have an executor injected. Useful for testing -func NewGitClientFromExecutor(executor executor.Executor) *Client { - return &Client{ - executor: executor, - } -} - -// CloneOptions are the options for cloning a Git repository -type CloneOptions struct { - URL string - Branch string - Bootstrap bool // create the branch if the repository is empty -} - -// WithDir directly sets the Client to use a directory, without havine to clone -// it -func (git *Client) WithDir(dir string) { - git.dir = dir -} - -// CloneRepoInTmpDir clones a repo specified in the gitURL in a temporary directory and checks out the specified branch -func (git *Client) CloneRepoInTmpDir(tmpDirPrefix string, options CloneOptions) (string, error) { - cloneDir, err := os.MkdirTemp(os.TempDir(), tmpDirPrefix) - if err != nil { - return "", fmt.Errorf("cannot create temporary directory: %s", err) - } - return cloneDir, git.cloneRepoInPath(cloneDir, options) -} - -// CloneRepoInPath behaves like CloneRepoInTmpDir but clones the repository in a specific directory -// which creates if needed -func (git *Client) CloneRepoInPath(clonePath string, options CloneOptions) error { - if err := os.MkdirAll(clonePath, 0700); err != nil { - return errors.Wrapf(err, "unable to create directory for cloning") - } - return git.cloneRepoInPath(clonePath, options) -} - -func (git *Client) cloneRepoInPath(clonePath string, options CloneOptions) error { - args := []string{"clone", options.URL, clonePath} - if err := git.runGitCmd(args...); err != nil { - return err - } - // Set the working directory to the cloned directory, but - // only do it after the clone so that it doesn't create an - // undesirable nested directory - git.dir = clonePath - - if options.Branch != "" { - // Switch to target branch - args := []string{"checkout", options.Branch} - if options.Bootstrap { - if !git.isRemoteBranch(options.Branch) { - args = []string{"checkout", "-b", options.Branch} - } - } - if err := git.runGitCmd(args...); err != nil { - return err - } - } - - return nil -} - -func (git *Client) isRemoteBranch(branch string) bool { - err := git.runGitCmd("ls-remote", "--heads", "--exit-code", "origin", branch) - return err == nil -} - -// Add performs can perform a `git add` operation on the given file paths -func (git Client) Add(files ...string) error { - args := append([]string{"add", "--"}, files...) - if err := git.runGitCmd(args...); err != nil { - return err - } - return nil -} - -// Commit makes a commit if there are staged changes -func (git Client) Commit(message, user, email string) error { - // Note, this used to do runGitCmd(diffCtx, git.dir, "diff", "--cached", "--quiet", "--", fi.opts.gitFluxPath); err == nil { - if err := git.runGitCmd("diff", "--cached", "--quiet"); err == nil { - logger.Info("Nothing to commit (the repository contained identical files), moving on") - return nil - } else if _, ok := err.(*exec.ExitError); !ok { - return err - } - - // If the username and email have been provided, configure and use these as - // otherwise, git will rely on the global configuration, which may lead to - // confusion at best, as a different username/email will be used, or if - // missing (e.g.: in CI, in a blank environment), will fail with: - // *** Please tell me who you are. - // [...] - // fatal: unable to auto-detect email address (got '[...]') - // N.B.: we do it before committing, instead of after cloning, as other - // operations will not fail because of missing configuration, and as we may - // commit on a repository we haven't cloned ourselves. - if email != "" { - if err := git.runGitCmd("config", "user.email", email); err != nil { - return err - } - } - if user != "" { - if err := git.runGitCmd("config", "user.name", user); err != nil { - return err - } - } - - // Commit - args := []string{"commit", - "-m", message, - fmt.Sprintf("--author=%s <%s>", user, email), - } - if err := git.runGitCmd(args...); err != nil { - return err - } - return nil -} - -// Push pushes the changes to the origin remote -func (git Client) Push() error { - if err := git.runGitCmd("config", "push.default", "current"); err != nil { - return err - } - err := git.runGitCmd("push") - return err -} - -func (git Client) DeleteRemoteBranch(branch string) error { - return git.runGitCmd("push", "origin", "--delete", branch) -} - -// DeleteLocalRepo deletes the local copy of a repository, including the directory -func (git Client) DeleteLocalRepo() error { - if git.dir != "" { - return os.RemoveAll(git.dir) - } - return fmt.Errorf("no cloned directory to delete") -} - -func (git Client) runGitCmd(args ...string) error { - logger.Debug(fmt.Sprintf("running git %v in %s", args, git.dir)) - return git.executor.ExecInDir("git", git.dir, args...) -} - -// RepoName returns the name of the repository given its URL -func RepoName(repoURL string) (string, error) { - u, err := giturls.Parse(repoURL) - if err != nil { - return "", errors.Wrapf(err, "unable to parse git URL '%s'", repoURL) - } - parts := strings.Split(u.Path, "/") - if len(parts) == 0 { - return "", fmt.Errorf("could not find name of repository %s", repoURL) - } - - lastPathSegment := parts[len(parts)-1] - return strings.TrimRight(lastPathSegment, ".git"), nil -} - -// ValidateURL validates the provided Git URL. -func ValidateURL(url string) error { - if url == "" { - return errors.New("empty Git URL") - } - if !IsGitURL(url) { - return errors.New("invalid Git URL") - } - if !isSSHURL(url) { - return errors.New("got a HTTP(S) Git URL, but eksctl currently only supports SSH Git URLs") - } - return nil -} - -// IsGitURL returns true if the argument matches the git url format -func IsGitURL(rawURL string) bool { - parsedURL, err := giturls.Parse(rawURL) - if err == nil && parsedURL.IsAbs() && parsedURL.Hostname() != "" { - return true - } - return false -} - -func isSSHURL(rawURL string) bool { - url, err := giturls.Parse(rawURL) - return err == nil && (url.Scheme == "git" || url.Scheme == "ssh") -} diff --git a/pkg/git/git_suite_test.go b/pkg/git/git_suite_test.go deleted file mode 100644 index 8058db8131..0000000000 --- a/pkg/git/git_suite_test.go +++ /dev/null @@ -1,12 +0,0 @@ -// FLUX V1 DEPRECATION NOTICE. https://github.com/weaveworks/eksctl/issues/2963 -package git_test - -import ( - "testing" - - "github.com/weaveworks/eksctl/pkg/testutils" -) - -func TestGit(t *testing.T) { - testutils.RegisterAndRun(t) -} diff --git a/pkg/git/git_test.go b/pkg/git/git_test.go deleted file mode 100644 index 09ed54f73f..0000000000 --- a/pkg/git/git_test.go +++ /dev/null @@ -1,199 +0,0 @@ -// FLUX V1 DEPRECATION NOTICE. https://github.com/weaveworks/eksctl/issues/2963 -package git_test - -import ( - "os" - "os/exec" - "strings" - - . "github.com/onsi/ginkgo" - . "github.com/onsi/gomega" - "github.com/weaveworks/eksctl/pkg/executor/fakes" - "github.com/weaveworks/eksctl/pkg/git" -) - -var _ = Describe("git", func() { - Describe("Client", func() { - var ( - fakeExecutor *fakes.FakeExecutor - gitClient *git.Client - tempCloneDir string - ) - - BeforeEach(func() { - fakeExecutor = new(fakes.FakeExecutor) - gitClient = git.NewGitClientFromExecutor(fakeExecutor) - }) - - AfterEach(func() { - deleteTempDir(tempCloneDir) - }) - - It("it can create a directory, clone the repo and delete it afterwards", func() { - deleteTempDir(tempCloneDir) - - var err error - options := git.CloneOptions{ - Branch: "my-branch", - URL: "git@example.com:test/example-repo.git", - } - tempCloneDir, err = gitClient.CloneRepoInTmpDir("test-git-", options) - - // It called clone and checkout on the branch - Expect(err).To(Not(HaveOccurred())) - Expect(fakeExecutor.ExecInDirCallCount()).To(Equal(2)) - - _, _, receivedArgs := fakeExecutor.ExecInDirArgsForCall(0) - Expect(receivedArgs).To(Equal([]string{"clone", "git@example.com:test/example-repo.git", tempCloneDir})) - - _, receivedDir, receivedArgs := fakeExecutor.ExecInDirArgsForCall(1) - Expect(receivedArgs).To(Equal([]string{"checkout", "my-branch"})) - Expect(receivedDir).To(Equal(tempCloneDir)) - - // The directory was created - _, err = os.Stat(tempCloneDir) - Expect(err).NotTo(HaveOccurred()) - - // It can delete it - err = gitClient.DeleteLocalRepo() - - Expect(err).NotTo(HaveOccurred()) - _, err = os.Stat(tempCloneDir) - Expect(err).To(HaveOccurred()) - Expect(os.IsNotExist(err)).To(BeTrue()) - }) - - It("can add files", func() { - err := gitClient.Add("file1", "file2") - Expect(err).To(Not(HaveOccurred())) - - _, _, receivedArgs := fakeExecutor.ExecInDirArgsForCall(0) - Expect(receivedArgs).To(Equal([]string{"add", "--", "file1", "file2"})) - }) - - It("can make commits", func() { - fakeExecutor.ExecInDirCalls(func(arg1, arg2 string, array ...string) error { - if array[0] == "diff" { - return &exec.ExitError{} - } - return nil - }) - - err := gitClient.Commit("test commit", "test-user", "test-user@example.com") - Expect(err).To(Not(HaveOccurred())) - - receivedCommand, _, receivedArgs := fakeExecutor.ExecInDirArgsForCall(0) - Expect(receivedCommand).To(Equal("git")) - Expect(receivedArgs).To(Equal([]string{"diff", "--cached", "--quiet"})) - - receivedCommand, _, receivedArgs = fakeExecutor.ExecInDirArgsForCall(1) - Expect(receivedCommand).To(Equal("git")) - Expect(receivedArgs).To(Equal([]string{"config", "user.email", "test-user@example.com"})) - - receivedCommand, _, receivedArgs = fakeExecutor.ExecInDirArgsForCall(2) - Expect(receivedCommand).To(Equal("git")) - Expect(receivedArgs).To(Equal([]string{"config", "user.name", "test-user"})) - - receivedCommand, _, receivedArgs = fakeExecutor.ExecInDirArgsForCall(3) - Expect(receivedCommand).To(Equal("git")) - Expect(receivedArgs).To(Equal([]string{"commit", "-m", "test commit", "--author=test-user "})) - }) - - It("can push", func() { - err := gitClient.Push() - Expect(err).To(Not(HaveOccurred())) - - _, _, receivedArgs := fakeExecutor.ExecInDirArgsForCall(0) - Expect(receivedArgs).To(Equal([]string{"config", "push.default", "current"})) - - _, _, receivedArgs = fakeExecutor.ExecInDirArgsForCall(1) - Expect(receivedArgs).To(Equal([]string{"push"})) - }) - }) - - Describe("RepoName", func() { - It("can parse the repository name from a URL", func() { - name, err := git.RepoName("git@github.com:weaveworks/eksctl.git") - Expect(err).NotTo(HaveOccurred()) - Expect(name).To(Equal("eksctl")) - - name, err = git.RepoName("git@github.com:weaveworks/sock-shop.git") - Expect(err).NotTo(HaveOccurred()) - Expect(name).To(Equal("sock-shop")) - - name, err = git.RepoName("https://example.com/department1/team1/some-repo-name.git") - Expect(err).NotTo(HaveOccurred()) - Expect(name).To(Equal("some-repo-name")) - - name, err = git.RepoName("https://github.com/department1/team2/another-repo-name") - Expect(err).NotTo(HaveOccurred()) - Expect(name).To(Equal("another-repo-name")) - }) - }) - - Describe("IsGitURL", func() { - It("can determine if a string is a git URL", func() { - Expect(git.IsGitURL("git@github.com:weaveworks/eksctl.git")).To(BeTrue()) - Expect(git.IsGitURL("https://github.com/weaveworks/eksctl.git")).To(BeTrue()) - Expect(git.IsGitURL("https://username@secr3t:my-repo.example.com:8080/weaveworks/eksctl.git")).To(BeTrue()) - - Expect(git.IsGitURL("git@github")).To(BeFalse()) - Expect(git.IsGitURL("https://")).To(BeFalse()) - Expect(git.IsGitURL("app-dev")).To(BeFalse()) - }) - }) - - Describe("ValidateURL", func() { - It("returns an error on empty Git URL", func() { - Expect(git.ValidateURL("")).To(MatchError("empty Git URL")) - }) - - It("returns an error on invalid Git URL", func() { - Expect(git.ValidateURL("https://")).To(MatchError("invalid Git URL")) - }) - - It("returns an error on HTTPS Git URL", func() { - Expect(git.ValidateURL("https://github.com/eksctl-bot/my-gitops-repo.git")). - To(MatchError("got a HTTP(S) Git URL, but eksctl currently only supports SSH Git URLs")) - }) - - It("succeeds when a SSH Git URL is provided", func() { - Expect(git.ValidateURL("git@github.com:eksctl-bot/my-gitops-repo.git")).NotTo(HaveOccurred()) - }) - }) - - Describe("Validate", func() { - It("returns an error on invalid Git URL", func() { - Expect(git.ValidateURL("https://")).To(MatchError("invalid Git URL")) - }) - - It("returns an error on HTTPS Git URL", func() { - Expect(git.ValidateURL("https://github.com/eksctl-bot/my-gitops-repo.git")). - To(MatchError("got a HTTP(S) Git URL, but eksctl currently only supports SSH Git URLs")) - }) - - It("succeeds when a SSH Git URL and an email address is provided", func() { - Expect(git.ValidateURL("git@github.com:eksctl-bot/my-gitops-repo.git")).NotTo(HaveOccurred()) - }) - - It("returns an error on non-existing file path", func() { - Expect(git.ValidatePrivateSSHKeyPath("/path/to/non/existing/file/id_rsa")). - To(MatchError("invalid path to private SSH key: /path/to/non/existing/file/id_rsa")) - }) - - It("succeeds when a valid path is provided", func() { - privateSSHKey, err := os.CreateTemp("", "fake_id_rsa") - Expect(err).To(Not(HaveOccurred())) - defer os.Remove(privateSSHKey.Name()) // clean up - - Expect(git.ValidatePrivateSSHKeyPath(privateSSHKey.Name())). - To(Not(HaveOccurred())) - }) - }) -}) - -func deleteTempDir(tempDir string) { - if tempDir != "" && strings.HasPrefix(tempDir, os.TempDir()) { - _ = os.RemoveAll(tempDir) - } -} diff --git a/pkg/gitops/deploykey/deploykey.go b/pkg/gitops/deploykey/deploykey.go deleted file mode 100644 index d072e1001e..0000000000 --- a/pkg/gitops/deploykey/deploykey.go +++ /dev/null @@ -1,50 +0,0 @@ -// FLUX V1 DEPRECATION NOTICE. https://github.com/weaveworks/eksctl/issues/2963 -package deploykey - -import ( - "context" - "os" - "strings" - - "github.com/fluxcd/go-git-providers/github" - "github.com/fluxcd/go-git-providers/gitprovider" - "github.com/pkg/errors" - giturls "github.com/whilp/git-urls" -) - -const githubTokenVariable = "GITHUB_TOKEN" - -// GetDeployKeyClient provides a DeployKeyClient for the repo at the given URL -func GetDeployKeyClient(ctx context.Context, url string) (gitprovider.DeployKeyClient, error) { - repo, err := giturls.Parse(url) - if err != nil { - return nil, err - } - if !strings.Contains(repo.Host, github.DefaultDomain) { - return nil, errors.New("only GitHub URLs are currently supported") - } - githubToken := os.Getenv(githubTokenVariable) - if githubToken == "" { - return nil, errors.Errorf("%s not set", githubTokenVariable) - } - gh, err := github.NewClient(github.WithOAuth2Token(githubToken)) - if err != nil { - return nil, err - } - ownerRepo := strings.Split(repo.Path, "/") - if len(ownerRepo) != 2 { - return nil, errors.New("couldn't understand path of URL") - } - repoName := strings.TrimSuffix(ownerRepo[1], ".git") - rep, err := gh.UserRepositories().Get(ctx, gitprovider.UserRepositoryRef{ - UserRef: gitprovider.UserRef{ - Domain: github.DefaultDomain, - UserLogin: ownerRepo[0], - }, - RepositoryName: repoName, - }) - if err != nil { - return nil, err - } - return rep.DeployKeys(), nil -} diff --git a/pkg/gitops/fileprocessor/fileprocessor.go b/pkg/gitops/fileprocessor/fileprocessor.go deleted file mode 100644 index fba19089c2..0000000000 --- a/pkg/gitops/fileprocessor/fileprocessor.go +++ /dev/null @@ -1,13 +0,0 @@ -// FLUX V1 DEPRECATION NOTICE. https://github.com/weaveworks/eksctl/issues/2963 -package fileprocessor - -// File represents the contents and the path to a file -type File struct { - Path string - Data []byte -} - -// FileProcessor can process a template file and produce an output file -type FileProcessor interface { - ProcessFile(file File) (File, error) -} diff --git a/pkg/gitops/fileprocessor/gotemplates.go b/pkg/gitops/fileprocessor/gotemplates.go deleted file mode 100644 index c4f35c279e..0000000000 --- a/pkg/gitops/fileprocessor/gotemplates.go +++ /dev/null @@ -1,65 +0,0 @@ -// FLUX V1 DEPRECATION NOTICE. https://github.com/weaveworks/eksctl/issues/2963 -package fileprocessor - -import ( - "bytes" - "strings" - "text/template" - - "github.com/kris-nova/logger" - "github.com/pkg/errors" - - api "github.com/weaveworks/eksctl/pkg/apis/eksctl.io/v1alpha5" -) - -const ( - templateExtension = ".tmpl" -) - -// TemplateParameters represents the API variables that can be used to template a profile. This set of variables will -// be applied to the go template files found. Templates filenames must end in .templ -type TemplateParameters struct { - ClusterName string - Region string -} - -// NewTemplateParameters creates a set of variables for templating given a ClusterConfig object -func NewTemplateParameters(clusterConfig *api.ClusterConfig) TemplateParameters { - return TemplateParameters{ - ClusterName: clusterConfig.Metadata.Name, - Region: clusterConfig.Metadata.Region, - } -} - -// GoTemplateProcessor is a FileProcessor that executes Go Templates -type GoTemplateProcessor struct { - Params TemplateParameters -} - -// ProcessFile takes a template file and executes the template applying the TemplateParameters -func (p *GoTemplateProcessor) ProcessFile(file File) (File, error) { - if !isGoTemplate(file.Path) { - logger.Debug("leaving non-template file unmodified %q", file.Path) - return file, nil - } - - parsedTemplate, err := template.New(file.Path).Parse(string(file.Data)) - if err != nil { - return File{}, errors.Wrapf(err, "cannot parse manifest template file %q", file.Path) - } - - out := bytes.NewBuffer(nil) - if err = parsedTemplate.Execute(out, p.Params); err != nil { - return File{}, errors.Wrapf(err, "cannot execute template for file %q", file.Path) - } - - newFileName := strings.TrimSuffix(file.Path, templateExtension) - return File{ - Data: out.Bytes(), - Path: newFileName, - }, nil -} - -func isGoTemplate(fileName string) bool { - return strings.HasSuffix(fileName, templateExtension) -} diff --git a/pkg/gitops/gitops.go b/pkg/gitops/gitops.go index 89f630c0da..d84dbf94c2 100644 --- a/pkg/gitops/gitops.go +++ b/pkg/gitops/gitops.go @@ -1,21 +1,15 @@ package gitops import ( - "context" "time" "github.com/kris-nova/logger" "github.com/pkg/errors" - "github.com/spf13/afero" kubeclient "k8s.io/client-go/kubernetes" "k8s.io/client-go/rest" "github.com/weaveworks/eksctl/pkg/actions/flux" - "github.com/weaveworks/eksctl/pkg/actions/repo" api "github.com/weaveworks/eksctl/pkg/apis/eksctl.io/v1alpha5" - "github.com/weaveworks/eksctl/pkg/git" - "github.com/weaveworks/eksctl/pkg/gitops/deploykey" - "github.com/weaveworks/eksctl/pkg/gitops/fileprocessor" ) // DefaultPodReadyTimeout is the time it will wait for Flux and Helm Operator to become ready @@ -27,7 +21,8 @@ type FluxInstaller interface { // Setup sets up gitops in a repository for a cluster. func Setup(kubeconfigPath string, k8sRestConfig *rest.Config, k8sClientSet kubeclient.Interface, cfg *api.ClusterConfig, timeout time.Duration) error { - installer, profilesSupported, err := newFluxInstaller(kubeconfigPath, k8sRestConfig, k8sClientSet, cfg, timeout) + installer, err := flux.New(k8sClientSet, cfg.GitOps) + logger.Info("gitops configuration detected, setting installer to Flux v2") if err != nil { return errors.Wrapf(err, "could not initialise Flux installer") } @@ -36,94 +31,5 @@ func Setup(kubeconfigPath string, k8sRestConfig *rest.Config, k8sClientSet kubec return err } - if profilesSupported { - return InstallProfile(cfg) - } - - return nil -} - -// InstallProfile installs the bootstrap profile in the user's repo if it's specified in the cluster config -func InstallProfile(cfg *api.ClusterConfig) error { - if !cfg.HasBootstrapProfile() { - logger.Debug("no bootstrap profiles configure. Skipping...") - return nil - } - - gitCfg := cfg.Git - - gitClient := git.NewGitClient(git.ClientParams{ - PrivateSSHKeyPath: gitCfg.Repo.PrivateSSHKeyPath, - }) - - profileGen := &Profile{ - Processor: &fileprocessor.GoTemplateProcessor{ - Params: fileprocessor.NewTemplateParameters(cfg), - }, - UserRepoGitClient: gitClient, - ProfileCloner: git.NewGitClient(git.ClientParams{ - PrivateSSHKeyPath: gitCfg.Repo.PrivateSSHKeyPath, - }), - FS: afero.NewOsFs(), - IO: afero.Afero{Fs: afero.NewOsFs()}, - } - - if err := profileGen.Install(cfg); err != nil { - return errors.Wrapf(err, "unable to install bootstrap profile") - } - - return nil -} - -// FLUX V1 DEPRECATION NOTICE. https://github.com/weaveworks/eksctl/issues/2963 -// DeleteKey deletes the authorized SSH key for the gitops repo if gitops are configured -// Will not fail if the key was not previously authorized -func DeleteKey(cfg *api.ClusterConfig) error { - if !cfg.HasGitopsRepoConfigured() { - return nil - } - - ctx := context.Background() - deployKeyClient, err := deploykey.GetDeployKeyClient(ctx, cfg.Git.Repo.URL) - if err != nil { - logger.Warning( - "could not find git provider implementation for url %q: %q. Skipping deletion of authorized SSH key", - cfg.Git.Repo.URL, - err.Error(), - ) - return nil - } - - clusterKeyTitle := repo.KeyTitle(*cfg.Metadata) - logger.Info("deleting SSH key %q from repo %q", clusterKeyTitle, cfg.Git.Repo.URL) - - key, err := deployKeyClient.Get(ctx, clusterKeyTitle) - if err != nil { - return errors.Wrapf(err, "unable to find SSH key") - } - if err := key.Delete(ctx); err != nil { - return errors.Wrapf(err, "unable to delete authorized key") - } return nil } - -func newFluxInstaller(kubeconfigPath string, k8sRestConfig *rest.Config, k8sClientSet kubeclient.Interface, cfg *api.ClusterConfig, timeout time.Duration) (FluxInstaller, bool, error) { - var ( - installer FluxInstaller - profilesSupported bool - err error - ) - - if cfg.GitOps != nil && cfg.GitOps.Flux != nil { - installer, err = flux.New(k8sClientSet, cfg.GitOps) - profilesSupported = false - logger.Info("gitops configuration detected, setting installer to Flux v2") - } else { - // FLUX V1 DEPRECATION NOTICE. https://github.com/weaveworks/eksctl/issues/2963 - installer, err = repo.New(k8sRestConfig, k8sClientSet, cfg, timeout) - profilesSupported = true - logger.Info("git.repo configuration detected, setting installer to Flux v1") - } - - return installer, profilesSupported, err -} diff --git a/pkg/gitops/gitops_suite_test.go b/pkg/gitops/gitops_suite_test.go deleted file mode 100644 index 617789876a..0000000000 --- a/pkg/gitops/gitops_suite_test.go +++ /dev/null @@ -1,15 +0,0 @@ -package gitops - -import ( - "testing" - - . "github.com/onsi/ginkgo" - . "github.com/onsi/gomega" - - "github.com/weaveworks/eksctl/pkg/testutils" -) - -func TestGitops(t *testing.T) { - RegisterFailHandler(Fail) - testutils.RegisterAndRun(t) -} diff --git a/pkg/gitops/profile.go b/pkg/gitops/profile.go deleted file mode 100644 index de8aad840d..0000000000 --- a/pkg/gitops/profile.go +++ /dev/null @@ -1,272 +0,0 @@ -package gitops - -import ( - "bufio" - "fmt" - "io" - "os" - "path" - "path/filepath" - "regexp" - "strings" - - "github.com/kris-nova/logger" - "github.com/pkg/errors" - "github.com/spf13/afero" - - api "github.com/weaveworks/eksctl/pkg/apis/eksctl.io/v1alpha5" - "github.com/weaveworks/eksctl/pkg/git" - "github.com/weaveworks/eksctl/pkg/gitops/fileprocessor" -) - -const ( - cloneDirPrefix = "quickstart-" - - eksctlIgnoreFilename = ".eksctlignore" -) - -// Profile represents a gitops profile -type Profile struct { - Processor fileprocessor.FileProcessor - ProfileCloner git.TmpCloner - UserRepoGitClient *git.Client - FS afero.Fs - IO afero.Afero -} - -// Install installs the profile specified in the cluster config into a user's repository -func (p *Profile) Install(clusterConfig *api.ClusterConfig) error { - if !clusterConfig.HasBootstrapProfile() { - return nil - } - - userRepo := clusterConfig.Git.Repo - - // Clone user's repo to apply Quick Start profile - gitCfg := clusterConfig.Git - bootstrapProfile := clusterConfig.Git.BootstrapProfile - - // Clone user's repo to apply Quick Start profile - usersRepoName, err := git.RepoName(gitCfg.Repo.URL) - if err != nil { - return err - } - usersRepoDir, err := os.MkdirTemp("", usersRepoName+"-") - if err != nil { - return errors.Wrapf(err, "unable to create temporary directory for %q", usersRepoName) - } - bootstrapProfile.OutputPath = filepath.Join(usersRepoDir, "base") - logger.Debug("directory %s will be used to clone the configuration repository and install the profile", usersRepoDir) - - err = p.UserRepoGitClient.CloneRepoInPath( - usersRepoDir, - git.CloneOptions{ - URL: gitCfg.Repo.URL, - Branch: gitCfg.Repo.Branch, - Bootstrap: true, - }, - ) - if err != nil { - return err - } - - // Add quickstart components to user's repo. Clones the quickstart base repo - err = p.Generate(*bootstrapProfile) - if err != nil { - return errors.Wrap(err, "error generating profile") - } - - // Git add, commit and push component files - if err = p.UserRepoGitClient.Add("."); err != nil { - return err - } - - commitMsg := fmt.Sprintf("Add %s quickstart components", bootstrapProfile.Source) - if err = p.UserRepoGitClient.Commit(commitMsg, userRepo.User, userRepo.Email); err != nil { - return err - } - - if err = p.UserRepoGitClient.Push(); err != nil { - return err - } - - logger.Debug("deleting cloned directory %q", usersRepoDir) - if err := p.IO.RemoveAll(usersRepoDir); err != nil { - logger.Warning("unable to delete cloned directory %q", usersRepoDir) - } - return nil -} - -// Generate clones the specified Git repo in a base directory and generates overlays if the Git repo -// points to a profile repo -func (p *Profile) Generate(profile api.Profile) error { - // Translate the profile name to a URL - var err error - profile.Source, err = RepositoryURL(profile.Source) - if err != nil { - return errors.Wrap(err, "please supply a valid Quick Start name or URL") - } - - logger.Info("cloning repository %q:%s", profile.Source, profile.Revision) - options := git.CloneOptions{ - URL: profile.Source, - Branch: profile.Revision, - } - clonedDir, err := p.ProfileCloner.CloneRepoInTmpDir(cloneDirPrefix, options) - if err != nil { - return errors.Wrapf(err, "error cloning repository %s", profile.Source) - } - - if err := p.ignoreFiles(clonedDir); err != nil { - return errors.Wrapf(err, "error ignoring files of repository %s", profile.Source) - } - - allManifests, err := p.loadFiles(clonedDir) - if err != nil { - return errors.Wrapf(err, "error loading files from repository %s", profile.Source) - } - - logger.Info("processing template files in repository") - outputFiles, err := p.processFiles(allManifests, clonedDir) - if err != nil { - return errors.Wrapf(err, "error processing manifests from repository %s", profile.Source) - } - - if len(outputFiles) > 0 { - logger.Info("writing new manifests to %q", profile.OutputPath) - } else { - logger.Info("no template files found, nothing to write") - return nil - } - - err = p.writeFiles(outputFiles, profile.OutputPath) - if err != nil { - return errors.Wrapf(err, "error writing manifests to dir: %q", profile.OutputPath) - } - - // Delete temporary clone of the quickstart repo - if clonedDir == "" { - logger.Debug("no cloned directory to delete") - return nil - } - logger.Debug("deleting cloned directory %q", clonedDir) - if err := p.IO.RemoveAll(clonedDir); err != nil { - logger.Warning("unable to delete cloned directory %q", clonedDir) - } - - return nil -} - -func (p *Profile) loadFiles(directory string) ([]fileprocessor.File, error) { - files := make([]fileprocessor.File, 0) - err := p.IO.Walk(directory, func(path string, info os.FileInfo, err error) error { - if err != nil { - return errors.Wrapf(err, "cannot walk files in directory: %q", directory) - } - if info.IsDir() || isGitFile(directory, path) { - return nil - } - - logger.Debug("found file %q", path) - fileContents, err := p.IO.ReadFile(path) - if err != nil { - return errors.Wrapf(err, "cannot read file %q", path) - } - files = append(files, fileprocessor.File{ - Path: path, - Data: fileContents, - }) - return nil - }) - if err != nil { - return nil, errors.Wrapf(err, "unable to load files from directory %q", directory) - } - return files, nil -} - -func (p *Profile) ignoreFiles(baseDir string) error { - ignoreFilePath := path.Join(baseDir, eksctlIgnoreFilename) - if exists, _ := p.IO.Exists(ignoreFilePath); exists { - logger.Info("ignoring files declared in %s", eksctlIgnoreFilename) - file, err := p.IO.Open(ignoreFilePath) - if err != nil { - return err - } - pathsToIgnores, err := parseDotIgnorefile(file) - // Need to close the ignore file here as it is also deleted - file.Close() - if err != nil { - return err - } - - for _, pathToIgnore := range pathsToIgnores { - err := p.IO.RemoveAll(path.Join(baseDir, pathToIgnore)) - if err != nil { - return err - } - logger.Info("ignored %q", pathToIgnore) - } - - // Remove the ignore file after finish - if err := p.IO.Remove(ignoreFilePath); err != nil { - return err - } - } - return nil -} - -func (p *Profile) processFiles(files []fileprocessor.File, baseDir string) ([]fileprocessor.File, error) { - outputFiles := make([]fileprocessor.File, 0, len(files)) - for _, file := range files { - outputFile, err := p.Processor.ProcessFile(file) - if err != nil { - return nil, errors.Wrapf(err, "error processing file %q ", file.Path) - } - - // Rewrite the path to a relative path from the root of the repo - relPath, err := filepath.Rel(baseDir, outputFile.Path) - if err != nil { - return nil, errors.Wrapf(err, "cannot get relative path for file %q", file.Path) - } - outputFile.Path = relPath - outputFiles = append(outputFiles, outputFile) - } - return outputFiles, nil -} - -func (p *Profile) writeFiles(manifests []fileprocessor.File, outputPath string) error { - for _, manifest := range manifests { - filePath := filepath.Join(outputPath, manifest.Path) - fileBase := filepath.Dir(filePath) - - if err := p.FS.MkdirAll(fileBase, 0755); err != nil { - return errors.Wrapf(err, "error creating output manifests dir: %q", outputPath) - } - - logger.Debug("writing file %q", filePath) - err := p.IO.WriteFile(filePath, manifest.Data, 0644) - if err != nil { - return errors.Wrapf(err, "error writing manifest: %q", filePath) - } - } - return nil -} - -func isGitFile(baseDir string, path string) bool { - return strings.HasPrefix(path, filepath.Join(baseDir, ".git")) -} - -func parseDotIgnorefile(reader io.Reader) ([]string, error) { - result := []string{} - scanner := bufio.NewScanner(reader) - re := regexp.MustCompile(`(?ms)^\s*(?P[^\s#]+).*$`) - for scanner.Scan() { - groups := re.FindStringSubmatch(scanner.Text()) - if len(groups) != 2 { - continue - } - pathToIgnore := groups[1] - result = append(result, pathToIgnore) - } - return result, nil -} diff --git a/pkg/gitops/profile_test.go b/pkg/gitops/profile_test.go deleted file mode 100644 index 2f98300c77..0000000000 --- a/pkg/gitops/profile_test.go +++ /dev/null @@ -1,201 +0,0 @@ -package gitops - -import ( - "path/filepath" - - . "github.com/onsi/ginkgo" - . "github.com/onsi/gomega" - "github.com/spf13/afero" - "github.com/stretchr/testify/mock" - - api "github.com/weaveworks/eksctl/pkg/apis/eksctl.io/v1alpha5" - "github.com/weaveworks/eksctl/pkg/git" - "github.com/weaveworks/eksctl/pkg/gitops/fileprocessor" -) - -type mockCloner struct { - mock.Mock -} - -func (m *mockCloner) CloneRepoInTmpDir(cloneDirPrefix string, options git.CloneOptions) (string, error) { - args := m.Called(cloneDirPrefix, options) - return args.String(0), args.Error(1) -} - -var _ = Describe("gitops profile", func() { - - var ( - gitCloner *mockCloner - memFs afero.Fs - io afero.Afero - testDir string - profile *Profile - outputDir string - processor fileprocessor.FileProcessor - ) - - Context("generating a profile", func() { - - BeforeEach(func() { - // In memory filesystem for the tests - memFs = afero.NewMemMapFs() - io = afero.Afero{Fs: memFs} - - // Create test data files instead of cloning - testDir, _ = io.TempDir("", "test-dir-") - createTestFiles(testDir, memFs) - - // mock git clone - gitCloner = new(mockCloner) - gitCloner.On("CloneRepoInTmpDir", mock.Anything, mock.Anything, mock.Anything).Return(testDir, nil) - - // output path - outputDir, _ = io.TempDir("", "test-output-dir-") - - processor = &fileprocessor.GoTemplateProcessor{ - Params: fileprocessor.TemplateParameters{ClusterName: "test-cluster"}, - } - profile = &Profile{ - IO: io, - FS: memFs, - ProfileCloner: gitCloner, - Processor: processor, - } - }) - - AfterEach(func() { - _ = io.RemoveAll(testDir) - _ = io.RemoveAll(outputDir) - }) - - It("processes go templates and writes them to the output directory", func() { - err := profile.Generate(api.Profile{ - Source: "git@github.com:someorg/test-gitops-repo.git", - Revision: "master", - OutputPath: outputDir}) - - Expect(err).NotTo(HaveOccurred()) - template1, err := io.ReadFile(filepath.Join(outputDir, "a/good-template1.yaml")) - Expect(err).NotTo(HaveOccurred()) - Expect(template1).To(MatchYAML([]byte("cluster: test-cluster"))) - - template2, err := io.ReadFile(filepath.Join(outputDir, "a/b/good-template2.yaml")) - Expect(err).NotTo(HaveOccurred()) - Expect(template2).To(MatchYAML([]byte("name: test-cluster"))) - }) - - It("can load files and ignore .git/ files", func() { - err := profile.ignoreFiles(testDir) - Expect(err).NotTo(HaveOccurred()) - - files, err := profile.loadFiles(testDir) - - Expect(err).NotTo(HaveOccurred()) - Expect(files).To(HaveLen(4)) - Expect(files).To(ConsistOf( - fileprocessor.File{ - Path: filepath.Join(testDir, "a/good-template1.yaml.tmpl"), - Data: []byte("cluster: {{ .ClusterName }}"), - }, - fileprocessor.File{ - Path: filepath.Join(testDir, "a/b/good-template2.yaml.tmpl"), - Data: []byte("name: {{ .ClusterName }}"), - }, - fileprocessor.File{ - Path: filepath.Join(testDir, "a/not-a-template2.yaml"), - Data: []byte("somekey2: value2"), - }, - fileprocessor.File{ - Path: filepath.Join(testDir, "not-a-template.yaml"), - Data: []byte("somekey: value"), - })) - }) - - Context("processing templates", func() { - - It("processes go templates and leaves the rest intact", func() { - templateContent := []byte(` -apiVersion: v1 -kind: Namespace -metadata: - labels: - name: {{ .ClusterName }} - name: flux`) - expectedProcessedTemplate := []byte(` -apiVersion: v1 -kind: Namespace -metadata: - labels: - name: test-cluster - name: flux`) - pureYaml := []byte("this: is just yaml") - inputFiles := []fileprocessor.File{ - { - Data: templateContent, - Path: "dir0/some-file.yaml.tmpl", - }, - { - Data: templateContent, - Path: "dir0/dir1/some-file2.yaml.tmpl", - }, - { - Data: pureYaml, - Path: "dir0/dir1/non-template.yaml", - }, - { - Data: templateContent, - Path: "dir0/dir1/dir2/some-file3.yaml.tmpl", - }, - } - - files, err := profile.processFiles(inputFiles, "dir0") - - Expect(err).NotTo(HaveOccurred()) - Expect(files).To(HaveLen(4)) - Expect(files).To(ConsistOf( - fileprocessor.File{ - Path: "some-file.yaml", - Data: expectedProcessedTemplate, - }, - fileprocessor.File{ - Path: "dir1/some-file2.yaml", - Data: expectedProcessedTemplate, - }, - fileprocessor.File{ - Path: "dir1/non-template.yaml", - Data: pureYaml, - }, - fileprocessor.File{ - Path: "dir1/dir2/some-file3.yaml", - Data: expectedProcessedTemplate, - }, - )) - }) - }) - }) -}) - -func createTestFiles(testDir string, memFs afero.Fs) { - _ = createFile(memFs, filepath.Join(testDir, "not-a-template.yaml"), "somekey: value") - _ = createFile(memFs, filepath.Join(testDir, "a/not-a-template2.yaml"), "somekey2: value2") - _ = createFile(memFs, filepath.Join(testDir, "a/good-template1.yaml.tmpl"), "cluster: {{ .ClusterName }}") - _ = createFile(memFs, filepath.Join(testDir, "a/b/good-template2.yaml.tmpl"), "name: {{ .ClusterName }}") - _ = memFs.Mkdir(".git", 0755) - _ = createFile(memFs, filepath.Join(testDir, ".git/some-git-file"), "this is a git file and should be ignored") - _ = createFile(memFs, filepath.Join(testDir, ".git/some-git-file.yaml"), "this is a git file and should be ignored") - _ = createFile(memFs, filepath.Join(testDir, ".git/some-git-file.yaml.tmpl"), "this is a git file and should be ignored") - - _ = createFile(memFs, filepath.Join(testDir, ".eksctlignore"), "path/to/ignore") - _ = createFile(memFs, filepath.Join(testDir, "path/to/ignore"), "this file should be ignored") -} - -func createFile(memFs afero.Fs, path string, content string) error { - file, err := memFs.Create(path) - if err != nil { - return err - } - if _, err := file.WriteString(content); err != nil { - return err - } - return nil -} diff --git a/pkg/gitops/url.go b/pkg/gitops/url.go deleted file mode 100644 index e8387998bd..0000000000 --- a/pkg/gitops/url.go +++ /dev/null @@ -1,23 +0,0 @@ -package gitops - -import ( - "fmt" - - "github.com/weaveworks/eksctl/pkg/git" -) - -// RepositoryURL returns the full Git repository URL corresponding to the -// provided "quickstart profile" mnemonic a.k.a. short name. If a valid Git URL -// is provided, this function returns it as-is. -func RepositoryURL(quickstartArgument string) (string, error) { - if git.IsGitURL(quickstartArgument) { - return quickstartArgument, nil - } - if quickstartArgument == "app-dev" { - return "https://github.com/weaveworks/eks-quickstart-app-dev", nil - } - if quickstartArgument == "appmesh" { - return "https://github.com/weaveworks/eks-appmesh-profile", nil - } - return "", fmt.Errorf("invalid URL or unknown Quick Start profile: %s", quickstartArgument) -} diff --git a/pkg/gitops/url_test.go b/pkg/gitops/url_test.go deleted file mode 100644 index 187752f4fc..0000000000 --- a/pkg/gitops/url_test.go +++ /dev/null @@ -1,40 +0,0 @@ -package gitops_test - -import ( - . "github.com/onsi/ginkgo" - . "github.com/onsi/gomega" - - "github.com/weaveworks/eksctl/pkg/gitops" -) - -var _ = Describe("profile", func() { - Describe("RepositoryURL", func() { - It("returns Git URLs as-is", func() { - url, err := gitops.RepositoryURL("https://github.com/eksctl-bot/my-gitops-repo") - Expect(err).To(Not(HaveOccurred())) - Expect(url).To(Equal("https://github.com/eksctl-bot/my-gitops-repo")) - }) - - It("returns full Git URLs for supported mnemonics", func() { - mnemonicToURLs := []struct { - mnemonic string - url string - }{ - {mnemonic: "app-dev", url: "https://github.com/weaveworks/eks-quickstart-app-dev"}, - {mnemonic: "appmesh", url: "https://github.com/weaveworks/eks-appmesh-profile"}, - } - for _, mnemonicToURL := range mnemonicToURLs { - url, err := gitops.RepositoryURL(mnemonicToURL.mnemonic) - Expect(err).To(Not(HaveOccurred())) - Expect(url).To(Equal(mnemonicToURL.url)) - } - }) - - It("returns an error otherwise", func() { - url, err := gitops.RepositoryURL("foo") - Expect(err).To(HaveOccurred()) - Expect(err.Error()).To(Equal("invalid URL or unknown Quick Start profile: foo")) - Expect(url).To(Equal("")) - }) - }) -}) diff --git a/userdocs/mkdocs.yml b/userdocs/mkdocs.yml index 762c8a0c11..7da2233066 100644 --- a/userdocs/mkdocs.yml +++ b/userdocs/mkdocs.yml @@ -41,7 +41,6 @@ nav: - usage/windows-worker-nodes.md - GitOps: - usage/gitops-v2.md - - usage/gitops-v1.md - Security: - usage/security.md - usage/kms-encryption.md diff --git a/userdocs/src/community.md b/userdocs/src/community.md index 9e27d6a5e7..98011cb379 100644 --- a/userdocs/src/community.md +++ b/userdocs/src/community.md @@ -66,6 +66,4 @@ GitOps will change to keep up with current standards. The first stage of this is implementing support for [Flux v2](https://fluxcd.io/). This support already exists in an experimental form in `eksctl` (`eksctl enable flux`) and work there will carry on throughout the year. -The next stage is to deprecate support for Flux v1, and expand the capacity of -quickstart profiles. More information can be found [here](https://github.com/weaveworks/eksctl/issues/2963). diff --git a/userdocs/src/usage/gitops-v1.md b/userdocs/src/usage/gitops-v1.md deleted file mode 100644 index 5b68515db6..0000000000 --- a/userdocs/src/usage/gitops-v1.md +++ /dev/null @@ -1,539 +0,0 @@ -# GitOps with Flux v1 - -!!! Tip "New" - Experimental support for [Flux v2 (part of the GitOps Toolkit)](https://toolkit.fluxcd.io/) - is available from `eksctl` version `0.38.0`. See [the v2 docs](/usage/gitops-v2). - -!!! Warning "Flux v1 support Deprecated" - As full support for Flux v2 (GitOps Toolkit) has now been rolled out, Flux v1 (Repo, Operator, BootstrapProfile) functionality - is now deprecated. Any significant changes or disruptions will be noted in [releases](https://github.com/weaveworks/eksctl/releases). - -[Gitops][gitops] is a way to do Kubernetes application delivery. It -works by using Git as a single source of truth for Kubernetes resources -and everything else. With Git at the center of your delivery pipelines, -you and your team can make pull requests to accelerate and simplify -application deployments and operations tasks to Kubernetes. - -[gitops]: https://www.weave.works/technologies/gitops/ - -## Installing Flux v1 - -`eksctl` provides an easy way to set up gitops in an existing cluster with the `eksctl enable repo` command. - -The main point of gitops is to keep everything (config, alerts, dashboards, -apps, literally everything) in Git and use it as a single source of truth. - -![Install Flux](../img/gitops-diagram1.svg#content) - -Installing [Flux v1](https://github.com/fluxcd/flux) on the cluster is the first step towards a gitops workflow. -To install it, you need a Git repository so first please go ahead and create an -_empty_ repository. On GitHub, for example, follow [these steps][github-repo]. - -[github-repo]: https://help.github.com/articles/create-a-repo - -To install Flux v1 on an existing cluster, use the `enable repo` command: - -```console -eksctl enable repo \ - --cluster= \ - --region= \ - --git-url= \ - --git-email= -``` - -Or use a config file: - -```YAML ---- -apiVersion: eksctl.io/v1alpha5 -kind: ClusterConfig - -metadata: - name: cluster-21 - region: eu-north-1 - -# other cluster config ... - -git: - repo: - url: "git@github.com:myorg/cluster-21.git" - branch: master - fluxPath: "flux/" - user: "gitops" - email: "@users.noreply.github.com" - operator: - namespace: "flux" - withHelm: true -``` - -Then: -```console -eksctl enable repo -f cluster-21.yaml -``` - -To install Flux v1 components into a new cluster as part of a `create cluster` -operation, simply add the above configuration to your config file, and run the create -command as normal. - -Note that, by default, `eksctl enable repo` installs [Flux Helm Operator](https://github.com/fluxcd/helm-operator) with Helm v3 support. -To disable the installation of the Helm Operator, pass the flag `--with-helm=false` or set `git.operator.withHelm` to `false`. - -Full example: - -```console -eksctl enable repo --cluster=cluster-1 --region=eu-west-2 --git-url=git@github.com:weaveworks/cluster-1-gitops.git --git-email=@users.noreply.github.com --namespace=flux -[ℹ] Generating manifests -[ℹ] Cloning git@github.com:weaveworks/cluster-1-gitops.git -Cloning into '/var/folders/zt/sh1tk7ts24sc6dybr5z9qtfh0000gn/T/eksctl-install-flux-clone-142184188'... -[ℹ] Writing Flux manifests -[ℹ] Applying manifests -[ℹ] created "Namespace/flux" -[ℹ] created "flux:Secret/flux-git-deploy" -[ℹ] created "flux:Deployment.apps/memcached" -[ℹ] created "flux:ServiceAccount/flux" -[ℹ] created "ClusterRole.rbac.authorization.k8s.io/flux" -[ℹ] created "ClusterRoleBinding.rbac.authorization.k8s.io/flux" -[ℹ] created "CustomResourceDefinition.apiextensions.k8s.io/helmreleases.helm.fluxcd.io" -[ℹ] created "flux:Deployment.apps/flux" -[ℹ] created "flux:Service/memcached" -[ℹ] created "flux:Deployment.apps/flux-helm-operator" -[ℹ] created "flux:ServiceAccount/flux-helm-operator" -[ℹ] created "ClusterRole.rbac.authorization.k8s.io/flux-helm-operator" -[ℹ] created "ClusterRoleBinding.rbac.authorization.k8s.io/flux-helm-operator" -[ℹ] Waiting for Helm Operator to start -[ℹ] Helm Operator started successfully -[ℹ] Waiting for Flux to start -[ℹ] Flux started successfully -[ℹ] Committing and pushing manifests to git@github.com:weaveworks/cluster-1-gitops.git -[master ec43024] Add Initial Flux configuration - Author: Flux -14 files changed, 694 insertions(+) -Enumerating objects: 11, done. -Counting objects: 100% (11/11), done. -Delta compression using up to 4 threads -Compressing objects: 100% (6/6), done. -Writing objects: 100% (6/6), 2.09 KiB | 2.09 MiB/s, done. -Total 6 (delta 3), reused 0 (delta 0) -remote: Resolving deltas: 100% (3/3), completed with 3 local objects. -To github.com:weaveworks/cluster-1-gitops.git - 5fe1eb8..ec43024 master -> master -[ℹ] Flux will only operate properly once it has write-access to the Git repository -[ℹ] please configure git@github.com:weaveworks/cluster-1-gitops.git so that the following Flux SSH public key has write access to it -ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDYYsPuHzo1L29u3zhr4uAOF29HNyMcS8zJmOTDNZC4EiIwa5BXgg/IBDKudxQ+NBJ7mknPlNv17cqo4ncEq1xiQidfaUawwx3xxtDkZWam5nCBMXEJwkr4VXx/6QQ9Z1QGXpaFwdoVRcY/kM4NaxM54pEh5m43yeqkcpRMKraE0EgbdqFNNARN8rIEHY/giDorCrXp7e6AbzBgZSvc/in7Ul9FQhJ6K4+7QuMFpJt3O/N8KDumoTG0e5ssJGp5L1ugIqhzqvbHdmHVfnXsEvq6cR1SJtYKi2GLCscypoF3XahfjK+xGV/92a1E7X+6fHXSq+bdOKfBc4Z3f9NBwz0v -``` - -The only thing left to do is to give Flux write access to the repository. -Copy the lines starting with `ssh-rsa` and give it read/write access to your -repository. For example, in GitHub, by adding it as a deploy key. There you -can easily do this in the `Settings > Deploy keys > Add deploy key`. Just -make sure you check `Allow write access` as well. - -At this point Flux and the Helm Operator should be installed in the specified cluster. - -```console -$ kubectl get pods --namespace flux -NAME -flux-699cc7f4cb-9qc45 -memcached-958f745c-qdfgz -flux-helm-operator-6bc7c85bb5-l2nzn -``` - -CLI arguments for `eksctl enable repo` - -| Flag | Default value | Type | Required | Use | -|-----------------------------------|---------------|---------|----------|------------------------------------------------------------------------------------------------------------------------------| -| `--cluster` | | string | required | name of the EKS cluster | -| `--region` | | string | required | AWS region | -| `--git-url` | | string | required | SSH URL of the Git repository to be used for GitOps | -| `--git-branch` | master | string | optional | Git branch to be used for GitOps | -| `--git-email` | | string | required | Email to use as Git committer | -| `--git-user` | Flux | string | optional | Username to use as Git committer | -| `--git-private-ssh-key-path` | | string | optional | Optional path to the private SSH key to use with Git | -| `--git-paths` | | string | optional | Relative paths within the Git repo for Flux to locate Kubernetes manifests | -| `--git-label` | flux | string | optional | Git label to keep track of Flux's sync progress; this is equivalent to overriding --git-sync-tag and --git-notes-ref in Flux | -| `--git-flux-subdir` | flux/ | string | optional | Directory within the Git repository where to commit the Flux manifests | -| `--namespace` | flux | string | optional | Cluster namespace where to install Flux and the Helm Operator | -| `--with-helm` | true | boolean | optional | Install the Helm Operator | -| `--commit-operator-manifests` | true | boolean | optional | Commit and push Flux manifests to the Git repo on install | -| `--read-only` | false | boolean | optional | Configure Flux in read-only mode and create the deploy key in read-only mode (only for Github) | -| `--additional-flux-args` | | string | optional | Additional command line arguments for the Flux daemon | -| `--additional-helm-operator-args` | | string | optional | Additional command line arguments for the Helm Operator | - -#### Adding a workload - -To deploy a new workload on the cluster using gitops just add a kubernetes manifest to the repository. After a few -minutes you should see the resources appearing in the cluster. - -![Deploying with gitops](../img/gitops-diagram2.svg#content) - -## Installing a Quickstart profile in your cluster - -In this part of the guide we will show you how to launch fully-configured Kubernetes -clusters that are ready to run production workloads in minutes. -At the end of this, you will have a Kubernetes cluster including control -plane, worker nodes, and all of the software needed for code deployment, -monitoring, and logging. - -![Enabling a profile](../img/gitops-diagram3.svg#content) - -The following command will set up your cluster with the -[app-dev](https://github.com/weaveworks/eks-quickstart-app-dev) profile, -the first gitops Quick Start. All of the config files you need for a -production-ready cluster will be in the git repo you have provided and -those components will be deployed to your cluster. When you make changes -in the configuration they will be reflected on your cluster. - -```console -eksctl enable profile \ - --cluster \ - --region \ - --git-url= \ - --git-email= \ - app-dev -``` - -or with a config file similar to the `enable repo` config, with the addition of -`bootstrapProfile` configuration: - -```YAML ---- -apiVersion: eksctl.io/v1alpha5 -kind: ClusterConfig - -metadata: - name: cluster-21 - region: eu-north-1 - -# other cluster config ... - -git: - repo: - url: "git@github.com:myorg/cluster-21.git" - branch: master - fluxPath: "flux/" - user: "gitops" - email: "@users.noreply.github.com" - operator: - namespace: "flux" - withHelm: true - bootstrapProfile: - source: app-dev - revision: master -``` - -To install your Quickstart components into a new cluster as part of a `create cluster` -operation, simply add the above configuration to your config file, and run the create -command as normal. - -The `enable profile` command will create a temporary clone of the specified repository and then it will follow these steps: - - 1. add the component manifests of the Quick Start profile to your repository inside the `base/` folder - 2. template values (eg cluster name) into configuration so that components can work - 3. commit the Quick Start files and push the changes to the origin remote - 4. Flux will install the components from the `base/` folder into your cluster - -Example: - -``` -eksctl enable profile --cluster production-cluster --region eu-north-1 --git-url=git@github.com:myorg/production-kubernetes --git-email=@users.noreply.github.com app-dev -Cloning into '/tmp/gitops-repos/flux-test-3'... -Resolving deltas: 100% (37/37), done. -[ℹ] cloning repository "git@github.com:weaveworks/eks-quickstart-app-dev.git":master -Cloning into '/tmp/quickstart-365477450'... -Resolving deltas: 100% (53/53), done. -[ℹ] processing template files in repository -[ℹ] writing new manifests to "/tmp/gitops-repos/flux-test-3/base" -[master d0810f7] Add app-dev quickstart components - Author: Flux <> - 27 files changed, 1207 insertions(+) - create mode 100644 base/LICENSE - create mode 100644 base/README.md - create mode 100644 base/amazon-cloudwatch/cloudwatch-agent-configmap.yaml - create mode 100644 base/amazon-cloudwatch/cloudwatch-agent-daemonset.yaml - create mode 100644 base/amazon-cloudwatch/cloudwatch-agent-rbac.yaml - create mode 100644 base/amazon-cloudwatch/fluentd-configmap-cluster-info.yaml - create mode 100644 base/amazon-cloudwatch/fluentd-configmap-fluentd-config.yaml - create mode 100644 base/amazon-cloudwatch/fluentd-daemonset.yaml - create mode 100644 base/amazon-cloudwatch/fluentd-rbac.yaml - create mode 100644 base/demo/helm-release.yaml - create mode 100644 base/kube-system/alb-ingress-controller-deployment.yaml - create mode 100644 base/kube-system/alb-ingress-controller-rbac.yaml - create mode 100644 base/kube-system/cluster-autoscaler-deployment.yaml - create mode 100644 base/kube-system/cluster-autoscaler-rbac.yaml - create mode 100644 base/kubernetes-dashboard/dashboard-metrics-scraper-deployment.yaml - create mode 100644 base/kubernetes-dashboard/dashboard-metrics-scraper-service.yaml - create mode 100644 base/kubernetes-dashboard/kubernetes-dashboard-configmap.yaml - create mode 100644 base/kubernetes-dashboard/kubernetes-dashboard-deployment.yaml - create mode 100644 base/kubernetes-dashboard/kubernetes-dashboard-rbac.yaml - create mode 100644 base/kubernetes-dashboard/kubernetes-dashboard-secrets.yaml - create mode 100644 base/kubernetes-dashboard/kubernetes-dashboard-service.yaml - create mode 100644 base/monitoring/metrics-server.yaml - create mode 100644 base/monitoring/prometheus-operator.yaml - create mode 100644 base/namespaces/amazon-cloudwatch.yaml - create mode 100644 base/namespaces/demo.yaml - create mode 100644 base/namespaces/kubernetes-dashboard.yaml - create mode 100644 base/namespaces/monitoring.yaml -Counting objects: 36, done. -Delta compression using up to 4 threads. -Compressing objects: 100% (27/27), done. -Writing objects: 100% (36/36), 11.17 KiB | 3.72 MiB/s, done. -Total 36 (delta 8), reused 27 (delta 8) -remote: Resolving deltas: 100% (8/8), done. -To github.com:myorg/production-kubernetes - 0985830..d0810f7 master -> master - -``` - -Flux will pick up the changes in the repository with the Quick Start components and deploy them to the cluster. -After a couple of minutes the pods should appear in the cluster: - -``` -$ kubectl get pods --all-namespaces -NAMESPACE NAME READY STATUS RESTARTS AGE -amazon-cloudwatch cloudwatch-agent-qtdmc 1/1 Running 0 4m28s -amazon-cloudwatch fluentd-cloudwatch-4rwwr 1/1 Running 0 4m28s -demo podinfo-75b8547f78-56dll 1/1 Running 0 103s -flux flux-56b5664cdd-nfzx2 1/1 Running 0 11m -flux flux-helm-operator-6bc7c85bb5-l2nzn 1/1 Running 0 11m -flux memcached-958f745c-dqllc 1/1 Running 0 11m -kube-system alb-ingress-controller-6b64bcbbd8-6l7kf 1/1 Running 0 4m28s -kube-system aws-node-l49ct 1/1 Running 0 14m -kube-system cluster-autoscaler-5b8c96cd98-26z5f 1/1 Running 0 4m28s -kube-system coredns-7d7755744b-4jkp6 1/1 Running 0 21m -kube-system coredns-7d7755744b-ls5d9 1/1 Running 0 21m -kube-system kube-proxy-wllff 1/1 Running 0 14m -kubernetes-dashboard dashboard-metrics-scraper-f7b5dbf7d-rm5z7 1/1 Running 0 4m28s -kubernetes-dashboard kubernetes-dashboard-7447f48f55-94rhg 1/1 Running 0 4m28s -monitoring alertmanager-prometheus-operator-alertmanager-0 2/2 Running 0 78s -monitoring metrics-server-7dfc675884-q9qps 1/1 Running 0 4m24s -monitoring prometheus-operator-grafana-9bb769cf-pjk4r 2/2 Running 0 89s -monitoring prometheus-operator-kube-state-metrics-79f476bff6-r9m2s 1/1 Running 0 89s -monitoring prometheus-operator-operator-58fcb66576-6dwpg 1/1 Running 0 89s -monitoring prometheus-operator-prometheus-node-exporter-tllwl 1/1 Running 0 89s -monitoring prometheus-prometheus-operator-prometheus-0 3/3 Running 1 72s -``` - -If you fetch the latest changes to your configuration repository, -you will see that eksctl has updated it with the templated files from the -Quick Start. The next time Flux syncs from this repo, it will start updating -the cluster with the current configuration. - -It's easy to confirm that all the [eks-quickstart-app-dev components](https://github.com/weaveworks/eks-quickstart-app-dev#components) -are up and running for you by checking the `podinfo` app: - -```console -kubectl get service --namespace demo -``` - -```console -NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE -podinfo ClusterIP 10.100.255.220 9898/TCP 2m -``` - -Now let's port-forward the service, so we can easily access it: - -```console -kubectl port-forward -n demo svc/podinfo 9898:9898 -``` - -If you open `localhost:9898` in your browser, you will see - -![podinfo up and running](../img/podinfo-screenshot.png) - -For any further changes you wish to make to your cluster you can simply PR more -manifests to your repo, and let Flux take care of the rest. - -All CLI arguments for `gitops enable profile`: - -| Flag | Default value | Type | Required | Use | -|------------------------------|---------------|--------|----------------|------------------------------------------------------------------| -| `--cluster` | | string | required | Name of the EKS cluster | -| `--region` | | string | required | AWS region where the cluster exists | -| `--profile-source` | | string | required | Name or URL of the Quickstart profile. For example, app-dev | -| `` | | string | required | Same as `--profile-source` | -| `--profile-revision` | master | string | optional | Git Branch of the Quickstart profile repository | -| `--git-url` | | string | required | URL | -| `--git-branch` | master | string | optional | Git branch | -| `--git-user` | Flux | string | optional | Username to use to commit to the Gitops repo | -| `--git-email` | | string | required | Email to use to commit to the Gitops repo | -| `--git-private-ssh-key-path` | | string | optional | Optional path to the private SSH key to use with the gitops repo | - - -#### Further reading - -To learn more about gitops and Flux, check the Flux documentation for [v1](https://docs.fluxcd.io/en/1.21.1/). - -### Installing components from a Quickstart profile on a specific directory without pushing - -To install the components from a Quickstart profile in a specified folder without committing and pushing to a Gitops -repo the `generate profile` command can be used: - -```console -eksctl generate profile \ - --cluster= \ - --region= \ - --profile-source git@github.com:weaveworks/eks-quickstart-app-dev.git \ - --profile-path -``` - -For example: -```console -Cloning into '/tmp/cluster-21-086715755'... -remote: Enumerating objects: 10, done. -remote: Counting objects: 100% (10/10), done. -remote: Compressing objects: 100% (10/10), done. -remote: Total 187 (delta 2), reused 8 (delta 0), pack-reused 177 -Receiving objects: 100% (187/187), 45.18 KiB | 616.00 KiB/s, done. -Resolving deltas: 100% (86/86), done. -Already on 'master' -Your branch is up to date with 'origin/master'. -[ℹ] cloning repository "https://github.com/weaveworks/eks-quickstart-app-dev":master -Cloning into '/tmp/quickstart-424579534'... -remote: Enumerating objects: 214, done. -remote: Total 214 (delta 0), reused 0 (delta 0), pack-reused 214 -Receiving objects: 100% (214/214), 57.06 KiB | 446.00 KiB/s, done. -Resolving deltas: 100% (93/93), done. -Already on 'master' -Your branch is up to date with 'origin/master'. -[ℹ] processing template files in repository -[ℹ] writing new manifests to "base/" -``` - -```console -$ tree my-gitops-repo/base -$ tree base/ -base/ -├── amazon-cloudwatch -│   ├── cloudwatch-agent-configmap.yaml -│   ├── cloudwatch-agent-daemonset.yaml -│   ├── cloudwatch-agent-rbac.yaml -│   ├── fluentd-configmap-cluster-info.yaml -│   ├── fluentd-configmap-fluentd-config.yaml -│   ├── fluentd-daemonset.yaml -│   └── fluentd-rbac.yaml -├── demo -│   └── helm-release.yaml -├── kubernetes-dashboard -│   ├── dashboard-metrics-scraper-deployment.yaml -│   ├── dashboard-metrics-scraper-service.yaml -│   ├── kubernetes-dashboard-configmap.yaml -│   ├── kubernetes-dashboard-deployment.yaml -│   ├── kubernetes-dashboard-rbac.yaml -│   ├── kubernetes-dashboard-secrets.yaml -│   └── kubernetes-dashboard-service.yaml -├── kube-system -│   ├── alb-ingress-controller-deployment.yaml -│   ├── alb-ingress-controller-rbac.yaml -│   ├── cluster-autoscaler-deployment.yaml -│   └── cluster-autoscaler-rbac.yaml -├── LICENSE -├── monitoring -│   ├── metrics-server.yaml -│   └── prometheus-operator.yaml -├── namespaces -│   ├── amazon-cloudwatch.yaml -│   ├── demo.yaml -│   ├── kubernetes-dashboard.yaml -│   └── monitoring.yaml -└── README.md - -``` - -```console -cd my-gitops-repo/ -git add . -git commit -m "Add component templates" -git push origin master -``` - -After a few minutes, Flux and Helm should have installed all the components in your cluster. - -## Creating your own Quick Start profile - -A Quick Start profile is a Git repository that contains Kubernetes manifests that can be installed in a cluster using -gitops (through [Flux][flux]). - -Some components will probably need some information about the cluster they will be installed in, such as the cluster -name or the AWS region. We can template these in via the manifests you add to your profile using [Go templates][go-templates]. - -The variables that can be templated are shown below: - -| Name | Template | -|---------------------|------------------------| -| cluster name | `{{ .ClusterName }}` | -| cluster region | `{{ .Region }}` | - - -For example, we could create a config map using these variables: - -```yaml -apiVersion: v1 -data: - cluster.name: {{ .ClusterName }} - logs.region: {{ .Region }} -kind: ConfigMap -metadata: - name: cluster-info - namespace: my-namespace -``` - -Write this into a file with the extension `*.yaml.tmpl` and commit it to your Quick Start repository. -Files with this extension get processed by eksctl before committing them to the user's gitops repository, while the rest get copied unmodified. - -Regarding the folder structure inside the Quick Start repository, we recommend using a folder for each `namespace` and -one file per Kubernetes resource. - -``` -repository-name/ -├── kube-system -│   ├── ingress-controller-deployment.yaml.tmpl -│   └── ingress-controller-rbac.yaml.tmpl -└── alerting -    ├── alerting-app-deployment.yaml -    ├── alerting-app-service.yaml.tmpl -    ├── monitoring-sidecar-deployment.yaml -    ├── monitoring-sidecar-service.yaml.tmpl -    ├── cluster-info-configmap.yaml.tmpl -    └── alerting-namespace.yaml - -``` - -Note that some files have the extension `*.yaml` while others have `*.yaml.tmpl`. The last ones are the ones that can -contain template actions while the former are plain `yaml` files. - -These files can now be committed and pushed to your Quick Start repository, for example `git@github.com:myorg/production-infra`. - -``` -cd repository-name/ -git add . -git commit -m "Add component templates" -git push origin master -``` - -Now that the templates are in the remote repository, the Quick Start is ready to be used with `eksctl enable profile`: - -```console -eksctl enable profile --cluster team1 --region eu-west-1 --git-url git@github.com:myorg/team1-cluster --git-email @users.noreply.github.com git@github.com:myorg/production-infra -``` - -In this example we provide `github.com:myorg/production-infra` as the Quick Start profile and -`github.com:myorg/team1-cluster` as the gitops repository that is connected to the Flux instance in the cluster named -`cluster1`. - -For a full example of a Quick Start profile, check out [App Dev][app-dev]. - -All CLI arguments for `gitops generate profile`: - -| Flag | Default value | Type | Required | Use | -|------------------------------|---------------|--------|----------------|------------------------------------------------------------------| -| `--cluster` | | string | required | Name of the EKS cluster | -| `--region` | | string | required | AWS region where the cluster exists | -| `--profile-source` | | string | required | Name or URL of the Quickstart profile. For example, app-dev | -| `--profile-revision` | master | string | optional | Git Branch of the Quickstart profile repository | -| `--profile-path` | ./ | string | optional | Path to generate the profile in | -| `` | | string | required | Same as `--profile-source` | - - -[flux]: https://docs.fluxcd.io/en/latest/ -[go-templates]: https://golang.org/pkg/text/template/ -[app-dev]: https://github.com/weaveworks/eks-quickstart-app-dev From 8ce7a66d3e99d44826ff5d0f3f4ebf47ad90945c Mon Sep 17 00:00:00 2001 From: Jake Date: Thu, 18 Nov 2021 10:33:23 +0000 Subject: [PATCH 091/124] update docs --- userdocs/src/community.md | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/userdocs/src/community.md b/userdocs/src/community.md index 98011cb379..7b2d5d51b7 100644 --- a/userdocs/src/community.md +++ b/userdocs/src/community.md @@ -57,13 +57,11 @@ and our [proposal contributing guide](https://github.com/weaveworks/eksctl/blob/ ### Flux v2 integration (GitOps Toolkit) In 2019 `eksctl` gave users a way to easily create a Gitops-ready ([Flux v1](https://docs.fluxcd.io/en/1.21.1/)) -cluster and to declare a set of pre-installed applications ([Quickstart profiles](/usage/gitops-v1/#installing-a-quickstart-profile-in-your-cluster)) -which can be managed via a git repo. +cluster and to declare a set of pre-installed applications Quickstart profiles which can be managed via a git repo. Since then, the practice of GitOps has matured, therefore `eksctl`'s support of -GitOps will change to keep up with current standards. +GitOps has changed to keep up with current standards. From version 0.76.0 Flux v1 support was removed after an 11 +month deprecation period. In its place support for [Flux v2](https://fluxcd.io/) can be used via +`eksctl enable flux` -The first stage of this is implementing support for [Flux v2](https://fluxcd.io/). -This support already exists in an experimental form in `eksctl` (`eksctl enable flux`) -and work there will carry on throughout the year. From aecf623232192bb36b1e163713ec5f4c06183b89 Mon Sep 17 00:00:00 2001 From: Jake Klein Date: Thu, 18 Nov 2021 12:33:39 +0000 Subject: [PATCH 092/124] add 0.75 release notes (#4472) * add 0.75 release notes * Update docs/release_notes/0.75.0.md Co-authored-by: Niki <18622989+nikimanoledaki@users.noreply.github.com> * Update docs/release_notes/0.75.0.md Co-authored-by: Chetan Patwal * Update docs/release_notes/0.75.0.md Co-authored-by: Himangini Co-authored-by: Niki <18622989+nikimanoledaki@users.noreply.github.com> Co-authored-by: Chetan Patwal Co-authored-by: Himangini --- docs/release_notes/0.75.0.md | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) create mode 100644 docs/release_notes/0.75.0.md diff --git a/docs/release_notes/0.75.0.md b/docs/release_notes/0.75.0.md new file mode 100644 index 0000000000..ccd44b6cfe --- /dev/null +++ b/docs/release_notes/0.75.0.md @@ -0,0 +1,19 @@ +# Release 0.75.0 + + +## Features + +- Add --config-file flag to get labels & nodegroups (#4469) (#4465) +- Add option to skip endpoint creation for private clusters (#4457) + +## Improvements + +- Improve kube-proxy updating to always get the latest version&build #4344 (#4440) +- Document logs:PutRetentionPolicy in IAM policies doc (#4456) + +## Bug Fixes + +- Add option to skip endpoint creation completely (#4457) +- Fix update logic in iam service account (#4460) +- Brew Deprecation Warning: Calling bottle :unneeded is deprecated (#4458) + From 407930a5bbd0d3832825e5c6c2bb2058afcca910 Mon Sep 17 00:00:00 2001 From: weaveworksbot Date: Thu, 18 Nov 2021 12:36:01 +0000 Subject: [PATCH 093/124] Prepare for next development iteration --- pkg/version/release.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkg/version/release.go b/pkg/version/release.go index 213afd934f..c672faf422 100644 --- a/pkg/version/release.go +++ b/pkg/version/release.go @@ -3,7 +3,7 @@ package version // This file was generated by release_generate.go; DO NOT EDIT. // Version is the version number in semver format X.Y.Z -var Version = "0.75.0" +var Version = "0.76.0" // PreReleaseID can be empty for releases, "rc.X" for release candidates and "dev" for snapshots var PreReleaseID = "dev" From c962534c5d480683bb637a25ebc76f4de82d4389 Mon Sep 17 00:00:00 2001 From: nikimanoledaki <18622989+nikimanoledaki@users.noreply.github.com> Date: Tue, 16 Nov 2021 10:40:41 +0100 Subject: [PATCH 094/124] Support scaling all nodegroups in config file --- .../tests/crud/creategetdelete_test.go | 57 ++- .../tests/crud/testdata/scale-nodegroups.yaml | 18 + pkg/ctl/cmdutils/scale.go | 31 +- pkg/ctl/cmdutils/scale_test.go | 347 ++++++++++-------- .../cmdutils/test_data/scale-all-ng-test.yaml | 20 + pkg/ctl/scale/nodegroup.go | 35 +- pkg/ctl/scale/nodegroup_test.go | 5 - userdocs/src/usage/managing-nodegroups.md | 10 +- 8 files changed, 339 insertions(+), 184 deletions(-) create mode 100644 integration/tests/crud/testdata/scale-nodegroups.yaml create mode 100644 pkg/ctl/cmdutils/test_data/scale-all-ng-test.yaml diff --git a/integration/tests/crud/creategetdelete_test.go b/integration/tests/crud/creategetdelete_test.go index 6942927cb0..01811138a8 100644 --- a/integration/tests/crud/creategetdelete_test.go +++ b/integration/tests/crud/creategetdelete_test.go @@ -203,19 +203,6 @@ var _ = Describe("(Integration) Create, Get, Scale & Delete", func() { }) }) - Context("and scale the initial nodegroup", func() { - It("should not return an error", func() { - cmd := params.EksctlScaleNodeGroupCmd.WithArgs( - "--cluster", params.ClusterName, - "--nodes-min", "3", - "--nodes", "4", - "--nodes-max", "5", - "--name", initNG, - ) - Expect(cmd).To(RunSuccessfully()) - }) - }) - Context("and create a new nodegroup with taints and maxPods", func() { It("should have taints and maxPods set", func() { By("creating a new nodegroup with taints and maxPods set") @@ -428,6 +415,50 @@ var _ = Describe("(Integration) Create, Get, Scale & Delete", func() { }) }) + When("scaling nodegroup(s)", func() { + It("should scale a single nodegroup", func() { + By("passing the name of the nodegroup as a flag") + cmd := params.EksctlScaleNodeGroupCmd.WithArgs( + "--cluster", params.ClusterName, + "--nodes-min", "3", + "--nodes", "4", + "--nodes-max", "5", + "--name", initNG, + ) + Expect(cmd).To(RunSuccessfully()) + }) + + It("should scale all nodegroups", func() { + By("scaling all nodegroups in the config file o the desired capacity, max size, and min size") + cmd := params.EksctlScaleNodeGroupCmd.WithArgs( + "--config-file", "-", + ). + WithoutArg("--region", params.Region). + WithStdin(clusterutils.ReaderFromFile(params.ClusterName, params.Region, "testdata/scale-nodegroups.yaml")) + Expect(cmd).To(RunSuccessfully()) + + getMngNgCmd := params.EksctlGetCmd.WithArgs( + "nodegroup", + "--cluster", params.ClusterName, + "--name", initNG, + "-o", "yaml", + ) + Expect(getMngNgCmd).To(RunSuccessfullyWithOutputString(ContainSubstring("MaxSize: 5"))) + Expect(getMngNgCmd).To(RunSuccessfullyWithOutputString(ContainSubstring("MinSize: 5"))) + Expect(getMngNgCmd).To(RunSuccessfullyWithOutputString(ContainSubstring("DesiredCapacity: 5"))) + + getUnmNgCmd := params.EksctlGetCmd.WithArgs( + "nodegroup", + "--cluster", params.ClusterName, + "--name", "n1", + "-o", "yaml", + ) + Expect(getUnmNgCmd).To(RunSuccessfullyWithOutputString(ContainSubstring("MaxSize: 5"))) + Expect(getUnmNgCmd).To(RunSuccessfullyWithOutputString(ContainSubstring("MinSize: 5"))) + Expect(getUnmNgCmd).To(RunSuccessfullyWithOutputString(ContainSubstring("DesiredCapacity: 5"))) + }) + }) + Context("and add a second (GPU) nodegroup", func() { It("should not return an error", func() { cmd := params.EksctlCreateCmd.WithArgs( diff --git a/integration/tests/crud/testdata/scale-nodegroups.yaml b/integration/tests/crud/testdata/scale-nodegroups.yaml new file mode 100644 index 0000000000..03f70dc397 --- /dev/null +++ b/integration/tests/crud/testdata/scale-nodegroups.yaml @@ -0,0 +1,18 @@ +apiVersion: eksctl.io/v1alpha5 +kind: ClusterConfig + +# name is generated +metadata: + name: + +nodeGroups: + - name: n1 + desiredCapacity: 5 + maxSize: 5 + minSize: 5 + +managedNodeGroups: + - name: ng-0 + desiredCapacity: 5 + maxSize: 5 + minSize: 5 diff --git a/pkg/ctl/cmdutils/scale.go b/pkg/ctl/cmdutils/scale.go index cf84068825..cbb03fe6a6 100644 --- a/pkg/ctl/cmdutils/scale.go +++ b/pkg/ctl/cmdutils/scale.go @@ -27,7 +27,7 @@ func NewScaleNodeGroupLoader(cmd *Cmd, ng *api.NodeGroupBase) ClusterConfigLoade return err } - if err := validateNumberOfNodes(loadedNG); err != nil { + if err := ValidateNumberOfNodes(loadedNG); err != nil { return err } *ng = *loadedNG @@ -54,6 +54,28 @@ func NewScaleNodeGroupLoader(cmd *Cmd, ng *api.NodeGroupBase) ClusterConfigLoade return l } +// NewScaleAllNodeGroupLoader will load config or use flags for 'eksctl scale nodegroup' +func NewScaleAllNodeGroupLoader(cmd *Cmd) ClusterConfigLoader { + l := newCommonClusterConfigLoader(cmd) + + l.flagsIncompatibleWithConfigFile.Insert( + "nodes", + "nodes-min", + "nodes-max", + ) + + l.validateWithConfigFile = func() error { + l.Plan = false + return nil + } + + l.validateWithoutConfigFile = func() error { + return fmt.Errorf("a config file is required when scaling multiple nodegroups") + } + + return l +} + func validateNameArgument(cmd *Cmd, ng *api.NodeGroupBase) error { if ng.Name != "" && cmd.NameArg != "" { return ErrFlagAndArg("--name", ng.Name, cmd.NameArg) @@ -63,14 +85,11 @@ func validateNameArgument(cmd *Cmd, ng *api.NodeGroupBase) error { ng.Name = cmd.NameArg } - if ng.Name == "" { - return ErrMustBeSet("--name") - } - return nil } -func validateNumberOfNodes(ng *api.NodeGroupBase) error { +// ValidateNumberOfNodes validates the scaling config of a nodegroup. +func ValidateNumberOfNodes(ng *api.NodeGroupBase) error { if ng.ScalingConfig == nil { ng.ScalingConfig = &api.ScalingConfig{} } diff --git a/pkg/ctl/cmdutils/scale_test.go b/pkg/ctl/cmdutils/scale_test.go index ce36263449..d29b418661 100644 --- a/pkg/ctl/cmdutils/scale_test.go +++ b/pkg/ctl/cmdutils/scale_test.go @@ -33,171 +33,208 @@ var _ = Describe("scale node group config file loader", func() { } } - DescribeTable("scale nodegroup successfully via config file", - func(params scaleNodeGroupCase) { - cmd := &Cmd{ - CobraCommand: newCmd(), - ClusterConfigFile: "test_data/scale-ng-test.yaml", - ClusterConfig: api.NewClusterConfig(), - ProviderConfig: api.ProviderConfig{}, - NameArg: params.name, - } - - ng := api.NewNodeGroup().BaseNodeGroup() - err := NewScaleNodeGroupLoader(cmd, ng).Load() - if params.err != nil { - Expect(err).To(HaveOccurred()) - Expect(err.Error()).To(ContainSubstring(params.err.Error())) - } else { - if params.minSize != nil { - Expect(ng.MinSize).To(Equal(params.minSize)) - } - Expect(err).NotTo(HaveOccurred()) - } - }, - Entry("one node group matched", scaleNodeGroupCase{ - name: "ng-all-details", - }), - Entry("no node group matched", scaleNodeGroupCase{ - name: "123123", - err: fmt.Errorf("nodegroup 123123 not found in config file"), - }), - Entry("with no desired capacity", scaleNodeGroupCase{ - name: "ng-no-desired-capacity", - err: fmt.Errorf("number of nodes must be 0 or greater"), - }), - Entry("with no minSize and no maxSize", scaleNodeGroupCase{ - name: "ng-no-min-max", - }), - Entry("ng with minSize", scaleNodeGroupCase{ - name: "ng-with-min", - minSize: aws.Int(1), - }), - Entry("ng with wrong value for minSize", scaleNodeGroupCase{ - name: "ng-with-wrong-min", - err: fmt.Errorf("minimum number of nodes must be less than or equal to number of nodes"), - }), - Entry("ng with maxSize", scaleNodeGroupCase{ - name: "ng-with-max", - }), - Entry("ng with wrong value for maxSize", scaleNodeGroupCase{ - name: "ng-with-wrong-max", - err: fmt.Errorf("maximum number of nodes must be greater than or equal to number of nodes"), - }), - Entry("ng with desired nodes outside [minSize, maxSize]", scaleNodeGroupCase{ - name: "ng-with-wrong-desired", - err: fmt.Errorf("number of nodes must be within range of min nodes and max nodes"), - }), - ) - - DescribeTable("scale nodegroup successfully via cli flags", - func(params scaleNodeGroupCLICase) { - cfg := api.NewClusterConfig() - cfg.Metadata.Name = "cluster" - cmd := &Cmd{ - CobraCommand: newCmd(), - ProviderConfig: api.ProviderConfig{}, - ClusterConfig: cfg, - NameArg: params.name, - } - - ng := api.NewNodeGroup().BaseNodeGroup() - ng.MinSize = params.minSize - ng.MaxSize = params.maxSize - ng.DesiredCapacity = params.desiredSize - err := NewScaleNodeGroupLoader(cmd, ng).Load() - if params.err != nil { - Expect(err).To(HaveOccurred()) - Expect(err.Error()).To(ContainSubstring(params.err.Error())) - } else { - if params.minSize != nil { - Expect(ng.MinSize).To(Equal(params.minSize)) - } - Expect(err).NotTo(HaveOccurred()) - } - }, - Entry("only specifying min-nodes", scaleNodeGroupCLICase{ - name: "ng-with-max", - minSize: aws.Int(1), - }), - Entry("only specifying max-nodes", scaleNodeGroupCLICase{ - name: "ng-with-max", - maxSize: aws.Int(1), - }), - Entry("only specifying nodes", scaleNodeGroupCLICase{ - name: "ng-with-max", - desiredSize: aws.Int(1), - }), - Entry("minSize 0", scaleNodeGroupCLICase{ - name: "ng-with-max", - minSize: aws.Int(-1), - err: fmt.Errorf("minimum of nodes must be 0 or greater"), - }), - Entry("maxSize 0", scaleNodeGroupCLICase{ - name: "ng-with-max", - maxSize: aws.Int(-1), - err: fmt.Errorf("maximum of nodes must be 0 or greater"), - }), - Entry("desiredSize 0", scaleNodeGroupCLICase{ - name: "ng-with-max", - desiredSize: aws.Int(-1), - err: fmt.Errorf("number of nodes must be 0 or greater"), - }), - Entry("desiredSize greater than max", scaleNodeGroupCLICase{ - name: "ng-with-max", - desiredSize: aws.Int(3), - maxSize: aws.Int(1), - err: fmt.Errorf("maximum number of nodes must be greater than or equal to number of nodes"), - }), - Entry("desiredSize fewer than min", scaleNodeGroupCLICase{ - name: "ng-with-max", - desiredSize: aws.Int(2), - minSize: aws.Int(3), - err: fmt.Errorf("minimum number of nodes must be fewer than or equal to number of nodes"), - }), - Entry("min greater than max", scaleNodeGroupCLICase{ - name: "ng-with-max", - minSize: aws.Int(3), - maxSize: aws.Int(2), - err: fmt.Errorf("maximum number of nodes must be greater than minimum number of nodes"), - }), - Entry("not specifying any", scaleNodeGroupCLICase{ - name: "ng-with-max", - err: fmt.Errorf("at least one of minimum, maximum and desired nodes must be set"), - }), - ) - - Describe("for managed nodegroups", func() { - Context("when using a config file", func() { - It("setting --name finds that individual nodegroup", func() { - ngName := "mng-ng" - ng := &api.NodeGroupBase{ - Name: ngName, - ScalingConfig: &api.ScalingConfig{ - DesiredCapacity: aws.Int(2), - }, + When("scaling a single nodegroup", func() { + DescribeTable("scale nodegroup successfully via config file", + func(params scaleNodeGroupCase) { + cmd := &Cmd{ + CobraCommand: newCmd(), + ClusterConfigFile: "test_data/scale-ng-test.yaml", + ClusterConfig: api.NewClusterConfig(), + ProviderConfig: api.ProviderConfig{}, + NameArg: params.name, } - config := api.NewClusterConfig() - config.Metadata.Name = "test-cluster" - config.ManagedNodeGroups = []*api.ManagedNodeGroup{ - { - NodeGroupBase: &api.NodeGroupBase{ - Name: ngName, - ScalingConfig: &api.ScalingConfig{ - DesiredCapacity: aws.Int(2), - }, - }, - }, + ng := api.NewNodeGroup().BaseNodeGroup() + err := NewScaleNodeGroupLoader(cmd, ng).Load() + if params.err != nil { + Expect(err).To(HaveOccurred()) + Expect(err.Error()).To(ContainSubstring(params.err.Error())) + } else { + if params.minSize != nil { + Expect(ng.MinSize).To(Equal(params.minSize)) + } + Expect(err).ToNot(HaveOccurred()) } + }, + Entry("one node group matched", scaleNodeGroupCase{ + name: "ng-all-details", + }), + Entry("no node group matched", scaleNodeGroupCase{ + name: "123123", + err: fmt.Errorf("nodegroup 123123 not found in config file"), + }), + Entry("with no desired capacity", scaleNodeGroupCase{ + name: "ng-no-desired-capacity", + err: fmt.Errorf("number of nodes must be 0 or greater"), + }), + Entry("with no minSize and no maxSize", scaleNodeGroupCase{ + name: "ng-no-min-max", + }), + Entry("ng with minSize", scaleNodeGroupCase{ + name: "ng-with-min", + minSize: aws.Int(1), + }), + Entry("ng with wrong value for minSize", scaleNodeGroupCase{ + name: "ng-with-wrong-min", + err: fmt.Errorf("minimum number of nodes must be less than or equal to number of nodes"), + }), + Entry("ng with maxSize", scaleNodeGroupCase{ + name: "ng-with-max", + }), + Entry("ng with wrong value for maxSize", scaleNodeGroupCase{ + name: "ng-with-wrong-max", + err: fmt.Errorf("maximum number of nodes must be greater than or equal to number of nodes"), + }), + Entry("ng with desired nodes outside [minSize, maxSize]", scaleNodeGroupCase{ + name: "ng-with-wrong-desired", + err: fmt.Errorf("number of nodes must be within range of min nodes and max nodes"), + }), + ) + + DescribeTable("scale nodegroup successfully via cli flags", + func(params scaleNodeGroupCLICase) { + cfg := api.NewClusterConfig() + cfg.Metadata.Name = "cluster" cmd := &Cmd{ CobraCommand: newCmd(), - ClusterConfig: config, ProviderConfig: api.ProviderConfig{}, + ClusterConfig: cfg, + NameArg: params.name, } + ng := api.NewNodeGroup().BaseNodeGroup() + ng.MinSize = params.minSize + ng.MaxSize = params.maxSize + ng.DesiredCapacity = params.desiredSize err := NewScaleNodeGroupLoader(cmd, ng).Load() + if params.err != nil { + Expect(err).To(HaveOccurred()) + Expect(err.Error()).To(ContainSubstring(params.err.Error())) + } else { + if params.minSize != nil { + Expect(ng.MinSize).To(Equal(params.minSize)) + } + Expect(err).ToNot(HaveOccurred()) + } + }, + Entry("only specifying min-nodes", scaleNodeGroupCLICase{ + name: "ng-with-max", + minSize: aws.Int(1), + }), + Entry("only specifying max-nodes", scaleNodeGroupCLICase{ + name: "ng-with-max", + maxSize: aws.Int(1), + }), + Entry("only specifying nodes", scaleNodeGroupCLICase{ + name: "ng-with-max", + desiredSize: aws.Int(1), + }), + Entry("minSize 0", scaleNodeGroupCLICase{ + name: "ng-with-max", + minSize: aws.Int(-1), + err: fmt.Errorf("minimum of nodes must be 0 or greater"), + }), + Entry("maxSize 0", scaleNodeGroupCLICase{ + name: "ng-with-max", + maxSize: aws.Int(-1), + err: fmt.Errorf("maximum of nodes must be 0 or greater"), + }), + Entry("desiredSize 0", scaleNodeGroupCLICase{ + name: "ng-with-max", + desiredSize: aws.Int(-1), + err: fmt.Errorf("number of nodes must be 0 or greater"), + }), + Entry("desiredSize greater than max", scaleNodeGroupCLICase{ + name: "ng-with-max", + desiredSize: aws.Int(3), + maxSize: aws.Int(1), + err: fmt.Errorf("maximum number of nodes must be greater than or equal to number of nodes"), + }), + Entry("desiredSize fewer than min", scaleNodeGroupCLICase{ + name: "ng-with-max", + desiredSize: aws.Int(2), + minSize: aws.Int(3), + err: fmt.Errorf("minimum number of nodes must be fewer than or equal to number of nodes"), + }), + Entry("min greater than max", scaleNodeGroupCLICase{ + name: "ng-with-max", + minSize: aws.Int(3), + maxSize: aws.Int(2), + err: fmt.Errorf("maximum number of nodes must be greater than minimum number of nodes"), + }), + Entry("not specifying any", scaleNodeGroupCLICase{ + name: "ng-with-max", + err: fmt.Errorf("at least one of minimum, maximum and desired nodes must be set"), + }), + ) + + Describe("for managed nodegroups", func() { + Context("when using a config file", func() { + It("setting --name finds that individual nodegroup", func() { + ngName := "mng-ng" + ng := &api.NodeGroupBase{ + Name: ngName, + ScalingConfig: &api.ScalingConfig{ + DesiredCapacity: aws.Int(2), + }, + } + + config := api.NewClusterConfig() + config.Metadata.Name = "test-cluster" + config.ManagedNodeGroups = []*api.ManagedNodeGroup{ + { + NodeGroupBase: &api.NodeGroupBase{ + Name: ngName, + ScalingConfig: &api.ScalingConfig{ + DesiredCapacity: aws.Int(2), + }, + }, + }, + } + cmd := &Cmd{ + CobraCommand: newCmd(), + ClusterConfig: config, + ProviderConfig: api.ProviderConfig{}, + } + + err := NewScaleNodeGroupLoader(cmd, ng).Load() + Expect(err).NotTo(HaveOccurred()) + }) + }) + }) + }) + + When("scaling all nodegroups", func() { + When("using a config file", func() { + It("finds all nodegroups", func() { + cmd := &Cmd{ + CobraCommand: newCmd(), + ClusterConfigFile: "test_data/scale-all-ng-test.yaml", + } + + err := NewScaleAllNodeGroupLoader(cmd).Load() Expect(err).NotTo(HaveOccurred()) + Expect(len(cmd.ClusterConfig.ManagedNodeGroups)).To(Equal(1)) + Expect(*cmd.ClusterConfig.ManagedNodeGroups[0].BaseNodeGroup().ScalingConfig.DesiredCapacity).To(Equal(3)) + Expect(*cmd.ClusterConfig.ManagedNodeGroups[0].BaseNodeGroup().ScalingConfig.MinSize).To(Equal(3)) + Expect(*cmd.ClusterConfig.ManagedNodeGroups[0].BaseNodeGroup().ScalingConfig.MaxSize).To(Equal(5)) + + Expect(len(cmd.ClusterConfig.NodeGroups)).To(Equal(1)) + Expect(*cmd.ClusterConfig.NodeGroups[0].BaseNodeGroup().ScalingConfig.DesiredCapacity).To(Equal(3)) + Expect(*cmd.ClusterConfig.NodeGroups[0].BaseNodeGroup().ScalingConfig.MinSize).To(Equal(3)) + Expect(*cmd.ClusterConfig.NodeGroups[0].BaseNodeGroup().ScalingConfig.MaxSize).To(Equal(5)) + }) + }) + + When("not using a config file", func() { + It("fails", func() { + cmd := &Cmd{ + CobraCommand: newCmd(), + } + + err := NewScaleAllNodeGroupLoader(cmd).Load() + Expect(err).To(HaveOccurred()) + Expect(err).To(MatchError("a config file is required when scaling multiple nodegroups")) }) }) }) diff --git a/pkg/ctl/cmdutils/test_data/scale-all-ng-test.yaml b/pkg/ctl/cmdutils/test_data/scale-all-ng-test.yaml new file mode 100644 index 0000000000..482f62ef28 --- /dev/null +++ b/pkg/ctl/cmdutils/test_data/scale-all-ng-test.yaml @@ -0,0 +1,20 @@ +# A simple example of ClusterConfig object: +--- +apiVersion: eksctl.io/v1alpha5 +kind: ClusterConfig + +metadata: + name: test-cluster-1 + region: eu-north-1 + +nodeGroups: + - name: ng-1 + minSize: 3 + desiredCapacity: 3 + maxSize: 5 + +managedNodeGroups: + - name: ng-2 + minSize: 3 + desiredCapacity: 3 + maxSize: 5 \ No newline at end of file diff --git a/pkg/ctl/scale/nodegroup.go b/pkg/ctl/scale/nodegroup.go index de5cba9ff4..298ee15ab4 100644 --- a/pkg/ctl/scale/nodegroup.go +++ b/pkg/ctl/scale/nodegroup.go @@ -1,11 +1,10 @@ package scale import ( - "github.com/weaveworks/eksctl/pkg/actions/nodegroup" - "github.com/spf13/cobra" "github.com/spf13/pflag" + "github.com/weaveworks/eksctl/pkg/actions/nodegroup" api "github.com/weaveworks/eksctl/pkg/apis/eksctl.io/v1alpha5" "github.com/weaveworks/eksctl/pkg/ctl/cmdutils" ) @@ -57,10 +56,38 @@ func scaleNodeGroupWithRunFunc(cmd *cmdutils.Cmd, runFunc func(cmd *cmdutils.Cmd } func doScaleNodeGroup(cmd *cmdutils.Cmd, ng *api.NodeGroupBase) error { - if err := cmdutils.NewScaleNodeGroupLoader(cmd, ng).Load(); err != nil { - return err + if ng.Name == "" && cmd.NameArg == "" { + if err := cmdutils.NewScaleAllNodeGroupLoader(cmd).Load(); err != nil { + return err + } + if err := scaleAllNodegroups(cmd); err != nil { + return err + } + } else { + if err := cmdutils.NewScaleNodeGroupLoader(cmd, ng).Load(); err != nil { + return err + } + if err := scaleNodegroup(cmd, ng); err != nil { + return err + } } + return nil +} + +func scaleAllNodegroups(cmd *cmdutils.Cmd) error { + allNg := cmd.ClusterConfig.AllNodeGroups() + for _, ng := range allNg { + if err := cmdutils.ValidateNumberOfNodes(ng); err != nil { + return err + } + if err := scaleNodegroup(cmd, ng); err != nil { + return err + } + } + return nil +} +func scaleNodegroup(cmd *cmdutils.Cmd, ng *api.NodeGroupBase) error { cfg := cmd.ClusterConfig ctl, err := cmd.NewProviderForExistingCluster() if err != nil { diff --git a/pkg/ctl/scale/nodegroup_test.go b/pkg/ctl/scale/nodegroup_test.go index a6a9f359f2..fc0a30bb01 100644 --- a/pkg/ctl/scale/nodegroup_test.go +++ b/pkg/ctl/scale/nodegroup_test.go @@ -49,7 +49,6 @@ var _ = Describe("scale", func() { func(c invalidParamsCase) { cmd := newDefaultCmd(c.args...) _, err := cmd.execute() - fmt.Println(err) Expect(err).To(HaveOccurred()) Expect(err.Error()).To(ContainSubstring(c.error.Error())) }, @@ -82,10 +81,6 @@ var _ = Describe("scale", func() { args: []string{"nodegroup", "ng", "--cluster", "dummy", "--nodes", "2", "--nodes-min", "3"}, error: fmt.Errorf("Error: minimum number of nodes must be fewer than or equal to number of nodes"), }), - Entry("with config file and no name flags", invalidParamsCase{ - args: []string{"nodegroup", "-f", "../cmdutils/test_data/scale-ng-test.yaml"}, - error: fmt.Errorf("Error: --name must be set"), - }), Entry("with config file and nodes flags", invalidParamsCase{ args: []string{"nodegroup", "-f", "../cmdutils/test_data/scale-ng-test.yaml", "--nodes", "2"}, error: fmt.Errorf("Error: cannot use --nodes when --config-file/-f is set"), diff --git a/userdocs/src/usage/managing-nodegroups.md b/userdocs/src/usage/managing-nodegroups.md index f239704693..86c10b39c7 100644 --- a/userdocs/src/usage/managing-nodegroups.md +++ b/userdocs/src/usage/managing-nodegroups.md @@ -134,7 +134,7 @@ By design, nodegroups are immutable. This means that if you need to change somet AMI or the instance type of a nodegroup, you would need to create a new nodegroup with the desired changes, move the load and delete the old one. Check [Deleting and draining](#deleting-and-draining). -### Scaling +### Scaling a single nodegroup A nodegroup can be scaled by using the `eksctl scale nodegroup` command: @@ -148,6 +148,8 @@ For example, to scale nodegroup `ng-a345f4e1` in `cluster-1` to 5 nodes, run: eksctl scale nodegroup --cluster=cluster-1 --nodes=5 ng-a345f4e1 ``` +A nodegroup can also be scaled by using a config file passed to `--config-file` and specifying the name of the nodegroup that should be scaled with `--name`. Eksctl will search the config file and discover that nodegroup as well as its scaling configuration values. + If the desired number of nodes is `NOT` within the range of current minimum and current maximum nodes, one specific error will be shown. Kindly note that these values can also be passed with flags `--nodes-min` and `--nodes-max` respectively. @@ -162,6 +164,12 @@ You can also enable SSH, ASG access and other features for a nodegroup, e.g.: eksctl create nodegroup --cluster=cluster-1 --node-labels="autoscaling=enabled,purpose=ci-worker" --asg-access --full-ecr-access --ssh-access ``` +### Scaling multiple nodegroups + +Eksctl can discover and scale all the nodegroups found in a config file that is passed with `--config-file`. + +The same validations apply to each nodegroup as when scaling a single nodegroup e.g. the desired number of nodes must be within the range of the current minimum and current maximum number of nodes. + ### Update labels There are no specific commands in `eksctl`to update the labels of a nodegroup but that can easily be achieved using From 438f85543d21329a2970809f3393091919e2422a Mon Sep 17 00:00:00 2001 From: nikimanoledaki <18622989+nikimanoledaki@users.noreply.github.com> Date: Thu, 18 Nov 2021 15:37:47 +0100 Subject: [PATCH 095/124] Rename consts and nodegroups for consistency * Also implement review feedback --- .../tests/crud/creategetdelete_test.go | 67 +++++++++++-------- .../tests/crud/testdata/scale-nodegroups.yaml | 4 +- .../tests/crud/testdata/taints-max-pods.yaml | 4 +- pkg/ctl/scale/nodegroup.go | 15 +++-- 4 files changed, 52 insertions(+), 38 deletions(-) diff --git a/integration/tests/crud/creategetdelete_test.go b/integration/tests/crud/creategetdelete_test.go index 01811138a8..7dedee33bb 100644 --- a/integration/tests/crud/creategetdelete_test.go +++ b/integration/tests/crud/creategetdelete_test.go @@ -59,8 +59,11 @@ func TestCRUD(t *testing.T) { var _ = Describe("(Integration) Create, Get, Scale & Delete", func() { const ( - initNG = "ng-0" - testNG = "ng-1" + mngNG1 = "mng-1" + mngNG2 = "mng-2" + + unmNG1 = "unm-1" + unmNG2 = "unm-2" ) commonTimeout := 10 * time.Minute @@ -104,8 +107,8 @@ var _ = Describe("(Integration) Create, Get, Scale & Delete", func() { "--verbose", "4", "--name", params.ClusterName, "--tags", "alpha.eksctl.io/description=eksctl integration test", - "--nodegroup-name", initNG, - "--node-labels", "ng-name="+initNG, + "--nodegroup-name", mngNG1, + "--node-labels", "ng-name="+mngNG1, "--nodes", "1", "--version", params.Version, "--kubeconfig", params.KubeconfigPath, @@ -130,7 +133,7 @@ var _ = Describe("(Integration) Create, Get, Scale & Delete", func() { Expect(awsSession).To(HaveExistingCluster(params.ClusterName, awseks.ClusterStatusActive, params.Version)) Expect(awsSession).To(HaveExistingStack(fmt.Sprintf("eksctl-%s-cluster", params.ClusterName))) - Expect(awsSession).To(HaveExistingStack(fmt.Sprintf("eksctl-%s-nodegroup-%s", params.ClusterName, initNG))) + Expect(awsSession).To(HaveExistingStack(fmt.Sprintf("eksctl-%s-nodegroup-%s", params.ClusterName, mngNG1))) }) It("should have created a valid kubectl config file", func() { @@ -223,8 +226,8 @@ var _ = Describe("(Integration) Create, Get, Scale & Delete", func() { By("asserting that both formats for taints are supported") var ( - nodeListN1 = tests.ListNodes(clientset, "n1") - nodeListN2 = tests.ListNodes(clientset, "n2") + nodeListN1 = tests.ListNodes(clientset) + nodeListN2 = tests.ListNodes(clientset, unmNG2) ) tests.AssertNodeTaints(nodeListN1, []corev1.Taint{ @@ -420,16 +423,26 @@ var _ = Describe("(Integration) Create, Get, Scale & Delete", func() { By("passing the name of the nodegroup as a flag") cmd := params.EksctlScaleNodeGroupCmd.WithArgs( "--cluster", params.ClusterName, - "--nodes-min", "3", + "--nodes-min", "4", "--nodes", "4", - "--nodes-max", "5", - "--name", initNG, + "--nodes-max", "4", + "--name", mngNG1, ) Expect(cmd).To(RunSuccessfully()) + + getMngNgCmd := params.EksctlGetCmd.WithArgs( + "nodegroup", + "--cluster", params.ClusterName, + "--name", mngNG1, + "-o", "yaml", + ) + Expect(getMngNgCmd).To(RunSuccessfullyWithOutputString(ContainSubstring("MaxSize: 4"))) + Expect(getMngNgCmd).To(RunSuccessfullyWithOutputString(ContainSubstring("MinSize: 4"))) + Expect(getMngNgCmd).To(RunSuccessfullyWithOutputString(ContainSubstring("DesiredCapacity: 4"))) }) It("should scale all nodegroups", func() { - By("scaling all nodegroups in the config file o the desired capacity, max size, and min size") + By("scaling all nodegroups in the config file to the desired capacity, max size, and min size") cmd := params.EksctlScaleNodeGroupCmd.WithArgs( "--config-file", "-", ). @@ -440,7 +453,7 @@ var _ = Describe("(Integration) Create, Get, Scale & Delete", func() { getMngNgCmd := params.EksctlGetCmd.WithArgs( "nodegroup", "--cluster", params.ClusterName, - "--name", initNG, + "--name", mngNG1, "-o", "yaml", ) Expect(getMngNgCmd).To(RunSuccessfullyWithOutputString(ContainSubstring("MaxSize: 5"))) @@ -450,7 +463,7 @@ var _ = Describe("(Integration) Create, Get, Scale & Delete", func() { getUnmNgCmd := params.EksctlGetCmd.WithArgs( "nodegroup", "--cluster", params.ClusterName, - "--name", "n1", + "--name", unmNG1, "-o", "yaml", ) Expect(getUnmNgCmd).To(RunSuccessfullyWithOutputString(ContainSubstring("MaxSize: 5"))) @@ -469,7 +482,7 @@ var _ = Describe("(Integration) Create, Get, Scale & Delete", func() { "--node-type", "p2.xlarge", "--node-private-networking", "--node-zones", "us-west-2b,us-west-2c", - testNG, + mngNG2, ) Expect(cmd).To(RunSuccessfully()) }) @@ -479,12 +492,12 @@ var _ = Describe("(Integration) Create, Get, Scale & Delete", func() { "nodegroup", "-o", "json", "--cluster", params.ClusterName, - initNG, + mngNG1, ) Expect(cmd).To(RunSuccessfullyWithOutputString(BeNodeGroupsWithNamesWhich( HaveLen(1), - ContainElement(initNG), - Not(ContainElement(testNG)), + ContainElement(mngNG1), + Not(ContainElement(mngNG2)), ))) Expect(cmd).To(RunSuccessfullyWithOutputString(ContainSubstring(params.Version))) @@ -492,12 +505,12 @@ var _ = Describe("(Integration) Create, Get, Scale & Delete", func() { "nodegroup", "-o", "json", "--cluster", params.ClusterName, - testNG, + mngNG2, ) Expect(cmd).To(RunSuccessfullyWithOutputString(BeNodeGroupsWithNamesWhich( HaveLen(1), - ContainElement(testNG), - Not(ContainElement(initNG)), + ContainElement(mngNG2), + Not(ContainElement(mngNG1)), ))) Expect(cmd).To(RunSuccessfullyWithOutputString(ContainSubstring(params.Version))) @@ -508,10 +521,10 @@ var _ = Describe("(Integration) Create, Get, Scale & Delete", func() { ) Expect(cmd).To(RunSuccessfullyWithOutputString(BeNodeGroupsWithNamesWhich( HaveLen(4), - ContainElement(initNG), - ContainElement(testNG), - ContainElement("n1"), - ContainElement("n2"), + ContainElement(mngNG1), + ContainElement(mngNG2), + ContainElement(unmNG1), + ContainElement(unmNG2), ))) Expect(cmd).To(RunSuccessfullyWithOutputString(ContainSubstring(params.Version))) }) @@ -1152,7 +1165,7 @@ var _ = Describe("(Integration) Create, Get, Scale & Delete", func() { "nodegroup", "--verbose", "4", "--cluster", params.ClusterName, - testNG, + mngNG2, ) Expect(cmd).To(RunSuccessfully()) }) @@ -1166,7 +1179,7 @@ var _ = Describe("(Integration) Create, Get, Scale & Delete", func() { "--nodes-min", "1", "--nodes", "1", "--nodes-max", "1", - "--name", initNG, + "--name", mngNG1, ) Expect(cmd).To(RunSuccessfully()) }) @@ -1176,7 +1189,7 @@ var _ = Describe("(Integration) Create, Get, Scale & Delete", func() { It("should not return an error", func() { cmd := params.EksctlDrainNodeGroupCmd.WithArgs( "--cluster", params.ClusterName, - "--name", initNG, + "--name", mngNG1, ) Expect(cmd).To(RunSuccessfully()) }) diff --git a/integration/tests/crud/testdata/scale-nodegroups.yaml b/integration/tests/crud/testdata/scale-nodegroups.yaml index 03f70dc397..82465b6ea3 100644 --- a/integration/tests/crud/testdata/scale-nodegroups.yaml +++ b/integration/tests/crud/testdata/scale-nodegroups.yaml @@ -6,13 +6,13 @@ metadata: name: nodeGroups: - - name: n1 + - name: unm-1 desiredCapacity: 5 maxSize: 5 minSize: 5 managedNodeGroups: - - name: ng-0 + - name: mng-1 desiredCapacity: 5 maxSize: 5 minSize: 5 diff --git a/integration/tests/crud/testdata/taints-max-pods.yaml b/integration/tests/crud/testdata/taints-max-pods.yaml index 9e3b3d7bd4..631c7c9ddf 100644 --- a/integration/tests/crud/testdata/taints-max-pods.yaml +++ b/integration/tests/crud/testdata/taints-max-pods.yaml @@ -6,12 +6,12 @@ metadata: name: nodeGroups: -- name: n1 +- name: unm-1 taints: key1: val1:NoSchedule key2: :NoExecute maxPodsPerNode: 123 -- name: n2 +- name: unm-2 volumeSize: 35 taints: - key: key1 diff --git a/pkg/ctl/scale/nodegroup.go b/pkg/ctl/scale/nodegroup.go index 298ee15ab4..d8f78ab484 100644 --- a/pkg/ctl/scale/nodegroup.go +++ b/pkg/ctl/scale/nodegroup.go @@ -63,13 +63,14 @@ func doScaleNodeGroup(cmd *cmdutils.Cmd, ng *api.NodeGroupBase) error { if err := scaleAllNodegroups(cmd); err != nil { return err } - } else { - if err := cmdutils.NewScaleNodeGroupLoader(cmd, ng).Load(); err != nil { - return err - } - if err := scaleNodegroup(cmd, ng); err != nil { - return err - } + return nil + } + + if err := cmdutils.NewScaleNodeGroupLoader(cmd, ng).Load(); err != nil { + return err + } + if err := scaleNodegroup(cmd, ng); err != nil { + return err } return nil } From 08aaea1e5247995809d3901952c1749300536ae7 Mon Sep 17 00:00:00 2001 From: nikimanoledaki <18622989+nikimanoledaki@users.noreply.github.com> Date: Fri, 19 Nov 2021 12:30:48 +0100 Subject: [PATCH 096/124] Add unit tests for scaling ng --- .../tests/crud/creategetdelete_test.go | 2 +- pkg/ctl/cmdutils/scale.go | 5 +- pkg/ctl/cmdutils/scale_test.go | 359 ++++++++++-------- pkg/ctl/scale/nodegroup_test.go | 2 +- 4 files changed, 203 insertions(+), 165 deletions(-) diff --git a/integration/tests/crud/creategetdelete_test.go b/integration/tests/crud/creategetdelete_test.go index 7dedee33bb..32a22bda7e 100644 --- a/integration/tests/crud/creategetdelete_test.go +++ b/integration/tests/crud/creategetdelete_test.go @@ -226,7 +226,7 @@ var _ = Describe("(Integration) Create, Get, Scale & Delete", func() { By("asserting that both formats for taints are supported") var ( - nodeListN1 = tests.ListNodes(clientset) + nodeListN1 = tests.ListNodes(clientset, unmNG1) nodeListN2 = tests.ListNodes(clientset, unmNG2) ) diff --git a/pkg/ctl/cmdutils/scale.go b/pkg/ctl/cmdutils/scale.go index cbb03fe6a6..b351cd0db8 100644 --- a/pkg/ctl/cmdutils/scale.go +++ b/pkg/ctl/cmdutils/scale.go @@ -65,12 +65,15 @@ func NewScaleAllNodeGroupLoader(cmd *Cmd) ClusterConfigLoader { ) l.validateWithConfigFile = func() error { + if len(l.ClusterConfig.AllNodeGroups()) == 0 { + return fmt.Errorf("no nodegroups found in config file") + } l.Plan = false return nil } l.validateWithoutConfigFile = func() error { - return fmt.Errorf("a config file is required when scaling multiple nodegroups") + return fmt.Errorf("a config file is required when --name is not set or when scaling multiple nodegroups") } return l diff --git a/pkg/ctl/cmdutils/scale_test.go b/pkg/ctl/cmdutils/scale_test.go index d29b418661..7b6f9a88b9 100644 --- a/pkg/ctl/cmdutils/scale_test.go +++ b/pkg/ctl/cmdutils/scale_test.go @@ -33,180 +33,204 @@ var _ = Describe("scale node group config file loader", func() { } } - When("scaling a single nodegroup", func() { - DescribeTable("scale nodegroup successfully via config file", - func(params scaleNodeGroupCase) { - cmd := &Cmd{ - CobraCommand: newCmd(), - ClusterConfigFile: "test_data/scale-ng-test.yaml", - ClusterConfig: api.NewClusterConfig(), - ProviderConfig: api.ProviderConfig{}, - NameArg: params.name, - } + When("a nodegroup name is passed with --name", func() { + Describe("for unmanaged nodegroups", func() { + DescribeTable("scales a single nodegroup successfully via config file", + func(params scaleNodeGroupCase) { + cmd := &Cmd{ + CobraCommand: newCmd(), + ClusterConfigFile: "test_data/scale-ng-test.yaml", + ClusterConfig: api.NewClusterConfig(), + ProviderConfig: api.ProviderConfig{}, + NameArg: params.name, + } - ng := api.NewNodeGroup().BaseNodeGroup() - err := NewScaleNodeGroupLoader(cmd, ng).Load() - if params.err != nil { - Expect(err).To(HaveOccurred()) - Expect(err.Error()).To(ContainSubstring(params.err.Error())) - } else { - if params.minSize != nil { - Expect(ng.MinSize).To(Equal(params.minSize)) + ng := api.NewNodeGroup().BaseNodeGroup() + err := NewScaleNodeGroupLoader(cmd, ng).Load() + if params.err != nil { + Expect(err).To(HaveOccurred()) + Expect(err.Error()).To(ContainSubstring(params.err.Error())) + } else { + if params.minSize != nil { + Expect(ng.MinSize).To(Equal(params.minSize)) + } + Expect(err).ToNot(HaveOccurred()) + } + }, + Entry("one node group matched", scaleNodeGroupCase{ + name: "ng-all-details", + }), + Entry("no node group matched", scaleNodeGroupCase{ + name: "123123", + err: fmt.Errorf("nodegroup 123123 not found in config file"), + }), + Entry("with no desired capacity", scaleNodeGroupCase{ + name: "ng-no-desired-capacity", + err: fmt.Errorf("number of nodes must be 0 or greater"), + }), + Entry("with no minSize and no maxSize", scaleNodeGroupCase{ + name: "ng-no-min-max", + }), + Entry("ng with minSize", scaleNodeGroupCase{ + name: "ng-with-min", + minSize: aws.Int(1), + }), + Entry("ng with wrong value for minSize", scaleNodeGroupCase{ + name: "ng-with-wrong-min", + err: fmt.Errorf("minimum number of nodes must be less than or equal to number of nodes"), + }), + Entry("ng with maxSize", scaleNodeGroupCase{ + name: "ng-with-max", + }), + Entry("ng with wrong value for maxSize", scaleNodeGroupCase{ + name: "ng-with-wrong-max", + err: fmt.Errorf("maximum number of nodes must be greater than or equal to number of nodes"), + }), + Entry("ng with desired nodes outside [minSize, maxSize]", scaleNodeGroupCase{ + name: "ng-with-wrong-desired", + err: fmt.Errorf("number of nodes must be within range of min nodes and max nodes"), + }), + ) + + DescribeTable("scales a single nodegroup successfully via cli flags", + func(params scaleNodeGroupCLICase) { + cfg := api.NewClusterConfig() + cfg.Metadata.Name = "cluster" + cmd := &Cmd{ + CobraCommand: newCmd(), + ProviderConfig: api.ProviderConfig{}, + ClusterConfig: cfg, + NameArg: params.name, } - Expect(err).ToNot(HaveOccurred()) - } - }, - Entry("one node group matched", scaleNodeGroupCase{ - name: "ng-all-details", - }), - Entry("no node group matched", scaleNodeGroupCase{ - name: "123123", - err: fmt.Errorf("nodegroup 123123 not found in config file"), - }), - Entry("with no desired capacity", scaleNodeGroupCase{ - name: "ng-no-desired-capacity", - err: fmt.Errorf("number of nodes must be 0 or greater"), - }), - Entry("with no minSize and no maxSize", scaleNodeGroupCase{ - name: "ng-no-min-max", - }), - Entry("ng with minSize", scaleNodeGroupCase{ - name: "ng-with-min", - minSize: aws.Int(1), - }), - Entry("ng with wrong value for minSize", scaleNodeGroupCase{ - name: "ng-with-wrong-min", - err: fmt.Errorf("minimum number of nodes must be less than or equal to number of nodes"), - }), - Entry("ng with maxSize", scaleNodeGroupCase{ - name: "ng-with-max", - }), - Entry("ng with wrong value for maxSize", scaleNodeGroupCase{ - name: "ng-with-wrong-max", - err: fmt.Errorf("maximum number of nodes must be greater than or equal to number of nodes"), - }), - Entry("ng with desired nodes outside [minSize, maxSize]", scaleNodeGroupCase{ - name: "ng-with-wrong-desired", - err: fmt.Errorf("number of nodes must be within range of min nodes and max nodes"), - }), - ) - - DescribeTable("scale nodegroup successfully via cli flags", - func(params scaleNodeGroupCLICase) { - cfg := api.NewClusterConfig() - cfg.Metadata.Name = "cluster" - cmd := &Cmd{ - CobraCommand: newCmd(), - ProviderConfig: api.ProviderConfig{}, - ClusterConfig: cfg, - NameArg: params.name, - } - ng := api.NewNodeGroup().BaseNodeGroup() - ng.MinSize = params.minSize - ng.MaxSize = params.maxSize - ng.DesiredCapacity = params.desiredSize - err := NewScaleNodeGroupLoader(cmd, ng).Load() - if params.err != nil { - Expect(err).To(HaveOccurred()) - Expect(err.Error()).To(ContainSubstring(params.err.Error())) - } else { - if params.minSize != nil { - Expect(ng.MinSize).To(Equal(params.minSize)) + ng := api.NewNodeGroup().BaseNodeGroup() + ng.MinSize = params.minSize + ng.MaxSize = params.maxSize + ng.DesiredCapacity = params.desiredSize + err := NewScaleNodeGroupLoader(cmd, ng).Load() + if params.err != nil { + Expect(err).To(HaveOccurred()) + Expect(err.Error()).To(ContainSubstring(params.err.Error())) + } else { + if params.minSize != nil { + Expect(ng.MinSize).To(Equal(params.minSize)) + } + Expect(err).ToNot(HaveOccurred()) } - Expect(err).ToNot(HaveOccurred()) - } - }, - Entry("only specifying min-nodes", scaleNodeGroupCLICase{ - name: "ng-with-max", - minSize: aws.Int(1), - }), - Entry("only specifying max-nodes", scaleNodeGroupCLICase{ - name: "ng-with-max", - maxSize: aws.Int(1), - }), - Entry("only specifying nodes", scaleNodeGroupCLICase{ - name: "ng-with-max", - desiredSize: aws.Int(1), - }), - Entry("minSize 0", scaleNodeGroupCLICase{ - name: "ng-with-max", - minSize: aws.Int(-1), - err: fmt.Errorf("minimum of nodes must be 0 or greater"), - }), - Entry("maxSize 0", scaleNodeGroupCLICase{ - name: "ng-with-max", - maxSize: aws.Int(-1), - err: fmt.Errorf("maximum of nodes must be 0 or greater"), - }), - Entry("desiredSize 0", scaleNodeGroupCLICase{ - name: "ng-with-max", - desiredSize: aws.Int(-1), - err: fmt.Errorf("number of nodes must be 0 or greater"), - }), - Entry("desiredSize greater than max", scaleNodeGroupCLICase{ - name: "ng-with-max", - desiredSize: aws.Int(3), - maxSize: aws.Int(1), - err: fmt.Errorf("maximum number of nodes must be greater than or equal to number of nodes"), - }), - Entry("desiredSize fewer than min", scaleNodeGroupCLICase{ - name: "ng-with-max", - desiredSize: aws.Int(2), - minSize: aws.Int(3), - err: fmt.Errorf("minimum number of nodes must be fewer than or equal to number of nodes"), - }), - Entry("min greater than max", scaleNodeGroupCLICase{ - name: "ng-with-max", - minSize: aws.Int(3), - maxSize: aws.Int(2), - err: fmt.Errorf("maximum number of nodes must be greater than minimum number of nodes"), - }), - Entry("not specifying any", scaleNodeGroupCLICase{ - name: "ng-with-max", - err: fmt.Errorf("at least one of minimum, maximum and desired nodes must be set"), - }), - ) + }, + Entry("only specifying min-nodes", scaleNodeGroupCLICase{ + name: "ng-with-max", + minSize: aws.Int(1), + }), + Entry("only specifying max-nodes", scaleNodeGroupCLICase{ + name: "ng-with-max", + maxSize: aws.Int(1), + }), + Entry("only specifying nodes", scaleNodeGroupCLICase{ + name: "ng-with-max", + desiredSize: aws.Int(1), + }), + Entry("minSize 0", scaleNodeGroupCLICase{ + name: "ng-with-max", + minSize: aws.Int(-1), + err: fmt.Errorf("minimum of nodes must be 0 or greater"), + }), + Entry("maxSize 0", scaleNodeGroupCLICase{ + name: "ng-with-max", + maxSize: aws.Int(-1), + err: fmt.Errorf("maximum of nodes must be 0 or greater"), + }), + Entry("desiredSize 0", scaleNodeGroupCLICase{ + name: "ng-with-max", + desiredSize: aws.Int(-1), + err: fmt.Errorf("number of nodes must be 0 or greater"), + }), + Entry("desiredSize greater than max", scaleNodeGroupCLICase{ + name: "ng-with-max", + desiredSize: aws.Int(3), + maxSize: aws.Int(1), + err: fmt.Errorf("maximum number of nodes must be greater than or equal to number of nodes"), + }), + Entry("desiredSize fewer than min", scaleNodeGroupCLICase{ + name: "ng-with-max", + desiredSize: aws.Int(2), + minSize: aws.Int(3), + err: fmt.Errorf("minimum number of nodes must be fewer than or equal to number of nodes"), + }), + Entry("min greater than max", scaleNodeGroupCLICase{ + name: "ng-with-max", + minSize: aws.Int(3), + maxSize: aws.Int(2), + err: fmt.Errorf("maximum number of nodes must be greater than minimum number of nodes"), + }), + Entry("not specifying any", scaleNodeGroupCLICase{ + name: "ng-with-max", + err: fmt.Errorf("at least one of minimum, maximum and desired nodes must be set"), + }), + ) + }) Describe("for managed nodegroups", func() { - Context("when using a config file", func() { - It("setting --name finds that individual nodegroup", func() { - ngName := "mng-ng" - ng := &api.NodeGroupBase{ - Name: ngName, - ScalingConfig: &api.ScalingConfig{ - DesiredCapacity: aws.Int(2), - }, - } + When("passing a config file", func() { + var ( + config *api.ClusterConfig + ng *api.NodeGroupBase + ) - config := api.NewClusterConfig() + BeforeEach(func() { + config = api.NewClusterConfig() config.Metadata.Name = "test-cluster" - config.ManagedNodeGroups = []*api.ManagedNodeGroup{ - { - NodeGroupBase: &api.NodeGroupBase{ - Name: ngName, - ScalingConfig: &api.ScalingConfig{ - DesiredCapacity: aws.Int(2), + ng = config.NewNodeGroup().BaseNodeGroup() + }) + + When("the nodegroup is in the config file", func() { + It("finds and scales that individual nodegroup", func() { + ngName := "mng-ng" + ng.Name = ngName + ng.ScalingConfig = &api.ScalingConfig{ + DesiredCapacity: aws.Int(2), + } + + config.ManagedNodeGroups = []*api.ManagedNodeGroup{ + { + NodeGroupBase: &api.NodeGroupBase{ + Name: ngName, + ScalingConfig: &api.ScalingConfig{ + DesiredCapacity: aws.Int(2), + }, }, }, - }, - } - cmd := &Cmd{ - CobraCommand: newCmd(), - ClusterConfig: config, - ProviderConfig: api.ProviderConfig{}, - } + } + cmd := &Cmd{ + CobraCommand: newCmd(), + ClusterConfig: config, + ProviderConfig: api.ProviderConfig{}, + } - err := NewScaleNodeGroupLoader(cmd, ng).Load() - Expect(err).NotTo(HaveOccurred()) + err := NewScaleNodeGroupLoader(cmd, ng).Load() + Expect(err).NotTo(HaveOccurred()) + }) + }) + + When("the nodegroup is not in the config file", func() { + It("fails to find and scale that nodegroup", func() { + cmd := &Cmd{ + CobraCommand: newCmd(), + ClusterConfig: config, + ProviderConfig: api.ProviderConfig{}, + } + + err := NewScaleNodeGroupLoader(cmd, ng).Load() + Expect(err).NotTo(BeNil()) + }) }) }) }) }) - When("scaling all nodegroups", func() { - When("using a config file", func() { - It("finds all nodegroups", func() { + When("a nodegroup name is not passed with --name", func() { + When("using a config file with nodegroups", func() { + It("finds and scales all nodegroups", func() { cmd := &Cmd{ CobraCommand: newCmd(), ClusterConfigFile: "test_data/scale-all-ng-test.yaml", @@ -226,15 +250,26 @@ var _ = Describe("scale node group config file loader", func() { }) }) - When("not using a config file", func() { - It("fails", func() { + When("using a config file with no nodegroups", func() { + It("fails to find find any nodegroup", func() { + cmd := &Cmd{ + CobraCommand: newCmd(), + ClusterConfigFile: "../../../examples/02-custom-vpc-cidr-no-nodes.yaml", + } + + err := NewScaleAllNodeGroupLoader(cmd).Load() + Expect(err).To(MatchError("no nodegroups found in config file")) + }) + }) + + When("a config file is not specified", func() { + It("fails to find find any nodegroups", func() { cmd := &Cmd{ CobraCommand: newCmd(), } err := NewScaleAllNodeGroupLoader(cmd).Load() - Expect(err).To(HaveOccurred()) - Expect(err).To(MatchError("a config file is required when scaling multiple nodegroups")) + Expect(err).To(MatchError("a config file is required when --name is not set or when scaling multiple nodegroups")) }) }) }) diff --git a/pkg/ctl/scale/nodegroup_test.go b/pkg/ctl/scale/nodegroup_test.go index fc0a30bb01..1a8b544fbf 100644 --- a/pkg/ctl/scale/nodegroup_test.go +++ b/pkg/ctl/scale/nodegroup_test.go @@ -12,7 +12,7 @@ import ( ) var _ = Describe("scale", func() { - Describe("nodegroup", func() { + Describe("scale nodegroup", func() { DescribeTable("scales a nodegroup successfully", func(args ...string) { cmd := newMockEmptyCmd(args...) From 8e140101f7ee24a41d42130d168f2e274347b5a8 Mon Sep 17 00:00:00 2001 From: brianrudolf-ep <80855380+brianrudolf-ep@users.noreply.github.com> Date: Fri, 19 Nov 2021 10:03:05 -0500 Subject: [PATCH 097/124] Update cluster-upgrade.md Add missing '=' --- userdocs/src/usage/cluster-upgrade.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/userdocs/src/usage/cluster-upgrade.md b/userdocs/src/usage/cluster-upgrade.md index e280e8a487..08857ebbff 100644 --- a/userdocs/src/usage/cluster-upgrade.md +++ b/userdocs/src/usage/cluster-upgrade.md @@ -37,7 +37,7 @@ This command will not apply any changes right away, you will need to re-run it w The target version for the cluster upgrade can be specified both with the CLI flag: ``` -eksctl upgrade cluster --name --version=1.16 +eksctl upgrade cluster --name= --version=1.16 ``` or with the config file From 8d285a825adc9db3c9401ba2eac290f9cfd6254c Mon Sep 17 00:00:00 2001 From: Adam Malcontenti-Wilson Date: Tue, 23 Nov 2021 18:15:48 +1100 Subject: [PATCH 098/124] Add AttachPolicy to NodeGroupIAM configuration (#4331) * Add AttachPolicy to NodeGroupIAM configuration * Add NodeGroup AttachPolicy tests * fix * Add nodegroup IAM attachPolicy field to userdocs * Add assertion for attachPolicy policy document * Compare JSON encoded policy due to interface differences --- .../eksctl.io/v1alpha5/assets/schema.json | 10 +++- pkg/apis/eksctl.io/v1alpha5/types.go | 4 ++ pkg/apis/eksctl.io/v1alpha5/validation.go | 3 ++ .../eksctl.io/v1alpha5/validation_test.go | 27 ++++++++++ .../v1alpha5/zz_generated.deepcopy.go | 1 + pkg/cfn/builder/fakes/fake_cfn_template.go | 1 + pkg/cfn/builder/iam.go | 8 +++ pkg/cfn/builder/iam_helper.go | 5 ++ pkg/cfn/builder/managed_nodegroup_test.go | 53 +++++++++++++++++-- pkg/cfn/builder/nodegroup_test.go | 23 ++++++++ userdocs/src/usage/iam-policies.md | 15 ++++++ 11 files changed, 144 insertions(+), 6 deletions(-) diff --git a/pkg/apis/eksctl.io/v1alpha5/assets/schema.json b/pkg/apis/eksctl.io/v1alpha5/assets/schema.json index cf31b49124..a966271467 100755 --- a/pkg/apis/eksctl.io/v1alpha5/assets/schema.json +++ b/pkg/apis/eksctl.io/v1alpha5/assets/schema.json @@ -1519,11 +1519,18 @@ }, "NodeGroupIAM": { "properties": { + "attachPolicy": { + "$ref": "#/definitions/InlineDocument", + "description": "holds a policy document to attach", + "x-intellij-html-description": "holds a policy document to attach" + }, "attachPolicyARNs": { "items": { "type": "string" }, - "type": "array" + "type": "array", + "description": "list of ARNs of the IAM policies to attach", + "x-intellij-html-description": "list of ARNs of the IAM policies to attach" }, "instanceProfileARN": { "type": "string" @@ -1542,6 +1549,7 @@ } }, "preferredOrder": [ + "attachPolicy", "attachPolicyARNs", "instanceProfileARN", "instanceRoleARN", diff --git a/pkg/apis/eksctl.io/v1alpha5/types.go b/pkg/apis/eksctl.io/v1alpha5/types.go index 12a8733cf9..e8f35cd813 100644 --- a/pkg/apis/eksctl.io/v1alpha5/types.go +++ b/pkg/apis/eksctl.io/v1alpha5/types.go @@ -1116,6 +1116,10 @@ type ( } // NodeGroupIAM holds all IAM attributes of a NodeGroup NodeGroupIAM struct { + // AttachPolicy holds a policy document to attach + // +optional + AttachPolicy InlineDocument `json:"attachPolicy,omitempty"` + // list of ARNs of the IAM policies to attach // +optional AttachPolicyARNs []string `json:"attachPolicyARNs,omitempty"` // +optional diff --git a/pkg/apis/eksctl.io/v1alpha5/validation.go b/pkg/apis/eksctl.io/v1alpha5/validation.go index 26a8688455..90f7739cf1 100644 --- a/pkg/apis/eksctl.io/v1alpha5/validation.go +++ b/pkg/apis/eksctl.io/v1alpha5/validation.go @@ -601,6 +601,9 @@ func validateNodeGroupIAM(iam *NodeGroupIAM, value, fieldName, path string) erro if iam.InstanceRoleName != "" { return fmtFieldConflictErr("instanceRoleName") } + if iam.AttachPolicy != nil { + return fmtFieldConflictErr("attachPolicy") + } if len(iam.AttachPolicyARNs) != 0 { return fmtFieldConflictErr("attachPolicyARNs") } diff --git a/pkg/apis/eksctl.io/v1alpha5/validation_test.go b/pkg/apis/eksctl.io/v1alpha5/validation_test.go index 2ac9ae6216..a61b75d002 100644 --- a/pkg/apis/eksctl.io/v1alpha5/validation_test.go +++ b/pkg/apis/eksctl.io/v1alpha5/validation_test.go @@ -9,6 +9,7 @@ import ( . "github.com/onsi/gomega" api "github.com/weaveworks/eksctl/pkg/apis/eksctl.io/v1alpha5" + cft "github.com/weaveworks/eksctl/pkg/cfn/template" "github.com/weaveworks/eksctl/pkg/utils/strings" ) @@ -228,6 +229,15 @@ var _ = Describe("ClusterConfig validation", func() { ng0 := cfg.NewNodeGroup() ng0.Name = "ng0" + ng0.IAM.AttachPolicy = cft.MakePolicyDocument( + cft.MapOfInterfaces{ + "Effect": "Allow", + "Action": []string{ + "s3:Get*", + }, + "Resource": "*", + }, + ) ng0.IAM.AttachPolicyARNs = []string{ "arn:aws:iam::aws:policy/Foo", "arn:aws:iam::aws:policy/Bar", @@ -308,6 +318,23 @@ var _ = Describe("ClusterConfig validation", func() { Expect(err.Error()).To(Equal("nodeGroups[1].iam.instanceRoleARN and nodeGroups[1].iam.instanceRoleName cannot be set at the same time")) }) + It("should not allow setting instanceRoleARN and attachPolicy", func() { + ng1.IAM.InstanceRoleARN = "r1" + ng1.IAM.AttachPolicy = cft.MakePolicyDocument( + cft.MapOfInterfaces{ + "Effect": "Allow", + "Action": []string{ + "s3:Get*", + }, + "Resource": "*", + }, + ) + + err = api.ValidateNodeGroup(1, ng1) + Expect(err).To(HaveOccurred()) + Expect(err.Error()).To(Equal("nodeGroups[1].iam.instanceRoleARN and nodeGroups[1].iam.attachPolicy cannot be set at the same time")) + }) + It("should not allow setting instanceRoleARN and attachPolicyARNs", func() { ng1.IAM.InstanceRoleARN = "r1" ng1.IAM.AttachPolicyARNs = []string{ diff --git a/pkg/apis/eksctl.io/v1alpha5/zz_generated.deepcopy.go b/pkg/apis/eksctl.io/v1alpha5/zz_generated.deepcopy.go index 9273a0095c..4f358e0bd6 100644 --- a/pkg/apis/eksctl.io/v1alpha5/zz_generated.deepcopy.go +++ b/pkg/apis/eksctl.io/v1alpha5/zz_generated.deepcopy.go @@ -1202,6 +1202,7 @@ func (in *NodeGroupBottlerocket) DeepCopy() *NodeGroupBottlerocket { // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *NodeGroupIAM) DeepCopyInto(out *NodeGroupIAM) { *out = *in + in.AttachPolicy.DeepCopyInto(&out.AttachPolicy) if in.AttachPolicyARNs != nil { in, out := &in.AttachPolicyARNs, &out.AttachPolicyARNs *out = make([]string, len(*in)) diff --git a/pkg/cfn/builder/fakes/fake_cfn_template.go b/pkg/cfn/builder/fakes/fake_cfn_template.go index 1462583f9b..0c6987664a 100644 --- a/pkg/cfn/builder/fakes/fake_cfn_template.go +++ b/pkg/cfn/builder/fakes/fake_cfn_template.go @@ -38,6 +38,7 @@ type Properties struct { AssumeRolePolicyDocument interface{} PolicyDocument struct { + Version string Statement []struct { Action []string Effect string diff --git a/pkg/cfn/builder/iam.go b/pkg/cfn/builder/iam.go index a9adcbcf72..fcddc7ff67 100644 --- a/pkg/cfn/builder/iam.go +++ b/pkg/cfn/builder/iam.go @@ -49,6 +49,14 @@ func (c *resourceSet) attachAllowPolicy(name string, refRole *gfnt.Value, statem }) } +func (c *resourceSet) attachAllowPolicyDocument(name string, refRole *gfnt.Value, document api.InlineDocument) { + c.newResource(name, &gfniam.Policy{ + PolicyName: makeName(name), + Roles: gfnt.NewSlice(refRole), + PolicyDocument: document, + }) +} + // WithIAM states, if IAM roles will be created or not func (c *ClusterResourceSet) WithIAM() bool { return c.rs.withIAM diff --git a/pkg/cfn/builder/iam_helper.go b/pkg/cfn/builder/iam_helper.go index d75e02affe..1f43e06b32 100644 --- a/pkg/cfn/builder/iam_helper.go +++ b/pkg/cfn/builder/iam_helper.go @@ -15,6 +15,7 @@ import ( type cfnTemplate interface { attachAllowPolicy(name string, refRole *gfnt.Value, statements []cft.MapOfInterfaces) + attachAllowPolicyDocument(name string, refRole *gfnt.Value, document api.InlineDocument) newResource(name string, resource gfn.Resource) *gfnt.Value } @@ -97,6 +98,10 @@ func createRole(cfnTemplate cfnTemplate, clusterIAMConfig *api.ClusterIAM, iamCo refIR := cfnTemplate.newResource(cfnIAMInstanceRoleName, &role) + if iamConfig.AttachPolicy != nil { + cfnTemplate.attachAllowPolicyDocument("Policy1", refIR, iamConfig.AttachPolicy) + } + if api.IsEnabled(iamConfig.WithAddonPolicies.AutoScaler) { cfnTemplate.attachAllowPolicy("PolicyAutoScaling", refIR, autoScalerStatements()) } diff --git a/pkg/cfn/builder/managed_nodegroup_test.go b/pkg/cfn/builder/managed_nodegroup_test.go index 03cd7c3bb1..16c8348082 100644 --- a/pkg/cfn/builder/managed_nodegroup_test.go +++ b/pkg/cfn/builder/managed_nodegroup_test.go @@ -1,11 +1,13 @@ package builder import ( + "encoding/json" "fmt" "testing" "github.com/stretchr/testify/require" api "github.com/weaveworks/eksctl/pkg/apis/eksctl.io/v1alpha5" + cft "github.com/weaveworks/eksctl/pkg/cfn/template" "github.com/weaveworks/eksctl/pkg/nodebootstrap" "github.com/weaveworks/eksctl/pkg/nodebootstrap/fakes" "github.com/weaveworks/eksctl/pkg/testutils/mockprovider" @@ -18,7 +20,9 @@ import ( func TestManagedPolicyResources(t *testing.T) { iamRoleTests := []struct { addons api.NodeGroupIAMAddonPolicies + attachPolicy api.InlineDocument attachPolicyARNs []string + expectedNewPolicies []string expectedManagedPolicies []*gfnt.Value description string }{ @@ -42,16 +46,36 @@ func TestManagedPolicyResources(t *testing.T) { "AmazonEC2ContainerRegistryReadOnly", "AmazonSSMManagedInstanceCore", "CloudWatchAgentServerPolicy"), description: "CloudWatch enabled", }, + { + addons: api.NodeGroupIAMAddonPolicies{ + AutoScaler: api.Enabled(), + }, + expectedNewPolicies: []string{"PolicyAutoScaling"}, + expectedManagedPolicies: makePartitionedPolicies("AmazonEKSWorkerNodePolicy", "AmazonEKS_CNI_Policy", "AmazonEC2ContainerRegistryReadOnly", "AmazonSSMManagedInstanceCore"), + description: "AutoScaler enabled", + }, + { + attachPolicy: cft.MakePolicyDocument(cft.MapOfInterfaces{ + "Effect": "Allow", + "Action": []string{ + "s3:Get*", + }, + "Resource": "*", + }), + expectedNewPolicies: []string{"Policy1"}, + expectedManagedPolicies: makePartitionedPolicies("AmazonEKSWorkerNodePolicy", "AmazonEKS_CNI_Policy", "AmazonEC2ContainerRegistryReadOnly", "AmazonSSMManagedInstanceCore"), + description: "Custom inline policies", + }, { attachPolicyARNs: []string{"AmazonEKSWorkerNodePolicy", "AmazonEKS_CNI_Policy"}, expectedManagedPolicies: subs(prefixPolicies("AmazonEKSWorkerNodePolicy", "AmazonEKS_CNI_Policy")), - description: "Custom policies", + description: "Custom managed policies", }, // should not attach any additional policies { attachPolicyARNs: []string{"CloudWatchAgentServerPolicy"}, expectedManagedPolicies: subs(prefixPolicies("CloudWatchAgentServerPolicy")), - description: "Custom policies", + description: "Custom managed policies", }, // no duplicate values { @@ -81,6 +105,7 @@ func TestManagedPolicyResources(t *testing.T) { ng := api.NewManagedNodeGroup() api.SetManagedNodeGroupDefaults(ng, clusterConfig.Metadata) ng.IAM.WithAddonPolicies = tt.addons + ng.IAM.AttachPolicy = tt.attachPolicy ng.IAM.AttachPolicyARNs = prefixPolicies(tt.attachPolicyARNs...) p := mockprovider.NewMockProvider() @@ -99,11 +124,29 @@ func TestManagedPolicyResources(t *testing.T) { template, err := goformation.ParseJSON(bytes) require.NoError(err) - role, ok := template.GetAllIAMRoleResources()["NodeInstanceRole"] - require.True(ok) + role, err := template.GetIAMRoleWithName(cfnIAMInstanceRoleName) + require.NoError(err) require.ElementsMatch(tt.expectedManagedPolicies, role.ManagedPolicyArns.Raw().(gfnt.Slice)) + policyNames := make([]string, 0) + for name := range template.GetAllIAMPolicyResources() { + policyNames = append(policyNames, name) + } + require.ElementsMatch(tt.expectedNewPolicies, policyNames) + + // assert custom inline policy matches + if tt.attachPolicy != nil { + policy, err := template.GetIAMPolicyWithName("Policy1") + require.NoError(err) + + // convert to json for comparison since interfaces are not identical + expectedPolicy, err := json.Marshal(tt.attachPolicy) + require.NoError(err) + actualPolicy, err := json.Marshal(policy.PolicyDocument) + require.NoError(err) + require.Equal(string(expectedPolicy), string(actualPolicy)) + } }) } @@ -167,7 +210,7 @@ func TestManagedNodeRole(t *testing.T) { template, err := goformation.ParseJSON(bytes) require.NoError(err) - ngResource, ok := template.Resources["ManagedNodeGroup"] + ngResource, ok := template.Resources[ManagedNodeGroupResourceName] require.True(ok) ng, ok := ngResource.(*gfneks.Nodegroup) require.True(ok) diff --git a/pkg/cfn/builder/nodegroup_test.go b/pkg/cfn/builder/nodegroup_test.go index da8e3c2d63..eafeaaa6de 100644 --- a/pkg/cfn/builder/nodegroup_test.go +++ b/pkg/cfn/builder/nodegroup_test.go @@ -14,6 +14,7 @@ import ( "github.com/weaveworks/eksctl/pkg/cfn/builder" "github.com/weaveworks/eksctl/pkg/cfn/builder/fakes" "github.com/weaveworks/eksctl/pkg/cfn/outputs" + cft "github.com/weaveworks/eksctl/pkg/cfn/template" "github.com/weaveworks/eksctl/pkg/eks/mocks" bootstrapfakes "github.com/weaveworks/eksctl/pkg/nodebootstrap/fakes" vpcfakes "github.com/weaveworks/eksctl/pkg/vpc/fakes" @@ -225,6 +226,28 @@ var _ = Describe("Unmanaged NodeGroup Template Builder", func() { }) // TODO move into IAM tests? + Context("attach policy is set", func() { + PolicyDocument := cft.MakePolicyDocument(cft.MapOfInterfaces{ + "Effect": "Allow", + "Action": []string{ + "s3:Get*", + }, + "Resource": "*", + }) + + BeforeEach(func() { + ng.IAM.AttachPolicy = PolicyDocument + }) + + It("adds a custom policy to the role", func() { + Expect(ngTemplate.Resources).To(HaveKey("Policy1")) + Expect(ngTemplate.Resources["Policy1"].Properties.PolicyDocument.Statement).To(HaveLen(1)) + Expect(ngTemplate.Resources["Policy1"].Properties.PolicyDocument.Statement[0].Action).To(Equal([]string{"s3:Get*"})) + Expect(ngTemplate.Resources["Policy1"].Properties.Roles).To(HaveLen(1)) + Expect(isRefTo(ngTemplate.Resources["Policy1"].Properties.Roles[0], "NodeInstanceRole")).To(BeTrue()) + }) + }) + Context("attach policy arns are set", func() { BeforeEach(func() { ng.IAM.AttachPolicyARNs = []string{"arn:aws:iam::1234567890:role/foo"} diff --git a/userdocs/src/usage/iam-policies.md b/userdocs/src/usage/iam-policies.md index 65845a85c6..f7a76dba59 100644 --- a/userdocs/src/usage/iam-policies.md +++ b/userdocs/src/usage/iam-policies.md @@ -59,6 +59,21 @@ nodeGroups: instanceRoleARN: "arn:aws:iam::123:role/eksctl-test-cluster-a-3-nodegroup-NodeInstanceRole-DNGMQTQHQHBJ" ``` +## Attaching inline policies + +```yaml +nodeGroups: + - name: my-special-nodegroup + iam: + attachPolicy: + Version: "2012-10-17" + Statement: + - Effect: Allow + Action: + - 's3:GetObject' + Resource: 'arn:aws:s3:::example-bucket/*' +``` + ## Attaching policies by ARN ```yaml From 075506a3c0cdcbeb90d84a78576661dfc894f2d9 Mon Sep 17 00:00:00 2001 From: Gergely Brautigam <182850+Skarlso@users.noreply.github.com> Date: Wed, 24 Nov 2021 13:25:25 +0100 Subject: [PATCH 099/124] Add config-file option to get cluster (#4468) --- pkg/ctl/cmdutils/configfile.go | 7 +++++++ pkg/ctl/get/cluster.go | 4 ++++ pkg/ctl/get/cluster_test.go | 22 ++++++++++++++++++++-- pkg/ctl/get/nodegroup_test.go | 6 +++--- pkg/eks/mocks/KubeNodeGroup.go | 2 +- 5 files changed, 35 insertions(+), 6 deletions(-) diff --git a/pkg/ctl/cmdutils/configfile.go b/pkg/ctl/cmdutils/configfile.go index 0d10447d7f..49ada47897 100644 --- a/pkg/ctl/cmdutils/configfile.go +++ b/pkg/ctl/cmdutils/configfile.go @@ -883,6 +883,13 @@ func NewGetLabelsLoader(cmd *Cmd, ngName string) ClusterConfigLoader { return l } +// NewGetClusterLoader will load config or use flags for 'eksctl get cluster(s)' +func NewGetClusterLoader(cmd *Cmd) ClusterConfigLoader { + l := newCommonClusterConfigLoader(cmd) + + return l +} + // validateSupportedConfigFields parses a config file's fields, evaluates if non-empty fields are supported, // and returns an error if a field is not supported. func validateSupportedConfigFields(obj interface{}, supportedFields []string, unsupportedFields []string) ([]string, error) { diff --git a/pkg/ctl/get/cluster.go b/pkg/ctl/get/cluster.go index e58b180884..3c87f5bc16 100644 --- a/pkg/ctl/get/cluster.go +++ b/pkg/ctl/get/cluster.go @@ -40,12 +40,16 @@ func getClusterCmd(cmd *cmdutils.Cmd) { cmdutils.AddRegionFlag(fs, &cmd.ProviderConfig) cmdutils.AddCommonFlagsForGetCmd(fs, ¶ms.chunkSize, ¶ms.output) cmdutils.AddTimeoutFlag(fs, &cmd.ProviderConfig.WaitTimeout) + cmdutils.AddConfigFileFlag(fs, &cmd.ClusterConfigFile) }) cmdutils.AddCommonFlagsForAWS(cmd.FlagSetGroup, &cmd.ProviderConfig, false) } func doGetCluster(cmd *cmdutils.Cmd, params *getCmdParams, listAllRegions bool) error { + if err := cmdutils.NewGetClusterLoader(cmd).Load(); err != nil { + return err + } cfg := cmd.ClusterConfig regionGiven := cfg.Metadata.Region != "" // eks.New resets this field, so we need to check if it was set in the first place diff --git a/pkg/ctl/get/cluster_test.go b/pkg/ctl/get/cluster_test.go index 2286010455..af6115c322 100644 --- a/pkg/ctl/get/cluster_test.go +++ b/pkg/ctl/get/cluster_test.go @@ -1,6 +1,8 @@ package get import ( + "os" + . "github.com/onsi/ginkgo" . "github.com/onsi/gomega" ) @@ -10,8 +12,24 @@ var _ = Describe("get", func() { It("with invalid flags", func() { cmd := newMockCmd("cluster", "--invalid", "dummy") _, err := cmd.execute() - Expect(err).To(HaveOccurred()) - Expect(err.Error()).To(ContainSubstring("Error: unknown flag: --invalid")) + Expect(err).To(MatchError(ContainSubstring("Error: unknown flag: --invalid"))) + }) + It("--name and --config-file together", func() { + f, err := os.CreateTemp("", "configfile") + Expect(err).NotTo(HaveOccurred()) + _, err = f.WriteString(getClusterConfigFile) + Expect(err).NotTo(HaveOccurred()) + cmd := newMockCmd("cluster", "--name", "dummy", "--config-file", f.Name()) + _, err = cmd.execute() + Expect(err).To(MatchError(ContainSubstring("Error: cannot use --name when --config-file/-f is set"))) }) }) }) + +var getClusterConfigFile = `apiVersion: eksctl.io/v1alpha5 +kind: ClusterConfig +metadata: + name: test-nodegroup-cluster-config + region: us-west-2 + version: '1.20' +` diff --git a/pkg/ctl/get/nodegroup_test.go b/pkg/ctl/get/nodegroup_test.go index ba365dd54a..e89922c904 100644 --- a/pkg/ctl/get/nodegroup_test.go +++ b/pkg/ctl/get/nodegroup_test.go @@ -24,7 +24,7 @@ var _ = Describe("get", func() { It("setting --name and --config-file at the same time", func() { f, err := os.CreateTemp("", "configfile") Expect(err).NotTo(HaveOccurred()) - _, err = f.WriteString(configFile) + _, err = f.WriteString(nodegroupConfigFile) Expect(err).NotTo(HaveOccurred()) cmd := newMockCmd("nodegroup", "--name", "name", "--config-file", f.Name()) _, err = cmd.execute() @@ -34,7 +34,7 @@ var _ = Describe("get", func() { It("setting --cluster and --config-file at the same time", func() { f, err := os.CreateTemp("", "configfile") Expect(err).NotTo(HaveOccurred()) - _, err = f.WriteString(configFile) + _, err = f.WriteString(nodegroupConfigFile) Expect(err).NotTo(HaveOccurred()) cmd := newMockCmd("nodegroup", "--cluster", "name", "--config-file", f.Name()) _, err = cmd.execute() @@ -49,7 +49,7 @@ var _ = Describe("get", func() { }) }) -var configFile = `apiVersion: eksctl.io/v1alpha5 +var nodegroupConfigFile = `apiVersion: eksctl.io/v1alpha5 kind: ClusterConfig metadata: diff --git a/pkg/eks/mocks/KubeNodeGroup.go b/pkg/eks/mocks/KubeNodeGroup.go index 49e2ea4f2b..c4714e2b50 100644 --- a/pkg/eks/mocks/KubeNodeGroup.go +++ b/pkg/eks/mocks/KubeNodeGroup.go @@ -1,4 +1,4 @@ -// Code generated by mockery v1.0.0. DO NOT EDIT. +// Code generated by mockery v0.0.0-dev. DO NOT EDIT. package mocks From 0724e0f9fb6dfc76a00620b2ce74eed34fc8f8eb Mon Sep 17 00:00:00 2001 From: Himangini Date: Wed, 24 Nov 2021 17:07:50 +0000 Subject: [PATCH 100/124] removed support for eks 1.17 --- pkg/actions/cluster/upgrade_test.go | 18 +- pkg/addons/default/assets/coredns-1.17.json | 358 -------- pkg/addons/default/coredns_test.go | 8 +- pkg/addons/default/testdata/sample-1.17.json | 841 ++++++++++++++++++ .../eksctl.io/v1alpha5/assets/schema.json | 5 +- pkg/apis/eksctl.io/v1alpha5/types.go | 7 +- pkg/eks/mocks/KubeNodeGroup.go | 2 +- 7 files changed, 861 insertions(+), 378 deletions(-) delete mode 100644 pkg/addons/default/assets/coredns-1.17.json create mode 100644 pkg/addons/default/testdata/sample-1.17.json diff --git a/pkg/actions/cluster/upgrade_test.go b/pkg/actions/cluster/upgrade_test.go index c3ad7f8fbb..8d06718e29 100644 --- a/pkg/actions/cluster/upgrade_test.go +++ b/pkg/actions/cluster/upgrade_test.go @@ -35,15 +35,15 @@ var _ = Describe("upgrade cluster", func() { Entry("upgrades by default when the version is not specified", upgradeCase{ givenVersion: "", - eksVersion: "1.16", - expectedUpgradeVersion: "1.17", + eksVersion: "1.17", + expectedUpgradeVersion: "1.18", expectedUpgrade: true, }), Entry("upgrades by default when the version is auto", upgradeCase{ givenVersion: "auto", - eksVersion: "1.16", - expectedUpgradeVersion: "1.17", + eksVersion: "1.17", + expectedUpgradeVersion: "1.18", expectedUpgrade: true, }), @@ -55,9 +55,9 @@ var _ = Describe("upgrade cluster", func() { }), Entry("upgrades to the next version when specified", upgradeCase{ - givenVersion: "1.17", - eksVersion: "1.16", - expectedUpgradeVersion: "1.17", + givenVersion: "1.18", + eksVersion: "1.17", + expectedUpgradeVersion: "1.18", expectedUpgrade: true, }), @@ -69,8 +69,8 @@ var _ = Describe("upgrade cluster", func() { }), Entry("fails when the upgrade jumps more than one kubernetes version", upgradeCase{ - givenVersion: "1.17", - eksVersion: "1.15", + givenVersion: "1.18", + eksVersion: "1.16", expectedErrorText: "upgrading more than one version at a time is not supported", }), diff --git a/pkg/addons/default/assets/coredns-1.17.json b/pkg/addons/default/assets/coredns-1.17.json deleted file mode 100644 index 0c592cf9fb..0000000000 --- a/pkg/addons/default/assets/coredns-1.17.json +++ /dev/null @@ -1,358 +0,0 @@ -{ - "apiVersion": "v1", - "items": [ - { - "apiVersion": "v1", - "kind": "Service", - "metadata": { - "annotations": { - "prometheus.io/port": "9153", - "prometheus.io/scrape": "true" - }, - "labels": { - "eks.amazonaws.com/component": "kube-dns", - "k8s-app": "kube-dns", - "kubernetes.io/cluster-service": "true", - "kubernetes.io/name": "CoreDNS" - }, - "name": "kube-dns", - "namespace": "kube-system" - }, - "spec": { - "ports": [ - { - "name": "dns", - "port": 53, - "protocol": "UDP", - "targetPort": 53 - }, - { - "name": "dns-tcp", - "port": 53, - "protocol": "TCP", - "targetPort": 53 - } - ], - "selector": { - "k8s-app": "kube-dns" - }, - "sessionAffinity": "None", - "type": "ClusterIP" - } - }, - { - "apiVersion": "v1", - "kind": "ServiceAccount", - "metadata": { - "annotations": {}, - "labels": { - "eks.amazonaws.com/component": "coredns", - "k8s-app": "kube-dns" - }, - "name": "coredns", - "namespace": "kube-system" - } - }, - { - "apiVersion": "v1", - "data": { - "Corefile": ".:53 {\n errors\n health\n kubernetes cluster.local in-addr.arpa ip6.arpa {\n pods insecure\n upstream\n fallthrough in-addr.arpa ip6.arpa\n }\n prometheus :9153\n forward . /etc/resolv.conf\n cache 30\n loop\n reload\n loadbalance\n}\n" - }, - "kind": "ConfigMap", - "metadata": { - "annotations": {}, - "labels": { - "eks.amazonaws.com/component": "coredns", - "k8s-app": "kube-dns" - }, - "name": "coredns", - "namespace": "kube-system" - } - }, - { - "apiVersion": "apps/v1", - "kind": "Deployment", - "metadata": { - "annotations": {}, - "labels": { - "eks.amazonaws.com/component": "coredns", - "k8s-app": "kube-dns", - "kubernetes.io/name": "CoreDNS" - }, - "name": "coredns", - "namespace": "kube-system" - }, - "spec": { - "progressDeadlineSeconds": 600, - "replicas": 2, - "revisionHistoryLimit": 10, - "selector": { - "matchLabels": { - "eks.amazonaws.com/component": "coredns", - "k8s-app": "kube-dns" - } - }, - "strategy": { - "rollingUpdate": { - "maxSurge": "25%", - "maxUnavailable": 1 - }, - "type": "RollingUpdate" - }, - "template": { - "metadata": { - "annotations": { - "eks.amazonaws.com/compute-type": "ec2" - }, - "creationTimestamp": null, - "labels": { - "eks.amazonaws.com/component": "coredns", - "k8s-app": "kube-dns" - } - }, - "spec": { - "affinity": { - "nodeAffinity": { - "requiredDuringSchedulingIgnoredDuringExecution": { - "nodeSelectorTerms": [ - { - "matchExpressions": [ - { - "key": "beta.kubernetes.io/os", - "operator": "In", - "values": [ - "linux" - ] - }, - { - "key": "beta.kubernetes.io/arch", - "operator": "In", - "values": [ - "amd64", - "arm64" - ] - } - ] - } - ] - } - }, - "podAntiAffinity": { - "preferredDuringSchedulingIgnoredDuringExecution": [ - { - "podAffinityTerm": { - "labelSelector": { - "matchExpressions": [ - { - "key": "k8s-app", - "operator": "In", - "values": [ - "kube-dns" - ] - } - ] - }, - "topologyKey": "kubernetes.io/hostname" - }, - "weight": 100 - } - ] - } - }, - "containers": [ - { - "args": [ - "-conf", - "/etc/coredns/Corefile" - ], - "image": "%s.dkr.ecr.%s.%s/eks/coredns:v1.6.6-eksbuild.1", - "imagePullPolicy": "IfNotPresent", - "livenessProbe": { - "failureThreshold": 5, - "httpGet": { - "path": "/health", - "port": 8080, - "scheme": "HTTP" - }, - "initialDelaySeconds": 60, - "periodSeconds": 10, - "successThreshold": 1, - "timeoutSeconds": 5 - }, - "name": "coredns", - "ports": [ - { - "containerPort": 53, - "name": "dns", - "protocol": "UDP" - }, - { - "containerPort": 53, - "name": "dns-tcp", - "protocol": "TCP" - }, - { - "containerPort": 9153, - "name": "metrics", - "protocol": "TCP" - } - ], - "readinessProbe": { - "failureThreshold": 3, - "httpGet": { - "path": "/health", - "port": 8080, - "scheme": "HTTP" - }, - "periodSeconds": 10, - "successThreshold": 1, - "timeoutSeconds": 1 - }, - "resources": { - "limits": { - "memory": "170Mi" - }, - "requests": { - "cpu": "100m", - "memory": "70Mi" - } - }, - "securityContext": { - "allowPrivilegeEscalation": false, - "capabilities": { - "add": [ - "NET_BIND_SERVICE" - ], - "drop": [ - "all" - ] - }, - "readOnlyRootFilesystem": true - }, - "terminationMessagePath": "/dev/termination-log", - "terminationMessagePolicy": "File", - "volumeMounts": [ - { - "mountPath": "/etc/coredns", - "name": "config-volume", - "readOnly": true - }, - { - "mountPath": "/tmp", - "name": "tmp" - } - ] - } - ], - "dnsPolicy": "Default", - "priorityClassName": "system-cluster-critical", - "restartPolicy": "Always", - "schedulerName": "default-scheduler", - "securityContext": {}, - "serviceAccount": "coredns", - "serviceAccountName": "coredns", - "terminationGracePeriodSeconds": 30, - "tolerations": [ - { - "effect": "NoSchedule", - "key": "node-role.kubernetes.io/master" - }, - { - "key": "CriticalAddonsOnly", - "operator": "Exists" - } - ], - "volumes": [ - { - "emptyDir": {}, - "name": "tmp" - }, - { - "configMap": { - "defaultMode": 420, - "items": [ - { - "key": "Corefile", - "path": "Corefile" - } - ], - "name": "coredns" - }, - "name": "config-volume" - } - ] - } - } - } - }, - { - "apiVersion": "rbac.authorization.k8s.io/v1", - "kind": "ClusterRole", - "metadata": { - "annotations": {}, - "labels": { - "eks.amazonaws.com/component": "coredns", - "k8s-app": "kube-dns", - "kubernetes.io/bootstrapping": "rbac-defaults" - }, - "name": "system:coredns" - }, - "rules": [ - { - "apiGroups": [ - "" - ], - "resources": [ - "endpoints", - "services", - "pods", - "namespaces" - ], - "verbs": [ - "list", - "watch" - ] - }, - { - "apiGroups": [ - "" - ], - "resources": [ - "nodes" - ], - "verbs": [ - "get" - ] - } - ] - }, - { - "apiVersion": "rbac.authorization.k8s.io/v1", - "kind": "ClusterRoleBinding", - "metadata": { - "annotations": { - "rbac.authorization.kubernetes.io/autoupdate": "true" - }, - "labels": { - "eks.amazonaws.com/component": "coredns", - "k8s-app": "kube-dns", - "kubernetes.io/bootstrapping": "rbac-defaults" - }, - "name": "system:coredns" - }, - "roleRef": { - "apiGroup": "rbac.authorization.k8s.io", - "kind": "ClusterRole", - "name": "system:coredns" - }, - "subjects": [ - { - "kind": "ServiceAccount", - "name": "coredns", - "namespace": "kube-system" - } - ] - } - ], - "kind": "List" -} diff --git a/pkg/addons/default/coredns_test.go b/pkg/addons/default/coredns_test.go index 94a2922341..7719ba380a 100644 --- a/pkg/addons/default/coredns_test.go +++ b/pkg/addons/default/coredns_test.go @@ -27,8 +27,8 @@ var _ = Describe("default addons - coredns", func() { rawClient.UseUnionTracker = true ct = rawClient.Collection region = "eu-west-2" - controlPlaneVersion = "1.17.x" - kubernetesVersion = "1.16" + controlPlaneVersion = "1.18.x" + kubernetesVersion = "1.17" input = da.AddonInput{ RawClient: rawClient, @@ -44,7 +44,7 @@ var _ = Describe("default addons - coredns", func() { BeforeEach(func() { createCoreDNSFromTestSample(rawClient, ct, kubernetesVersion) - expectedImageTag = "v1.6.6-eksbuild.1" + expectedImageTag = "v1.7.0-eksbuild.1" }) It("updates coredns to the correct version", func() { @@ -80,7 +80,7 @@ var _ = Describe("default addons - coredns", func() { Context("when CoreDNS is NOT up to date", func() { BeforeEach(func() { - input.ControlPlaneVersion = "1.18.x" + input.ControlPlaneVersion = "1.19.x" }) It("reports 'false'", func() { diff --git a/pkg/addons/default/testdata/sample-1.17.json b/pkg/addons/default/testdata/sample-1.17.json new file mode 100644 index 0000000000..1686d2fa4d --- /dev/null +++ b/pkg/addons/default/testdata/sample-1.17.json @@ -0,0 +1,841 @@ +{ + "apiVersion": "v1", + "items": [ + { + "apiVersion": "apps/v1", + "kind": "DaemonSet", + "metadata": { + "annotations": { + "deprecated.daemonset.template.generation": "1" + }, + "labels": { + "eks.amazonaws.com/component": "kube-proxy", + "k8s-app": "kube-proxy" + }, + "name": "kube-proxy", + "namespace": "kube-system" + }, + "spec": { + "revisionHistoryLimit": 10, + "selector": { + "matchLabels": { + "k8s-app": "kube-proxy" + } + }, + "template": { + "metadata": { + "creationTimestamp": null, + "labels": { + "k8s-app": "kube-proxy" + } + }, + "spec": { + "affinity": { + "nodeAffinity": { + "requiredDuringSchedulingIgnoredDuringExecution": { + "nodeSelectorTerms": [ + { + "matchExpressions": [ + { + "key": "beta.kubernetes.io/os", + "operator": "In", + "values": [ + "linux" + ] + }, + { + "key": "beta.kubernetes.io/arch", + "operator": "In", + "values": [ + "amd64" + ] + }, + { + "key": "eks.amazonaws.com/compute-type", + "operator": "NotIn", + "values": [ + "fargate" + ] + } + ] + } + ] + } + } + }, + "containers": [ + { + "command": [ + "kube-proxy", + "--v=2", + "--config=/var/lib/kube-proxy-config/config" + ], + "image": "602401143452.dkr.ecr.eu-west-1.amazonaws.com/eks/kube-proxy:v1.16.8", + "imagePullPolicy": "IfNotPresent", + "name": "kube-proxy", + "resources": { + "requests": { + "cpu": "100m" + } + }, + "securityContext": { + "privileged": true + }, + "terminationMessagePath": "/dev/termination-log", + "terminationMessagePolicy": "File", + "volumeMounts": [ + { + "mountPath": "/var/log", + "name": "varlog" + }, + { + "mountPath": "/run/xtables.lock", + "name": "xtables-lock" + }, + { + "mountPath": "/lib/modules", + "name": "lib-modules", + "readOnly": true + }, + { + "mountPath": "/var/lib/kube-proxy/", + "name": "kubeconfig" + }, + { + "mountPath": "/var/lib/kube-proxy-config/", + "name": "config" + } + ] + } + ], + "dnsPolicy": "ClusterFirst", + "hostNetwork": true, + "priorityClassName": "system-node-critical", + "restartPolicy": "Always", + "schedulerName": "default-scheduler", + "securityContext": {}, + "serviceAccount": "kube-proxy", + "serviceAccountName": "kube-proxy", + "terminationGracePeriodSeconds": 30, + "tolerations": [ + { + "operator": "Exists" + } + ], + "volumes": [ + { + "hostPath": { + "path": "/var/log", + "type": "" + }, + "name": "varlog" + }, + { + "hostPath": { + "path": "/run/xtables.lock", + "type": "FileOrCreate" + }, + "name": "xtables-lock" + }, + { + "hostPath": { + "path": "/lib/modules", + "type": "" + }, + "name": "lib-modules" + }, + { + "configMap": { + "defaultMode": 420, + "name": "kube-proxy" + }, + "name": "kubeconfig" + }, + { + "configMap": { + "defaultMode": 420, + "name": "kube-proxy-config" + }, + "name": "config" + } + ] + } + }, + "updateStrategy": { + "rollingUpdate": { + "maxUnavailable": "10%" + }, + "type": "RollingUpdate" + } + } + }, + { + "apiVersion": "v1", + "kind": "Service", + "metadata": { + "annotations": { + "prometheus.io/port": "9153", + "prometheus.io/scrape": "true" + }, + "labels": { + "eks.amazonaws.com/component": "kube-dns", + "k8s-app": "kube-dns", + "kubernetes.io/cluster-service": "true", + "kubernetes.io/name": "CoreDNS" + }, + "name": "kube-dns", + "namespace": "kube-system" + }, + "spec": { + "clusterIP": "10.100.0.10", + "ports": [ + { + "name": "dns", + "port": 53, + "protocol": "UDP", + "targetPort": 53 + }, + { + "name": "dns-tcp", + "port": 53, + "protocol": "TCP", + "targetPort": 53 + } + ], + "selector": { + "k8s-app": "kube-dns" + }, + "sessionAffinity": "None", + "type": "ClusterIP" + } + }, + { + "apiVersion": "v1", + "kind": "ServiceAccount", + "metadata": { + "annotations": {}, + "labels": { + "eks.amazonaws.com/component": "coredns", + "k8s-app": "kube-dns" + }, + "name": "coredns", + "namespace": "kube-system" + } + }, + { + "apiVersion": "v1", + "data": { + "Corefile": ".:53 {\n errors\n health\n kubernetes cluster.local in-addr.arpa ip6.arpa {\n pods insecure\n upstream\n fallthrough in-addr.arpa ip6.arpa\n }\n prometheus :9153\n forward . /etc/resolv.conf\n cache 30\n loop\n reload\n loadbalance\n}\n" + }, + "kind": "ConfigMap", + "metadata": { + "annotations": {}, + "labels": { + "eks.amazonaws.com/component": "coredns", + "k8s-app": "kube-dns" + }, + "name": "coredns", + "namespace": "kube-system" + } + }, + { + "apiVersion": "apps/v1", + "kind": "Deployment", + "metadata": { + "annotations": {}, + "labels": { + "eks.amazonaws.com/component": "coredns", + "k8s-app": "kube-dns", + "kubernetes.io/name": "CoreDNS" + }, + "name": "coredns", + "namespace": "kube-system" + }, + "spec": { + "progressDeadlineSeconds": 600, + "replicas": 2, + "revisionHistoryLimit": 10, + "selector": { + "matchLabels": { + "eks.amazonaws.com/component": "coredns", + "k8s-app": "kube-dns" + } + }, + "strategy": { + "rollingUpdate": { + "maxSurge": "25%", + "maxUnavailable": 1 + }, + "type": "RollingUpdate" + }, + "template": { + "metadata": { + "annotations": { + "eks.amazonaws.com/compute-type": "ec2" + }, + "creationTimestamp": null, + "labels": { + "eks.amazonaws.com/component": "coredns", + "k8s-app": "kube-dns" + } + }, + "spec": { + "affinity": { + "nodeAffinity": { + "requiredDuringSchedulingIgnoredDuringExecution": { + "nodeSelectorTerms": [ + { + "matchExpressions": [ + { + "key": "beta.kubernetes.io/os", + "operator": "In", + "values": [ + "linux" + ] + }, + { + "key": "beta.kubernetes.io/arch", + "operator": "In", + "values": [ + "amd64" + ] + } + ] + } + ] + } + }, + "podAntiAffinity": { + "preferredDuringSchedulingIgnoredDuringExecution": [ + { + "podAffinityTerm": { + "labelSelector": { + "matchExpressions": [ + { + "key": "k8s-app", + "operator": "In", + "values": [ + "kube-dns" + ] + } + ] + }, + "topologyKey": "kubernetes.io/hostname" + }, + "weight": 100 + } + ] + } + }, + "containers": [ + { + "args": [ + "-conf", + "/etc/coredns/Corefile" + ], + "image": "%s.dkr.ecr.%s.%s/eks/coredns:v1.6.6", + "imagePullPolicy": "IfNotPresent", + "livenessProbe": { + "failureThreshold": 5, + "httpGet": { + "path": "/health", + "port": 8080, + "scheme": "HTTP" + }, + "initialDelaySeconds": 60, + "periodSeconds": 10, + "successThreshold": 1, + "timeoutSeconds": 5 + }, + "name": "coredns", + "ports": [ + { + "containerPort": 53, + "name": "dns", + "protocol": "UDP" + }, + { + "containerPort": 53, + "name": "dns-tcp", + "protocol": "TCP" + }, + { + "containerPort": 9153, + "name": "metrics", + "protocol": "TCP" + } + ], + "readinessProbe": { + "failureThreshold": 3, + "httpGet": { + "path": "/health", + "port": 8080, + "scheme": "HTTP" + }, + "periodSeconds": 10, + "successThreshold": 1, + "timeoutSeconds": 1 + }, + "resources": { + "limits": { + "memory": "170Mi" + }, + "requests": { + "cpu": "100m", + "memory": "70Mi" + } + }, + "securityContext": { + "allowPrivilegeEscalation": false, + "capabilities": { + "add": [ + "NET_BIND_SERVICE" + ], + "drop": [ + "all" + ] + }, + "readOnlyRootFilesystem": true + }, + "terminationMessagePath": "/dev/termination-log", + "terminationMessagePolicy": "File", + "volumeMounts": [ + { + "mountPath": "/etc/coredns", + "name": "config-volume", + "readOnly": true + }, + { + "mountPath": "/tmp", + "name": "tmp" + } + ] + } + ], + "dnsPolicy": "Default", + "priorityClassName": "system-cluster-critical", + "restartPolicy": "Always", + "schedulerName": "default-scheduler", + "securityContext": {}, + "serviceAccount": "coredns", + "serviceAccountName": "coredns", + "terminationGracePeriodSeconds": 30, + "tolerations": [ + { + "effect": "NoSchedule", + "key": "node-role.kubernetes.io/master" + }, + { + "key": "CriticalAddonsOnly", + "operator": "Exists" + } + ], + "volumes": [ + { + "emptyDir": {}, + "name": "tmp" + }, + { + "configMap": { + "defaultMode": 420, + "items": [ + { + "key": "Corefile", + "path": "Corefile" + } + ], + "name": "coredns" + }, + "name": "config-volume" + } + ] + } + } + } + }, + { + "apiVersion": "rbac.authorization.k8s.io/v1", + "kind": "ClusterRole", + "metadata": { + "annotations": {}, + "labels": { + "eks.amazonaws.com/component": "coredns", + "k8s-app": "kube-dns", + "kubernetes.io/bootstrapping": "rbac-defaults" + }, + "name": "system:coredns" + }, + "rules": [ + { + "apiGroups": [ + "" + ], + "resources": [ + "endpoints", + "services", + "pods", + "namespaces" + ], + "verbs": [ + "list", + "watch" + ] + }, + { + "apiGroups": [ + "" + ], + "resources": [ + "nodes" + ], + "verbs": [ + "get" + ] + } + ] + }, + { + "apiVersion": "rbac.authorization.k8s.io/v1", + "kind": "ClusterRoleBinding", + "metadata": { + "annotations": { + "rbac.authorization.kubernetes.io/autoupdate": "true" + }, + "labels": { + "eks.amazonaws.com/component": "coredns", + "k8s-app": "kube-dns", + "kubernetes.io/bootstrapping": "rbac-defaults" + }, + "name": "system:coredns" + }, + "roleRef": { + "apiGroup": "rbac.authorization.k8s.io", + "kind": "ClusterRole", + "name": "system:coredns" + }, + "subjects": [ + { + "kind": "ServiceAccount", + "name": "coredns", + "namespace": "kube-system" + } + ] + }, + { + "apiVersion": "apps/v1", + "kind": "DaemonSet", + "metadata": { + "annotations": { + "deprecated.daemonset.template.generation": "1" + }, + "labels": { + "k8s-app": "aws-node" + }, + "name": "aws-node", + "namespace": "kube-system" + }, + "spec": { + "revisionHistoryLimit": 10, + "selector": { + "matchLabels": { + "k8s-app": "aws-node" + } + }, + "template": { + "metadata": { + "creationTimestamp": null, + "labels": { + "k8s-app": "aws-node" + } + }, + "spec": { + "affinity": { + "nodeAffinity": { + "requiredDuringSchedulingIgnoredDuringExecution": { + "nodeSelectorTerms": [ + { + "matchExpressions": [ + { + "key": "kubernetes.io/os", + "operator": "In", + "values": [ + "linux" + ] + }, + { + "key": "kubernetes.io/arch", + "operator": "In", + "values": [ + "amd64" + ] + }, + { + "key": "eks.amazonaws.com/compute-type", + "operator": "NotIn", + "values": [ + "fargate" + ] + } + ] + } + ] + } + } + }, + "containers": [ + { + "env": [ + { + "name": "AWS_VPC_K8S_CNI_LOGLEVEL", + "value": "DEBUG" + }, + { + "name": "AWS_VPC_K8S_CNI_VETHPREFIX", + "value": "eni" + }, + { + "name": "AWS_VPC_ENI_MTU", + "value": "9001" + }, + { + "name": "MY_NODE_NAME", + "valueFrom": { + "fieldRef": { + "apiVersion": "v1", + "fieldPath": "spec.nodeName" + } + } + } + ], + "image": "602401143452.dkr.ecr.us-west-2.amazonaws.com/amazon-k8s-cni:v1.7.6", + "imagePullPolicy": "Always", + "livenessProbe": { + "exec": { + "command": [ + "/app/grpc-health-probe", + "-addr=:50051" + ] + }, + "failureThreshold": 3, + "initialDelaySeconds": 35, + "periodSeconds": 10, + "successThreshold": 1, + "timeoutSeconds": 1 + }, + "name": "aws-node", + "ports": [ + { + "containerPort": 61678, + "hostPort": 61678, + "name": "metrics", + "protocol": "TCP" + } + ], + "readinessProbe": { + "exec": { + "command": [ + "/app/grpc-health-probe", + "-addr=:50051" + ] + }, + "failureThreshold": 3, + "initialDelaySeconds": 35, + "periodSeconds": 10, + "successThreshold": 1, + "timeoutSeconds": 1 + }, + "resources": { + "requests": { + "cpu": "10m" + } + }, + "securityContext": { + "privileged": true + }, + "terminationMessagePath": "/dev/termination-log", + "terminationMessagePolicy": "File", + "volumeMounts": [ + { + "mountPath": "/host/opt/cni/bin", + "name": "cni-bin-dir" + }, + { + "mountPath": "/host/etc/cni/net.d", + "name": "cni-net-dir" + }, + { + "mountPath": "/host/var/log", + "name": "log-dir" + }, + { + "mountPath": "/var/run/docker.sock", + "name": "dockersock" + }, + { + "mountPath": "/var/run/dockershim.sock", + "name": "dockershim" + } + ] + } + ], + "dnsPolicy": "ClusterFirst", + "hostNetwork": true, + "priorityClassName": "system-node-critical", + "restartPolicy": "Always", + "schedulerName": "default-scheduler", + "securityContext": {}, + "serviceAccount": "aws-node", + "serviceAccountName": "aws-node", + "terminationGracePeriodSeconds": 30, + "tolerations": [ + { + "operator": "Exists" + } + ], + "volumes": [ + { + "hostPath": { + "path": "/opt/cni/bin", + "type": "" + }, + "name": "cni-bin-dir" + }, + { + "hostPath": { + "path": "/etc/cni/net.d", + "type": "" + }, + "name": "cni-net-dir" + }, + { + "hostPath": { + "path": "/var/log", + "type": "" + }, + "name": "log-dir" + }, + { + "hostPath": { + "path": "/var/run/docker.sock", + "type": "" + }, + "name": "dockersock" + }, + { + "hostPath": { + "path": "/var/run/dockershim.sock", + "type": "" + }, + "name": "dockershim" + } + ] + } + }, + "updateStrategy": { + "rollingUpdate": { + "maxUnavailable": "10%" + }, + "type": "RollingUpdate" + } + } + }, + { + "apiVersion": "apiextensions.k8s.io/v1", + "kind": "CustomResourceDefinition", + "metadata": { + "annotations": {}, + "name": "eniconfigs.crd.k8s.amazonaws.com" + }, + "spec": { + "conversion": { + "strategy": "None" + }, + "group": "crd.k8s.amazonaws.com", + "names": { + "kind": "ENIConfig", + "listKind": "ENIConfigList", + "plural": "eniconfigs", + "singular": "eniconfig" + }, + "preserveUnknownFields": true, + "scope": "Cluster", + "versions": [ + { + "name": "v1alpha1", + "served": true, + "storage": true + } + ] + } + }, + { + "apiVersion": "rbac.authorization.k8s.io/v1", + "kind": "ClusterRole", + "metadata": { + "annotations": {}, + "name": "aws-node" + }, + "rules": [ + { + "apiGroups": [ + "crd.k8s.amazonaws.com" + ], + "resources": [ + "*" + ], + "verbs": [ + "*" + ] + }, + { + "apiGroups": [ + "" + ], + "resources": [ + "pods", + "nodes", + "namespaces" + ], + "verbs": [ + "list", + "watch", + "get" + ] + }, + { + "apiGroups": [ + "extensions" + ], + "resources": [ + "daemonsets" + ], + "verbs": [ + "list", + "watch" + ] + } + ] + }, + { + "apiVersion": "rbac.authorization.k8s.io/v1", + "kind": "ClusterRoleBinding", + "metadata": { + "annotations": {}, + "name": "aws-node" + }, + "roleRef": { + "apiGroup": "rbac.authorization.k8s.io", + "kind": "ClusterRole", + "name": "aws-node" + }, + "subjects": [ + { + "kind": "ServiceAccount", + "name": "aws-node", + "namespace": "kube-system" + } + ] + } + ], + "kind": "List" +} diff --git a/pkg/apis/eksctl.io/v1alpha5/assets/schema.json b/pkg/apis/eksctl.io/v1alpha5/assets/schema.json index a966271467..e81687ec2d 100755 --- a/pkg/apis/eksctl.io/v1alpha5/assets/schema.json +++ b/pkg/apis/eksctl.io/v1alpha5/assets/schema.json @@ -487,11 +487,10 @@ }, "version": { "type": "string", - "description": "Valid variants are: `\"1.17\"`, `\"1.18\"`, `\"1.19\"`, `\"1.20\"`, `\"1.21\"` (default).", - "x-intellij-html-description": "Valid variants are: "1.17", "1.18", "1.19", "1.20", "1.21" (default).", + "description": "Valid variants are: `\"1.18\"`, `\"1.19\"`, `\"1.20\"`, `\"1.21\"` (default).", + "x-intellij-html-description": "Valid variants are: "1.18", "1.19", "1.20", "1.21" (default).", "default": "1.21", "enum": [ - "1.17", "1.18", "1.19", "1.20", diff --git a/pkg/apis/eksctl.io/v1alpha5/types.go b/pkg/apis/eksctl.io/v1alpha5/types.go index e8f35cd813..ff166a6850 100644 --- a/pkg/apis/eksctl.io/v1alpha5/types.go +++ b/pkg/apis/eksctl.io/v1alpha5/types.go @@ -34,8 +34,6 @@ import ( // Values for `KubernetesVersion` // All valid values should go in this block const ( - Version1_17 = "1.17" - Version1_18 = "1.18" Version1_19 = "1.19" @@ -71,6 +69,9 @@ const ( // Version1_16 represents Kubernetes version 1.16.x Version1_16 = "1.16" + + // Version1_17 represents Kubernetes version 1.17.x + Version1_17 = "1.17" ) // Not yet supported versions @@ -415,6 +416,7 @@ func DeprecatedVersions() []string { Version1_14, Version1_15, Version1_16, + Version1_17, } } @@ -431,7 +433,6 @@ func IsDeprecatedVersion(version string) bool { // SupportedVersions are the versions of Kubernetes that EKS supports func SupportedVersions() []string { return []string{ - Version1_17, Version1_18, Version1_19, Version1_20, diff --git a/pkg/eks/mocks/KubeNodeGroup.go b/pkg/eks/mocks/KubeNodeGroup.go index c4714e2b50..49e2ea4f2b 100644 --- a/pkg/eks/mocks/KubeNodeGroup.go +++ b/pkg/eks/mocks/KubeNodeGroup.go @@ -1,4 +1,4 @@ -// Code generated by mockery v0.0.0-dev. DO NOT EDIT. +// Code generated by mockery v1.0.0. DO NOT EDIT. package mocks From 58f8cb80cd08e4593a3645e446ca958652b5f394 Mon Sep 17 00:00:00 2001 From: Himangini Date: Thu, 25 Nov 2021 10:50:27 +0000 Subject: [PATCH 101/124] update docs for eks supported version --- userdocs/src/introduction.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/userdocs/src/introduction.md b/userdocs/src/introduction.md index f26e71f80f..fad64983f7 100644 --- a/userdocs/src/introduction.md +++ b/userdocs/src/introduction.md @@ -23,7 +23,7 @@ eksctl create cluster --name=cluster-1 --nodes=4 ``` -EKS supports versions `1.16`, `1.17`, `1.18`, `1.19`, `1.20` and `1.21` (default). +EKS supports versions `1.18`, `1.19`, `1.20` and `1.21` (default). With `eksctl` you can deploy any of the supported versions by passing `--version`. ``` From ba7bf72d63c79b3e338415f923760c1b0ef0c860 Mon Sep 17 00:00:00 2001 From: Gergely Brautigam <182850+Skarlso@users.noreply.github.com> Date: Fri, 26 Nov 2021 13:06:50 +0100 Subject: [PATCH 102/124] Fix panic in node affinity adder (#4491) --- pkg/addons/default/kube_proxy.go | 35 +++-- pkg/addons/default/kube_proxy_test.go | 23 ++- .../testdata/sample-old-kube-proxy-amd.json | 141 ++++++++++++++++++ 3 files changed, 180 insertions(+), 19 deletions(-) create mode 100644 pkg/addons/default/testdata/sample-old-kube-proxy-amd.json diff --git a/pkg/addons/default/kube_proxy.go b/pkg/addons/default/kube_proxy.go index c53a2faed1..37135d06b3 100644 --- a/pkg/addons/default/kube_proxy.go +++ b/pkg/addons/default/kube_proxy.go @@ -6,22 +6,19 @@ import ( "sort" "strings" - v1 "k8s.io/api/apps/v1" - "github.com/aws/aws-sdk-go/aws" "github.com/aws/aws-sdk-go/service/eks" "github.com/aws/aws-sdk-go/service/eks/eksiface" + "github.com/hashicorp/go-version" "github.com/kris-nova/logger" "github.com/pkg/errors" - - "github.com/hashicorp/go-version" - "github.com/weaveworks/eksctl/pkg/addons" - "github.com/weaveworks/eksctl/pkg/printers" - - api "github.com/weaveworks/eksctl/pkg/apis/eksctl.io/v1alpha5" + v1 "k8s.io/api/apps/v1" apierrs "k8s.io/apimachinery/pkg/api/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "github.com/weaveworks/eksctl/pkg/addons" + api "github.com/weaveworks/eksctl/pkg/apis/eksctl.io/v1alpha5" + "github.com/weaveworks/eksctl/pkg/printers" "github.com/weaveworks/eksctl/pkg/utils" ) @@ -127,7 +124,9 @@ func UpdateKubeProxy(input AddonInput, plan bool) (bool, error) { } if !hasArm64NodeSelector { - addArm64NodeSelector(d, archLabel) + if err := addArm64NodeSelector(d, archLabel); err != nil { + return false, err + } } if _, err := input.RawClient.ClientSet().AppsV1().DaemonSets(metav1.NamespaceSystem).Update(context.TODO(), d, metav1.UpdateOptions{}); err != nil { @@ -157,16 +156,20 @@ func daemeonSetHasArm64NodeSelector(daemonSet *v1.DaemonSet, archLabel string) b return false } -func addArm64NodeSelector(daemonSet *v1.DaemonSet, archLabel string) { - for nodeSelectorTermsIndex, nodeSelectorTerms := range daemonSet.Spec.Template.Spec.Affinity.NodeAffinity. - RequiredDuringSchedulingIgnoredDuringExecution.NodeSelectorTerms { - for nodeSelectorIndex, nodeSelector := range nodeSelectorTerms.MatchExpressions { - if nodeSelector.Key == archLabel { - daemonSet.Spec.Template.Spec.Affinity.NodeAffinity.RequiredDuringSchedulingIgnoredDuringExecution. - NodeSelectorTerms[nodeSelectorTermsIndex].MatchExpressions[nodeSelectorIndex].Values = append(nodeSelector.Values, "arm64") +func addArm64NodeSelector(daemonSet *v1.DaemonSet, archLabel string) error { + if daemonSet.Spec.Template.Spec.Affinity != nil && daemonSet.Spec.Template.Spec.Affinity.NodeAffinity != nil { + for nodeSelectorTermsIndex, nodeSelectorTerms := range daemonSet.Spec.Template.Spec.Affinity.NodeAffinity. + RequiredDuringSchedulingIgnoredDuringExecution.NodeSelectorTerms { + for nodeSelectorIndex, nodeSelector := range nodeSelectorTerms.MatchExpressions { + if nodeSelector.Key == archLabel { + daemonSet.Spec.Template.Spec.Affinity.NodeAffinity.RequiredDuringSchedulingIgnoredDuringExecution. + NodeSelectorTerms[nodeSelectorTermsIndex].MatchExpressions[nodeSelectorIndex].Values = append(nodeSelector.Values, "arm64") + } } } + return nil } + return fmt.Errorf("NodeAffinity not configured on kube-proxy. Either manually update the proxy deployment, or switch to Managed Addons") } func getLatestKubeProxyImage(input AddonInput, greaterThanOrEqualTo1_18 bool) (string, error) { diff --git a/pkg/addons/default/kube_proxy_test.go b/pkg/addons/default/kube_proxy_test.go index 131cbb0a85..06b3de9b51 100644 --- a/pkg/addons/default/kube_proxy_test.go +++ b/pkg/addons/default/kube_proxy_test.go @@ -5,16 +5,15 @@ import ( "fmt" "github.com/aws/aws-sdk-go/aws" + awseks "github.com/aws/aws-sdk-go/service/eks" . "github.com/onsi/ginkgo" . "github.com/onsi/gomega" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - awseks "github.com/aws/aws-sdk-go/service/eks" da "github.com/weaveworks/eksctl/pkg/addons/default" "github.com/weaveworks/eksctl/pkg/kubernetes" "github.com/weaveworks/eksctl/pkg/testutils" "github.com/weaveworks/eksctl/pkg/testutils/mockprovider" - - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" ) var _ = Describe("KubeProxy", func() { @@ -118,6 +117,24 @@ var _ = Describe("KubeProxy", func() { Expect(kubeProxyImage(clientSet)).To(Equal("602401143452.dkr.ecr.eu-west-1.amazonaws.com/eks/kube-proxy:v1.15.11")) }) + When("nodeaffinity is not set on kube-proxy", func() { + BeforeEach(func() { + rawClient := testutils.NewFakeRawClientWithSamples("testdata/sample-old-kube-proxy-amd.json") + clientSet = rawClient.ClientSet() + mockProvider = mockprovider.NewMockProvider() + input = da.AddonInput{ + RawClient: rawClient, + ControlPlaneVersion: "1.16.0", + Region: "eu-west-1", + EKSAPI: mockProvider.EKS(), + } + }) + It("errors", func() { + _, err := da.UpdateKubeProxy(input, false) + Expect(err).To(MatchError(ContainSubstring("NodeAffinity not configured on kube-proxy. Either manually update the proxy deployment, or switch to Managed Addons"))) + }) + }) + When("the cluster version is 1.18 or newer", func() { BeforeEach(func() { input.ControlPlaneVersion = "1.18.1" diff --git a/pkg/addons/default/testdata/sample-old-kube-proxy-amd.json b/pkg/addons/default/testdata/sample-old-kube-proxy-amd.json new file mode 100644 index 0000000000..e93035c9e8 --- /dev/null +++ b/pkg/addons/default/testdata/sample-old-kube-proxy-amd.json @@ -0,0 +1,141 @@ +{ + "apiVersion": "v1", + "items": [ + { + "apiVersion": "apps/v1", + "kind": "DaemonSet", + "metadata": { + "annotations": { + "deprecated.daemonset.template.generation": "10", + "kubectl.kubernetes.io/last-applied-configuration": "{\"apiVersion\":\"extensions/v1beta1\",\"kind\":\"DaemonSet\",\"metadata\":{\"annotations\":{},\"labels\":{\"eks.amazonaws.com/component\":\"kube-proxy\",\"k8s-app\":\"kube-proxy\"},\"name\":\"kube-proxy\",\"namespace\":\"kube-system\"},\"spec\":{\"selector\":{\"matchLabels\":{\"k8s-app\":\"kube-proxy\"}},\"template\":{\"metadata\":{\"annotations\":{\"scheduler.alpha.kubernetes.io/critical-pod\":\"\"},\"labels\":{\"k8s-app\":\"kube-proxy\"}},\"spec\":{\"containers\":[{\"command\":[\"/bin/sh\",\"-c\",\"kube-proxy --resource-container=\\\"\\\" --oom-score-adj=-998 --master=https://59eba41dbb3e69921e4d0af76b2814ee.yl4.us-east-1.eks.amazonaws.com --kubeconfig=/var/lib/kube-proxy/kubeconfig --proxy-mode=iptables --v=2 1\\u003e\\u003e/var/log/kube-proxy.log 2\\u003e\\u00261\"],\"image\":\"602401143452.dkr.ecr.us-east-1.amazonaws.com/eks/kube-proxy:v1.10.3\",\"name\":\"kube-proxy\",\"resources\":{\"requests\":{\"cpu\":\"100m\"}},\"securityContext\":{\"privileged\":true},\"volumeMounts\":[{\"mountPath\":\"/var/log\",\"name\":\"varlog\",\"readOnly\":false},{\"mountPath\":\"/run/xtables.lock\",\"name\":\"xtables-lock\",\"readOnly\":false},{\"mountPath\":\"/var/lib/kube-proxy/\",\"name\":\"kubeconfig\"}]}],\"hostNetwork\":true,\"serviceAccountName\":\"kube-proxy\",\"tolerations\":[{\"effect\":\"NoExecute\",\"operator\":\"Exists\"},{\"effect\":\"NoSchedule\",\"operator\":\"Exists\"}],\"volumes\":[{\"hostPath\":{\"path\":\"/var/log\"},\"name\":\"varlog\"},{\"hostPath\":{\"path\":\"/run/xtables.lock\",\"type\":\"FileOrCreate\"},\"name\":\"xtables-lock\"},{\"configMap\":{\"name\":\"kube-proxy\"},\"name\":\"kubeconfig\"}]}},\"updateStrategy\":{\"rollingUpdate\":{\"maxUnavailable\":\"10%\"},\"type\":\"RollingUpdate\"}}}\n" + }, + "creationTimestamp": "2018-08-29T12:55:10Z", + "generation": 10, + "labels": { + "eks.amazonaws.com/component": "kube-proxy", + "k8s-app": "kube-proxy" + }, + "name": "kube-proxy", + "namespace": "kube-system", + "resourceVersion": "196859403", + "selfLink": "/apis/apps/v1/namespaces/kube-system/daemonsets/kube-proxy", + "uid": "c339a828-ab8a-11e8-a044-12c352781cb6" + }, + "spec": { + "revisionHistoryLimit": 10, + "selector": { + "matchLabels": { + "k8s-app": "kube-proxy" + } + }, + "template": { + "metadata": { + "annotations": { + "scheduler.alpha.kubernetes.io/critical-pod": "" + }, + "creationTimestamp": null, + "labels": { + "k8s-app": "kube-proxy" + } + }, + "spec": { + "containers": [ + { + "command": [ + "/bin/sh", + "-c", + "kube-proxy --resource-container=\"\" --oom-score-adj=-998 --master=https://59eba41dbb3e69921e4d0af76b2814ee.yl4.us-east-1.eks.amazonaws.com --kubeconfig=/var/lib/kube-proxy/kubeconfig --proxy-mode=iptables --v=2 1>>/var/log/kube-proxy.log 2>&1" + ], + "image": "602401143452.dkr.ecr.us-west-2.amazonaws.com/eks/kube-proxy:v1.15.11", + "imagePullPolicy": "IfNotPresent", + "name": "kube-proxy", + "resources": { + "requests": { + "cpu": "100m" + } + }, + "securityContext": { + "privileged": true, + "procMount": "Default" + }, + "terminationMessagePath": "/dev/termination-log", + "terminationMessagePolicy": "File", + "volumeMounts": [ + { + "mountPath": "/var/log", + "name": "varlog" + }, + { + "mountPath": "/run/xtables.lock", + "name": "xtables-lock" + }, + { + "mountPath": "/var/lib/kube-proxy/", + "name": "kubeconfig" + } + ] + } + ], + "dnsPolicy": "ClusterFirst", + "hostNetwork": true, + "restartPolicy": "Always", + "schedulerName": "default-scheduler", + "securityContext": {}, + "serviceAccount": "kube-proxy", + "serviceAccountName": "kube-proxy", + "terminationGracePeriodSeconds": 30, + "tolerations": [ + { + "effect": "NoExecute", + "operator": "Exists" + }, + { + "effect": "NoSchedule", + "operator": "Exists" + } + ], + "volumes": [ + { + "hostPath": { + "path": "/var/log", + "type": "" + }, + "name": "varlog" + }, + { + "hostPath": { + "path": "/run/xtables.lock", + "type": "FileOrCreate" + }, + "name": "xtables-lock" + }, + { + "configMap": { + "defaultMode": 420, + "name": "kube-proxy" + }, + "name": "kubeconfig" + } + ] + } + }, + "updateStrategy": { + "rollingUpdate": { + "maxUnavailable": "10%" + }, + "type": "RollingUpdate" + } + }, + "status": { + "currentNumberScheduled": 3, + "desiredNumberScheduled": 3, + "numberAvailable": 3, + "numberMisscheduled": 0, + "numberReady": 3, + "observedGeneration": 10, + "updatedNumberScheduled": 3 + } + } + ], + "kind": "List" +} From 5d7e25d6ba1a3c4d3f4029bca666070683e25fa5 Mon Sep 17 00:00:00 2001 From: nikimanoledaki Date: Fri, 26 Nov 2021 16:06:56 +0100 Subject: [PATCH 103/124] Add release notes for 0.76.0 --- docs/release_notes/0.76.0.md | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) create mode 100644 docs/release_notes/0.76.0.md diff --git a/docs/release_notes/0.76.0.md b/docs/release_notes/0.76.0.md new file mode 100644 index 0000000000..c2e8f6da53 --- /dev/null +++ b/docs/release_notes/0.76.0.md @@ -0,0 +1,20 @@ +# Release 0.76.0 + +## Features + +- Remove support for EKS 1.17 (#4487) +- Support scaling all nodegroups found in a config file (#4464) +- Add config-file option to get cluster (#4468) +- Add AttachPolicy to NodeGroupIAM configuration (#4331) + +## Bug Fixes + +- Fix panic in node affinity adder (#4491) + +## Improvements + +- Update cluster-upgrade.md docs (#4479) + +## Acknowledgments +Weaveworks would like to sincerely thank: + @adammw and @brianrudolf-ep From e9acd733304d57053fca748b416e3fa67109c185 Mon Sep 17 00:00:00 2001 From: weaveworksbot Date: Fri, 26 Nov 2021 15:38:22 +0000 Subject: [PATCH 104/124] Prepare for next development iteration --- pkg/version/release.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkg/version/release.go b/pkg/version/release.go index c672faf422..0fdbb722f2 100644 --- a/pkg/version/release.go +++ b/pkg/version/release.go @@ -3,7 +3,7 @@ package version // This file was generated by release_generate.go; DO NOT EDIT. // Version is the version number in semver format X.Y.Z -var Version = "0.76.0" +var Version = "0.77.0" // PreReleaseID can be empty for releases, "rc.X" for release candidates and "dev" for snapshots var PreReleaseID = "dev" From 32cdc50072b8dd5dc22987f89bcdf8fa178504c0 Mon Sep 17 00:00:00 2001 From: Gergely Brautigam <182850+Skarlso@users.noreply.github.com> Date: Mon, 29 Nov 2021 10:36:05 +0100 Subject: [PATCH 105/124] Add integration test for `utils schema` (#4497) --- integration/tests/utils/utils_test.go | 40 +++++++++++++++++++++++++++ 1 file changed, 40 insertions(+) create mode 100644 integration/tests/utils/utils_test.go diff --git a/integration/tests/utils/utils_test.go b/integration/tests/utils/utils_test.go new file mode 100644 index 0000000000..4be394c209 --- /dev/null +++ b/integration/tests/utils/utils_test.go @@ -0,0 +1,40 @@ +//go:build integration +// +build integration + +package utils + +import ( + "testing" + + . "github.com/onsi/ginkgo" + . "github.com/onsi/gomega" + + "github.com/weaveworks/eksctl/integration/tests" + api "github.com/weaveworks/eksctl/pkg/apis/eksctl.io/v1alpha5" + "github.com/weaveworks/eksctl/pkg/testutils" +) + +var params *tests.Params + +func init() { + testing.Init() + params = tests.NewParams("schema") +} + +func TestUtils(t *testing.T) { + testutils.RegisterAndRun(t) +} + +var _ = BeforeSuite(func() { +}) + +var _ = Describe("Utils", func() { + Context("schema", func() { + It("displays the schema", func() { + cmd := params.EksctlUtilsCmd.WithArgs("schema").WithoutArg("--region", params.Region) + session := cmd.Run() + Expect(session.ExitCode()).To(BeZero()) + Expect(string(session.Out.Contents())).To(Equal(api.SchemaJSON)) + }) + }) +}) From 1f5e9637375953a77fbb47f30743094f8ae393b6 Mon Sep 17 00:00:00 2001 From: Gergely Brautigam <182850+Skarlso@users.noreply.github.com> Date: Tue, 30 Nov 2021 13:37:37 +0100 Subject: [PATCH 106/124] Add integration test for `describe-stacks` (#4492) * Add integration test for describe-stacks * Update integration/tests/crud/creategetdelete_test.go Co-authored-by: Jake Klein Co-authored-by: Jake Klein --- .../tests/crud/creategetdelete_test.go | 27 ++++++++++++++++--- 1 file changed, 23 insertions(+), 4 deletions(-) diff --git a/integration/tests/crud/creategetdelete_test.go b/integration/tests/crud/creategetdelete_test.go index 32a22bda7e..207a3b01f3 100644 --- a/integration/tests/crud/creategetdelete_test.go +++ b/integration/tests/crud/creategetdelete_test.go @@ -12,8 +12,8 @@ import ( "testing" "time" + "github.com/aws/aws-sdk-go/service/cloudformation" "github.com/pkg/errors" - "github.com/weaveworks/eksctl/pkg/utils/file" corev1 "k8s.io/api/core/v1" "k8s.io/client-go/kubernetes" @@ -25,6 +25,10 @@ import ( . "github.com/onsi/ginkgo" . "github.com/onsi/gomega" "github.com/onsi/gomega/gexec" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/client-go/tools/clientcmd" + "sigs.k8s.io/yaml" + . "github.com/weaveworks/eksctl/integration/matchers" . "github.com/weaveworks/eksctl/integration/runner" "github.com/weaveworks/eksctl/integration/tests" @@ -35,9 +39,7 @@ import ( "github.com/weaveworks/eksctl/pkg/iam" iamoidc "github.com/weaveworks/eksctl/pkg/iam/oidc" "github.com/weaveworks/eksctl/pkg/testutils" - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - "k8s.io/client-go/tools/clientcmd" - "sigs.k8s.io/yaml" + "github.com/weaveworks/eksctl/pkg/utils/file" ) var params *tests.Params @@ -155,6 +157,23 @@ var _ = Describe("(Integration) Create, Get, Scale & Delete", func() { }) }) + Context("and describe the stack for the cluster", func() { + It("should describe the cluster's stack", func() { + cmd := params.EksctlUtilsCmd.WithArgs("describe-stacks", "--cluster", params.ClusterName, "-o", "yaml") + session := cmd.Run() + Expect(session.ExitCode()).To(BeZero()) + var stacks []*cloudformation.Stack + Expect(yaml.Unmarshal(session.Out.Contents(), &stacks)).To(Succeed()) + Expect(stacks).To(HaveLen(2)) + nodegroupStack := stacks[0] + clusterStack := stacks[1] + Expect(aws.StringValue(clusterStack.StackName)).To(ContainSubstring(params.ClusterName)) + Expect(aws.StringValue(nodegroupStack.StackName)).To(ContainSubstring(params.ClusterName)) + Expect(aws.StringValue(clusterStack.Description)).To(Equal("EKS cluster (dedicated VPC: true, dedicated IAM: true) [created and managed by eksctl]")) + Expect(aws.StringValue(nodegroupStack.Description)).To(Equal("EKS Managed Nodes (SSH access: false) [created by eksctl]")) + }) + }) + Context("toggling kubernetes API access", func() { var ( clientSet *kubernetes.Clientset From 0882700af0ac05fbd618517f38b2db10fd80964b Mon Sep 17 00:00:00 2001 From: Gergely Brautigam <182850+Skarlso@users.noreply.github.com> Date: Tue, 30 Nov 2021 14:12:30 +0100 Subject: [PATCH 107/124] Deprecate golint and apply some changes from revive (#4489) --- .golangci.yml | 29 ++++++++++++++++--- .../backwards_compatibility_test.go | 1 + .../createdeletebeforeactive_test.go | 9 +++--- .../cloudwatch_logging_test.go | 2 ++ .../cluster_api/cluster_api_endpoints_test.go | 1 + .../tests/cluster_dns/cluster_dns_test.go | 2 ++ integration/tests/dry_run/dry_run_test.go | 6 ++-- .../tests/eks_connector/eks_connector_test.go | 2 ++ .../instance_selector_test.go | 1 + .../quickstart_profiles_gen_test.go | 1 + .../unowned_cluster/unowned_cluster_test.go | 21 ++++++-------- pkg/actions/identityproviders/wait.go | 6 ++-- pkg/actions/nodegroup/create.go | 12 ++------ pkg/actions/repo/enable.go | 14 ++++----- pkg/apis/eksctl.io/v1alpha5/addon.go | 8 ++--- pkg/cfn/builder/managed_nodegroup.go | 8 ++--- pkg/cfn/builder/network_interfaces.go | 2 +- pkg/ctl/cmdutils/nodegroup.go | 6 ++-- pkg/ctl/create/cluster.go | 20 ++++--------- pkg/ctl/enable/flux.go | 7 ++--- pkg/ctl/get/identityprovider.go | 6 +--- pkg/ctl/scale/nodegroup.go | 10 ++----- pkg/eks/eks.go | 21 +++++--------- pkg/git/git.go | 10 ++----- pkg/printers/table.go | 5 +--- pkg/version/generate/release_generate.go | 5 +--- pkg/vpc/vpc.go | 16 ++++------ 27 files changed, 99 insertions(+), 132 deletions(-) diff --git a/.golangci.yml b/.golangci.yml index 7413263bba..e438f29af6 100644 --- a/.golangci.yml +++ b/.golangci.yml @@ -77,9 +77,30 @@ linters-settings: # 2. you use go >= 1.10 # 3. you do repeated runs (false for CI) or cache $GOPATH/pkg or `go env GOCACHE` dir in CI. use-installed-packages: false - golint: - # minimal confidence for issues, default is 0.8 - min-confidence: 0.8 + revive: + confidence: 0.8 + severity: warning + errorCode: 0 + warningCode: 0 + rules: + - name: blank-imports + - name: context-as-argument + - name: context-keys-type + - name: error-return + - name: error-strings + - name: error-naming + - name: exported + - name: if-return + - name: increment-decrement + - name: var-naming + - name: var-declaration + - name: package-comments + - name: range + - name: receiver-naming + - name: time-naming + - name: unexported-return + - name: indent-error-flow + - name: errorf gofmt: # simplify code: gofmt with `-s` option, true by default simplify: false @@ -157,7 +178,7 @@ linters: - errcheck - gofmt - goimports - - golint + - revive - gosimple - govet - ineffassign diff --git a/integration/tests/backwards_compat/backwards_compatibility_test.go b/integration/tests/backwards_compat/backwards_compatibility_test.go index 1ef76876e1..eb3e4a6bd4 100644 --- a/integration/tests/backwards_compat/backwards_compatibility_test.go +++ b/integration/tests/backwards_compat/backwards_compatibility_test.go @@ -1,6 +1,7 @@ //go:build integration // +build integration +//revive:disable Not changing package name package backwards_compat import ( diff --git a/integration/tests/before_active/createdeletebeforeactive_test.go b/integration/tests/before_active/createdeletebeforeactive_test.go index b6a3296860..c54b265202 100644 --- a/integration/tests/before_active/createdeletebeforeactive_test.go +++ b/integration/tests/before_active/createdeletebeforeactive_test.go @@ -1,20 +1,21 @@ //go:build integration // +build integration +//revive:disable Not changing package name package before_active import ( "fmt" "testing" + awseks "github.com/aws/aws-sdk-go/service/eks" + . "github.com/onsi/ginkgo" + . "github.com/onsi/gomega" + . "github.com/weaveworks/eksctl/integration/matchers" . "github.com/weaveworks/eksctl/integration/runner" "github.com/weaveworks/eksctl/integration/tests" "github.com/weaveworks/eksctl/pkg/testutils" - - awseks "github.com/aws/aws-sdk-go/service/eks" - . "github.com/onsi/ginkgo" - . "github.com/onsi/gomega" ) var params *tests.Params diff --git a/integration/tests/cloudwatch_logging/cloudwatch_logging_test.go b/integration/tests/cloudwatch_logging/cloudwatch_logging_test.go index 4081852a60..26b3da631b 100644 --- a/integration/tests/cloudwatch_logging/cloudwatch_logging_test.go +++ b/integration/tests/cloudwatch_logging/cloudwatch_logging_test.go @@ -1,6 +1,7 @@ //go:build integration // +build integration +//revive:disable Not changing package name package cloudwatch_logging import ( @@ -15,6 +16,7 @@ import ( api "github.com/weaveworks/eksctl/pkg/apis/eksctl.io/v1alpha5" "github.com/pkg/errors" + "github.com/weaveworks/eksctl/pkg/testutils" . "github.com/weaveworks/eksctl/integration/runner" diff --git a/integration/tests/cluster_api/cluster_api_endpoints_test.go b/integration/tests/cluster_api/cluster_api_endpoints_test.go index c1dd7727a4..9ddc874245 100644 --- a/integration/tests/cluster_api/cluster_api_endpoints_test.go +++ b/integration/tests/cluster_api/cluster_api_endpoints_test.go @@ -1,6 +1,7 @@ //go:build integration // +build integration +//revive:disable Not changing package name package cluster_api import ( diff --git a/integration/tests/cluster_dns/cluster_dns_test.go b/integration/tests/cluster_dns/cluster_dns_test.go index 71d45e0c80..dbcb726677 100644 --- a/integration/tests/cluster_dns/cluster_dns_test.go +++ b/integration/tests/cluster_dns/cluster_dns_test.go @@ -1,6 +1,7 @@ //go:build integration // +build integration +//revive:disable Not changing package name package cluster_dns import ( @@ -10,6 +11,7 @@ import ( "github.com/aws/aws-sdk-go/aws" . "github.com/onsi/gomega" + . "github.com/weaveworks/eksctl/integration/runner" "github.com/weaveworks/eksctl/integration/utilities/kube" diff --git a/integration/tests/dry_run/dry_run_test.go b/integration/tests/dry_run/dry_run_test.go index 4fcb34ab10..2cf8c96c63 100644 --- a/integration/tests/dry_run/dry_run_test.go +++ b/integration/tests/dry_run/dry_run_test.go @@ -1,6 +1,7 @@ //go:build integration // +build integration +//revive:disable Not changing package name package dry_run import ( @@ -10,18 +11,17 @@ import ( "testing" "github.com/aws/aws-sdk-go/aws" + . "github.com/onsi/ginkgo" . "github.com/onsi/ginkgo/extensions/table" . "github.com/onsi/gomega" "github.com/pkg/errors" - . "github.com/weaveworks/eksctl/integration/runner" + . "github.com/weaveworks/eksctl/integration/runner" "github.com/weaveworks/eksctl/integration/tests" api "github.com/weaveworks/eksctl/pkg/apis/eksctl.io/v1alpha5" "github.com/weaveworks/eksctl/pkg/eks" "github.com/weaveworks/eksctl/pkg/testutils" "github.com/weaveworks/eksctl/pkg/utils/ipnet" - - . "github.com/onsi/ginkgo" ) var params *tests.Params diff --git a/integration/tests/eks_connector/eks_connector_test.go b/integration/tests/eks_connector/eks_connector_test.go index ed1be3f907..5a1549d122 100644 --- a/integration/tests/eks_connector/eks_connector_test.go +++ b/integration/tests/eks_connector/eks_connector_test.go @@ -1,6 +1,7 @@ //go:build integration // +build integration +//revive:disable Not changing package name package eks_connector_test import ( @@ -14,6 +15,7 @@ import ( awseks "github.com/aws/aws-sdk-go/service/eks" . "github.com/onsi/ginkgo" . "github.com/onsi/gomega" + . "github.com/weaveworks/eksctl/integration/runner" "github.com/weaveworks/eksctl/integration/tests" api "github.com/weaveworks/eksctl/pkg/apis/eksctl.io/v1alpha5" diff --git a/integration/tests/instance_selector/instance_selector_test.go b/integration/tests/instance_selector/instance_selector_test.go index 755da69180..a06d8a4fa2 100644 --- a/integration/tests/instance_selector/instance_selector_test.go +++ b/integration/tests/instance_selector/instance_selector_test.go @@ -1,6 +1,7 @@ //go:build integration // +build integration +//revive:disable Not changing package name package instance_selector import ( diff --git a/integration/tests/quickstart_profiles_gen/quickstart_profiles_gen_test.go b/integration/tests/quickstart_profiles_gen/quickstart_profiles_gen_test.go index 13e957d6f7..c8940b5af4 100644 --- a/integration/tests/quickstart_profiles_gen/quickstart_profiles_gen_test.go +++ b/integration/tests/quickstart_profiles_gen/quickstart_profiles_gen_test.go @@ -1,6 +1,7 @@ //go:build integration // +build integration +//revive:disable Not changing package name package quickstart_profiles_gen import ( diff --git a/integration/tests/unowned_cluster/unowned_cluster_test.go b/integration/tests/unowned_cluster/unowned_cluster_test.go index 61531563d2..a316673d11 100644 --- a/integration/tests/unowned_cluster/unowned_cluster_test.go +++ b/integration/tests/unowned_cluster/unowned_cluster_test.go @@ -1,6 +1,7 @@ //go:build integration // +build integration +//revive:disable Not changing package name package unowned_clusters import ( @@ -11,23 +12,19 @@ import ( "testing" "time" - "github.com/aws/aws-sdk-go/service/kms" - "github.com/weaveworks/eksctl/pkg/eks" - - cfn "github.com/aws/aws-sdk-go/service/cloudformation" - "github.com/aws/aws-sdk-go/aws" - - api "github.com/weaveworks/eksctl/pkg/apis/eksctl.io/v1alpha5" - + cfn "github.com/aws/aws-sdk-go/service/cloudformation" awseks "github.com/aws/aws-sdk-go/service/eks" - . "github.com/weaveworks/eksctl/integration/runner" - "github.com/weaveworks/eksctl/integration/tests" - "github.com/weaveworks/eksctl/pkg/testutils" - + "github.com/aws/aws-sdk-go/service/kms" . "github.com/onsi/ginkgo" . "github.com/onsi/gomega" "github.com/onsi/gomega/gbytes" + + . "github.com/weaveworks/eksctl/integration/runner" + "github.com/weaveworks/eksctl/integration/tests" + api "github.com/weaveworks/eksctl/pkg/apis/eksctl.io/v1alpha5" + "github.com/weaveworks/eksctl/pkg/eks" + "github.com/weaveworks/eksctl/pkg/testutils" ) var params *tests.Params diff --git a/pkg/actions/identityproviders/wait.go b/pkg/actions/identityproviders/wait.go index 9577da1957..da53cf4c55 100644 --- a/pkg/actions/identityproviders/wait.go +++ b/pkg/actions/identityproviders/wait.go @@ -7,6 +7,7 @@ import ( "github.com/aws/aws-sdk-go/aws" "github.com/aws/aws-sdk-go/aws/request" "github.com/aws/aws-sdk-go/service/eks" + "github.com/weaveworks/eksctl/pkg/utils/waiters" ) @@ -38,8 +39,5 @@ func (m *Manager) waitForUpdate( clusterName, ) - if err := waiters.Wait(clusterName, msg, acceptors, newRequest, timeout, nil); err != nil { - return err - } - return nil + return waiters.Wait(clusterName, msg, acceptors, newRequest, timeout, nil) } diff --git a/pkg/actions/nodegroup/create.go b/pkg/actions/nodegroup/create.go index 3623d76a4f..4ce40da2dd 100644 --- a/pkg/actions/nodegroup/create.go +++ b/pkg/actions/nodegroup/create.go @@ -189,11 +189,7 @@ func (m *Manager) nodeCreationTasks(options CreateOpts, nodegroupFilter filter.N } taskTree.Append(allNodeGroupTasks) - if err := m.init.DoAllNodegroupStackTasks(taskTree, meta.Region, meta.Name); err != nil { - return err - } - - return nil + return m.init.DoAllNodegroupStackTasks(taskTree, meta.Region, meta.Name) } func (m *Manager) postNodeCreationTasks(clientSet kubernetes.Interface, options CreateOpts) error { @@ -307,9 +303,5 @@ func loadVPCFromConfig(provider api.ClusterProvider, cfg *api.ClusterConfig) err return err } - if err := cfg.CanUseForPrivateNodeGroups(); err != nil { - return err - } - - return nil + return cfg.CanUseForPrivateNodeGroups() } diff --git a/pkg/actions/repo/enable.go b/pkg/actions/repo/enable.go index ac3ae5cd90..dfa16a0287 100644 --- a/pkg/actions/repo/enable.go +++ b/pkg/actions/repo/enable.go @@ -17,14 +17,15 @@ import ( portforward "github.com/justinbarrick/go-k8s-portforward" "github.com/kris-nova/logger" "github.com/pkg/errors" - api "github.com/weaveworks/eksctl/pkg/apis/eksctl.io/v1alpha5" - "github.com/weaveworks/eksctl/pkg/git" - "github.com/weaveworks/eksctl/pkg/gitops/deploykey" - "github.com/weaveworks/eksctl/pkg/kubernetes" apierrs "k8s.io/apimachinery/pkg/api/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" kubeclient "k8s.io/client-go/kubernetes" "k8s.io/client-go/rest" + + api "github.com/weaveworks/eksctl/pkg/apis/eksctl.io/v1alpha5" + "github.com/weaveworks/eksctl/pkg/git" + "github.com/weaveworks/eksctl/pkg/gitops/deploykey" + "github.com/weaveworks/eksctl/pkg/kubernetes" ) const ( @@ -215,10 +216,7 @@ func (fi *Installer) addFilesToRepo() error { } // git push - if err := fi.GitClient.Push(); err != nil { - return err - } - return nil + return fi.GitClient.Push() } func (fi *Installer) createFluxNamespaceIfMissing(manifestsMap map[string][]byte) error { diff --git a/pkg/apis/eksctl.io/v1alpha5/addon.go b/pkg/apis/eksctl.io/v1alpha5/addon.go index a57b88e020..e3bf840dc2 100644 --- a/pkg/apis/eksctl.io/v1alpha5/addon.go +++ b/pkg/apis/eksctl.io/v1alpha5/addon.go @@ -19,7 +19,7 @@ type Addon struct { // AttachPolicy holds a policy document to attach // +optional AttachPolicy InlineDocument `json:"attachPolicy,omitempty"` - // ARN of the permissions boundary to associate + // ARN of the permissions' boundary to associate // +optional PermissionsBoundary string `json:"permissionsBoundary,omitempty"` // WellKnownPolicies for attaching common IAM policies @@ -41,11 +41,7 @@ func (a Addon) Validate() error { return fmt.Errorf("name required") } - if err := a.checkOnlyOnePolicyProviderIsSet(); err != nil { - return err - } - - return nil + return a.checkOnlyOnePolicyProviderIsSet() } func (a Addon) checkOnlyOnePolicyProviderIsSet() error { diff --git a/pkg/cfn/builder/managed_nodegroup.go b/pkg/cfn/builder/managed_nodegroup.go index 5fc8a8744d..99c41b7925 100644 --- a/pkg/cfn/builder/managed_nodegroup.go +++ b/pkg/cfn/builder/managed_nodegroup.go @@ -262,17 +262,17 @@ func validateLaunchTemplate(launchTemplateData *ec2.ResponseLaunchTemplateData, func getAMIType(ng *api.ManagedNodeGroup, instanceType string) string { amiTypeMapping := map[string]struct { - X86_64 string + X86x64 string GPU string ARM string }{ api.NodeImageFamilyAmazonLinux2: { - X86_64: eks.AMITypesAl2X8664, + X86x64: eks.AMITypesAl2X8664, GPU: eks.AMITypesAl2X8664Gpu, ARM: eks.AMITypesAl2Arm64, }, api.NodeImageFamilyBottlerocket: { - X86_64: eks.AMITypesBottlerocketX8664, + X86x64: eks.AMITypesBottlerocketX8664, ARM: eks.AMITypesBottlerocketArm64, }, } @@ -288,7 +288,7 @@ func getAMIType(ng *api.ManagedNodeGroup, instanceType string) string { case instanceutils.IsARMInstanceType(instanceType): return amiType.ARM default: - return amiType.X86_64 + return amiType.X86x64 } } diff --git a/pkg/cfn/builder/network_interfaces.go b/pkg/cfn/builder/network_interfaces.go index 0c59beb986..0391c0a02c 100644 --- a/pkg/cfn/builder/network_interfaces.go +++ b/pkg/cfn/builder/network_interfaces.go @@ -39,7 +39,7 @@ func buildNetworkInterfaces( return errors.Wrapf(err, "couldn't retrieve instance type description for %v", instanceTypes) } - var numEFAs float64 = math.MaxFloat64 + var numEFAs = math.MaxFloat64 for _, it := range info.InstanceTypes { networkInfo := it.NetworkInfo numEFAs = math.Min(float64(aws.Int64Value(networkInfo.MaximumNetworkCards)), numEFAs) diff --git a/pkg/ctl/cmdutils/nodegroup.go b/pkg/ctl/cmdutils/nodegroup.go index af7e2ddb75..fc02bfd0ee 100644 --- a/pkg/ctl/cmdutils/nodegroup.go +++ b/pkg/ctl/cmdutils/nodegroup.go @@ -3,6 +3,7 @@ package cmdutils import ( "github.com/aws/aws-sdk-go/service/eks" "github.com/kris-nova/logger" + api "github.com/weaveworks/eksctl/pkg/apis/eksctl.io/v1alpha5" "github.com/weaveworks/eksctl/pkg/cfn/manager" ) @@ -21,11 +22,8 @@ func PopulateNodegroup(stackManager manager.StackManager, name string, cfg *api. } nodeGroupType = api.NodeGroupTypeUnowned } - if err = PopulateNodegroupFromStack(nodeGroupType, name, cfg); err != nil { - return err - } - return nil + return PopulateNodegroupFromStack(nodeGroupType, name, cfg) } // PopulateNodegroupFromStack populates the nodegroup field of an api.ClusterConfig by type from its CF stack. diff --git a/pkg/ctl/create/cluster.go b/pkg/ctl/create/cluster.go index a25cd5057f..8a503698a3 100644 --- a/pkg/ctl/create/cluster.go +++ b/pkg/ctl/create/cluster.go @@ -7,24 +7,22 @@ import ( "strings" "github.com/aws/amazon-ec2-instance-selector/v2/pkg/selector" - "github.com/weaveworks/eksctl/pkg/kops" - "github.com/weaveworks/eksctl/pkg/utils" - - "github.com/weaveworks/eksctl/pkg/actions/addon" - "github.com/kris-nova/logger" "github.com/pkg/errors" "github.com/spf13/cobra" "github.com/spf13/pflag" "k8s.io/client-go/tools/clientcmd" + "github.com/weaveworks/eksctl/pkg/actions/addon" api "github.com/weaveworks/eksctl/pkg/apis/eksctl.io/v1alpha5" "github.com/weaveworks/eksctl/pkg/authconfigmap" "github.com/weaveworks/eksctl/pkg/ctl/cmdutils" "github.com/weaveworks/eksctl/pkg/ctl/cmdutils/filter" "github.com/weaveworks/eksctl/pkg/eks" "github.com/weaveworks/eksctl/pkg/gitops" + "github.com/weaveworks/eksctl/pkg/kops" "github.com/weaveworks/eksctl/pkg/printers" + "github.com/weaveworks/eksctl/pkg/utils" "github.com/weaveworks/eksctl/pkg/utils/kubeconfig" "github.com/weaveworks/eksctl/pkg/utils/kubectl" "github.com/weaveworks/eksctl/pkg/utils/names" @@ -398,11 +396,7 @@ func doCreateCluster(cmd *cmdutils.Cmd, ngFilter *filter.NodeGroupFilter, params logger.Success("%s is ready", meta.LogString()) - if err := printer.LogObj(logger.Debug, "cfg.json = \\\n%s\n", cfg); err != nil { - return err - } - - return nil + return printer.LogObj(logger.Debug, "cfg.json = \\\n%s\n", cfg) } func createOrImportVPC(cmd *cmdutils.Cmd, cfg *api.ClusterConfig, params *cmdutils.CreateClusterCmdParams, ctl *eks.ClusterProvider) error { @@ -421,10 +415,8 @@ func createOrImportVPC(cmd *cmdutils.Cmd, cfg *api.ClusterConfig, params *cmduti if params.DryRun { return nil } - if err := vpc.SetSubnets(cfg.VPC, cfg.AvailabilityZones); err != nil { - return err - } - return nil + + return vpc.SetSubnets(cfg.VPC, cfg.AvailabilityZones) } if params.KopsClusterNameForVPC != "" { diff --git a/pkg/ctl/enable/flux.go b/pkg/ctl/enable/flux.go index 4965e06680..7cc5ec0b39 100644 --- a/pkg/ctl/enable/flux.go +++ b/pkg/ctl/enable/flux.go @@ -6,6 +6,7 @@ import ( "github.com/kris-nova/logger" "github.com/spf13/cobra" "github.com/spf13/pflag" + "github.com/weaveworks/eksctl/pkg/actions/flux" api "github.com/weaveworks/eksctl/pkg/apis/eksctl.io/v1alpha5" "github.com/weaveworks/eksctl/pkg/ctl/cmdutils" @@ -84,11 +85,7 @@ func flux2Install(cmd *cmdutils.Cmd) error { return err } - if err := installer.Run(); err != nil { - return err - } - - return nil + return installer.Run() } func kubeconfAndContextNotSet(flags map[string]string) bool { diff --git a/pkg/ctl/get/identityprovider.go b/pkg/ctl/get/identityprovider.go index efaef5db94..c9d88ac209 100644 --- a/pkg/ctl/get/identityprovider.go +++ b/pkg/ctl/get/identityprovider.go @@ -84,11 +84,7 @@ func doGetIdentityProvider(cmd *cmdutils.Cmd, params getCmdParams, name string) addIdentityProviderTableColumns(printer.(*printers.TablePrinter), len(summaries)) } - if err := printer.PrintObjWithKind("identity provider summary", summaries, os.Stdout); err != nil { - return err - } - - return nil + return printer.PrintObjWithKind("identity provider summary", summaries, os.Stdout) } func addIdentityProviderTableColumns(printer *printers.TablePrinter, num int) { diff --git a/pkg/ctl/scale/nodegroup.go b/pkg/ctl/scale/nodegroup.go index d8f78ab484..4d59f1fb17 100644 --- a/pkg/ctl/scale/nodegroup.go +++ b/pkg/ctl/scale/nodegroup.go @@ -60,19 +60,13 @@ func doScaleNodeGroup(cmd *cmdutils.Cmd, ng *api.NodeGroupBase) error { if err := cmdutils.NewScaleAllNodeGroupLoader(cmd).Load(); err != nil { return err } - if err := scaleAllNodegroups(cmd); err != nil { - return err - } - return nil + return scaleAllNodegroups(cmd) } if err := cmdutils.NewScaleNodeGroupLoader(cmd, ng).Load(); err != nil { return err } - if err := scaleNodegroup(cmd, ng); err != nil { - return err - } - return nil + return scaleNodegroup(cmd, ng) } func scaleAllNodegroups(cmd *cmdutils.Cmd) error { diff --git a/pkg/eks/eks.go b/pkg/eks/eks.go index 14a5d0abd7..f75993fe61 100644 --- a/pkg/eks/eks.go +++ b/pkg/eks/eks.go @@ -7,25 +7,23 @@ import ( "strconv" "time" - "github.com/aws/aws-sdk-go/aws/awserr" - "github.com/weaveworks/eksctl/pkg/cfn/manager" - "github.com/weaveworks/eksctl/pkg/cfn/waiter" - "github.com/weaveworks/eksctl/pkg/version" - "github.com/aws/aws-sdk-go/aws" "github.com/aws/aws-sdk-go/aws/arn" - "github.com/kris-nova/logger" - "github.com/pkg/errors" - "github.com/aws/aws-sdk-go/service/ec2" awseks "github.com/aws/aws-sdk-go/service/eks" - + "github.com/kris-nova/logger" + "github.com/pkg/errors" "k8s.io/client-go/kubernetes" + "github.com/aws/aws-sdk-go/aws/awserr" + api "github.com/weaveworks/eksctl/pkg/apis/eksctl.io/v1alpha5" + "github.com/weaveworks/eksctl/pkg/cfn/manager" + "github.com/weaveworks/eksctl/pkg/cfn/waiter" "github.com/weaveworks/eksctl/pkg/fargate" iamoidc "github.com/weaveworks/eksctl/pkg/iam/oidc" "github.com/weaveworks/eksctl/pkg/utils" + "github.com/weaveworks/eksctl/pkg/version" "github.com/weaveworks/eksctl/pkg/vpc" ) @@ -299,10 +297,7 @@ func (c *ClusterProvider) LoadClusterIntoSpecFromStack(spec *api.ClusterConfig, if err := c.RefreshClusterStatus(spec); err != nil { return err } - if err := c.loadClusterKubernetesNetworkConfig(spec); err != nil { - return err - } - return nil + return c.loadClusterKubernetesNetworkConfig(spec) } // LoadClusterVPC loads the VPC configuration diff --git a/pkg/git/git.go b/pkg/git/git.go index 33c1871a12..ade3334c4b 100644 --- a/pkg/git/git.go +++ b/pkg/git/git.go @@ -132,10 +132,7 @@ func (git *Client) isRemoteBranch(branch string) bool { // Add performs can perform a `git add` operation on the given file paths func (git Client) Add(files ...string) error { args := append([]string{"add", "--"}, files...) - if err := git.runGitCmd(args...); err != nil { - return err - } - return nil + return git.runGitCmd(args...) } // Commit makes a commit if there are staged changes @@ -174,10 +171,7 @@ func (git Client) Commit(message, user, email string) error { "-m", message, fmt.Sprintf("--author=%s <%s>", user, email), } - if err := git.runGitCmd(args...); err != nil { - return err - } - return nil + return git.runGitCmd(args...) } // Push pushes the changes to the origin remote diff --git a/pkg/printers/table.go b/pkg/printers/table.go index 36a8264cbf..9d516fa315 100644 --- a/pkg/printers/table.go +++ b/pkg/printers/table.go @@ -44,10 +44,7 @@ func (t *TablePrinter) PrintObjWithKind(kind string, obj interface{}, writer io. if _, err := w.WriteString(fmt.Sprintf("No %s found\n", strings.ToLower(kind))); err != nil { return err } - if err := w.Flush(); err != nil { - return err - } - return nil + return w.Flush() } return t.table.Render(obj, writer, t.columnames...) diff --git a/pkg/version/generate/release_generate.go b/pkg/version/generate/release_generate.go index 070f866d53..4472df4e6c 100644 --- a/pkg/version/generate/release_generate.go +++ b/pkg/version/generate/release_generate.go @@ -104,8 +104,5 @@ func writeVersionToFile(version, preReleaseID, fileName string) error { f.Comment("buildDate is the time of the build with format yyyy-mm-ddThh:mm:ssZ. It will be set by the linker.") f.Var().Id("buildDate").Op("=").Lit("") - if err := f.Save(fileName); err != nil { - return err - } - return nil + return f.Save(fileName) } diff --git a/pkg/vpc/vpc.go b/pkg/vpc/vpc.go index bb4320f47a..9c500ed2f7 100644 --- a/pkg/vpc/vpc.go +++ b/pkg/vpc/vpc.go @@ -6,17 +6,14 @@ import ( "net" "strings" - "github.com/aws/aws-sdk-go/service/ec2/ec2iface" - - "github.com/pkg/errors" - "k8s.io/apimachinery/pkg/util/sets" - - "github.com/kris-nova/logger" - "github.com/aws/aws-sdk-go/aws" cfn "github.com/aws/aws-sdk-go/service/cloudformation" "github.com/aws/aws-sdk-go/service/ec2" + "github.com/aws/aws-sdk-go/service/ec2/ec2iface" awseks "github.com/aws/aws-sdk-go/service/eks" + "github.com/kris-nova/logger" + "github.com/pkg/errors" + "k8s.io/apimachinery/pkg/util/sets" api "github.com/weaveworks/eksctl/pkg/apis/eksctl.io/v1alpha5" "github.com/weaveworks/eksctl/pkg/cfn/outputs" @@ -443,10 +440,7 @@ func ValidateExistingPublicSubnets(provider api.ClusterProvider, vpcID string, s if err != nil { return err } - if err := validatePublicSubnet(subnets); err != nil { - return err - } - return nil + return validatePublicSubnet(subnets) } // EnsureMapPublicIPOnLaunchEnabled will enable MapPublicIpOnLaunch in EC2 for all given subnet IDs From 688af96513afa616359062894f9f4505734b742d Mon Sep 17 00:00:00 2001 From: Gergely Brautigam <182850+Skarlso@users.noreply.github.com> Date: Wed, 1 Dec 2021 16:14:54 +0100 Subject: [PATCH 108/124] Separate VPC Networking into meaningful sections (#4490) * Separate VPC Networking into meaningful sections * Apply suggestions from code review Co-authored-by: Himangini * Renamed the file Co-authored-by: Himangini --- userdocs/mkdocs.yml | 4 + userdocs/src/usage/nodegroup-customize-dns.md | 38 ++ userdocs/src/usage/vpc-cluster-access.md | 76 +++ userdocs/src/usage/vpc-configuration.md | 223 +++++++++ userdocs/src/usage/vpc-networking.md | 448 +----------------- userdocs/src/usage/vpc-subnet-settings.md | 103 ++++ 6 files changed, 450 insertions(+), 442 deletions(-) create mode 100644 userdocs/src/usage/nodegroup-customize-dns.md create mode 100644 userdocs/src/usage/vpc-cluster-access.md create mode 100644 userdocs/src/usage/vpc-configuration.md create mode 100644 userdocs/src/usage/vpc-subnet-settings.md diff --git a/userdocs/mkdocs.yml b/userdocs/mkdocs.yml index 762c8a0c11..f9229adeaa 100644 --- a/userdocs/mkdocs.yml +++ b/userdocs/mkdocs.yml @@ -29,6 +29,7 @@ nav: - usage/managing-nodegroups.md - usage/nodegroup-upgrade.md - usage/nodegroup-with-custom-subnet.md + - usage/nodegroup-customize-dns.md - usage/eks-managed-nodes.md - usage/launch-template-support.md - usage/instance-selector.md @@ -47,6 +48,9 @@ nav: - usage/kms-encryption.md - Networking: - usage/vpc-networking.md + - usage/vpc-configuration.md + - usage/vpc-subnet-settings.md + - usage/vpc-cluster-access.md - IAM: - usage/minimum-iam-policies.md - usage/iam-permissions-boundary.md diff --git a/userdocs/src/usage/nodegroup-customize-dns.md b/userdocs/src/usage/nodegroup-customize-dns.md new file mode 100644 index 0000000000..b4e04447bd --- /dev/null +++ b/userdocs/src/usage/nodegroup-customize-dns.md @@ -0,0 +1,38 @@ +# Nodegroups with custom DNS + +There are two ways of overwriting the DNS server IP address used for all the internal and external DNS lookups. This +is the equivalent of the `--cluster-dns` flag for the `kubelet`. + +The first, is through the `clusterDNS` field. [Config files](../schema) accepts a `string` field called +`clusterDNS` with the IP address of the DNS server to use. +This will be passed to the `kubelet` that in turn will pass it to the pods through the `/etc/resolv.conf` file. + +```yaml +apiVersion: eksctl.io/v1alpha5 +kind: ClusterConfig + +metadata: + name: cluster-1 + region: eu-north-1 + +nodeGroups: +- name: ng-1 + clusterDNS: 169.254.20.10 +``` + +Note that this configuration only accepts one IP address. To specify more than one address, use the +[`kubeletExtraConfig` parameter](../customizing-the-kubelet): + +```yaml +apiVersion: eksctl.io/v1alpha5 +kind: ClusterConfig + +metadata: + name: cluster-1 + region: eu-north-1 + +nodeGroups: + - name: ng-1 + kubeletExtraConfig: + clusterDNS: ["169.254.20.10","172.20.0.10"] +``` diff --git a/userdocs/src/usage/vpc-cluster-access.md b/userdocs/src/usage/vpc-cluster-access.md new file mode 100644 index 0000000000..5d1c8da616 --- /dev/null +++ b/userdocs/src/usage/vpc-cluster-access.md @@ -0,0 +1,76 @@ +# Cluster Access + +## Managing Access to the Kubernetes API Server Endpoints + +The default creation of an EKS cluster exposes the Kubernetes API server publicly but not directly from within the +VPC subnets (public=true, private=false). Traffic destined for the API server from within the VPC must first exit the +VPC networks (but not Amazon's network) and then re-enter to reach the API server. + +The Kubernetes API server endpoint access for a cluster can be configured for public and private access when creating +the cluster using the cluster config file. Example below: + +```yaml +vpc: + clusterEndpoints: + publicAccess: + privateAccess: +``` + +There are some additional caveats when configuring Kubernetes API endpoint access: + +1. EKS doesn't allow one to create or update a cluster without at least one private or public access being + enabled. +1. EKS does allow creating a configuration that allows only private access to be enabled, but eksctl doesn't + support it during cluster creation as it prevents eksctl from being able to join the worker nodes to the cluster. +1. Updating a cluster to have private only Kubernetes API endpoint access means that Kubernetes commands, by default, + (e.g. `kubectl`) as well as `eksctl delete cluster`, `eksctl utils write-kubeconfig`, and possibly the command + `eksctl utils update-kube-proxy` must be run within the cluster VPC. This requires some changes to various AWS + resources. See: + [EKS user guide](https://docs.aws.amazon.com/en_pv/eks/latest/userguide/cluster-endpoint#private-access) + A user can provide `vpc.extraCIDRs` which will append additional CIDR ranges to the ControlPlaneSecurityGroup, + allowing subnets outside the VPC to reach the Kubernetes API endpoint. + +The following is an example of how one could configure the Kubernetes API endpoint access using the `utils` sub-command: + +``` +eksctl utils update-cluster-endpoints --name= --private-access=true --public-access=false +``` + +To update the setting using a `ClusterConfig` file, use: + +```console +eksctl utils update-cluster-endpoints -f config.yaml --approve +``` + +Note that if you don't pass a flag, it will keep the current value. Once you are satisfied with the proposed changes, +add the `approve` flag to make the change to the running cluster. + +## Restricting Access to the EKS Kubernetes Public API endpoint + +The default creation of an EKS cluster exposes the Kubernetes API server publicly. To restrict access to the public API +endpoint to a set of CIDRs when creating a cluster, set the `publicAccessCIDRs` field: + +```yaml +vpc: + publicAccessCIDRs: ["1.1.1.1/32", "2.2.2.0/24"] +``` + +To update the restrictions on an existing cluster, use: + +```console +eksctl utils set-public-access-cidrs --cluster= 1.1.1.1/32,2.2.2.0/24 +``` + +To update the restrictions using a `ClusterConfig` file, set the new CIDRs in `vpc.publicAccessCIDRs` and run: + +```console +eksctl utils set-public-access-cidrs -f config.yaml +``` + +!!!note + This feature only applies to the public endpoint. The + [API server endpoint access configuration options](https://docs.aws.amazon.com/eks/latest/userguide/cluster-endpoint.html) + won't change, and you will still have the option to disable the public endpoint so your cluster is not accessible from + the internet. (Source: https://github.com/aws/containers-roadmap/issues/108#issuecomment-552766489) + + Implementation notes: https://github.com/aws/containers-roadmap/issues/108#issuecomment-552698875 diff --git a/userdocs/src/usage/vpc-configuration.md b/userdocs/src/usage/vpc-configuration.md new file mode 100644 index 0000000000..5d9f241052 --- /dev/null +++ b/userdocs/src/usage/vpc-configuration.md @@ -0,0 +1,223 @@ +# VPC Configuration + +## Change VPC CIDR + +If you need to set up peering with another VPC, or simply need a larger or smaller range of IPs, you can use `--vpc-cidr` flag to +change it. Please refer to [the AWS docs][vpcsizing] for guides on choosing CIDR blocks which are permitted for use in an AWS VPC. + +[vpcsizing]: https://docs.aws.amazon.com/vpc/latest/userguide/VPC_Subnets.html#VPC_Sizing + +## Use an existing VPC: shared with kops + +You can use the VPC of an existing Kubernetes cluster managed by [kops](https://github.com/kubernetes/kops). This feature is provided to facilitate migration and/or cluster peering. + +If you have previously created a cluster with kops, e.g. using commands similar to this: + +``` +export KOPS_STATE_STORE=s3://kops +kops create cluster cluster-1.k8s.local --zones=us-west-2c,us-west-2b,us-west-2a --networking=weave --yes +``` + +You can create an EKS cluster in the same AZs using the same VPC subnets (NOTE: at least 2 AZs/subnets are required): + +``` +eksctl create cluster --name=cluster-2 --region=us-west-2 --vpc-from-kops-cluster=cluster-1.k8s.local +``` + +## Use existing VPC: other custom configuration + +`eksctl` provides some, but not complete, flexibility for custom VPC and subnet topologies. + +You can use an existing VPC by supplying private and/or public subnets using the `--vpc-private-subnets` and `--vpc-public-subnets` flags. +It is up to you to ensure the subnets you use are categorised correctly, as there is no simple way to verify whether a subnet is actually private or +public, because configurations vary. + +Given these flags, `eksctl create cluster` will determine the VPC ID automatically, but it will not create any routing tables or other +resources, such as internet/NAT gateways. It will, however, create dedicated security groups for the initial nodegroup and the control +plane. + +You must ensure to provide **at least 2 subnets in different AZs**. There are other requirements that you will need to follow (listed below), but it's +entirely up to you to address those. (For example, tagging is not strictly necessary, tests have shown that it is possible to create +a functional cluster without any tags set on the subnets, however there is no guarantee that this will always hold and tagging is +recommended.) + +Standard requirements: + +- all given subnets must be in the same VPC, within the same block of IPs +- a sufficient number IP addresses are available, based on needs +- sufficient number of subnets (minimum 2), based on needs +- subnets are tagged with at least the following: + - `kubernetes.io/cluster/` tag set to either `shared` or `owned` + - `kubernetes.io/role/internal-elb` tag set to `1` for _private_ subnets + - `kubernetes.io/role/elb` tag set to `1` for _public_ subnets +- correctly configured internet and/or NAT gateways +- routing tables have correct entries and the network is functional +- **NEW**: all public subnets should have the property `MapPublicIpOnLaunch` enabled (i.e. `Auto-assign public IPv4 address` in the AWS console) + +There may be other requirements imposed by EKS or Kubernetes, and it is entirely up to you to stay up-to-date on any requirements and/or +recommendations, and implement those as needed/possible. + +Default security group settings applied by `eksctl` may or may not be sufficient for sharing access with resources in other security +groups. If you wish to modify the ingress/egress rules of the security groups, you might need to use another tool to automate +changes, or do it via EC2 console. + +When in doubt, don't use a custom VPC. Using `eksctl create cluster` without any `--vpc-*` flags will always configure the cluster +with a fully-functional dedicated VPC. + +**Examples** + +Create a cluster using a custom VPC with 2x private and 2x public subnets: + +``` +eksctl create cluster \ + --vpc-private-subnets=subnet-0ff156e0c4a6d300c,subnet-0426fb4a607393184 \ + --vpc-public-subnets=subnet-0153e560b3129a696,subnet-009fa0199ec203c37 +``` + +or use the following equivalent config file: + +```yaml +apiVersion: eksctl.io/v1alpha5 +kind: ClusterConfig + +metadata: + name: my-test + region: us-west-2 + +vpc: + id: "vpc-11111" + subnets: + private: + us-west-2a: + id: "subnet-0ff156e0c4a6d300c" + us-west-2c: + id: "subnet-0426fb4a607393184" + public: + us-west-2a: + id: "subnet-0153e560b3129a696" + us-west-2c: + id: "subnet-009fa0199ec203c37" + +nodeGroups: + - name: ng-1 +``` + +Create a cluster using a custom VPC with 3x private subnets and make initial nodegroup use those subnets: + +``` +eksctl create cluster \ + --vpc-private-subnets=subnet-0ff156e0c4a6d300c,subnet-0549cdab573695c03,subnet-0426fb4a607393184 \ + --node-private-networking +``` + +or use the following equivalent config file: + +```yaml +apiVersion: eksctl.io/v1alpha5 +kind: ClusterConfig + +metadata: + name: my-test + region: us-west-2 + +vpc: + id: "vpc-11111" + subnets: + private: + us-west-2d: + id: "subnet-0ff156e0c4a6d300c" + us-west-2c: + id: "subnet-0549cdab573695c03" + us-west-2a: + id: "subnet-0426fb4a607393184" + +nodeGroups: + - name: ng-1 + privateNetworking: true + +``` + +Create a cluster using a custom VPC 4x public subnets: + +``` +eksctl create cluster \ + --vpc-public-subnets=subnet-0153e560b3129a696,subnet-0cc9c5aebe75083fd,subnet-009fa0199ec203c37,subnet-018fa0176ba320e45 +``` + + +```yaml +apiVersion: eksctl.io/v1alpha5 +kind: ClusterConfig + +metadata: + name: my-test + region: us-west-2 + +vpc: + id: "vpc-11111" + subnets: + public: + us-west-2d: + id: "subnet-0153e560b3129a696" + us-west-2c: + id: "subnet-0cc9c5aebe75083fd" + us-west-2a: + id: "subnet-009fa0199ec203c37" + us-west-2b: + id: "subnet-018fa0176ba320e45" + +nodeGroups: + - name: ng-1 +``` + +More examples can be found in the repo's `examples` folder: + +- [using an existing VPC](https://github.com/weaveworks/eksctl/blob/master/examples/04-existing-vpc.yaml) +- [using a custom VPC CIDR](https://github.com/weaveworks/eksctl/blob/master/examples/02-custom-vpc-cidr-no-nodes.yaml) + +## Custom Shared Node Security Group + +`eksctl` will create and manage a shared node security group that allows communication between +unmanaged nodes and the cluster control plane and managed nodes. + +If you wish to provide your own custom security group instead, you may override the `sharedNodeSecurityGroup` +field in the config file: + + +```yaml +vpc: + sharedNodeSecurityGroup: sg-0123456789 +``` + +By default, when creating the cluster, `eksctl` will add rules to this security group to allow communication to and +from the default cluster security group that EKS creates. The default cluster security group is used by both +the EKS control plane and managed node groups. + +If you wish to manage the security group rules yourself, you may prevent `eksctl` from creating the rules +by setting `manageSharedNodeSecurityGroupRules` to `false` in the config file: + +```yaml +vpc: + sharedNodeSecurityGroup: sg-0123456789 + manageSharedNodeSecurityGroupRules: false +``` + +## NAT Gateway + +The NAT Gateway for a cluster can be configured to be `Disabled`, `Single` (default) or `HighlyAvailable`. +The `HighlyAvailable` option will deploy a NAT Gateway in each Availability Zone of the Region, so that if +an AZ is down, nodes in the other AZs will still be able to communicate to the Internet. + +It can be specified through the `--vpc-nat-mode` CLI flag or in the cluster config file like the example below: + + +```yaml +vpc: + nat: + gateway: HighlyAvailable # other options: Disable, Single (default) +``` + +See the complete example [here](https://github.com/weaveworks/eksctl/blob/master/examples/09-nat-gateways.yaml). + +**Note**: Specifying the NAT Gateway is only supported during cluster creation. It isn't touched during a cluster +upgrade. There are plans to support changing between different modes on cluster update in the future. diff --git a/userdocs/src/usage/vpc-networking.md b/userdocs/src/usage/vpc-networking.md index f1827809bb..a1cedb4c68 100644 --- a/userdocs/src/usage/vpc-networking.md +++ b/userdocs/src/usage/vpc-networking.md @@ -1,4 +1,4 @@ -# VPC Networking +# Networking By default `eksctl create cluster` will create a dedicated VPC for the cluster. This is done in order to avoid interference with existing resources for a @@ -16,447 +16,11 @@ The nodegroup by default allows inbound traffic from the control plane security the property `AssociatePublicIpAddress` disabled in the Auto Scaling Group for the nodegroups. This means that when creating a **new nodegroup** on a **cluster made with an earlier version** of `eksctl`, the nodegroup must **either** be private **or** have `MapPublicIpOnLaunch` enabled in its public subnets. Without one of these, the new nodes won't have access to - the internet and won't be able to download the basic add-ons (CNI plugin, kube-proxy, etc). To help set up + the internet and won't be able to download the basic add-ons (CNI plugin, kube-proxy, etc.). To help set up subnets correctly for old clusters you can use the new command `eksctl utils update-legacy-subnet-settings`. -If the default functionality doesn't suit you, the following options are currently available. +If the default functionality doesn't suit you, the following sections explain how to customize VPC configuration further: -## Change VPC CIDR - -If you need to setup peering with another VPC, or simply need a larger or smaller range of IPs, you can use `--vpc-cidr` flag to -change it. Please refer to [the AWS docs][vpcsizing] for guides on choosing CIDR blocks which are permitted for use in an AWS VPC. - -[vpcsizing]: https://docs.aws.amazon.com/vpc/latest/userguide/VPC_Subnets.html#VPC_Sizing - -## Use private subnets for initial nodegroup - -If you prefer to isolate the initial nodegroup from the public internet, you can use the `--node-private-networking` flag. -When used in conjunction with the `--ssh-access` flag, the SSH port can only be accessed from inside the VPC. - -!!! note - Using the `--node-private-networking` flag will result in outgoing traffic to go through the NAT gateway using its - Elastic IP. On the other hand, if the nodes are in a public subnet, the outgoing traffic won't go through the - NAT gateway and hence the outgoing traffic has the IP of each individual node. - -## Use an existing VPC: shared with kops - -You can use the VPC of an existing Kubernetes cluster managed by [kops](https://github.com/kubernetes/kops). This feature is provided to facilitate migration and/or -cluster peering. - -If you have previously created a cluster with kops, e.g. using commands similar to this: - -``` -export KOPS_STATE_STORE=s3://kops -kops create cluster cluster-1.k8s.local --zones=us-west-2c,us-west-2b,us-west-2a --networking=weave --yes -``` - -You can create an EKS cluster in the same AZs using the same VPC subnets (NOTE: at least 2 AZs/subnets are required): - -``` -eksctl create cluster --name=cluster-2 --region=us-west-2 --vpc-from-kops-cluster=cluster-1.k8s.local -``` - -## Use existing VPC: other custom configuration - -`eksctl` provides some, but not complete, flexibility for custom VPC and subnet topologies. - -You can use an existing VPC by supplying private and/or public subnets using the `--vpc-private-subnets` and `--vpc-public-subnets` flags. -It is up to you to ensure the subnets you use are categorised correctly, as there is no simple way to verify whether a subnet is actually private or -public, because configurations vary. - -Given these flags, `eksctl create cluster` will determine the VPC ID automatically, but it will not create any routing tables or other -resources, such as internet/NAT gateways. It will, however, create dedicated security groups for the initial nodegroup and the control -plane. - -You must ensure to provide **at least 2 subnets in different AZs**. There are other requirements that you will need to follow (listed below), but it's -entirely up to you to address those. (For example, tagging is not strictly necessary, tests have shown that it is possible to create -a functional cluster without any tags set on the subnets, however there is no guarantee that this will always hold and tagging is -recommended.) - -Standard requirements: - -- all given subnets must be in the same VPC, within the same block of IPs -- a sufficient number IP addresses are available, based on needs -- sufficient number of subnets (minimum 2), based on needs -- subnets are tagged with at least the following: - - `kubernetes.io/cluster/` tag set to either `shared` or `owned` - - `kubernetes.io/role/internal-elb` tag set to `1` for _private_ subnets - - `kubernetes.io/role/elb` tag set to `1` for _public_ subnets -- correctly configured internet and/or NAT gateways -- routing tables have correct entries and the network is functional -- **NEW**: all public subnets should have the property `MapPublicIpOnLaunch` enabled (i.e. `Auto-assign public IPv4 address` in the AWS console) - -There may be other requirements imposed by EKS or Kubernetes, and it is entirely up to you to stay up-to-date on any requirements and/or -recommendations, and implement those as needed/possible. - -Default security group settings applied by `eksctl` may or may not be sufficient for sharing access with resources in other security -groups. If you wish to modify the ingress/egress rules of the security groups, you might need to use another tool to automate -changes, or do it via EC2 console. - -When in doubt, don't use a custom VPC. Using `eksctl create cluster` without any `--vpc-*` flags will always configure the cluster -with a fully-functional dedicated VPC. - -**Examples** - -Create a cluster using a custom VPC with 2x private and 2x public subnets: - -``` -eksctl create cluster \ - --vpc-private-subnets=subnet-0ff156e0c4a6d300c,subnet-0426fb4a607393184 \ - --vpc-public-subnets=subnet-0153e560b3129a696,subnet-009fa0199ec203c37 -``` - -or use the following equivalent config file: - -```yaml -apiVersion: eksctl.io/v1alpha5 -kind: ClusterConfig - -metadata: - name: my-test - region: us-west-2 - -vpc: - id: "vpc-11111" - subnets: - private: - us-west-2a: - id: "subnet-0ff156e0c4a6d300c" - us-west-2c: - id: "subnet-0426fb4a607393184" - public: - us-west-2a: - id: "subnet-0153e560b3129a696" - us-west-2c: - id: "subnet-009fa0199ec203c37" - -nodeGroups: - - name: ng-1 -``` - -Create a cluster using a custom VPC with 3x private subnets and make initial nodegroup use those subnets: - -``` -eksctl create cluster \ - --vpc-private-subnets=subnet-0ff156e0c4a6d300c,subnet-0549cdab573695c03,subnet-0426fb4a607393184 \ - --node-private-networking -``` - -or use the following equivalent config file: - -```yaml -apiVersion: eksctl.io/v1alpha5 -kind: ClusterConfig - -metadata: - name: my-test - region: us-west-2 - -vpc: - id: "vpc-11111" - subnets: - private: - us-west-2d: - id: "subnet-0ff156e0c4a6d300c" - us-west-2c: - id: "subnet-0549cdab573695c03" - us-west-2a: - id: "subnet-0426fb4a607393184" - -nodeGroups: - - name: ng-1 - privateNetworking: true - -``` - -Create a cluster using a custom VPC 4x public subnets: - -``` -eksctl create cluster \ - --vpc-public-subnets=subnet-0153e560b3129a696,subnet-0cc9c5aebe75083fd,subnet-009fa0199ec203c37,subnet-018fa0176ba320e45 -``` - - -```yaml -apiVersion: eksctl.io/v1alpha5 -kind: ClusterConfig - -metadata: - name: my-test - region: us-west-2 - -vpc: - id: "vpc-11111" - subnets: - public: - us-west-2d: - id: "subnet-0153e560b3129a696" - us-west-2c: - id: "subnet-0cc9c5aebe75083fd" - us-west-2a: - id: "subnet-009fa0199ec203c37" - us-west-2b: - id: "subnet-018fa0176ba320e45" - -nodeGroups: - - name: ng-1 -``` - -Further examples can be found in the repo's `examples` dir: - -- [using an existing VPC](https://github.com/weaveworks/eksctl/blob/master/examples/04-existing-vpc.yaml) -- [using a custom VPC CIDR](https://github.com/weaveworks/eksctl/blob/master/examples/02-custom-vpc-cidr-no-nodes.yaml) - - -### Custom subnet topology - -`eksctl` version `0.32.0` introduced further subnet topology customisation with the ability to: - -- List multiple subnets per AZ in VPC configuration -- Specify subnets in nodegroup configuration - -In earlier versions custom subnets had to be provided by availability zone, meaning just one subnet per AZ could be listed. -From `0.32.0` the identifying keys can be arbitrary. - -```yaml -vpc: - id: "vpc-11111" - subnets: - public: - public-one: # arbitrary key - id: "subnet-0153e560b3129a696" - public-two: - id: "subnet-0cc9c5aebe75083fd" - us-west-2b: # or list by AZ - id: "subnet-018fa0176ba320e45" - private: - private-one: - id: "subnet-0153e560b3129a696" - private-two: - id: "subnet-0cc9c5aebe75083fd" -``` - -!!! important - If using the AZ as the identifying key, the `az` value can be omitted. - - If using an arbitrary string as the identifying key, like above, either: - - * `id` must be set (`az` and `cidr` optional) - * or `az` must be set (`cidr` optional) - - If a user specifies a subnet by AZ without specifying CIDR and ID, a subnet - in that AZ will be chosen from the VPC, arbitrarily if multiple such subnets - exist. - -!!! note - A complete subnet spec must be provided, ie. both `public` and `private` configurations - declared in the VPC spec. - -Nodegroups can be restricted to named subnets via the configuration. -When specifying subnets on nodegroup configuration, use the identifying key as given in the VPC spec **not** the subnet id. -For example: - -```yaml -vpc: - id: "vpc-11111" - subnets: - public: - public-one: - id: "subnet-0153e560b3129a696" - ... # subnet spec continued - -nodeGroups: - - name: ng-1 - instanceType: m5.xlarge - desiredCapacity: 2 - subnets: - - public-one -``` - -!!! note - Only one of `subnets` or `availabilityZones` can be provided in nodegroup configuration. - -When placing nodegroups inside a private subnet, `privateNetworking` must be set to `true` -on the nodegroup: - -```yaml -vpc: - id: "vpc-11111" - subnets: - public: - private-one: - id: "subnet-0153e560b3129a696" - ... # subnet spec continued - -nodeGroups: - - name: ng-1 - instanceType: m5.xlarge - desiredCapacity: 2 - privateNetworking: true - subnets: - - private-one -``` - -See [here](https://github.com/weaveworks/eksctl/blob/master/examples/24-nodegroup-subnets.yaml) for a full -configuration example. - -## Custom Cluster DNS address - -There are two ways of overwriting the DNS server IP address used for all the internal and external DNS lookups. This -is the equivalent of the `--cluster-dns` flag for the `kubelet`. - -The first, is through the `clusterDNS` field. [Config files](../schema) accept a `string` field called -`clusterDNS` with the IP address of the DNS server to use. -This will be passed to the `kubelet` that in turn will pass it to the pods through the `/etc/resolv.conf` file. - -```yaml -apiVersion: eksctl.io/v1alpha5 -kind: ClusterConfig - -metadata: - name: cluster-1 - region: eu-north-1 - -nodeGroups: -- name: ng-1 - clusterDNS: 169.254.20.10 -``` - -Note that this configuration only accepts one IP address. To specify more than one address, use the -[`kubeletExtraConfig` parameter](../customizing-the-kubelet): - -```yaml -apiVersion: eksctl.io/v1alpha5 -kind: ClusterConfig - -metadata: - name: cluster-1 - region: eu-north-1 - -nodeGroups: - - name: ng-1 - kubeletExtraConfig: - clusterDNS: ["169.254.20.10","172.20.0.10"] -``` - -## Custom Shared Node Security Group - -`eksctl` will create and manage a shared node security group that allows communication between -unmanaged nodes and the cluster control plane and managed nodes. - -If you wish to provide your own custom security group instead, you may override the `sharedNodeSecurityGroup` -field in the config file: - - -```yaml -vpc: - sharedNodeSecurityGroup: sg-0123456789 -``` - -By default, when creating the cluster, `eksctl` will add rules to this security group to allow communication to and -from the default cluster security group that EKS creates. The default cluster security group is used by both -the EKS control plane and managed node groups. - -If you wish to manage the security group rules yourself, you may prevent `eksctl` from creating the rules -by setting `manageSharedNodeSecurityGroupRules` to `false` in the config file: - -```yaml -vpc: - sharedNodeSecurityGroup: sg-0123456789 - manageSharedNodeSecurityGroupRules: false -``` - -## NAT Gateway - -The NAT Gateway for a cluster can be configured to be `Disabled`, `Single` (default) or `HighlyAvailable`. -The `HighlyAvailable` option will deploy a NAT Gateway in each Availability Zone of the Region, so that if -an AZ is down, nodes in the other AZs will still be able to communicate to the Internet. - -It can be specified through the `--vpc-nat-mode` CLI flag or in the cluster config file like the example below: - - -```yaml -vpc: - nat: - gateway: HighlyAvailable # other options: Disable, Single (default) -``` - -See the complete example [here](https://github.com/weaveworks/eksctl/blob/master/examples/09-nat-gateways.yaml). - -**Note**: Specifying the NAT Gateway is only supported during cluster creation and it is not touched during a cluster -upgrade. There are plans to support changing between different modes on cluster update in the future. - -## Managing Access to the Kubernetes API Server Endpoints - -The default creation of an EKS cluster exposes the Kubernetes API server publicly but not directly from within the -VPC subnets (public=true, private=false). Traffic destined for the API server from within the VPC must first exit the -VPC networks (but not Amazon's network) and then re-enter to reach the API server. - -The Kubernetes API server endpoint access for a cluster can be configured for public and private access when creating -the cluster using the cluster config file. Example below: - -```yaml -vpc: - clusterEndpoints: - publicAccess: - privateAccess: -``` - -There are some additional caveats when configuring Kubernetes API endpoint access: - -1. EKS doesn't allow one to create or update a cluster without at least one of private or public access being - enabled. -1. EKS does allow creating a configuration which allows only private access to be enabled, but eksctl doesn't - support it during cluster creation as it prevents eksctl from being able to join the worker nodes to the cluster. -1. Updating a cluster to have private only Kubernetes API endpoint access means that Kubernetes commands, by default, - (e.g. `kubectl`) as well as `eksctl delete cluster`, `eksctl utils write-kubeconfig`, and possibly the command - `eksctl utils update-kube-proxy` must be run within the cluster VPC. This requires some changes to various AWS - resources. See: - [EKS user guide](https://docs.aws.amazon.com/en_pv/eks/latest/userguide/cluster-endpoint#private-access) - A user can elect to supply vpc.extraCIDRs which will append additional CIDR ranges to the ControlPlaneSecurityGroup, - allowing subnets outside the VPC to reach the kubernetes API endpoint. - -The following is an example of how one could configure the Kubernetes API endpoint access using the `utils` sub-command: - -``` -eksctl utils update-cluster-endpoints --name= --private-access=true --public-access=false -``` - -To update the setting using a `ClusterConfig` file, use: - -```console -eksctl utils update-cluster-endpoints -f config.yaml --approve -``` - -Note that if you don't pass a flag in it will keep the current value. Once you are satisfied with the proposed changes, -add the `approve` flag to make the change to the running cluster. - -## Restricting Access to the EKS Kubernetes Public API endpoint - -The default creation of an EKS cluster exposes the Kubernetes API server publicly. To restrict access to the public API -endpoint to a set of CIDRs when creating a cluster, set the `publicAccessCIDRs` field: - -```yaml -vpc: - publicAccessCIDRs: ["1.1.1.1/32", "2.2.2.0/24"] -``` - -To update the restrictions on an existing cluster, use: - -```console -eksctl utils set-public-access-cidrs --cluster= 1.1.1.1/32,2.2.2.0/24 -``` - -To update the restrictions using a `ClusterConfig` file, set the new CIDRs in `vpc.publicAccessCIDRs` and run: - -```console -eksctl utils set-public-access-cidrs -f config.yaml -``` - -!!!note - This feature only applies to the public endpoint. The - [API server endpoint access configuration options](https://docs.aws.amazon.com/eks/latest/userguide/cluster-endpoint.html) - won't change, and you will still have the option to disable the public endpoint so your cluster is not accessible from - the internet. (Source: https://github.com/aws/containers-roadmap/issues/108#issuecomment-552766489) - - Implementation notes: https://github.com/aws/containers-roadmap/issues/108#issuecomment-552698875 +- [VPC Configuration](../vpc-configuration) +- [Subnet Settings](../vpc-subnet-settings) +- [Cluster Access](../vpc-cluster-access) diff --git a/userdocs/src/usage/vpc-subnet-settings.md b/userdocs/src/usage/vpc-subnet-settings.md new file mode 100644 index 0000000000..ebafac6222 --- /dev/null +++ b/userdocs/src/usage/vpc-subnet-settings.md @@ -0,0 +1,103 @@ +# Subnet Settings + +## Use private subnets for initial nodegroup + +If you prefer to isolate the initial nodegroup from the public internet, you can use the `--node-private-networking` flag. +When used in conjunction with the `--ssh-access` flag, the SSH port can only be accessed from inside the VPC. + +!!! note + Using the `--node-private-networking` flag will result in outgoing traffic to go through the NAT gateway using its + Elastic IP. On the other hand, if the nodes are in a public subnet, the outgoing traffic won't go through the + NAT gateway and hence the outgoing traffic has the IP of each individual node. + +## Custom subnet topology + +`eksctl` version `0.32.0` introduced further subnet topology customisation with the ability to: + +- List multiple subnets per AZ in VPC configuration +- Specify subnets in nodegroup configuration + +In earlier versions custom subnets had to be provided by availability zone, meaning just one subnet per AZ could be listed. +From `0.32.0` the identifying keys can be arbitrary. + +```yaml +vpc: + id: "vpc-11111" + subnets: + public: + public-one: # arbitrary key + id: "subnet-0153e560b3129a696" + public-two: + id: "subnet-0cc9c5aebe75083fd" + us-west-2b: # or list by AZ + id: "subnet-018fa0176ba320e45" + private: + private-one: + id: "subnet-0153e560b3129a696" + private-two: + id: "subnet-0cc9c5aebe75083fd" +``` + +!!! important + If using the AZ as the identifying key, the `az` value can be omitted. + + If using an arbitrary string as the identifying key, like above, either: + + * `id` must be set (`az` and `cidr` optional) + * or `az` must be set (`cidr` optional) + + If a user specifies a subnet by AZ without specifying CIDR and ID, a subnet + in that AZ will be chosen from the VPC, arbitrarily if multiple such subnets + exist. + +!!! note + A complete subnet spec must be provided, i.e. both `public` and `private` configurations + declared in the VPC spec. + +Nodegroups can be restricted to named subnets via the configuration. +When specifying subnets on nodegroup configuration, use the identifying key as given in the VPC spec **not** the subnet id. +For example: + +```yaml +vpc: + id: "vpc-11111" + subnets: + public: + public-one: + id: "subnet-0153e560b3129a696" + ... # subnet spec continued + +nodeGroups: + - name: ng-1 + instanceType: m5.xlarge + desiredCapacity: 2 + subnets: + - public-one +``` + +!!! note + Only one of `subnets` or `availabilityZones` can be provided in nodegroup configuration. + +When placing nodegroups inside a private subnet, `privateNetworking` must be set to `true` +on the nodegroup: + +```yaml +vpc: + id: "vpc-11111" + subnets: + public: + private-one: + id: "subnet-0153e560b3129a696" + ... # subnet spec continued + +nodeGroups: + - name: ng-1 + instanceType: m5.xlarge + desiredCapacity: 2 + privateNetworking: true + subnets: + - private-one +``` + +See [here](https://github.com/weaveworks/eksctl/blob/master/examples/24-nodegroup-subnets.yaml) for a full +configuration example. From ab4e900fdf74b9aa745ca4704cd76fda160d4229 Mon Sep 17 00:00:00 2001 From: Gergely Brautigam <182850+Skarlso@users.noreply.github.com> Date: Thu, 2 Dec 2021 13:37:56 +0100 Subject: [PATCH 109/124] Add `--config-file` to `set labels` (#4502) * Add config-file to set-labels * Updated to only update new labels, never to delete or update them * Added integration test * Proper schema. * Updated the tests and updated the wait time with a comment on why --- integration/tests/labels/label_test.go | 101 ++++++++++++++++++ .../managed-nodegroup-with-labels.yaml | 14 +++ integration/tests/params.go | 8 +- .../eksctl.io/v1alpha5/assets/schema.json | 4 +- pkg/ctl/cmdutils/configfile.go | 51 +++++++++ pkg/ctl/cmdutils/configfile_test.go | 57 ++++++++++ .../test_data/cluster-with-labels.yaml | 20 ++++ pkg/ctl/set/labels.go | 60 +++++++---- pkg/ctl/set/set_test.go | 3 +- 9 files changed, 293 insertions(+), 25 deletions(-) create mode 100644 integration/tests/labels/label_test.go create mode 100644 integration/tests/labels/testdata/managed-nodegroup-with-labels.yaml create mode 100644 pkg/ctl/cmdutils/test_data/cluster-with-labels.yaml diff --git a/integration/tests/labels/label_test.go b/integration/tests/labels/label_test.go new file mode 100644 index 0000000000..b7a43284ad --- /dev/null +++ b/integration/tests/labels/label_test.go @@ -0,0 +1,101 @@ +//go:build integration +// +build integration + +package labels + +import ( + "testing" + "time" + + . "github.com/onsi/ginkgo" + . "github.com/onsi/gomega" + "github.com/onsi/gomega/gbytes" + + . "github.com/weaveworks/eksctl/integration/runner" + "github.com/weaveworks/eksctl/integration/tests" + clusterutils "github.com/weaveworks/eksctl/integration/utilities/cluster" + api "github.com/weaveworks/eksctl/pkg/apis/eksctl.io/v1alpha5" + "github.com/weaveworks/eksctl/pkg/testutils" +) + +var params *tests.Params + +func init() { + // Call testing.Init() prior to tests.NewParams(), as otherwise -test.* will not be recognised. See also: https://golang.org/doc/go1.13#testing + testing.Init() + params = tests.NewParams("labels") + if err := api.Register(); err != nil { + panic("unexpected error registering API scheme") + } +} + +func TestLabels(t *testing.T) { + testutils.RegisterAndRun(t) +} + +var _ = Describe("Labels", func() { + var ( + mng1 string + ) + BeforeSuite(func() { + cmd := params.EksctlCreateCmd. + WithArgs( + "cluster", + "--config-file=-", + "--verbose=4", + ). + WithoutArg("--region", params.Region). + WithStdin(clusterutils.ReaderFromFile(params.ClusterName, params.Region, "testdata/managed-nodegroup-with-labels.yaml")) + Expect(cmd).To(RunSuccessfully()) + // corresponds to the label name in the cluster config file + mng1 = "mng-1" + }) + + AfterSuite(func() { + params.DeleteClusters() + }) + + It("supports labels", func() { + By("getting existing labels") + cmd := params.EksctlGetCmd. + WithArgs( + "labels", + "--cluster", params.ClusterName, + "--nodegroup", mng1, + "--verbose", "2", + ) + // It sometimes takes forever for the above set to take effect + Eventually(func() *gbytes.Buffer { return cmd.Run().Out }, time.Minute*4).Should(gbytes.Say("preset=value")) + + By("setting labels on a managed nodegroup") + cmd = params.EksctlSetLabelsCmd. + WithArgs( + "--cluster", params.ClusterName, + "--nodegroup", mng1, + "--labels", "fantastic=zombieman", + "--verbose", "2", + ) + Expect(cmd).To(RunSuccessfully()) + + By("getting the newly set labels for a managed nodegroup") + cmd = params.EksctlGetCmd. + WithArgs( + "labels", + "--cluster", params.ClusterName, + "--nodegroup", mng1, + "--verbose", "2", + ) + // It sometimes takes forever for the above set to take effect + Eventually(func() *gbytes.Buffer { return cmd.Run().Out }, time.Minute*4).Should(gbytes.Say("fantastic=zombieman")) + + By("unsetting labels on a managed nodegroup") + cmd = params.EksctlUnsetLabelsCmd. + WithArgs( + "--cluster", params.ClusterName, + "--nodegroup", mng1, + "--labels", "fantastic", + "--verbose", "2", + ) + Expect(cmd).To(RunSuccessfully()) + }) +}) diff --git a/integration/tests/labels/testdata/managed-nodegroup-with-labels.yaml b/integration/tests/labels/testdata/managed-nodegroup-with-labels.yaml new file mode 100644 index 0000000000..c579feb78b --- /dev/null +++ b/integration/tests/labels/testdata/managed-nodegroup-with-labels.yaml @@ -0,0 +1,14 @@ +apiVersion: eksctl.io/v1alpha5 +kind: ClusterConfig + +# name is generated +metadata: + name: + +managedNodeGroups: + - name: mng-1 + desiredCapacity: 1 + maxSize: 2 + minSize: 1 + labels: + preset: value diff --git a/integration/tests/params.go b/integration/tests/params.go index 08d04d1df3..340493c6d9 100644 --- a/integration/tests/params.go +++ b/integration/tests/params.go @@ -98,11 +98,15 @@ func (p *Params) GenerateCommands() { p.EksctlSetLabelsCmd = p.EksctlCmd. WithArgs("set", "labels"). - WithTimeout(1 * time.Minute) + // increased timeout reason: set label updates the cloudformation stack to propagate labels + // down to the nodes. That can take a while... + WithTimeout(10 * time.Minute) p.EksctlUnsetLabelsCmd = p.EksctlCmd. WithArgs("unset", "labels"). - WithTimeout(1 * time.Minute) + // increased timeout reason: unset label updates the cloudformation stack to propagate labels + // down to the nodes. That can take a while... + WithTimeout(10 * time.Minute) p.EksctlDeleteCmd = p.EksctlCmd. WithArgs("delete"). diff --git a/pkg/apis/eksctl.io/v1alpha5/assets/schema.json b/pkg/apis/eksctl.io/v1alpha5/assets/schema.json index e81687ec2d..104858f15f 100755 --- a/pkg/apis/eksctl.io/v1alpha5/assets/schema.json +++ b/pkg/apis/eksctl.io/v1alpha5/assets/schema.json @@ -56,8 +56,8 @@ }, "permissionsBoundary": { "type": "string", - "description": "ARN of the permissions boundary to associate", - "x-intellij-html-description": "ARN of the permissions boundary to associate" + "description": "ARN of the permissions' boundary to associate", + "x-intellij-html-description": "ARN of the permissions' boundary to associate" }, "serviceAccountRoleARN": { "type": "string" diff --git a/pkg/ctl/cmdutils/configfile.go b/pkg/ctl/cmdutils/configfile.go index 49ada47897..78a0b88974 100644 --- a/pkg/ctl/cmdutils/configfile.go +++ b/pkg/ctl/cmdutils/configfile.go @@ -890,6 +890,57 @@ func NewGetClusterLoader(cmd *Cmd) ClusterConfigLoader { return l } +// NewSetLabelLoader will load config or use flags for 'eksctl set labels' +func NewSetLabelLoader(cmd *Cmd, nodeGroupName string, labels map[string]string) ClusterConfigLoader { + l := newCommonClusterConfigLoader(cmd) + l.validateWithoutConfigFile = func() error { + if len(labels) == 0 { + return ErrMustBeSet("--labels") + } + meta := cmd.ClusterConfig.Metadata + + if meta.Name == "" { + return ErrMustBeSet(ClusterNameFlag(cmd)) + } + + if nodeGroupName == "" { + return ErrMustBeSet("--nodegroup") + } + + if cmd.NameArg != "" { + return ErrUnsupportedNameArg() + } + + return nil + } + // we use the config file to update the labels, thus providing is invalid + l.flagsIncompatibleWithConfigFile.Insert("labels") + l.validateWithConfigFile = func() error { + meta := cmd.ClusterConfig.Metadata + + if meta.Name == "" { + return ErrMustBeSet(ClusterNameFlag(cmd)) + } + + // if nodegroup is not empty, load only the nodegroup which has been added + if nodeGroupName != "" { + var ng *api.ManagedNodeGroup + for _, mng := range cmd.ClusterConfig.ManagedNodeGroups { + if mng.Name == nodeGroupName { + ng = mng + break + } + } + if ng == nil { + return fmt.Errorf("nodegroup with name %s not found in the config file", nodeGroupName) + } + cmd.ClusterConfig.ManagedNodeGroups = []*api.ManagedNodeGroup{ng} + } + return nil + } + return l +} + // validateSupportedConfigFields parses a config file's fields, evaluates if non-empty fields are supported, // and returns an error if a field is not supported. func validateSupportedConfigFields(obj interface{}, supportedFields []string, unsupportedFields []string) ([]string, error) { diff --git a/pkg/ctl/cmdutils/configfile_test.go b/pkg/ctl/cmdutils/configfile_test.go index 59c075c6e9..fe68e8554c 100644 --- a/pkg/ctl/cmdutils/configfile_test.go +++ b/pkg/ctl/cmdutils/configfile_test.go @@ -367,6 +367,63 @@ var _ = Describe("cmdutils configfile", func() { }) }) }) + + Describe("SetLabelLoader", func() { + It("should load the right data", func() { + cmd := &Cmd{ + CobraCommand: newCmd(), + ClusterConfigFile: filepath.Join("test_data", "cluster-with-labels.yaml"), + ClusterConfig: api.NewClusterConfig(), + ProviderConfig: api.ProviderConfig{}, + } + + Expect(NewSetLabelLoader(cmd, "ng-1", nil).Load()).To(Succeed()) + cfg := cmd.ClusterConfig + Expect(cfg.Metadata.Name).To(Equal("test-labels-1")) + Expect(cfg.ManagedNodeGroups[0].Name).To(Equal("ng-1")) + }) + When("no config file is provided and no labels", func() { + It("errors", func() { + cmd := &Cmd{ + CobraCommand: newCmd(), + ClusterConfig: api.NewClusterConfig(), + ProviderConfig: api.ProviderConfig{}, + } + + err := NewSetLabelLoader(cmd, "", nil).Load() + Expect(err).To(MatchError(ContainSubstring("--labels must be set"))) + }) + }) + When("config file with no nodegroup name is provided", func() { + It("should load all nodegroups", func() { + cmd := &Cmd{ + CobraCommand: newCmd(), + ClusterConfigFile: filepath.Join("test_data", "cluster-with-labels.yaml"), + ClusterConfig: api.NewClusterConfig(), + ProviderConfig: api.ProviderConfig{}, + } + + Expect(NewSetLabelLoader(cmd, "", nil).Load()).To(Succeed()) + cfg := cmd.ClusterConfig + Expect(cfg.Metadata.Name).To(Equal("test-labels-1")) + Expect(cfg.ManagedNodeGroups[0].Name).To(Equal("ng-1")) + Expect(cfg.ManagedNodeGroups[1].Name).To(Equal("ng-2")) + }) + }) + When("config file with missing nodegroup name is provided", func() { + It("errors", func() { + cmd := &Cmd{ + CobraCommand: newCmd(), + ClusterConfigFile: filepath.Join("test_data", "cluster-with-labels.yaml"), + ClusterConfig: api.NewClusterConfig(), + ProviderConfig: api.ProviderConfig{}, + } + + err := NewSetLabelLoader(cmd, "invalid", nil).Load() + Expect(err).To(MatchError(ContainSubstring("nodegroup with name invalid not found in the config file"))) + }) + }) + }) }) func assertValidClusterEndpoint(endpoints *api.ClusterEndpoints, privateAccess, publicAccess bool) { diff --git a/pkg/ctl/cmdutils/test_data/cluster-with-labels.yaml b/pkg/ctl/cmdutils/test_data/cluster-with-labels.yaml new file mode 100644 index 0000000000..4f582dac4e --- /dev/null +++ b/pkg/ctl/cmdutils/test_data/cluster-with-labels.yaml @@ -0,0 +1,20 @@ +# A simple example of ClusterConfig object with labels: +--- +apiVersion: eksctl.io/v1alpha5 +kind: ClusterConfig + +metadata: + name: test-labels-1 + region: us-west-2 + +managedNodeGroups: + - name: ng-1 + instanceType: m5.large + desiredCapacity: 1 + labels: + key: value + - name: ng-2 + instanceType: m5.large + desiredCapacity: 1 + labels: + key2: value2 diff --git a/pkg/ctl/set/labels.go b/pkg/ctl/set/labels.go index b2fb56f623..165bf62536 100644 --- a/pkg/ctl/set/labels.go +++ b/pkg/ctl/set/labels.go @@ -4,12 +4,12 @@ import ( "github.com/kris-nova/logger" "github.com/spf13/cobra" "github.com/spf13/pflag" - "github.com/weaveworks/eksctl/pkg/actions/label" - "github.com/weaveworks/eksctl/pkg/cfn/manager" - "github.com/weaveworks/eksctl/pkg/managed" + "github.com/weaveworks/eksctl/pkg/actions/label" api "github.com/weaveworks/eksctl/pkg/apis/eksctl.io/v1alpha5" + "github.com/weaveworks/eksctl/pkg/cfn/manager" "github.com/weaveworks/eksctl/pkg/ctl/cmdutils" + "github.com/weaveworks/eksctl/pkg/managed" ) type labelOptions struct { @@ -33,41 +33,61 @@ func setLabelsCmd(cmd *cmdutils.Cmd) { fs.StringVar(&cfg.Metadata.Name, "cluster", "", "EKS cluster name") fs.StringVarP(&options.nodeGroupName, "nodegroup", "n", "", "Nodegroup name") cmdutils.AddStringToStringVarPFlag(fs, &options.labels, "labels", "l", nil, "Labels") - _ = cobra.MarkFlagRequired(fs, "labels") cmdutils.AddRegionFlag(fs, &cmd.ProviderConfig) cmdutils.AddTimeoutFlag(fs, &cmd.ProviderConfig.WaitTimeout) + cmdutils.AddConfigFileFlag(fs, &cmd.ClusterConfigFile) }) cmdutils.AddCommonFlagsForAWS(cmd.FlagSetGroup, &cmd.ProviderConfig, false) - } func setLabels(cmd *cmdutils.Cmd, options labelOptions) error { - cfg := cmd.ClusterConfig - if cfg.Metadata.Name == "" { - return cmdutils.ErrMustBeSet(cmdutils.ClusterNameFlag(cmd)) - } - if options.nodeGroupName == "" { - return cmdutils.ErrMustBeSet("--nodegroup") - } - - if cmd.NameArg != "" { - return cmdutils.ErrUnsupportedNameArg() + // if nodeGroupName is defined, the loader will filter managed nodegroups + // for that nodegroup only. + if err := cmdutils.NewSetLabelLoader(cmd, options.nodeGroupName, options.labels).Load(); err != nil { + return err } - + cfg := cmd.ClusterConfig ctl, err := cmd.NewProviderForExistingCluster() if err != nil { return err } cmdutils.LogRegionAndVersionInfo(cmd.ClusterConfig.Metadata) - logger.Info("setting label(s) on nodegroup %s in cluster %s", options.nodeGroupName, cmd.ClusterConfig.Metadata) - service := managed.NewService(ctl.Provider.EKS(), ctl.Provider.SSM(), ctl.Provider.EC2(), manager.NewStackCollection(ctl.Provider, cfg), cfg.Metadata.Name) + + if options.nodeGroupName == "" && cmd.ClusterConfigFile != "" { + logger.Info("setting label(s) on %d nodegroup(s) in cluster %s", len(cfg.ManagedNodeGroups), cmd.ClusterConfig.Metadata) + } else if options.nodeGroupName != "" { + logger.Info("setting label(s) on nodegroup %s in cluster %s", options.nodeGroupName, cmd.ClusterConfig.Metadata) + } + manager := label.New(cfg.Metadata.Name, service, ctl.Provider.EKS()) - if err := manager.Set(options.nodeGroupName, options.labels); err != nil { - return err + // when there is no config file provided + if cmd.ClusterConfigFile == "" { + cfg.ManagedNodeGroups = append(cfg.ManagedNodeGroups, &api.ManagedNodeGroup{ + NodeGroupBase: &api.NodeGroupBase{ + Name: options.nodeGroupName, + Labels: options.labels, + }, + }) + } + for _, mng := range cfg.ManagedNodeGroups { + existingLabels, err := service.GetLabels(mng.Name) + if err != nil { + return err + } + for k := range existingLabels { + delete(mng.Labels, k) + } + if len(mng.Labels) == 0 { + logger.Info("no new labels to add for nodegroup %s", mng.Name) + continue + } + if err := manager.Set(mng.Name, mng.Labels); err != nil { + return err + } } logger.Info("done") diff --git a/pkg/ctl/set/set_test.go b/pkg/ctl/set/set_test.go index 70f253a630..9310d4ba34 100644 --- a/pkg/ctl/set/set_test.go +++ b/pkg/ctl/set/set_test.go @@ -7,6 +7,7 @@ import ( . "github.com/onsi/ginkgo" . "github.com/onsi/gomega" "github.com/spf13/cobra" + "github.com/weaveworks/eksctl/pkg/ctl/cmdutils" ) @@ -26,7 +27,7 @@ var _ = Describe("set", func() { cmd := newMockCmd("labels") _, err := cmd.execute() Expect(err).To(HaveOccurred()) - Expect(err.Error()).To(ContainSubstring("Error: required flag(s) \"labels\" not set")) + Expect(err.Error()).To(ContainSubstring("Error: --labels must be set")) }) It("fails when cluster flag not set", func() { From 808b7265fbf0514454650ccd2ab560a1cd2f041b Mon Sep 17 00:00:00 2001 From: Jake Date: Mon, 6 Dec 2021 10:28:51 +0000 Subject: [PATCH 110/124] pend failing integration test --- integration/tests/managed/managed_nodegroup_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/integration/tests/managed/managed_nodegroup_test.go b/integration/tests/managed/managed_nodegroup_test.go index 71ed0701d4..5ecf611fe4 100644 --- a/integration/tests/managed/managed_nodegroup_test.go +++ b/integration/tests/managed/managed_nodegroup_test.go @@ -120,7 +120,7 @@ var _ = Describe("(Integration) Create Managed Nodegroups", func() { }, }), - Entry("Ubuntu", &api.ManagedNodeGroup{ + PEntry("Ubuntu", &api.ManagedNodeGroup{ NodeGroupBase: &api.NodeGroupBase{ Name: "ubuntu", VolumeSize: aws.Int(25), From 2b3d8f08c547ee183081f71654ea5e10ab302d5f Mon Sep 17 00:00:00 2001 From: Gergely Brautigam <182850+Skarlso@users.noreply.github.com> Date: Mon, 6 Dec 2021 12:17:04 +0100 Subject: [PATCH 111/124] Do not use GetLabels all the time (#4520) --- pkg/ctl/set/labels.go | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/pkg/ctl/set/labels.go b/pkg/ctl/set/labels.go index 165bf62536..cea38fc6e3 100644 --- a/pkg/ctl/set/labels.go +++ b/pkg/ctl/set/labels.go @@ -66,13 +66,13 @@ func setLabels(cmd *cmdutils.Cmd, options labelOptions) error { manager := label.New(cfg.Metadata.Name, service, ctl.Provider.EKS()) // when there is no config file provided if cmd.ClusterConfigFile == "" { - cfg.ManagedNodeGroups = append(cfg.ManagedNodeGroups, &api.ManagedNodeGroup{ - NodeGroupBase: &api.NodeGroupBase{ - Name: options.nodeGroupName, - Labels: options.labels, - }, - }) + if err := manager.Set(options.nodeGroupName, options.labels); err != nil { + return err + } + logger.Info("done") + return nil } + // when there is a config file, we call GetLabels first. for _, mng := range cfg.ManagedNodeGroups { existingLabels, err := service.GetLabels(mng.Name) if err != nil { From b5a2c9c021b144f504cf4c98ce42af343961966b Mon Sep 17 00:00:00 2001 From: Herlon Aguiar Date: Mon, 6 Dec 2021 20:45:31 +0100 Subject: [PATCH 112/124] added missing --region flags --- userdocs/src/usage/iam-identity-mappings.md | 12 ++++++------ userdocs/src/usage/nodegroup-upgrade.md | 10 +++++----- 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/userdocs/src/usage/iam-identity-mappings.md b/userdocs/src/usage/iam-identity-mappings.md index dc950d74aa..1445bf1298 100644 --- a/userdocs/src/usage/iam-identity-mappings.md +++ b/userdocs/src/usage/iam-identity-mappings.md @@ -6,25 +6,25 @@ called `aws-auth`. `eksctl` provides commands to read and edit this config map. Get all identity mappings: ```bash -eksctl get iamidentitymapping --cluster my-cluster-1 +eksctl get iamidentitymapping --cluster --region= ``` Get all identity mappings matching an arn: ```bash -eksctl get iamidentitymapping --cluster my-cluster-1 --arn arn:aws:iam::123456:role/testing-role +eksctl get iamidentitymapping --cluster --region= --arn arn:aws:iam::123456:role/testing-role ``` Create an identity mapping: ```bash - eksctl create iamidentitymapping --cluster my-cluster-1 --arn arn:aws:iam::123456:role/testing --group system:masters --username admin + eksctl create iamidentitymapping --cluster --region= --arn arn:aws:iam::123456:role/testing --group system:masters --username admin ``` Delete an identity mapping: ```bash -eksctl delete iamidentitymapping --cluster my-cluster-1 --arn arn:aws:iam::123456:role/testing +eksctl delete iamidentitymapping --cluster --region= --arn arn:aws:iam::123456:role/testing ``` !!!note @@ -34,11 +34,11 @@ more mappings matching this role are found. Create an account mapping: ```bash - eksctl create iamidentitymapping --cluster my-cluster-1 --account user-account + eksctl create iamidentitymapping --cluster --region= --account user-account ``` Delete an account mapping: ```bash - eksctl delete iamidentitymapping --cluster my-cluster-1 --account user-account + eksctl delete iamidentitymapping --cluster --region= --account user-account ``` diff --git a/userdocs/src/usage/nodegroup-upgrade.md b/userdocs/src/usage/nodegroup-upgrade.md index e8e6fa0334..3c99f0a1f0 100644 --- a/userdocs/src/usage/nodegroup-upgrade.md +++ b/userdocs/src/usage/nodegroup-upgrade.md @@ -12,7 +12,7 @@ If you have a simple cluster with just an initial nodegroup (i.e. created with Get the name of old nodegroup: ``` -eksctl get nodegroups --cluster= +eksctl get nodegroups --cluster= --region= ``` !!!note @@ -21,13 +21,13 @@ eksctl get nodegroups --cluster= Create new nodegroup: ``` -eksctl create nodegroup --cluster= --managed=false +eksctl create nodegroup --cluster= --region= --managed=false ``` Delete old nodegroup: ``` -eksctl delete nodegroup --cluster= --name= +eksctl delete nodegroup --cluster= --region= --name= ``` !!!note @@ -47,13 +47,13 @@ In general terms, you are looking to: To create a new nodegroup: ``` -eksctl create nodegroup --cluster= --name= --managed=false +eksctl create nodegroup --cluster= --region= --name= --managed=false ``` To delete old nodegroup: ``` -eksctl delete nodegroup --cluster= --name= +eksctl delete nodegroup --cluster= --region= --name= ``` ## Updating multiple nodegroups with config file From 023e19761ca167689b6276a64bbc4cca4b996308 Mon Sep 17 00:00:00 2001 From: Gergely Brautigam <182850+Skarlso@users.noreply.github.com> Date: Fri, 10 Dec 2021 16:34:01 +0100 Subject: [PATCH 113/124] New release 0.77.0 (#4535) * New release 0.77.0 * Update docs/release_notes/0.77.0.md Co-authored-by: Niki Co-authored-by: Niki --- docs/release_notes/0.77.0.md | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) create mode 100644 docs/release_notes/0.77.0.md diff --git a/docs/release_notes/0.77.0.md b/docs/release_notes/0.77.0.md new file mode 100644 index 0000000000..9c1baaf3bc --- /dev/null +++ b/docs/release_notes/0.77.0.md @@ -0,0 +1,20 @@ +# Release 0.77.0 + +## Features + +- Added `--config-file` flag to `set labels` (#4502) + +## Linting + +- Removing the usage of deprecated `golint` (#4489) + +## Documentation + +- Added missing --region flag in the for nodegroup and iamidentitymapping pages (#4521) +- Separated the VPC networking documentation into meaningful sub-sections (#4492) + +## Acknowledgments + +Weaveworks would like to sincerely thank: + +- @herlon214 From 9da42670324dd4aa447d4a7415402a03a715e085 Mon Sep 17 00:00:00 2001 From: Weaveworks Bot Date: Fri, 10 Dec 2021 10:49:15 -0500 Subject: [PATCH 114/124] Prepare for next development iteration (#4537) --- pkg/version/release.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkg/version/release.go b/pkg/version/release.go index 0fdbb722f2..64cce0988d 100644 --- a/pkg/version/release.go +++ b/pkg/version/release.go @@ -3,7 +3,7 @@ package version // This file was generated by release_generate.go; DO NOT EDIT. // Version is the version number in semver format X.Y.Z -var Version = "0.77.0" +var Version = "0.78.0" // PreReleaseID can be empty for releases, "rc.X" for release candidates and "dev" for snapshots var PreReleaseID = "dev" From 1faa08b31f724d0267a14233a4910790222441a6 Mon Sep 17 00:00:00 2001 From: cpu1 Date: Tue, 30 Nov 2021 18:44:05 +0530 Subject: [PATCH 115/124] Add integration test for `associate identityprovider` --- go.mod | 1 + go.sum | 2 + .../identity_provider_test.go | 349 ++++++++++++++++++ .../testdata/cluster-role-binding.yaml | 13 + .../testdata/cluster-role.yaml | 13 + 5 files changed, 378 insertions(+) create mode 100644 integration/tests/identity_provider/identity_provider_test.go create mode 100644 integration/tests/identity_provider/testdata/cluster-role-binding.yaml create mode 100644 integration/tests/identity_provider/testdata/cluster-role.yaml diff --git a/go.mod b/go.mod index 8ae7415079..f07c752b94 100644 --- a/go.mod +++ b/go.mod @@ -251,6 +251,7 @@ require ( github.com/sassoftware/go-rpmutils v0.0.0-20190420191620-a8f1baeba37b // indirect github.com/securego/gosec/v2 v2.8.1 // indirect github.com/sergi/go-diff v1.2.0 // indirect + github.com/sethvargo/go-password v0.2.0 github.com/shazow/go-diff v0.0.0-20160112020656-b6b7b6733b8c // indirect github.com/shurcooL/httpfs v0.0.0-20190707220628-8d4bc4ba7749 // indirect github.com/shurcooL/vfsgen v0.0.0-20181202132449-6a9ea43bcacd // indirect diff --git a/go.sum b/go.sum index 5853462998..8011d98a97 100644 --- a/go.sum +++ b/go.sum @@ -1721,6 +1721,8 @@ github.com/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAm github.com/sergi/go-diff v1.1.0/go.mod h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNXdaHfM= github.com/sergi/go-diff v1.2.0 h1:XU+rvMAioB0UC3q1MFrIQy4Vo5/4VsRDQQXHsEya6xQ= github.com/sergi/go-diff v1.2.0/go.mod h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNXdaHfM= +github.com/sethvargo/go-password v0.2.0 h1:BTDl4CC/gjf/axHMaDQtw507ogrXLci6XRiLc7i/UHI= +github.com/sethvargo/go-password v0.2.0/go.mod h1:Ym4Mr9JXLBycr02MFuVQ/0JHidNetSgbzutTr3zsYXE= github.com/shazow/go-diff v0.0.0-20160112020656-b6b7b6733b8c h1:W65qqJCIOVP4jpqPQ0YvHYKwcMEMVWIzWC5iNQQfBTU= github.com/shazow/go-diff v0.0.0-20160112020656-b6b7b6733b8c/go.mod h1:/PevMnwAxekIXwN8qQyfc5gl2NlkB3CQlkizAbOkeBs= github.com/shirou/gopsutil/v3 v3.21.7/go.mod h1:RGl11Y7XMTQPmHh8F0ayC6haKNBgH4PXMJuTAcMOlz4= diff --git a/integration/tests/identity_provider/identity_provider_test.go b/integration/tests/identity_provider/identity_provider_test.go new file mode 100644 index 0000000000..76d76a4767 --- /dev/null +++ b/integration/tests/identity_provider/identity_provider_test.go @@ -0,0 +1,349 @@ +//go:build integration +// +build integration + +package identity_provider + +import ( + "context" + "encoding/base64" + "fmt" + "strings" + "testing" + "time" + + "github.com/aws/aws-sdk-go/aws" + "github.com/aws/aws-sdk-go/service/cognitoidentityprovider" + "github.com/aws/aws-sdk-go/service/eks" + "github.com/aws/aws-sdk-go/service/eks/eksiface" + + . "github.com/onsi/ginkgo" + . "github.com/onsi/gomega" + + "github.com/pkg/errors" + + v1 "k8s.io/api/core/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/client-go/kubernetes" + _ "k8s.io/client-go/plugin/pkg/client/auth/oidc" + "k8s.io/client-go/tools/clientcmd" + clientcmdapi "k8s.io/client-go/tools/clientcmd/api" + + "github.com/sethvargo/go-password/password" + + . "github.com/weaveworks/eksctl/integration/matchers" + . "github.com/weaveworks/eksctl/integration/runner" + + "github.com/weaveworks/eksctl/integration/tests" + "github.com/weaveworks/eksctl/integration/utilities/kube" + "github.com/weaveworks/eksctl/pkg/testutils" +) + +const ( + oidcGroupName = "oidc-reader" +) + +var ( + params *tests.Params + oidcConfig *OIDCConfig + cleanupCognitoResources func() error +) + +type OIDCConfig struct { + clientID string + idToken string + refreshToken string + idpIssuerURL string +} + +func init() { + // Call testing.Init() prior to tests.NewParams(), as otherwise -test.* will not be recognised. See also: https://golang.org/doc/go1.13#testing + testing.Init() + params = tests.NewParams("identity-provider") +} + +func TestIdentityProvider(t *testing.T) { + testutils.RegisterAndRun(t) +} + +var _ = BeforeSuite(func() { + if !params.SkipCreate { + cmd := params.EksctlCreateCmd.WithArgs( + "cluster", + "--verbose", "4", + "--name", params.ClusterName, + "--kubeconfig", params.KubeconfigPath, + "--nodes", "1", + ) + Expect(cmd).To(RunSuccessfully()) + } + + var err error + fmt.Fprintf(GinkgoWriter, "creating Cognito OIDC provider\n") + oidcConfig, err = setupCognitoProvider(params.ClusterName, params.Region) + Expect(err).NotTo(HaveOccurred()) + fmt.Fprintf(GinkgoWriter, "created Cognito provider; client ID: %s\n", oidcConfig.clientID) +}) + +var _ = Describe("(Integration) [Identity Provider]", func() { + + It("should associate, get and disassociate identity provider", func() { + By("associating a new identity provider") + cmd := associateOIDCProviderCMD(oidcConfig, params.ClusterName, params.Region) + Expect(cmd).To(RunSuccessfully()) + + By("creating RBAC resources") + test, err := kube.NewTest(params.KubeconfigPath) + Expect(err).NotTo(HaveOccurred()) + defer test.Close() + + test.CreateClusterRoleFromFile("testdata/cluster-role.yaml") + test.CreateClusterRoleBindingFromFile("testdata/cluster-role-binding.yaml") + + By("creating an OIDC Clientset") + clientset, err := createOIDCClientset(eks.New(NewSession(params.Region)), oidcConfig, params.ClusterName) + Expect(err).NotTo(HaveOccurred()) + + By("reading Kubernetes resources") + list, err := clientset.CoreV1().Nodes().List(context.Background(), metav1.ListOptions{}) + Expect(err).NotTo(HaveOccurred()) + Expect(list.Items).To(HaveLen(1)) + + secrets, err := clientset.CoreV1().Secrets(metav1.NamespaceAll).List(context.Background(), metav1.ListOptions{}) + Expect(err).NotTo(HaveOccurred()) + Expect(secrets.Items).NotTo(BeEmpty()) + + By("ensuring the client does not have write access") + _, err = clientset.CoreV1().ConfigMaps(metav1.NamespaceDefault).Create(context.Background(), &v1.ConfigMap{ + ObjectMeta: metav1.ObjectMeta{ + Name: "testdata", + }, + Data: map[string]string{ + "key": "value", + }, + }, metav1.CreateOptions{}) + + Expect(err).To(HaveOccurred()) + }) + +}) + +var _ = AfterSuite(func() { + if !params.SkipCreate && !params.SkipDelete { + params.DeleteClusters() + } + if cleanupCognitoResources != nil { + Expect(cleanupCognitoResources()).To(Succeed()) + } +}) + +func createOIDCClientset(eksAPI eksiface.EKSAPI, o *OIDCConfig, clusterName string) (kubernetes.Interface, error) { + contextName := fmt.Sprintf("%s@%s", "test", clusterName) + + cluster, err := eksAPI.DescribeCluster(&eks.DescribeClusterInput{ + Name: aws.String(clusterName), + }) + if err != nil { + return nil, errors.Wrap(err, "describing cluster") + } + + certData, err := base64.StdEncoding.DecodeString(*cluster.Cluster.CertificateAuthority.Data) + if err != nil { + return nil, errors.Wrap(err, "unexpected error decoding certificate authority data") + } + + config := clientcmdapi.Config{ + Clusters: map[string]*clientcmdapi.Cluster{ + clusterName: { + Server: *cluster.Cluster.Endpoint, + CertificateAuthorityData: certData, + }, + }, + Contexts: map[string]*clientcmdapi.Context{ + contextName: { + Cluster: clusterName, + AuthInfo: contextName, + }, + }, + AuthInfos: map[string]*clientcmdapi.AuthInfo{ + contextName: { + AuthProvider: &clientcmdapi.AuthProviderConfig{ + Name: "oidc", + Config: map[string]string{ + "client-id": o.clientID, + "id-token": o.idToken, + "refresh-token": o.refreshToken, + "idp-issuer-url": o.idpIssuerURL, + }, + }, + }, + }, + CurrentContext: contextName, + } + + clientConfig, err := clientcmd.NewDefaultClientConfig(config, &clientcmd.ConfigOverrides{}).ClientConfig() + if err != nil { + return nil, errors.Wrap(err, "creating default client config") + } + + return kubernetes.NewForConfig(clientConfig) +} + +func setupCognitoProvider(clusterName, region string) (*OIDCConfig, error) { + c := cognitoidentityprovider.New(NewSession(region)) + + pool, err := c.CreateUserPool(&cognitoidentityprovider.CreateUserPoolInput{ + Policies: &cognitoidentityprovider.UserPoolPolicyType{ + PasswordPolicy: &cognitoidentityprovider.PasswordPolicyType{ + MinimumLength: aws.Int64(10), + RequireLowercase: aws.Bool(false), + RequireNumbers: aws.Bool(true), + RequireSymbols: aws.Bool(true), + RequireUppercase: aws.Bool(false), + }, + }, + PoolName: aws.String(clusterName), + UsernameAttributes: aws.StringSlice([]string{"email"}), + }) + + if err != nil { + return nil, errors.Wrap(err, "creating user pool") + } + + cleanupCognitoResources = func() error { + _, err := c.DeleteUserPool(&cognitoidentityprovider.DeleteUserPoolInput{ + UserPoolId: pool.UserPool.Id, + }) + return err + } + + client, err := c.CreateUserPoolClient(&cognitoidentityprovider.CreateUserPoolClientInput{ + ClientName: aws.String("eks-client"), + ExplicitAuthFlows: aws.StringSlice([]string{ + cognitoidentityprovider.ExplicitAuthFlowsTypeAllowAdminUserPasswordAuth, + cognitoidentityprovider.ExplicitAuthFlowsTypeAllowUserPasswordAuth, + cognitoidentityprovider.ExplicitAuthFlowsTypeAllowRefreshTokenAuth, + }), + AllowedOAuthFlows: aws.StringSlice([]string{ + cognitoidentityprovider.OAuthFlowTypeImplicit, + }), + AllowedOAuthScopes: aws.StringSlice([]string{ + "profile", + "phone", + "email", + "openid", + "aws.cognito.signin.user.admin", + }), + UserPoolId: pool.UserPool.Id, + GenerateSecret: aws.Bool(false), + SupportedIdentityProviders: aws.StringSlice([]string{"COGNITO"}), + // TODO this is likely not required, check if this can be removed. + CallbackURLs: aws.StringSlice([]string{"https://example.com"}), + }) + + if err != nil { + return nil, errors.Wrap(err, "creating user pool client") + } + + var ( + userPoolID = pool.UserPool.Id + clientUsername = aws.String(fmt.Sprintf("%s@weave.works", clusterName)) + ) + + _, err = c.AdminCreateUser(&cognitoidentityprovider.AdminCreateUserInput{ + UserPoolId: userPoolID, + Username: clientUsername, + }) + + if err != nil { + return nil, errors.Wrap(err, "creating user") + } + + pass, err := password.Generate(10, 2, 3, false, false) + if err != nil { + return nil, errors.Wrap(err, "generating password") + } + + _, err = c.AdminSetUserPassword(&cognitoidentityprovider.AdminSetUserPasswordInput{ + UserPoolId: userPoolID, + Username: clientUsername, + Password: aws.String(pass), + Permanent: aws.Bool(true), + }) + + if err != nil { + return nil, errors.Wrap(err, "setting user password") + } + + groupName := aws.String(oidcGroupName) + + _, err = c.CreateGroup(&cognitoidentityprovider.CreateGroupInput{ + UserPoolId: userPoolID, + GroupName: groupName, + }) + + if err != nil { + return nil, errors.Wrap(err, "creating group") + } + + _, err = c.AdminAddUserToGroup(&cognitoidentityprovider.AdminAddUserToGroupInput{ + GroupName: groupName, + UserPoolId: userPoolID, + Username: clientUsername, + }) + + if err != nil { + return nil, errors.Wrap(err, "adding user to group") + } + + auth, err := c.AdminInitiateAuth(&cognitoidentityprovider.AdminInitiateAuthInput{ + AuthFlow: aws.String(cognitoidentityprovider.AuthFlowTypeAdminUserPasswordAuth), + AuthParameters: map[string]*string{ + "USERNAME": clientUsername, + "PASSWORD": aws.String(pass), + }, + ClientId: client.UserPoolClient.ClientId, + UserPoolId: userPoolID, + }) + + if err != nil { + return nil, errors.Wrap(err, "initiating auth") + } + + return &OIDCConfig{ + clientID: *client.UserPoolClient.ClientId, + idToken: *auth.AuthenticationResult.IdToken, + refreshToken: *auth.AuthenticationResult.RefreshToken, + idpIssuerURL: fmt.Sprintf("https://cognito-idp.%s.amazonaws.com/%s", region, *userPoolID), + }, nil + +} + +func associateOIDCProviderCMD(o *OIDCConfig, clusterName, region string) Cmd { + clusterConfig := fmt.Sprintf(`apiVersion: eksctl.io/v1alpha5 +kind: ClusterConfig + +metadata: + name: %s + region: %s + +identityProviders: + - name: cognito + issuerURL: %s + clientID: %s + usernameClaim: email + groupsClaim: "cognito:groups" + groupsPrefix: "gid:" + type: oidc +`, clusterName, region, o.idpIssuerURL, o.clientID) + + return params.EksctlCmd.WithArgs( + "associate", + "identityprovider", + "--config-file", "-", + "--verbose", "4", + "--wait", + ). + WithStdin(strings.NewReader(clusterConfig)). + WithoutArg("--region", region). + WithTimeout(35 * time.Minute) +} diff --git a/integration/tests/identity_provider/testdata/cluster-role-binding.yaml b/integration/tests/identity_provider/testdata/cluster-role-binding.yaml new file mode 100644 index 0000000000..f85c4c151a --- /dev/null +++ b/integration/tests/identity_provider/testdata/cluster-role-binding.yaml @@ -0,0 +1,13 @@ +kind: ClusterRoleBinding +apiVersion: rbac.authorization.k8s.io/v1 +metadata: + name: oidc-reader + namespace: default +subjects: + - kind: Group + name: "gid:oidc-reader" + apiGroup: rbac.authorization.k8s.io +roleRef: + kind: ClusterRole + name: oidc-reader + apiGroup: rbac.authorization.k8s.io diff --git a/integration/tests/identity_provider/testdata/cluster-role.yaml b/integration/tests/identity_provider/testdata/cluster-role.yaml new file mode 100644 index 0000000000..e0e60fe364 --- /dev/null +++ b/integration/tests/identity_provider/testdata/cluster-role.yaml @@ -0,0 +1,13 @@ +kind: ClusterRole +apiVersion: rbac.authorization.k8s.io/v1 +metadata: + name: oidc-reader +rules: + - apiGroups: + - "" + resources: + - "*" + verbs: + - "get" + - "watch" + - "list" From b0a3a2d205ca22bef84dbc085cb25cadcfcd0d98 Mon Sep 17 00:00:00 2001 From: cpu1 Date: Tue, 30 Nov 2021 18:44:30 +0530 Subject: [PATCH 116/124] Add integration test for `get identityprovider` --- .../tests/identity_provider/identity_provider_test.go | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/integration/tests/identity_provider/identity_provider_test.go b/integration/tests/identity_provider/identity_provider_test.go index 76d76a4767..0c402d84d3 100644 --- a/integration/tests/identity_provider/identity_provider_test.go +++ b/integration/tests/identity_provider/identity_provider_test.go @@ -91,6 +91,17 @@ var _ = Describe("(Integration) [Identity Provider]", func() { cmd := associateOIDCProviderCMD(oidcConfig, params.ClusterName, params.Region) Expect(cmd).To(RunSuccessfully()) + By("getting the identity provider") + cmd = params.EksctlGetCmd. + WithArgs( + "identityprovider", + "--cluster", params.ClusterName, + "-o", "yaml", + ) + Expect(cmd).To(RunSuccessfullyWithOutputStringLines( + ContainElement(ContainSubstring(fmt.Sprintf("ClientID: %s", oidcConfig.clientID)))), + ) + By("creating RBAC resources") test, err := kube.NewTest(params.KubeconfigPath) Expect(err).NotTo(HaveOccurred()) From de3266c1750aa2fd81946e81d4aa78c2cc249575 Mon Sep 17 00:00:00 2001 From: cpu1 Date: Tue, 30 Nov 2021 18:44:52 +0530 Subject: [PATCH 117/124] Add integration test for `disassociate identityprovider` --- .../identity_provider/identity_provider_test.go | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/integration/tests/identity_provider/identity_provider_test.go b/integration/tests/identity_provider/identity_provider_test.go index 0c402d84d3..77ecb5b9c7 100644 --- a/integration/tests/identity_provider/identity_provider_test.go +++ b/integration/tests/identity_provider/identity_provider_test.go @@ -134,6 +134,18 @@ var _ = Describe("(Integration) [Identity Provider]", func() { }, metav1.CreateOptions{}) Expect(err).To(HaveOccurred()) + + By("disassociating the identity provider") + cmd = params.EksctlCmd. + WithArgs( + "disassociate", + "identityprovider", + "--cluster", params.ClusterName, + "--wait", + ). + WithTimeout(30 * time.Minute) + Expect(cmd).To(RunSuccessfully()) + }) }) From e812fc7ab7e78ef7c2a81cbad8efcecfb68f26af Mon Sep 17 00:00:00 2001 From: cpu1 Date: Tue, 30 Nov 2021 18:53:02 +0530 Subject: [PATCH 118/124] Rename import alias and function --- .../identity_provider_test.go | 47 +++++++++++-------- 1 file changed, 27 insertions(+), 20 deletions(-) diff --git a/integration/tests/identity_provider/identity_provider_test.go b/integration/tests/identity_provider/identity_provider_test.go index 77ecb5b9c7..107a6aaace 100644 --- a/integration/tests/identity_provider/identity_provider_test.go +++ b/integration/tests/identity_provider/identity_provider_test.go @@ -1,6 +1,7 @@ //go:build integration // +build integration +//revive:disable package identity_provider import ( @@ -21,10 +22,12 @@ import ( "github.com/pkg/errors" - v1 "k8s.io/api/core/v1" + // Register the OIDC provider + _ "k8s.io/client-go/plugin/pkg/client/auth/oidc" + + corev1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/client-go/kubernetes" - _ "k8s.io/client-go/plugin/pkg/client/auth/oidc" "k8s.io/client-go/tools/clientcmd" clientcmdapi "k8s.io/client-go/tools/clientcmd/api" @@ -88,7 +91,19 @@ var _ = Describe("(Integration) [Identity Provider]", func() { It("should associate, get and disassociate identity provider", func() { By("associating a new identity provider") - cmd := associateOIDCProviderCMD(oidcConfig, params.ClusterName, params.Region) + identityProviderClusterConfig := makeIdentityProviderClusterConfig(oidcConfig, params.ClusterName, params.Region) + + cmd := params.EksctlCmd.WithArgs( + "associate", + "identityprovider", + "--config-file", "-", + "--verbose", "4", + "--wait", + ). + WithStdin(strings.NewReader(identityProviderClusterConfig)). + WithoutArg("--region", params.Region). + WithTimeout(35 * time.Minute) + Expect(cmd).To(RunSuccessfully()) By("getting the identity provider") @@ -115,16 +130,16 @@ var _ = Describe("(Integration) [Identity Provider]", func() { Expect(err).NotTo(HaveOccurred()) By("reading Kubernetes resources") - list, err := clientset.CoreV1().Nodes().List(context.Background(), metav1.ListOptions{}) + list, err := clientset.CoreV1().Nodes().List(context.TODO(), metav1.ListOptions{}) Expect(err).NotTo(HaveOccurred()) Expect(list.Items).To(HaveLen(1)) - secrets, err := clientset.CoreV1().Secrets(metav1.NamespaceAll).List(context.Background(), metav1.ListOptions{}) + secrets, err := clientset.CoreV1().Secrets(metav1.NamespaceAll).List(context.TODO(), metav1.ListOptions{}) Expect(err).NotTo(HaveOccurred()) Expect(secrets.Items).NotTo(BeEmpty()) By("ensuring the client does not have write access") - _, err = clientset.CoreV1().ConfigMaps(metav1.NamespaceDefault).Create(context.Background(), &v1.ConfigMap{ + _, err = clientset.CoreV1().ConfigMaps(metav1.NamespaceDefault).Create(context.TODO(), &corev1.ConfigMap{ ObjectMeta: metav1.ObjectMeta{ Name: "testdata", }, @@ -140,10 +155,13 @@ var _ = Describe("(Integration) [Identity Provider]", func() { WithArgs( "disassociate", "identityprovider", - "--cluster", params.ClusterName, + "--config-file", "-", "--wait", ). + WithStdin(strings.NewReader(identityProviderClusterConfig)). + WithoutArg("--region", params.Region). WithTimeout(30 * time.Minute) + Expect(cmd).To(RunSuccessfully()) }) @@ -341,8 +359,8 @@ func setupCognitoProvider(clusterName, region string) (*OIDCConfig, error) { } -func associateOIDCProviderCMD(o *OIDCConfig, clusterName, region string) Cmd { - clusterConfig := fmt.Sprintf(`apiVersion: eksctl.io/v1alpha5 +func makeIdentityProviderClusterConfig(o *OIDCConfig, clusterName, region string) string { + return fmt.Sprintf(`apiVersion: eksctl.io/v1alpha5 kind: ClusterConfig metadata: @@ -358,15 +376,4 @@ identityProviders: groupsPrefix: "gid:" type: oidc `, clusterName, region, o.idpIssuerURL, o.clientID) - - return params.EksctlCmd.WithArgs( - "associate", - "identityprovider", - "--config-file", "-", - "--verbose", "4", - "--wait", - ). - WithStdin(strings.NewReader(clusterConfig)). - WithoutArg("--region", region). - WithTimeout(35 * time.Minute) } From 5a76a7edc5e0c3dcfdfe02de9a29de2100c1237e Mon Sep 17 00:00:00 2001 From: cpu1 Date: Wed, 1 Dec 2021 16:17:58 +0530 Subject: [PATCH 119/124] Increase timeout --- integration/tests/identity_provider/identity_provider_test.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/integration/tests/identity_provider/identity_provider_test.go b/integration/tests/identity_provider/identity_provider_test.go index 107a6aaace..dd6339fddf 100644 --- a/integration/tests/identity_provider/identity_provider_test.go +++ b/integration/tests/identity_provider/identity_provider_test.go @@ -102,7 +102,7 @@ var _ = Describe("(Integration) [Identity Provider]", func() { ). WithStdin(strings.NewReader(identityProviderClusterConfig)). WithoutArg("--region", params.Region). - WithTimeout(35 * time.Minute) + WithTimeout(40 * time.Minute) Expect(cmd).To(RunSuccessfully()) @@ -160,7 +160,7 @@ var _ = Describe("(Integration) [Identity Provider]", func() { ). WithStdin(strings.NewReader(identityProviderClusterConfig)). WithoutArg("--region", params.Region). - WithTimeout(30 * time.Minute) + WithTimeout(45 * time.Minute) Expect(cmd).To(RunSuccessfully()) From 53b1c785c4295c06249ce32bca56e2afe85254cf Mon Sep 17 00:00:00 2001 From: cpu1 Date: Wed, 8 Dec 2021 15:51:53 +0530 Subject: [PATCH 120/124] Split Cognito setup func --- .../identity_provider_test.go | 107 ++++++++++-------- 1 file changed, 62 insertions(+), 45 deletions(-) diff --git a/integration/tests/identity_provider/identity_provider_test.go b/integration/tests/identity_provider/identity_provider_test.go index dd6339fddf..c5b7bd2879 100644 --- a/integration/tests/identity_provider/identity_provider_test.go +++ b/integration/tests/identity_provider/identity_provider_test.go @@ -14,14 +14,13 @@ import ( "github.com/aws/aws-sdk-go/aws" "github.com/aws/aws-sdk-go/service/cognitoidentityprovider" + "github.com/aws/aws-sdk-go/service/cognitoidentityprovider/cognitoidentityprovideriface" "github.com/aws/aws-sdk-go/service/eks" "github.com/aws/aws-sdk-go/service/eks/eksiface" . "github.com/onsi/ginkgo" . "github.com/onsi/gomega" - "github.com/pkg/errors" - // Register the OIDC provider _ "k8s.io/client-go/plugin/pkg/client/auth/oidc" @@ -184,12 +183,12 @@ func createOIDCClientset(eksAPI eksiface.EKSAPI, o *OIDCConfig, clusterName stri Name: aws.String(clusterName), }) if err != nil { - return nil, errors.Wrap(err, "describing cluster") + return nil, fmt.Errorf("describing cluster: %w", err) } certData, err := base64.StdEncoding.DecodeString(*cluster.Cluster.CertificateAuthority.Data) if err != nil { - return nil, errors.Wrap(err, "unexpected error decoding certificate authority data") + return nil, fmt.Errorf("unexpected error decoding certificate authority data: %w", err) } config := clientcmdapi.Config{ @@ -223,15 +222,58 @@ func createOIDCClientset(eksAPI eksiface.EKSAPI, o *OIDCConfig, clusterName stri clientConfig, err := clientcmd.NewDefaultClientConfig(config, &clientcmd.ConfigOverrides{}).ClientConfig() if err != nil { - return nil, errors.Wrap(err, "creating default client config") + return nil, fmt.Errorf("creating default client config: %w", err) } return kubernetes.NewForConfig(clientConfig) } +type userPoolClient struct { + userPoolID *string + clientID *string +} + func setupCognitoProvider(clusterName, region string) (*OIDCConfig, error) { c := cognitoidentityprovider.New(NewSession(region)) + userPoolClient, err := createCognitoUserPoolClient(c, clusterName) + if err != nil { + return nil, err + } + + userPass, err := password.Generate(10, 2, 3, false, false) + if err != nil { + return nil, fmt.Errorf("generating password: %w", err) + } + + clientUsername := aws.String(fmt.Sprintf("%s@weave.works", clusterName)) + if err := createCognitoUserGroup(c, userPoolClient.userPoolID, clientUsername, userPass); err != nil { + return nil, err + } + + auth, err := c.AdminInitiateAuth(&cognitoidentityprovider.AdminInitiateAuthInput{ + AuthFlow: aws.String(cognitoidentityprovider.AuthFlowTypeAdminUserPasswordAuth), + AuthParameters: map[string]*string{ + "USERNAME": clientUsername, + "PASSWORD": aws.String(userPass), + }, + ClientId: userPoolClient.clientID, + UserPoolId: userPoolClient.userPoolID, + }) + + if err != nil { + return nil, fmt.Errorf("initiating auth: %w", err) + } + + return &OIDCConfig{ + clientID: *userPoolClient.clientID, + idToken: *auth.AuthenticationResult.IdToken, + refreshToken: *auth.AuthenticationResult.RefreshToken, + idpIssuerURL: fmt.Sprintf("https://cognito-idp.%s.amazonaws.com/%s", region, *userPoolClient.userPoolID), + }, nil +} + +func createCognitoUserPoolClient(c cognitoidentityprovideriface.CognitoIdentityProviderAPI, clusterName string) (*userPoolClient, error) { pool, err := c.CreateUserPool(&cognitoidentityprovider.CreateUserPoolInput{ Policies: &cognitoidentityprovider.UserPoolPolicyType{ PasswordPolicy: &cognitoidentityprovider.PasswordPolicyType{ @@ -247,7 +289,7 @@ func setupCognitoProvider(clusterName, region string) (*OIDCConfig, error) { }) if err != nil { - return nil, errors.Wrap(err, "creating user pool") + return nil, fmt.Errorf("creating user pool: %w", err) } cleanupCognitoResources = func() error { @@ -282,37 +324,33 @@ func setupCognitoProvider(clusterName, region string) (*OIDCConfig, error) { }) if err != nil { - return nil, errors.Wrap(err, "creating user pool client") + return nil, fmt.Errorf("creating user pool client: %w", err) } + return &userPoolClient{ + userPoolID: pool.UserPool.Id, + clientID: client.UserPoolClient.ClientId, + }, nil +} - var ( - userPoolID = pool.UserPool.Id - clientUsername = aws.String(fmt.Sprintf("%s@weave.works", clusterName)) - ) - - _, err = c.AdminCreateUser(&cognitoidentityprovider.AdminCreateUserInput{ +func createCognitoUserGroup(c cognitoidentityprovideriface.CognitoIdentityProviderAPI, userPoolID, clientUsername *string, userPass string) error { + _, err := c.AdminCreateUser(&cognitoidentityprovider.AdminCreateUserInput{ UserPoolId: userPoolID, Username: clientUsername, }) if err != nil { - return nil, errors.Wrap(err, "creating user") - } - - pass, err := password.Generate(10, 2, 3, false, false) - if err != nil { - return nil, errors.Wrap(err, "generating password") + return fmt.Errorf("creating user: %w", err) } _, err = c.AdminSetUserPassword(&cognitoidentityprovider.AdminSetUserPasswordInput{ UserPoolId: userPoolID, Username: clientUsername, - Password: aws.String(pass), + Password: aws.String(userPass), Permanent: aws.Bool(true), }) if err != nil { - return nil, errors.Wrap(err, "setting user password") + return fmt.Errorf("setting user password: %w", err) } groupName := aws.String(oidcGroupName) @@ -323,7 +361,7 @@ func setupCognitoProvider(clusterName, region string) (*OIDCConfig, error) { }) if err != nil { - return nil, errors.Wrap(err, "creating group") + return fmt.Errorf("creating group: %w", err) } _, err = c.AdminAddUserToGroup(&cognitoidentityprovider.AdminAddUserToGroupInput{ @@ -333,30 +371,9 @@ func setupCognitoProvider(clusterName, region string) (*OIDCConfig, error) { }) if err != nil { - return nil, errors.Wrap(err, "adding user to group") + return fmt.Errorf("adding user to group: %w", err) } - - auth, err := c.AdminInitiateAuth(&cognitoidentityprovider.AdminInitiateAuthInput{ - AuthFlow: aws.String(cognitoidentityprovider.AuthFlowTypeAdminUserPasswordAuth), - AuthParameters: map[string]*string{ - "USERNAME": clientUsername, - "PASSWORD": aws.String(pass), - }, - ClientId: client.UserPoolClient.ClientId, - UserPoolId: userPoolID, - }) - - if err != nil { - return nil, errors.Wrap(err, "initiating auth") - } - - return &OIDCConfig{ - clientID: *client.UserPoolClient.ClientId, - idToken: *auth.AuthenticationResult.IdToken, - refreshToken: *auth.AuthenticationResult.RefreshToken, - idpIssuerURL: fmt.Sprintf("https://cognito-idp.%s.amazonaws.com/%s", region, *userPoolID), - }, nil - + return nil } func makeIdentityProviderClusterConfig(o *OIDCConfig, clusterName, region string) string { From b24dc36ecb1b383ead38453298c98cfedcbea0bc Mon Sep 17 00:00:00 2001 From: Gergely Brautigam <182850+Skarlso@users.noreply.github.com> Date: Fri, 17 Dec 2021 13:48:19 +0100 Subject: [PATCH 121/124] Fix ignoring partitions on EBS controller (#4547) --- pkg/cfn/builder/iam_test.go | 156 ++++++++++++++++++++++++++++++++++- pkg/cfn/builder/statement.go | 15 ++-- 2 files changed, 163 insertions(+), 8 deletions(-) diff --git a/pkg/cfn/builder/iam_test.go b/pkg/cfn/builder/iam_test.go index 9c2284ac45..0abcedf3ad 100644 --- a/pkg/cfn/builder/iam_test.go +++ b/pkg/cfn/builder/iam_test.go @@ -293,8 +293,8 @@ var _ = Describe("template builder for IAM", func() { "Fn::Sub": "arn:${AWS::Partition}:iam::aws:policy/AmazonEC2ContainerRegistryPowerUser" } ]`)) - Expect(t).To(HaveOutputWithValue("Role1", `{ "Fn::GetAtt": "Role1.Arn" }`)) + Expect(t).To(HaveResourceWithPropertyValue("PolicyEBSCSIController", "PolicyDocument", expectedEbsPolicyDocument)) }) It("can parse an iamserviceaccount addon template", func() { @@ -465,3 +465,157 @@ const expectedAssumeRolePolicyDocument = `{ ], "Version": "2012-10-17" }` + +const expectedEbsPolicyDocument = `{ + "Statement": [ + { + "Action": [ + "ec2:CreateSnapshot", + "ec2:AttachVolume", + "ec2:DetachVolume", + "ec2:ModifyVolume", + "ec2:DescribeAvailabilityZones", + "ec2:DescribeInstances", + "ec2:DescribeSnapshots", + "ec2:DescribeTags", + "ec2:DescribeVolumes", + "ec2:DescribeVolumesModifications" + ], + "Effect": "Allow", + "Resource": "*" + }, + { + "Action": [ + "ec2:CreateTags" + ], + "Condition": { + "StringEquals": { + "ec2:CreateAction": [ + "CreateVolume", + "CreateSnapshot" + ] + } + }, + "Effect": "Allow", + "Resource": [ + { + "Fn::Sub": "arn:${AWS::Partition}:ec2:*:*:volume/*" + }, + { + "Fn::Sub": "arn:${AWS::Partition}:ec2:*:*:snapshot/*" + } + ] + }, + { + "Action": [ + "ec2:DeleteTags" + ], + "Effect": "Allow", + "Resource": [ + { + "Fn::Sub": "arn:${AWS::Partition}:ec2:*:*:volume/*" + }, + { + "Fn::Sub": "arn:${AWS::Partition}:ec2:*:*:snapshot/*" + } + ] + }, + { + "Action": [ + "ec2:CreateVolume" + ], + "Condition": { + "StringLike": { + "aws:RequestTag/ebs.csi.aws.com/cluster": "true" + } + }, + "Effect": "Allow", + "Resource": "*" + }, + { + "Action": [ + "ec2:CreateVolume" + ], + "Condition": { + "StringLike": { + "aws:RequestTag/CSIVolumeName": "*" + } + }, + "Effect": "Allow", + "Resource": "*" + }, + { + "Action": [ + "ec2:CreateVolume" + ], + "Condition": { + "StringLike": { + "aws:RequestTag/kubernetes.io/cluster/*": "owned" + } + }, + "Effect": "Allow", + "Resource": "*" + }, + { + "Action": [ + "ec2:DeleteVolume" + ], + "Condition": { + "StringLike": { + "ec2:ResourceTag/ebs.csi.aws.com/cluster": "true" + } + }, + "Effect": "Allow", + "Resource": "*" + }, + { + "Action": [ + "ec2:DeleteVolume" + ], + "Condition": { + "StringLike": { + "ec2:ResourceTag/CSIVolumeName": "*" + } + }, + "Effect": "Allow", + "Resource": "*" + }, + { + "Action": [ + "ec2:DeleteVolume" + ], + "Condition": { + "StringLike": { + "ec2:ResourceTag/kubernetes.io/cluster/*": "owned" + } + }, + "Effect": "Allow", + "Resource": "*" + }, + { + "Action": [ + "ec2:DeleteSnapshot" + ], + "Condition": { + "StringLike": { + "ec2:ResourceTag/CSIVolumeSnapshotName": "*" + } + }, + "Effect": "Allow", + "Resource": "*" + }, + { + "Action": [ + "ec2:DeleteSnapshot" + ], + "Condition": { + "StringLike": { + "ec2:ResourceTag/ebs.csi.aws.com/cluster": "true" + } + }, + "Effect": "Allow", + "Resource": "*" + } + ], + "Version": "2012-10-17" +}` diff --git a/pkg/cfn/builder/statement.go b/pkg/cfn/builder/statement.go index 6419a1ce30..0246b7f08f 100644 --- a/pkg/cfn/builder/statement.go +++ b/pkg/cfn/builder/statement.go @@ -1,8 +1,9 @@ package builder import ( - cft "github.com/weaveworks/eksctl/pkg/cfn/template" gfnt "github.com/weaveworks/goformation/v4/cloudformation/types" + + cft "github.com/weaveworks/eksctl/pkg/cfn/template" ) const ( @@ -319,9 +320,9 @@ func ebsStatements() []cft.MapOfInterfaces { "Action": []string{ "ec2:CreateTags", }, - "Resource": []string{ - "arn:aws:ec2:*:*:volume/*", - "arn:aws:ec2:*:*:snapshot/*", + "Resource": []*gfnt.Value{ + addARNPartitionPrefix("ec2:*:*:volume/*"), + addARNPartitionPrefix("ec2:*:*:snapshot/*"), }, "Condition": cft.MapOfInterfaces{ "StringEquals": cft.MapOfInterfaces{ @@ -337,9 +338,9 @@ func ebsStatements() []cft.MapOfInterfaces { "Action": []string{ "ec2:DeleteTags", }, - "Resource": []string{ - "arn:aws:ec2:*:*:volume/*", - "arn:aws:ec2:*:*:snapshot/*", + "Resource": []*gfnt.Value{ + addARNPartitionPrefix("ec2:*:*:volume/*"), + addARNPartitionPrefix("ec2:*:*:snapshot/*"), }, }, { From ad4b972a90505770effc77d8fb25cb907a10dd29 Mon Sep 17 00:00:00 2001 From: Gergely Brautigam <182850+Skarlso@users.noreply.github.com> Date: Fri, 17 Dec 2021 16:53:51 +0100 Subject: [PATCH 122/124] Increase delete wait time (#4548) --- integration/tests/params.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/integration/tests/params.go b/integration/tests/params.go index 340493c6d9..a73481eab1 100644 --- a/integration/tests/params.go +++ b/integration/tests/params.go @@ -110,7 +110,7 @@ func (p *Params) GenerateCommands() { p.EksctlDeleteCmd = p.EksctlCmd. WithArgs("delete"). - WithTimeout(15 * time.Minute) + WithTimeout(30 * time.Minute) p.EksctlDeleteClusterCmd = p.EksctlDeleteCmd. WithArgs("cluster", "--verbose", "4"). From de821be785e8fd59439bee5929f69a31a55c5e6d Mon Sep 17 00:00:00 2001 From: nikimanoledaki Date: Tue, 21 Dec 2021 11:17:24 +0200 Subject: [PATCH 123/124] Fix linter complaining about pkg name --- integration/tests/existing_vpc/existing_vpc_test.go | 2 +- integration/tests/unowned_cluster/unowned_cluster_test.go | 5 ++--- pkg/actions/addon/create.go | 2 +- 3 files changed, 4 insertions(+), 5 deletions(-) diff --git a/integration/tests/existing_vpc/existing_vpc_test.go b/integration/tests/existing_vpc/existing_vpc_test.go index 6c9b019b2d..f4af012f69 100644 --- a/integration/tests/existing_vpc/existing_vpc_test.go +++ b/integration/tests/existing_vpc/existing_vpc_test.go @@ -1,7 +1,7 @@ //go:build integration // +build integration -package unowned_clusters +package unowned import ( "encoding/json" diff --git a/integration/tests/unowned_cluster/unowned_cluster_test.go b/integration/tests/unowned_cluster/unowned_cluster_test.go index a316673d11..3e39a37300 100644 --- a/integration/tests/unowned_cluster/unowned_cluster_test.go +++ b/integration/tests/unowned_cluster/unowned_cluster_test.go @@ -2,7 +2,7 @@ // +build integration //revive:disable Not changing package name -package unowned_clusters +package unowned import ( "encoding/json" @@ -32,8 +32,7 @@ var params *tests.Params func init() { // Call testing.Init() prior to tests.NewParams(), as otherwise -test.* will not be recognised. See also: https://golang.org/doc/go1.13#testing testing.Init() - // "unowned_clusters" lead to names longer than allowed for CF stacks - params = tests.NewParams("uc") + params = tests.NewParams("unowned") } func TestE2E(t *testing.T) { diff --git a/pkg/actions/addon/create.go b/pkg/actions/addon/create.go index 7a6b43d9db..62b2254bca 100644 --- a/pkg/actions/addon/create.go +++ b/pkg/actions/addon/create.go @@ -189,6 +189,7 @@ func (a *Manager) patchAWSNodeDaemonSet() error { return nil } + func (a *Manager) getRecommendedPolicies(addon *api.Addon) (api.InlineDocument, []string, *api.WellKnownPolicies) { // API isn't case sensitive switch addon.CanonicalName() { @@ -204,7 +205,6 @@ func (a *Manager) getRecommendedPolicies(addon *api.Addon) (api.InlineDocument, default: return nil, nil, nil } - return nil, nil, nil } func (a *Manager) getKnownServiceAccountLocation(addon *api.Addon) (string, string) { From bfc830f5204091f79d9eaabac01e9cb4297a1cdc Mon Sep 17 00:00:00 2001 From: nikimanoledaki Date: Tue, 21 Dec 2021 16:53:47 +0200 Subject: [PATCH 124/124] Update dry-run integ test with IP family field --- integration/tests/dry_run/dry_run_test.go | 1 + 1 file changed, 1 insertion(+) diff --git a/integration/tests/dry_run/dry_run_test.go b/integration/tests/dry_run/dry_run_test.go index 2cf8c96c63..2900dd95a7 100644 --- a/integration/tests/dry_run/dry_run_test.go +++ b/integration/tests/dry_run/dry_run_test.go @@ -137,6 +137,7 @@ managedNodeGroups: privateCluster: enabled: false vpc: + ipFamily: IPv4 autoAllocateIPv6: false cidr: 192.168.0.0/16 clusterEndpoints: