Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add kubevirt_cdi_upload module #52990

Merged
merged 1 commit into from
Mar 1, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
177 changes: 177 additions & 0 deletions lib/ansible/modules/cloud/kubevirt/kubevirt_cdi_upload.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,177 @@
#!/usr/bin/python
# -*- coding: utf-8 -*-

# Copyright: (c) 2019, Ansible Project
# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)

from __future__ import absolute_import, division, print_function

__metaclass__ = type


ANSIBLE_METADATA = {'metadata_version': '1.1',
'status': ['preview'],
'supported_by': 'community'}

DOCUMENTATION = '''

module: kubevirt_cdi_upload

short_description: Upload local VM images to CDI Upload Proxy.

version_added: "2.8"

author: KubeVirt Team (@kubevirt)


description:
- Use Openshift Python SDK to create UploadTokenRequest objects.
- Transfer contents of local files to the CDI Upload Proxy.

options:
pvc_name:
description:
- Use to specify the name of the target PersistentVolumeClaim.
required: true
pvc_namespace:
description:
- Use to specify the namespace of the target PersistentVolumeClaim.
required: true
upload_host:
description:
- URL containing the host and port on which the CDI Upload Proxy is available.
- "More info: U(https://github.com/kubevirt/containerized-data-importer/blob/master/doc/upload.md#expose-cdi-uploadproxy-service)"
upload_host_verify_ssl:
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this different than the equivalent option specified in k8s_auth_options? Does this module connect to two API endpoints, and you could have two different cert-validation settings? Can we re-use the one defined in k8s_auth_options here?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, this is completely different. Stuff in k8s_auth_options controls connectivity to the kubernetes cluster's api server endpoint. This module does that, but then also connects to a service running on the cluster itself (called the Containerized Data Importer Upload Proxy), which is why it has a completely separate set of upload_host_* parameters that control that.

It's probable that before The Freeze I'll be attempting to switch the default on upload_host_verify_ssl to autodetect (aka "look for a Secret with the certs in a standard place") for ease of use.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for that clarification. Upon reviewing the code, it wasn't obvious to me that this module is actively using both connection paths (to the k8s API and also to the Upload Proxy.) I've taken your word for it and updated my related PR.

description:
- Whether or not to verify the CDI Upload Proxy's SSL certificates against your system's CA trust store.
default: true
type: bool
path:
description:
- Path of local image file to transfer.
merge_type:
description:
- Whether to override the default patch merge approach with a specific type. By default, the strategic
merge will typically be used.
type: list
choices: [ json, merge, strategic-merge ]

extends_documentation_fragment:
- k8s_auth_options

requirements:
- python >= 2.7
- openshift >= 0.8.2
- requests >= 2.0.0
'''

EXAMPLES = '''
- name: Upload local image to pvc-vm1
kubevirt_cdi_upload:
pvc_namespace: default
pvc_name: pvc-vm1
upload_host: https://localhost:8443
upload_host_verify_ssl: false
path: /tmp/cirros-0.4.0-x86_64-disk.img
'''

RETURN = '''# '''

import copy
import traceback

from collections import defaultdict

from ansible.module_utils.k8s.common import AUTH_ARG_SPEC
from ansible.module_utils.k8s.raw import KubernetesRawModule

# 3rd party imports
try:
import requests
HAS_REQUESTS = True
except ImportError:
HAS_REQUESTS = False


SERVICE_ARG_SPEC = {
'pvc_name': {'required': True},
'pvc_namespace': {'required': True},
'upload_host': {'required': True},
'upload_host_verify_ssl': {
'type': 'bool',
'default': True
},
'path': {'required': True},
'merge_type': {
'type': 'list',
'choices': ['json', 'merge', 'strategic-merge']
},
}


class KubeVirtCDIUpload(KubernetesRawModule):
def __init__(self, *args, **kwargs):
super(KubeVirtCDIUpload, self).__init__(*args, k8s_kind='UploadTokenRequest', **kwargs)

if not HAS_REQUESTS:
self.fail("This module requires the python 'requests' package. Try `pip install requests`.")

@property
def argspec(self):
""" argspec property builder """
argument_spec = copy.deepcopy(AUTH_ARG_SPEC)
argument_spec.update(SERVICE_ARG_SPEC)
return argument_spec

def execute_module(self):
""" Module execution """

API = 'v1alpha1'
KIND = 'UploadTokenRequest'

self.client = self.get_api_client()

api_version = 'upload.cdi.kubevirt.io/{0}'.format(API)
pvc_name = self.params.get('pvc_name')
pvc_namespace = self.params.get('pvc_namespace')
upload_host = self.params.get('upload_host')
upload_host_verify_ssl = self.params.get('upload_host_verify_ssl')
path = self.params.get('path')

definition = defaultdict(defaultdict)

definition['kind'] = KIND
definition['apiVersion'] = api_version

def_meta = definition['metadata']
def_meta['name'] = pvc_name
def_meta['namespace'] = pvc_namespace

def_spec = definition['spec']
def_spec['pvcName'] = pvc_name

# Let's check the file's there before we do anything else
imgfile = open(path, 'rb')

resource = self.find_resource(KIND, api_version, fail=True)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What about using find_supported_resource here?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh, sh… I forgot.

definition = self.set_defaults(resource, definition)
result = self.perform_action(resource, definition)

headers = {'Authorization': "Bearer {0}".format(result['result']['status']['token'])}
files = {'file': imgfile}
url = "{0}/{1}/upload".format(upload_host, API)
requests.post(url, files=files, headers=headers, verify=upload_host_verify_ssl)

self.exit_json(changed=True)


def main():
module = KubeVirtCDIUpload()
try:
module.execute_module()
except Exception as e:
module.fail_json(msg=str(e), exception=traceback.format_exc())


if __name__ == '__main__':
main()
1 change: 1 addition & 0 deletions test/sanity/validate-modules/ignore.txt
Original file line number Diff line number Diff line change
Expand Up @@ -161,6 +161,7 @@ lib/ansible/modules/cloud/google/gcpubsub_facts.py E322
lib/ansible/modules/cloud/google/gcpubsub_facts.py E324
lib/ansible/modules/cloud/google/gcpubsub_facts.py E326
lib/ansible/modules/cloud/google/gcspanner.py E322
lib/ansible/modules/cloud/kubevirt/kubevirt_cdi_upload.py E203
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why we can't fix this issue? AFAIK shouldn't be complex to fix,no?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd need to take this and rewrite it: #32049, then get it merged, then modify this patch to use it. The first time this issue came came up (when merging k8s_auth) I figured that'd be my plan B, as that's quite a time investment.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh, and openshift which we depend on uses requests (or was it urllib3?) anyways under the hood, so it's not like there's anything gained from the user's POV.

lib/ansible/modules/cloud/linode/linode.py E322
lib/ansible/modules/cloud/linode/linode.py E324
lib/ansible/modules/cloud/lxc/lxc_container.py E210
Expand Down