Add a command to create a new Kayobe environment
Change-Id: I2f33bda5f2f84bbbb0f40240d2575a0b69ddceea Story: 2002009 Task: 40038
This commit is contained in:
parent
1419636930
commit
2bc568debb
@ -21,6 +21,7 @@ from cliff.command import Command
|
|||||||
from cliff.hooks import CommandHook
|
from cliff.hooks import CommandHook
|
||||||
|
|
||||||
from kayobe import ansible
|
from kayobe import ansible
|
||||||
|
from kayobe import environment
|
||||||
from kayobe import kolla_ansible
|
from kayobe import kolla_ansible
|
||||||
from kayobe import utils
|
from kayobe import utils
|
||||||
from kayobe import vault
|
from kayobe import vault
|
||||||
@ -1687,3 +1688,34 @@ class BaremetalComputeUpdateDeploymentImage(KayobeAnsibleMixin, VaultMixin,
|
|||||||
)
|
)
|
||||||
self.run_kayobe_playbooks(parsed_args, playbooks,
|
self.run_kayobe_playbooks(parsed_args, playbooks,
|
||||||
extra_vars=extra_vars)
|
extra_vars=extra_vars)
|
||||||
|
|
||||||
|
|
||||||
|
class EnvironmentCreate(KayobeAnsibleMixin, VaultMixin, Command):
|
||||||
|
"""Create a new Kayobe environment."""
|
||||||
|
|
||||||
|
def get_parser(self, prog_name):
|
||||||
|
parser = super(EnvironmentCreate, self).get_parser(prog_name)
|
||||||
|
group = parser.add_argument_group("Kayobe Environments")
|
||||||
|
environment.add_args(group)
|
||||||
|
return parser
|
||||||
|
|
||||||
|
def take_action(self, parsed_args):
|
||||||
|
self.app.LOG.debug("Creating new Kayobe environment")
|
||||||
|
if not parsed_args.environment:
|
||||||
|
self.app.LOG.error("An environment must be specified")
|
||||||
|
sys.exit(1)
|
||||||
|
|
||||||
|
source_config_path = parsed_args.source_config_path
|
||||||
|
if source_config_path:
|
||||||
|
result = utils.is_readable_dir(source_config_path)
|
||||||
|
if not result["result"]:
|
||||||
|
self.app.LOG.error("Kayobe configuration %s is invalid: %s",
|
||||||
|
source_config_path, result["message"])
|
||||||
|
sys.exit(1)
|
||||||
|
|
||||||
|
try:
|
||||||
|
environment.create_kayobe_environment(parsed_args)
|
||||||
|
except Exception as e:
|
||||||
|
self.app.LOG.error("Failed to create environment %s: %s",
|
||||||
|
parsed_args.environment, repr(e))
|
||||||
|
sys.exit(1)
|
||||||
|
64
kayobe/environment.py
Normal file
64
kayobe/environment.py
Normal file
@ -0,0 +1,64 @@
|
|||||||
|
# Copyright (c) 2021 StackHPC Ltd.
|
||||||
|
#
|
||||||
|
# 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
|
||||||
|
# a copy of the License at
|
||||||
|
#
|
||||||
|
# http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
#
|
||||||
|
# Unless required by applicable law or agreed to in writing, software
|
||||||
|
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||||
|
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||||
|
# License for the specific language governing permissions and limitations
|
||||||
|
# under the License.
|
||||||
|
|
||||||
|
import logging
|
||||||
|
import os
|
||||||
|
import os.path
|
||||||
|
import sys
|
||||||
|
|
||||||
|
from kayobe import utils
|
||||||
|
|
||||||
|
|
||||||
|
LOG = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
|
def add_args(parser):
|
||||||
|
"""Add arguments required for managing Kayobe environments to a parser."""
|
||||||
|
parser.add_argument("--source-config-path",
|
||||||
|
help="Kayobe configuration to import")
|
||||||
|
|
||||||
|
|
||||||
|
def create_kayobe_environment(parsed_args):
|
||||||
|
"""Create a new Kayobe environment."""
|
||||||
|
if not parsed_args.environment:
|
||||||
|
LOG.error("You must specify an environment to create")
|
||||||
|
sys.exit(1)
|
||||||
|
|
||||||
|
# Ensure environments directory exists and is readable inside config path
|
||||||
|
kc_environments = os.path.join(parsed_args.config_path, "environments")
|
||||||
|
result = utils.is_readable_dir(kc_environments)
|
||||||
|
if not result["result"]:
|
||||||
|
if result["message"] == "Path does not exist":
|
||||||
|
os.mkdir(kc_environments)
|
||||||
|
else:
|
||||||
|
LOG.error("Kayobe global environments directory %s is invalid: %s",
|
||||||
|
kc_environments, result["message"])
|
||||||
|
sys.exit(1)
|
||||||
|
|
||||||
|
env_path = os.path.join(kc_environments, parsed_args.environment)
|
||||||
|
result = utils.is_readable_dir(env_path)
|
||||||
|
if result["result"]:
|
||||||
|
LOG.error("Kayobe environment directory %s already exists", env_path)
|
||||||
|
sys.exit(1)
|
||||||
|
else:
|
||||||
|
if result["message"] == "Path does not exist":
|
||||||
|
os.mkdir(env_path)
|
||||||
|
else:
|
||||||
|
LOG.error("Kayobe environment directory %s is invalid: %s",
|
||||||
|
env_path, result["message"])
|
||||||
|
sys.exit(1)
|
||||||
|
|
||||||
|
source_config_path = parsed_args.source_config_path
|
||||||
|
if source_config_path:
|
||||||
|
utils.copy_dir(source_config_path, env_path)
|
83
kayobe/tests/unit/test_environment.py
Normal file
83
kayobe/tests/unit/test_environment.py
Normal file
@ -0,0 +1,83 @@
|
|||||||
|
# Copyright (c) 2021 StackHPC Ltd.
|
||||||
|
#
|
||||||
|
# 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
|
||||||
|
# a copy of the License at
|
||||||
|
#
|
||||||
|
# http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
#
|
||||||
|
# Unless required by applicable law or agreed to in writing, software
|
||||||
|
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||||
|
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||||
|
# License for the specific language governing permissions and limitations
|
||||||
|
# under the License.
|
||||||
|
|
||||||
|
import argparse
|
||||||
|
import os
|
||||||
|
import unittest
|
||||||
|
from unittest import mock
|
||||||
|
|
||||||
|
from kayobe import ansible
|
||||||
|
from kayobe import environment
|
||||||
|
from kayobe import utils
|
||||||
|
|
||||||
|
|
||||||
|
class TestCase(unittest.TestCase):
|
||||||
|
|
||||||
|
@mock.patch.object(utils, "is_readable_dir")
|
||||||
|
def test_unreadable_environments_directory(self, mock_readable_dir):
|
||||||
|
mock_readable_dir.return_value = {
|
||||||
|
"result": False,
|
||||||
|
"message": "Directory is not readable"
|
||||||
|
}
|
||||||
|
parser = argparse.ArgumentParser()
|
||||||
|
args = [
|
||||||
|
"--config-path", "/path/to/config",
|
||||||
|
"--environment", "foo",
|
||||||
|
]
|
||||||
|
ansible.add_args(parser)
|
||||||
|
environment.add_args(parser)
|
||||||
|
parsed_args = parser.parse_args(args)
|
||||||
|
self.assertRaises(SystemExit,
|
||||||
|
environment.create_kayobe_environment, parsed_args)
|
||||||
|
|
||||||
|
@mock.patch.object(utils, "is_readable_dir")
|
||||||
|
def test_environment_exists(self, mock_readable_dir):
|
||||||
|
mock_readable_dir.side_effect = [{"result": True}, {"result": True}]
|
||||||
|
parser = argparse.ArgumentParser()
|
||||||
|
args = [
|
||||||
|
"--config-path", "/path/to/config",
|
||||||
|
"--environment", "foo",
|
||||||
|
]
|
||||||
|
ansible.add_args(parser)
|
||||||
|
environment.add_args(parser)
|
||||||
|
parsed_args = parser.parse_args(args)
|
||||||
|
self.assertRaises(SystemExit,
|
||||||
|
environment.create_kayobe_environment, parsed_args)
|
||||||
|
|
||||||
|
@mock.patch.object(utils, "copy_dir")
|
||||||
|
@mock.patch.object(os, "mkdir")
|
||||||
|
@mock.patch.object(utils, "is_readable_dir")
|
||||||
|
def test_create_kayobe_environment(self, mock_readable_dir, mock_mkdir,
|
||||||
|
mock_copy_dir):
|
||||||
|
mock_readable_dir.return_value = {
|
||||||
|
"result": False,
|
||||||
|
"message": "Path does not exist"
|
||||||
|
}
|
||||||
|
parser = argparse.ArgumentParser()
|
||||||
|
args = [
|
||||||
|
"--config-path", "/path/to/config",
|
||||||
|
"--source-config-path", "/path/to/foo",
|
||||||
|
"--environment", "foo",
|
||||||
|
]
|
||||||
|
ansible.add_args(parser)
|
||||||
|
environment.add_args(parser)
|
||||||
|
parsed_args = parser.parse_args(args)
|
||||||
|
environment.create_kayobe_environment(parsed_args)
|
||||||
|
expected_calls = [
|
||||||
|
mock.call("/path/to/config/environments"),
|
||||||
|
mock.call("/path/to/config/environments/foo"),
|
||||||
|
]
|
||||||
|
self.assertEqual(expected_calls, mock_mkdir.call_args_list)
|
||||||
|
mock_copy_dir.assert_called_once_with(
|
||||||
|
"/path/to/foo", "/path/to/config/environments/foo")
|
@ -17,6 +17,7 @@ import glob
|
|||||||
import itertools
|
import itertools
|
||||||
import logging
|
import logging
|
||||||
import os
|
import os
|
||||||
|
import shutil
|
||||||
import subprocess
|
import subprocess
|
||||||
import sys
|
import sys
|
||||||
|
|
||||||
@ -222,3 +223,16 @@ def intersect_limits(args_limit, cli_limit):
|
|||||||
separator = ':&'
|
separator = ':&'
|
||||||
limits = [l for l in [args_limit, cli_limit] if l]
|
limits = [l for l in [args_limit, cli_limit] if l]
|
||||||
return separator.join(limits)
|
return separator.join(limits)
|
||||||
|
|
||||||
|
|
||||||
|
def copy_dir(src, dest):
|
||||||
|
if not os.path.isdir(dest):
|
||||||
|
shutil.copytree(src, dest)
|
||||||
|
else:
|
||||||
|
for file in os.listdir(src):
|
||||||
|
src_path = os.path.join(src, file)
|
||||||
|
dest_path = os.path.join(dest, file)
|
||||||
|
if os.path.isdir(src_path):
|
||||||
|
copy_dir(src_path, dest_path)
|
||||||
|
else:
|
||||||
|
shutil.copy2(src_path, dest_path)
|
||||||
|
@ -48,6 +48,7 @@ kayobe.cli=
|
|||||||
control_host_bootstrap = kayobe.cli.commands:ControlHostBootstrap
|
control_host_bootstrap = kayobe.cli.commands:ControlHostBootstrap
|
||||||
control_host_upgrade = kayobe.cli.commands:ControlHostUpgrade
|
control_host_upgrade = kayobe.cli.commands:ControlHostUpgrade
|
||||||
configuration_dump = kayobe.cli.commands:ConfigurationDump
|
configuration_dump = kayobe.cli.commands:ConfigurationDump
|
||||||
|
environment_create = kayobe.cli.commands:EnvironmentCreate
|
||||||
kolla_ansible_run = kayobe.cli.commands:KollaAnsibleRun
|
kolla_ansible_run = kayobe.cli.commands:KollaAnsibleRun
|
||||||
network_connectivity_check = kayobe.cli.commands:NetworkConnectivityCheck
|
network_connectivity_check = kayobe.cli.commands:NetworkConnectivityCheck
|
||||||
overcloud_bios_raid_configure = kayobe.cli.commands:OvercloudBIOSRAIDConfigure
|
overcloud_bios_raid_configure = kayobe.cli.commands:OvercloudBIOSRAIDConfigure
|
||||||
|
Loading…
Reference in New Issue
Block a user