Support subcloud deploy upload prestaging images
Modify the existing REST API to upload the prestaging images list to system controller Test Cases Completed on local VM as well as DC Lab a. (Passed) With all 4 variables b. (Passed) With only --prestage-images c. (Passed) With all other variables expect for --prestage-images d. (Passed) With 1 or 2 missing varibles when --prestage-images is present e. (Passed) With 1 or multiple invalid directory path REST APIs: curl -X POST -H "X-Auth-Token: $TOKEN" $APIURL/subcloud-deploy \ -F deploy_playbook=@<full path of the playbook name> \ -F deploy_overrides=@<full path of the override file name> \ -F deploy_chart=@full path of the helm chart name> \ -F prestage_images=@<full path of the prestage image name> CLI: dcmanager subcloud-deploy upload \ --deploy-playbook <full path of the playbook name> \ <- Existing --deploy-chart <full path of the override file name> \ <- Existing --deploy-overrides <full path of the override file name> <- Existing --prestage-images <full path of the override file name> <- Added Story: 2009799 Task: 44342 Change-Id: I75d4ac0931d2a37ceb68281a2ab6137ee2459e99
This commit is contained in:
parent
d12eeb4a06
commit
0d05b33719
@ -1433,7 +1433,7 @@ Subcloud Deploy
|
|||||||
----------------
|
----------------
|
||||||
|
|
||||||
These APIs allow for the display and upload of the deployment manager common
|
These APIs allow for the display and upload of the deployment manager common
|
||||||
files which include deploy playbook, deploy overrides, and deploy helm charts.
|
files which include deploy playbook, deploy overrides, deploy helm charts, and prestage images list.
|
||||||
|
|
||||||
|
|
||||||
**************************
|
**************************
|
||||||
@ -1463,6 +1463,7 @@ internalServerError (500), serviceUnavailable (503)
|
|||||||
- deploy_chart: subcloud_deploy_chart
|
- deploy_chart: subcloud_deploy_chart
|
||||||
- deploy_playbook: subcloud_deploy_playbook
|
- deploy_playbook: subcloud_deploy_playbook
|
||||||
- deploy_overrides: subcloud_deploy_overrides
|
- deploy_overrides: subcloud_deploy_overrides
|
||||||
|
- prestage_images: subcloud_deploy_prestage_images
|
||||||
|
|
||||||
Response Example
|
Response Example
|
||||||
----------------
|
----------------
|
||||||
@ -1496,6 +1497,7 @@ serviceUnavailable (503)
|
|||||||
- deploy_chart: subcloud_deploy_chart_content
|
- deploy_chart: subcloud_deploy_chart_content
|
||||||
- deploy_playbook: subcloud_deploy_playbook_content
|
- deploy_playbook: subcloud_deploy_playbook_content
|
||||||
- deploy_overrides: subcloud_deploy_overrides_content
|
- deploy_overrides: subcloud_deploy_overrides_content
|
||||||
|
- prestage_images: subcloud_deploy_prestage_images_content
|
||||||
|
|
||||||
Request Example
|
Request Example
|
||||||
----------------
|
----------------
|
||||||
@ -1510,6 +1512,7 @@ Request Example
|
|||||||
- deploy_chart: subcloud_deploy_chart
|
- deploy_chart: subcloud_deploy_chart
|
||||||
- deploy_playbook: subcloud_deploy_playbook
|
- deploy_playbook: subcloud_deploy_playbook
|
||||||
- deploy_overrides: subcloud_deploy_overrides
|
- deploy_overrides: subcloud_deploy_overrides
|
||||||
|
- prestage_images: subcloud_deploy_prestage_images
|
||||||
|
|
||||||
Response Example
|
Response Example
|
||||||
----------------
|
----------------
|
||||||
|
@ -359,6 +359,18 @@ subcloud_deploy_playbook_content:
|
|||||||
in: body
|
in: body
|
||||||
required: false
|
required: false
|
||||||
type: string
|
type: string
|
||||||
|
subcloud_deploy_prestage_images:
|
||||||
|
description: |
|
||||||
|
The file name of the deployment manager prestage images.
|
||||||
|
in: body
|
||||||
|
required: false
|
||||||
|
type: string
|
||||||
|
subcloud_deploy_prestage_images_content:
|
||||||
|
description: |
|
||||||
|
The content of the deployment manager prestage images.
|
||||||
|
in: body
|
||||||
|
required: false
|
||||||
|
type: string
|
||||||
subcloud_description:
|
subcloud_description:
|
||||||
description: |
|
description: |
|
||||||
The description of a subcloud.
|
The description of a subcloud.
|
||||||
|
@ -12,7 +12,7 @@
|
|||||||
# License for the specific language governing permissions and limitations
|
# License for the specific language governing permissions and limitations
|
||||||
# under the License.
|
# under the License.
|
||||||
#
|
#
|
||||||
# Copyright (c) 2020 Wind River Systems, Inc.
|
# Copyright (c) 2020, 2022 Wind River Systems, Inc.
|
||||||
#
|
#
|
||||||
# SPDX-License-Identifier: Apache-2.0
|
# SPDX-License-Identifier: Apache-2.0
|
||||||
#
|
#
|
||||||
@ -47,6 +47,7 @@ class SubcloudDeployController(object):
|
|||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def _upload_files(dir_path, file_option, file_item, binary):
|
def _upload_files(dir_path, file_option, file_item, binary):
|
||||||
|
|
||||||
prefix = file_option + '_'
|
prefix = file_option + '_'
|
||||||
# create the version directory if it does not exist
|
# create the version directory if it does not exist
|
||||||
if not os.path.isdir(dir_path):
|
if not os.path.isdir(dir_path):
|
||||||
@ -78,18 +79,37 @@ class SubcloudDeployController(object):
|
|||||||
@index.when(method='POST', template='json')
|
@index.when(method='POST', template='json')
|
||||||
def post(self):
|
def post(self):
|
||||||
deploy_dicts = dict()
|
deploy_dicts = dict()
|
||||||
|
missing_options = set()
|
||||||
for f in consts.DEPLOY_COMMON_FILE_OPTIONS:
|
for f in consts.DEPLOY_COMMON_FILE_OPTIONS:
|
||||||
if f not in request.POST:
|
if f not in request.POST:
|
||||||
pecan.abort(httpclient.BAD_REQUEST,
|
missing_options.add(f)
|
||||||
_("Missing required file for %s") % f)
|
|
||||||
|
# The API will only accept three types of input scenarios:
|
||||||
|
# 1. DEPLOY_PLAYBOOK, DEPLOY_OVERRIDES, and DEPLOY_CHART
|
||||||
|
# 2. DEPLOY_PLAYBOOK, DEPLOY_OVERRIDES, DEPLOY_CHART, and DEPLOY_PRESTAGE
|
||||||
|
# 3. DEPLOY_PRESTAGE
|
||||||
|
size = len(missing_options)
|
||||||
|
if len(missing_options) > 0:
|
||||||
|
if ((consts.DEPLOY_PRESTAGE in missing_options and size != 1) or
|
||||||
|
(consts.DEPLOY_PRESTAGE not in missing_options and size != 3)):
|
||||||
|
missing_str = str()
|
||||||
|
for missing in missing_options:
|
||||||
|
if missing is not consts.DEPLOY_PRESTAGE:
|
||||||
|
missing_str += '--%s ' % missing
|
||||||
|
error_msg = "error: argument %s is required" % missing_str.rstrip()
|
||||||
|
pecan.abort(httpclient.BAD_REQUEST, error_msg)
|
||||||
|
|
||||||
|
for f in consts.DEPLOY_COMMON_FILE_OPTIONS:
|
||||||
|
if f not in request.POST:
|
||||||
|
continue
|
||||||
|
|
||||||
file_item = request.POST[f]
|
file_item = request.POST[f]
|
||||||
filename = getattr(file_item, 'filename', '')
|
filename = getattr(file_item, 'filename', '')
|
||||||
if not filename:
|
if not filename:
|
||||||
pecan.abort(httpclient.BAD_REQUEST,
|
pecan.abort(httpclient.BAD_REQUEST,
|
||||||
_("No %s file uploaded" % f))
|
_("No %s file uploaded" % f))
|
||||||
|
|
||||||
dir_path = tsc.DEPLOY_PATH
|
dir_path = tsc.DEPLOY_PATH
|
||||||
|
|
||||||
binary = False
|
binary = False
|
||||||
if f == consts.DEPLOY_CHART:
|
if f == consts.DEPLOY_CHART:
|
||||||
binary = True
|
binary = True
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
# Copyright (c) 2016 Ericsson AB.
|
# Copyright (c) 2016 Ericsson AB.
|
||||||
# Copyright (c) 2017-2021 Wind River Systems, Inc.
|
# Copyright (c) 2017-2022 Wind River Systems, Inc.
|
||||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||||
# not use this file except in compliance with the License. You may obtain
|
# not use this file except in compliance with the License. You may obtain
|
||||||
# a copy of the License at
|
# a copy of the License at
|
||||||
@ -212,11 +212,13 @@ DEPLOY_PLAYBOOK = "deploy_playbook"
|
|||||||
DEPLOY_OVERRIDES = "deploy_overrides"
|
DEPLOY_OVERRIDES = "deploy_overrides"
|
||||||
DEPLOY_CHART = "deploy_chart"
|
DEPLOY_CHART = "deploy_chart"
|
||||||
DEPLOY_CONFIG = 'deploy_config'
|
DEPLOY_CONFIG = 'deploy_config'
|
||||||
|
DEPLOY_PRESTAGE = "prestage_images"
|
||||||
|
|
||||||
DEPLOY_COMMON_FILE_OPTIONS = [
|
DEPLOY_COMMON_FILE_OPTIONS = [
|
||||||
DEPLOY_PLAYBOOK,
|
DEPLOY_PLAYBOOK,
|
||||||
DEPLOY_OVERRIDES,
|
DEPLOY_OVERRIDES,
|
||||||
DEPLOY_CHART
|
DEPLOY_CHART,
|
||||||
|
DEPLOY_PRESTAGE
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
# Copyright (c) 2020-2021 Wind River Systems, Inc.
|
# Copyright (c) 2020-2022 Wind River Systems, Inc.
|
||||||
# All Rights Reserved.
|
# All Rights Reserved.
|
||||||
#
|
#
|
||||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||||
@ -50,7 +50,23 @@ class TestSubcloudDeploy(testroot.DCManagerApiTest):
|
|||||||
|
|
||||||
@mock.patch.object(subcloud_deploy.SubcloudDeployController,
|
@mock.patch.object(subcloud_deploy.SubcloudDeployController,
|
||||||
'_upload_files')
|
'_upload_files')
|
||||||
def test_post_subcloud_deploy_missing_file(self, mock_upload_files):
|
def test_post_subcloud_deploy_missing_chart(self, mock_upload_files):
|
||||||
|
opts = [consts.DEPLOY_PLAYBOOK, consts.DEPLOY_OVERRIDES, consts.DEPLOY_PRESTAGE]
|
||||||
|
fields = list()
|
||||||
|
for opt in opts:
|
||||||
|
fake_name = opt + "_fake"
|
||||||
|
fake_content = "fake content".encode('utf-8')
|
||||||
|
fields.append((opt, fake_name, fake_content))
|
||||||
|
mock_upload_files.return_value = True
|
||||||
|
response = self.app.post(FAKE_URL,
|
||||||
|
headers=FAKE_HEADERS,
|
||||||
|
upload_files=fields,
|
||||||
|
expect_errors=True)
|
||||||
|
self.assertEqual(response.status_code, http_client.BAD_REQUEST)
|
||||||
|
|
||||||
|
@mock.patch.object(subcloud_deploy.SubcloudDeployController,
|
||||||
|
'_upload_files')
|
||||||
|
def test_post_subcloud_deploy_missing_chart_prestages(self, mock_upload_files):
|
||||||
opts = [consts.DEPLOY_PLAYBOOK, consts.DEPLOY_OVERRIDES]
|
opts = [consts.DEPLOY_PLAYBOOK, consts.DEPLOY_OVERRIDES]
|
||||||
fields = list()
|
fields = list()
|
||||||
for opt in opts:
|
for opt in opts:
|
||||||
@ -64,6 +80,68 @@ class TestSubcloudDeploy(testroot.DCManagerApiTest):
|
|||||||
expect_errors=True)
|
expect_errors=True)
|
||||||
self.assertEqual(response.status_code, http_client.BAD_REQUEST)
|
self.assertEqual(response.status_code, http_client.BAD_REQUEST)
|
||||||
|
|
||||||
|
@mock.patch.object(subcloud_deploy.SubcloudDeployController,
|
||||||
|
'_upload_files')
|
||||||
|
def test_post_subcloud_deploy_missing_playbook_overrides(self, mock_upload_files):
|
||||||
|
opts = [consts.DEPLOY_CHART, consts.DEPLOY_PRESTAGE]
|
||||||
|
fields = list()
|
||||||
|
for opt in opts:
|
||||||
|
fake_name = opt + "_fake"
|
||||||
|
fake_content = "fake content".encode('utf-8')
|
||||||
|
fields.append((opt, fake_name, fake_content))
|
||||||
|
mock_upload_files.return_value = True
|
||||||
|
response = self.app.post(FAKE_URL,
|
||||||
|
headers=FAKE_HEADERS,
|
||||||
|
upload_files=fields,
|
||||||
|
expect_errors=True)
|
||||||
|
self.assertEqual(response.status_code, http_client.BAD_REQUEST)
|
||||||
|
|
||||||
|
@mock.patch.object(subcloud_deploy.SubcloudDeployController,
|
||||||
|
'_upload_files')
|
||||||
|
def test_post_subcloud_deploy_missing_prestage(self, mock_upload_files):
|
||||||
|
opts = [consts.DEPLOY_PLAYBOOK, consts.DEPLOY_OVERRIDES, consts.DEPLOY_CHART]
|
||||||
|
fields = list()
|
||||||
|
for opt in opts:
|
||||||
|
fake_name = opt + "_fake"
|
||||||
|
fake_content = "fake content".encode('utf-8')
|
||||||
|
fields.append((opt, fake_name, fake_content))
|
||||||
|
mock_upload_files.return_value = True
|
||||||
|
response = self.app.post(FAKE_URL,
|
||||||
|
headers=FAKE_HEADERS,
|
||||||
|
upload_files=fields)
|
||||||
|
self.assertEqual(response.status_code, http_client.OK)
|
||||||
|
|
||||||
|
@mock.patch.object(subcloud_deploy.SubcloudDeployController,
|
||||||
|
'_upload_files')
|
||||||
|
def test_post_subcloud_deploy_all_input(self, mock_upload_files):
|
||||||
|
opts = [consts.DEPLOY_PLAYBOOK, consts.DEPLOY_OVERRIDES,
|
||||||
|
consts.DEPLOY_CHART, consts.DEPLOY_PRESTAGE]
|
||||||
|
fields = list()
|
||||||
|
for opt in opts:
|
||||||
|
fake_name = opt + "_fake"
|
||||||
|
fake_content = "fake content".encode('utf-8')
|
||||||
|
fields.append((opt, fake_name, fake_content))
|
||||||
|
mock_upload_files.return_value = True
|
||||||
|
response = self.app.post(FAKE_URL,
|
||||||
|
headers=FAKE_HEADERS,
|
||||||
|
upload_files=fields)
|
||||||
|
self.assertEqual(response.status_code, http_client.OK)
|
||||||
|
|
||||||
|
@mock.patch.object(subcloud_deploy.SubcloudDeployController,
|
||||||
|
'_upload_files')
|
||||||
|
def test_post_subcloud_deploy_prestage(self, mock_upload_files):
|
||||||
|
opts = [consts.DEPLOY_PRESTAGE]
|
||||||
|
fields = list()
|
||||||
|
for opt in opts:
|
||||||
|
fake_name = opt + "_fake"
|
||||||
|
fake_content = "fake content".encode('utf-8')
|
||||||
|
fields.append((opt, fake_name, fake_content))
|
||||||
|
mock_upload_files.return_value = True
|
||||||
|
response = self.app.post(FAKE_URL,
|
||||||
|
headers=FAKE_HEADERS,
|
||||||
|
upload_files=fields)
|
||||||
|
self.assertEqual(response.status_code, http_client.OK)
|
||||||
|
|
||||||
@mock.patch.object(subcloud_deploy.SubcloudDeployController,
|
@mock.patch.object(subcloud_deploy.SubcloudDeployController,
|
||||||
'_upload_files')
|
'_upload_files')
|
||||||
def test_post_subcloud_deploy_missing_file_name(self, mock_upload_files):
|
def test_post_subcloud_deploy_missing_file_name(self, mock_upload_files):
|
||||||
|
Loading…
Reference in New Issue
Block a user