diff options
| author | Jhon Honce <jhonce@redhat.com> | 2015-03-24 17:05:13 -0700 | 
|---|---|---|
| committer | Jhon Honce <jhonce@redhat.com> | 2015-03-24 17:05:13 -0700 | 
| commit | 16cac480197bfe1738b785aed55204b53d06ad57 (patch) | |
| tree | cb89434733c26c8751e7a11c7cf455eb26423784 /bin/cluster | |
| parent | f2f0167b605b541ad74d0aef0392609772692f0d (diff) | |
| download | openshift-16cac480197bfe1738b785aed55204b53d06ad57.tar.gz openshift-16cac480197bfe1738b785aed55204b53d06ad57.tar.bz2 openshift-16cac480197bfe1738b785aed55204b53d06ad57.tar.xz openshift-16cac480197bfe1738b785aed55204b53d06ad57.zip  | |
* Refactor bin/cluster to use argparse.subparsers
Diffstat (limited to 'bin/cluster')
| -rwxr-xr-x | bin/cluster | 182 | 
1 files changed, 126 insertions, 56 deletions
diff --git a/bin/cluster b/bin/cluster index 823f50671..b99286b46 100755 --- a/bin/cluster +++ b/bin/cluster @@ -8,33 +8,79 @@ import os  class Cluster(object): -    """Python wrapper to ensure environment is correct for running ansible playbooks      """ - -    def __init__(self, args): -        self.args = args - +    Control and Configuration Interface for OpenShift Clusters +    """ +    def __init__(self):          # setup ansible ssh environment          if 'ANSIBLE_SSH_ARGS' not in os.environ:              os.environ['ANSIBLE_SSH_ARGS'] = ( -                '-o ForwardAgent=yes' -                ' -o StrictHostKeyChecking=no' -                ' -o UserKnownHostsFile=/dev/null' -                ' -o ControlMaster=auto' -                ' -o ControlPersist=600s' +                '-o ForwardAgent=yes ' +                '-o StrictHostKeyChecking=no ' +                '-o UserKnownHostsFile=/dev/null ' +                '-o ControlMaster=auto ' +                '-o ControlPersist=600s '              ) -    def apply(self): -        # setup ansible playbook environment +    def create(self, args): +        """ +        Create an OpenShift cluster for given provider +        :param args: command line arguments provided by user +        :return: exit status from run command +        """ +        env = {'cluster_id': args.cluster_id} +        playbook = "playbooks/{}/openshift-cluster/launch.yml".format(args.provider) +        inventory = self.setup_provider(args.provider) + +        env['masters'] = args.masters +        env['nodes'] = args.nodes + +        return self.action(args, inventory, env, playbook) + +    def terminate(self, args): +        """ +        Destroy OpenShift cluster +        :param args: command line arguments provided by user +        :return: exit status from run command +        """ +        env = {'cluster_id': args.cluster_id} +        playbook = "playbooks/{}/openshift-cluster/terminate.yml".format(args.provider) +        inventory = self.setup_provider(args.provider) + +        return self.action(args, inventory, env, playbook) + +    def list(self, args): +        """ +        List VMs in cluster +        :param args: command line arguments provided by user +        :return: exit status from run command +        """ +        raise NotImplementedError("ACTION [{}] not implemented".format(sys._getframe().f_code.co_name)) + +    def update(self, args): +        """ +        Update OpenShift across clustered VMs +        :param args: command line arguments provided by user +        :return: exit status from run command +        """ +        raise NotImplementedError("ACTION [{}] not implemented".format(sys._getframe().f_code.co_name)) + + +    def setup_provider(self, provider): +        """ +        Setup ansible playbook environment +        :param provider: command line arguments provided by user +        :return: path to inventory for given provider +        """          config = ConfigParser.ConfigParser() -        if 'gce' == self.args.provider: +        if 'gce' == provider:              config.readfp(open('inventory/gce/gce.ini'))              for key in config.options('gce'):                  os.environ[key] = config.get('gce', key)              inventory = '-i inventory/gce/gce.py' -        elif 'aws' == self.args.provider: +        elif 'aws' == provider:              config.readfp(open('inventory/aws/ec2.ini'))              for key in config.options('ec2'): @@ -43,30 +89,23 @@ class Cluster(object):              inventory = '-i inventory/aws/ec2.py'          else:              # this code should never be reached -            raise argparse.ArgumentError("invalid PROVIDER {}".format(self.args.provider)) - -        env = {'cluster_id': self.args.cluster_id} - -        if 'create' == self.args.action: -            playbook = "playbooks/{}/openshift-cluster/launch.yml".format(self.args.provider) -            env['masters'] = self.args.masters -            env['nodes'] = self.args.nodes - -        elif 'terminate' == self.args.action: -            playbook = "playbooks/{}/openshift-cluster/terminate.yml".format(self.args.provider) -        elif 'list' == self.args.action: -            # todo: implement cluster list -            raise argparse.ArgumentError("ACTION {} not implemented".format(self.args.action)) -        elif 'update' == self.args.action: -            # todo: implement cluster update -            raise argparse.ArgumentError("ACTION {} not implemented".format(self.args.action)) -        else: -            # this code should never be reached -            raise argparse.ArgumentError("invalid ACTION {}".format(self.args.action)) +            raise ValueError("invalid PROVIDER {}".format(provider)) + +        return inventory + +    def action(self, args, inventory, env, playbook): +        """ +        Build ansible-playbook command line and execute +        :param args: command line arguments provided by user +        :param inventory: derived provider library +        :param env: environment variables for kubernetes +        :param playbook: ansible playbook to execute +        :return: exit status from ansible-playbook command +        """          verbose = '' -        if self.args.verbose > 0: -            verbose = '-{}'.format('v' * self.args.verbose) +        if args.verbose > 0: +            verbose = '-{}'.format('v' * args.verbose)          ansible_env = '-e \'{}\''.format(              ' '.join(['%s=%s' % (key, value) for (key, value) in env.items()]) @@ -76,36 +115,67 @@ class Cluster(object):              verbose, inventory, ansible_env, playbook          ) -        if self.args.verbose > 1: +        if args.verbose > 1:              command = 'time {}'.format(command) -        if self.args.verbose > 0: +        if args.verbose > 0:              sys.stderr.write('RUN [{}]\n'.format(command))              sys.stderr.flush() -        status = os.system(command) -        if status != 0: -            sys.stderr.write("RUN [{}] failed with exit status %d".format(command, status)) -            exit(status) - +        return os.system(command)  if __name__ == '__main__': -    parser = argparse.ArgumentParser(description='Manage OpenShift Cluster') -    parser.add_argument('-m', '--masters', default=1, type=int, help='number of masters to create in cluster') -    parser.add_argument('-n', '--nodes', default=2, type=int, help='number of nodes to create in cluster') +    """ +    Implemented to support writing unit tests +    """ + +    cluster = Cluster() + +    providers = ['gce', 'aws'] +    parser = argparse.ArgumentParser( +        description='Python wrapper to ensure proper environment for OpenShift ansible playbooks', +    )      parser.add_argument('-v', '--verbose', action='count', help='Multiple -v options increase the verbosity') -    parser.add_argument('--version', action='version', version='%(prog)s 0.1') -    parser.add_argument('action', choices=['create', 'terminate', 'update', 'list']) -    parser.add_argument('provider', choices=['gce', 'aws']) -    parser.add_argument('cluster_id', help='prefix for cluster VM names') +    parser.add_argument('--version', action='version', version='%(prog)s 0.2') + +    meta_parser = argparse.ArgumentParser(add_help=False) +    meta_parser.add_argument('provider', choices=providers, help='provider') +    meta_parser.add_argument('cluster_id', help='prefix for cluster VM names') + +    action_parser = parser.add_subparsers(dest='action', title='actions', description='Choose from valid actions') + +    create_parser = action_parser.add_parser('create', help='Create a cluster', parents=[meta_parser]) +    create_parser.add_argument('-m', '--masters', default=1, type=int, help='number of masters to create in cluster') +    create_parser.add_argument('-n', '--nodes', default=2, type=int, help='number of nodes to create in cluster') +    create_parser.set_defaults(func=cluster.create) + +    terminate_parser = action_parser.add_parser('terminate', help='Destroy a cluster', parents=[meta_parser]) +    terminate_parser.add_argument('-f', '--force', action='store_true', help='Destroy cluster without confirmation') +    terminate_parser.set_defaults(func=cluster.terminate) + +    update_parser = action_parser.add_parser('update', help='Update OpenShift across cluster', parents=[meta_parser]) +    update_parser.add_argument('-f', '--force', action='store_true', help='Update cluster without confirmation') +    update_parser.set_defaults(func=cluster.update) + +    list_parser = action_parser.add_parser('list', help='List VMs in cluster', parents=[meta_parser]) +    list_parser.set_defaults(func=cluster.list) +      args = parser.parse_args() -    if 'terminate' == args.action: -        sys.stderr.write("This will terminate the ENTIRE {} environment. Are you sure? [y/N] ".format(args.cluster_id)) -        sys.stderr.flush() -        answer = sys.stdin.read(1) +    if 'terminate' == args.action and not args.force: +        answer = raw_input("This will destroy the ENTIRE {} environment. Are you sure? [y/N] ".format(args.cluster_id)) +        if answer not in ['y', 'Y']: +            sys.stderr.write('\nACTION [terminate] aborted by user!\n') +            exit(1) + +    if 'update' == args.action and not args.force: +        answer = raw_input("This is destructive and could corrupt {} environment. Continue? [y/N] ".format(args.cluster_id))          if answer not in ['y', 'Y']: -            exit(0) +            sys.stderr.write('\nACTION [update] aborted by user!\n') +            exit(1) -    Cluster(args).apply() +    status = args.func(args) +    if status != 0: +        sys.stderr.write("ACTION [{}] failed with exit status {}\n".format(args.action, status)) +    exit(status)  | 
