#!/usr/bin/env python

# 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.

# Update the clouds.yaml file.


import argparse
import os.path

import yaml


class UpdateCloudsYaml(object):
    def __init__(self, args):
        if args.file:
            self._clouds_path = args.file
            self._create_directory = False
        else:
            self._clouds_path = os.path.expanduser(
                '~/.config/openstack/clouds.yaml')
            self._create_directory = True
        self._clouds = {}

        self._cloud = args.os_cloud
        self._cloud_data = {
            'region_name': args.os_region_name,
            'identity_api_version': args.os_identity_api_version,
            'auth': {
                'auth_url': args.os_auth_url,
                'username': args.os_username,
                'password': args.os_password,
                'project_name': args.os_project_name,
            },
        }
        if args.os_cacert:
            self._cloud_data['cacert'] = args.os_cacert

    def run(self):
        self._read_clouds()
        self._update_clouds()
        self._write_clouds()

    def _read_clouds(self):
        try:
            with open(self._clouds_path) as clouds_file:
                self._clouds = yaml.load(clouds_file)
        except IOError:
            # The user doesn't have a clouds.yaml file.
            print("The user clouds.yaml file didn't exist.")
            self._clouds = {}

    def _update_clouds(self):
        self._clouds.setdefault('clouds', {})[self._cloud] = self._cloud_data

    def _write_clouds(self):

        if self._create_directory:
            clouds_dir = os.path.dirname(self._clouds_path)
            os.makedirs(clouds_dir)

        with open(self._clouds_path, 'w') as clouds_file:
            yaml.dump(self._clouds, clouds_file, default_flow_style=False)


def main():
    parser = argparse.ArgumentParser('Update clouds.yaml file.')
    parser.add_argument('--file')
    parser.add_argument('--os-cloud', required=True)
    parser.add_argument('--os-region-name', default='RegionOne')
    parser.add_argument('--os-identity-api-version', default='3')
    parser.add_argument('--os-cacert')
    parser.add_argument('--os-auth-url', required=True)
    parser.add_argument('--os-username', required=True)
    parser.add_argument('--os-password', required=True)
    parser.add_argument('--os-project-name', required=True)

    args = parser.parse_args()

    update_clouds_yaml = UpdateCloudsYaml(args)
    update_clouds_yaml.run()


if __name__ == "__main__":
    main()
