From 23639cc1a0d629a87b13f1b6b4f3fc53fc580eef Mon Sep 17 00:00:00 2001 From: Alex Stephen Date: Wed, 19 Jun 2019 15:43:40 -0700 Subject: [PATCH 1/9] code written --- products/container/api.yaml | 36 +++------- products/container/helpers/python/kubectl.py | 76 ++++++++++++++++++++ 2 files changed, 86 insertions(+), 26 deletions(-) create mode 100644 products/container/helpers/python/kubectl.py diff --git a/products/container/api.yaml b/products/container/api.yaml index 2bdd984d3ba8..8e9f2a04bd3c 100644 --- a/products/container/api.yaml +++ b/products/container/api.yaml @@ -58,6 +58,16 @@ objects: description: 'The location where the cluster is deployed' required: true properties: + - !ruby/object:Api::Type::String + name: 'kubectlPath' + description: | + The path that the kubectl config file will be written to. + + The file will not be created if this path is unset. + required: true + - !ruby/object:Api::Type::String + name: 'kubectlContext' + description: 'The name of the context for the kubectl config file. Will default to the cluster name' - !ruby/object:Api::Type::String name: 'name' description: | @@ -838,29 +848,3 @@ objects: name: 'podIpv4CidrSize' description: The pod CIDR block size per node in this node pool. output: true - - !ruby/object:Api::Resource - name: 'KubeConfig' - base_url: 'unused' - description: | - Generates a compatible Kuberenetes '.kube/config' file - properties: - - !ruby/object:Api::Type::String - name: 'name' - description: 'The config file kubectl settings will be written to.' - required: true - - !ruby/object:Api::Type::ResourceRef - name: 'cluster' - resource: 'Cluster' - imports: 'name' - description: 'A reference to Cluster resource' - required: true - # TODO(nelsonjr): Make 'zone' a ResourceRef once cross-module references - # are possible. - - !ruby/object:Api::Type::String - name: 'location' - description: 'The location where the container is deployed' - required: true - - !ruby/object:Api::Type::String - name: 'context' - description: 'The name of the context. Defaults to cluster name.' - required: true diff --git a/products/container/helpers/python/kubectl.py b/products/container/helpers/python/kubectl.py new file mode 100644 index 000000000000..4dbe980dddd0 --- /dev/null +++ b/products/container/helpers/python/kubectl.py @@ -0,0 +1,76 @@ +class Kubectl(object): + def initialize(self, module): + self.module = module + + """ + Writes a kubectl config file + kubectl_path must be set or this will fail. + """ + def write_file(self): + with open(module.params['kubectl_path'], 'w') as f: + f.write(yaml.dump(self._contents())) + + """ + Returns the contents of a kubectl file + """ + def _contents(self): + token = self._auth_token() + endpoint = "https://{}".format(fetch["endpoint"]) + context = module.params.get('kubectl_context') + if not context: + context = module.params['name'] + + return { + 'apiVersion': 'v1', + 'clusters': [ + { + 'name': context, + 'cluster': { + 'certificate-authority-data': + self.fetch['masterAuth']['clusterCaCertificate'], + 'server': endpoint, + } + } + ], + 'contexts': [ + { + 'name': context, + 'context': { + 'cluster': context, + 'user': context + } + } + ], + 'current-context': context, + 'kind': 'Config', + 'preferences': {}, + 'users': [ + { + 'name': context, + 'user': { + 'auth-provider': { + 'config': { + 'access-token': token, + 'cmd-args': 'config config-helper --format=json', + 'cmd-path': '/usr/lib64/google-cloud-sdk/bin/gcloud', + 'expiry-key': '{.credential.token_expiry}', + 'token-key': '{.credential.access_token}' + }, + 'name': 'gcp' + }, + 'username': self.fetch['masterAuth']['username'], + 'password': self.fetch['masterAuth']['password'] + } + } + ] + } + + """ + Returns the auth token used in kubectl + This also sets the 'fetch' variable used in creating the kubectl + """ + def _auth_token(self): + auth = GcpSession(module, 'auth') + response = auth.get(self_link(module)) + self.fetch = response.json() + return response.request.headers.authorization.split(' ')[1] From 0ff10a231902e41473d3184c1704e07be70dd70b Mon Sep 17 00:00:00 2001 From: Alex Stephen Date: Wed, 19 Jun 2019 15:56:36 -0700 Subject: [PATCH 2/9] kubectl on Ansible --- products/container/ansible.yaml | 9 ++++---- products/container/ansible_version_added.yaml | 4 ++++ products/container/helpers/python/kubectl.py | 22 +++++++++---------- 3 files changed, 20 insertions(+), 15 deletions(-) diff --git a/products/container/ansible.yaml b/products/container/ansible.yaml index 062b94728288..6178e567d24e 100644 --- a/products/container/ansible.yaml +++ b/products/container/ansible.yaml @@ -37,10 +37,9 @@ datasources: !ruby/object:Overrides::ResourceOverrides "'my-pool' in \"{{ results['resources'] | map(attribute='name') | list }}\"" does_not_exist: | "'my-pool' not in \"{{ results['resources'] | map(attribute='name') | list }}\"" - KubeConfig: !ruby/object:Overrides::Ansible::ResourceOverride - exclude: true overrides: !ruby/object:Overrides::ResourceOverrides Cluster: !ruby/object:Overrides::Ansible::ResourceOverride + imports: ["yaml"] notes: - This module does not create any node pools (including default). Please use the M(gcp_container_node_pool) module to create node pools. @@ -53,10 +52,12 @@ overrides: !ruby/object:Overrides::ResourceOverrides aliases: ['zone'] post_create: | delete_default_node_pool(module) + post_action: | + if module.params.get('kubectl_path'): + Kubectl(module).write_file() provider_helpers: - 'products/container/helpers/python/provider_cluster.py' - KubeConfig: !ruby/object:Overrides::Ansible::ResourceOverride - exclude: true + - 'products/container/helpers/python/kubectl.py' NodePool: !ruby/object:Overrides::Ansible::ResourceOverride transport: !ruby/object:Overrides::Ansible::Transport encoder: encode_request diff --git a/products/container/ansible_version_added.yaml b/products/container/ansible_version_added.yaml index 59b39cde2445..15e2495c79e9 100644 --- a/products/container/ansible_version_added.yaml +++ b/products/container/ansible_version_added.yaml @@ -7,6 +7,10 @@ :regular: :Cluster: :version_added: '2.6' + :kubectlPath: + :version_added: '2.9' + :kubectlContext: + :version_added: '2.9' :name: :version_added: '2.6' :description: diff --git a/products/container/helpers/python/kubectl.py b/products/container/helpers/python/kubectl.py index 4dbe980dddd0..ce60c5ffe021 100644 --- a/products/container/helpers/python/kubectl.py +++ b/products/container/helpers/python/kubectl.py @@ -1,5 +1,5 @@ class Kubectl(object): - def initialize(self, module): + def __init__(self, module): self.module = module """ @@ -7,7 +7,7 @@ def initialize(self, module): kubectl_path must be set or this will fail. """ def write_file(self): - with open(module.params['kubectl_path'], 'w') as f: + with open(self.module.params['kubectl_path'], 'w') as f: f.write(yaml.dump(self._contents())) """ @@ -15,10 +15,10 @@ def write_file(self): """ def _contents(self): token = self._auth_token() - endpoint = "https://{}".format(fetch["endpoint"]) - context = module.params.get('kubectl_context') + endpoint = "https://{}".format(self.fetch["endpoint"]) + context = self.module.params.get('kubectl_context') if not context: - context = module.params['name'] + context = self.module.params['name'] return { 'apiVersion': 'v1', @@ -27,7 +27,7 @@ def _contents(self): 'name': context, 'cluster': { 'certificate-authority-data': - self.fetch['masterAuth']['clusterCaCertificate'], + str(self.fetch['masterAuth']['clusterCaCertificate']), 'server': endpoint, } } @@ -58,8 +58,8 @@ def _contents(self): }, 'name': 'gcp' }, - 'username': self.fetch['masterAuth']['username'], - 'password': self.fetch['masterAuth']['password'] + 'username': str(self.fetch['masterAuth']['username']), + 'password': str(self.fetch['masterAuth']['password']) } } ] @@ -70,7 +70,7 @@ def _contents(self): This also sets the 'fetch' variable used in creating the kubectl """ def _auth_token(self): - auth = GcpSession(module, 'auth') - response = auth.get(self_link(module)) + auth = GcpSession(self.module, 'auth') + response = auth.get(self_link(self.module)) self.fetch = response.json() - return response.request.headers.authorization.split(' ')[1] + return response.request.headers['authorization'].split(' ')[1] From 04c60187e631c9b7a0c01c05094071e28e61f7cd Mon Sep 17 00:00:00 2001 From: Alex Stephen Date: Wed, 19 Jun 2019 15:58:50 -0700 Subject: [PATCH 3/9] note --- products/container/api.yaml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/products/container/api.yaml b/products/container/api.yaml index 8e9f2a04bd3c..148762829d3b 100644 --- a/products/container/api.yaml +++ b/products/container/api.yaml @@ -64,6 +64,8 @@ objects: The path that the kubectl config file will be written to. The file will not be created if this path is unset. + + This requires the PyYaml library. required: true - !ruby/object:Api::Type::String name: 'kubectlContext' From c91ff2d00d8f264ad64c83f2477d444943407281 Mon Sep 17 00:00:00 2001 From: Alex Stephen Date: Wed, 19 Jun 2019 16:00:59 -0700 Subject: [PATCH 4/9] warning --- products/container/api.yaml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/products/container/api.yaml b/products/container/api.yaml index 148762829d3b..612e498f2bcc 100644 --- a/products/container/api.yaml +++ b/products/container/api.yaml @@ -65,6 +65,8 @@ objects: The file will not be created if this path is unset. + Any existing file at this path will be completely overridden. + This requires the PyYaml library. required: true - !ruby/object:Api::Type::String From 1f5424dd7c9e52b9ff341ff615a7731686beba95 Mon Sep 17 00:00:00 2001 From: Alex Stephen Date: Fri, 21 Jun 2019 13:31:14 -0700 Subject: [PATCH 5/9] inspec fixes --- products/container/inspec.yaml | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/products/container/inspec.yaml b/products/container/inspec.yaml index 23a4db5c2dfb..37b6c524a3d1 100644 --- a/products/container/inspec.yaml +++ b/products/container/inspec.yaml @@ -18,6 +18,11 @@ overrides: !ruby/object:Overrides::ResourceOverrides # there exists a `container_cluster` resource in InSpec already # that can handle zonal resources only name: 'RegionalCluster' + properties: + kubectlPath: !ruby/object:Overrides::Inspec::PropertyOverride + exclude: true + kubectlContext: !ruby/object:Overrides::Inspec::PropertyOverride + exclude: true NodePool: !ruby/object:Overrides::Inspec::ResourceOverride # See note on RegionalCluster, similar for NodePool name: 'RegionalNodePool' @@ -25,8 +30,6 @@ overrides: !ruby/object:Overrides::ResourceOverrides properties: cluster: !ruby/object:Overrides::Inspec::PropertyOverride resource: 'RegionalCluster' - KubeConfig: !ruby/object:Overrides::Inspec::ResourceOverride - exclude: true files: !ruby/object:Provider::Config::Files copy: 'Gemfile': 'provider/inspec/Gemfile' From d5ffa8647bf97388045ce525aae889fd37539f47 Mon Sep 17 00:00:00 2001 From: Alex Stephen Date: Fri, 21 Jun 2019 13:45:51 -0700 Subject: [PATCH 6/9] better imports --- products/container/ansible.yaml | 1 - products/container/helpers/python/kubectl.py | 5 +++++ 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/products/container/ansible.yaml b/products/container/ansible.yaml index 6178e567d24e..804b2e4c2872 100644 --- a/products/container/ansible.yaml +++ b/products/container/ansible.yaml @@ -39,7 +39,6 @@ datasources: !ruby/object:Overrides::ResourceOverrides "'my-pool' not in \"{{ results['resources'] | map(attribute='name') | list }}\"" overrides: !ruby/object:Overrides::ResourceOverrides Cluster: !ruby/object:Overrides::Ansible::ResourceOverride - imports: ["yaml"] notes: - This module does not create any node pools (including default). Please use the M(gcp_container_node_pool) module to create node pools. diff --git a/products/container/helpers/python/kubectl.py b/products/container/helpers/python/kubectl.py index ce60c5ffe021..9adb3a522288 100644 --- a/products/container/helpers/python/kubectl.py +++ b/products/container/helpers/python/kubectl.py @@ -7,6 +7,11 @@ def __init__(self, module): kubectl_path must be set or this will fail. """ def write_file(self): + try: + import yaml + except ImportError: + self.module.fail_json(msg="Please install the pyyaml module") + with open(self.module.params['kubectl_path'], 'w') as f: f.write(yaml.dump(self._contents())) From 42a74525ee65c4586d11b44e2a6bd0c0f08e03b1 Mon Sep 17 00:00:00 2001 From: Alex Stephen Date: Mon, 24 Jun 2019 13:24:42 -0700 Subject: [PATCH 7/9] typo --- products/container/api.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/products/container/api.yaml b/products/container/api.yaml index 612e498f2bcc..c598fac2c3b0 100644 --- a/products/container/api.yaml +++ b/products/container/api.yaml @@ -65,7 +65,7 @@ objects: The file will not be created if this path is unset. - Any existing file at this path will be completely overridden. + Any existing file at this path will be completely overwritten. This requires the PyYaml library. required: true From 8680a2f628f04a1ca9b34a7d4cdb62b5cc5368e0 Mon Sep 17 00:00:00 2001 From: Alex Stephen Date: Mon, 24 Jun 2019 13:46:24 -0700 Subject: [PATCH 8/9] ignore path + context on facts modules --- products/container/ansible.yaml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/products/container/ansible.yaml b/products/container/ansible.yaml index 804b2e4c2872..b87884ce15a0 100644 --- a/products/container/ansible.yaml +++ b/products/container/ansible.yaml @@ -17,6 +17,10 @@ datasources: !ruby/object:Overrides::ResourceOverrides properties: location: !ruby/object:Overrides::Ansible::PropertyOverride aliases: ["region", "zone"] + kubectlPath: !ruby/object:Overrides::Ansible::PropertyOverride + exclude: true + kubectlContext: !ruby/object:Overrides::Ansible::PropertyOverride + exclude: true facts: !ruby/object:Provider::Ansible::FactsOverride has_filters: false test: !ruby/object:Provider::Ansible::AnsibleFactsTestInformation From 492654df198937b65e742be166203b8d728e8a24 Mon Sep 17 00:00:00 2001 From: Modular Magician Date: Mon, 24 Jun 2019 20:59:41 +0000 Subject: [PATCH 9/9] Update tracked submodules -> HEAD on Mon Jun 24 20:59:41 UTC 2019 Tracked submodules are build/terraform-beta build/terraform-mapper build/terraform build/ansible build/inspec. --- build/ansible | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build/ansible b/build/ansible index 56616f092179..6feba06ae196 160000 --- a/build/ansible +++ b/build/ansible @@ -1 +1 @@ -Subproject commit 56616f0921798daf2aeea0974a1dc59dbd47c118 +Subproject commit 6feba06ae196900d8c5a501674b4f065e899bea7