def logs_command(args): """Gets (or streams) the logs for an application.""" args.app = args.app.lower() k8s = Kubernetes(args.kubernetes_url, namespace='noelapp') pods = k8s.pods(params={'labelSelector': 'noel-app={}'.format(args.app)}) if not pods['items']: logger.error('No running pods found for app {}'.format(args.app)) return False pod = pods['items'].pop() logger.info('Using pod {}'.format(pod['metadata']['name'])) if args.follow: logger.warning('Streaming logs. Press ctrl+c to quit.') try: it = k8s.logs(pod['metadata']['name'], container='noel-app', lines=args.lines, follow=args.follow) for log in it: print(log) except KeyboardInterrupt: pass
def logs_command(args): """Gets (or streams) the logs for an application.""" args.app = args.app.lower() k8s = Kubernetes(args.kubernetes_url, namespace='noelapp') pods = k8s.pods(params={ 'labelSelector': 'noel-app={}'.format(args.app)}) if not pods['items']: logger.error('No running pods found for app {}'.format(args.app)) return False pod = pods['items'].pop() logger.info('Using pod {}'.format(pod['metadata']['name'])) if args.follow: logger.warning('Streaming logs. Press ctrl+c to quit.') try: it = k8s.logs( pod['metadata']['name'], container='noel-app', lines=args.lines, follow=args.follow) for log in it: print(log) except KeyboardInterrupt: pass
def run(args): k8s = Kubernetes(args.kubernetes_url, namespace='noel') wait_for_kubernetes(k8s) keys = get_host_keys(k8s) if keys: logger.info('Existing ssh host keys found.') write_ssh_host_keys(args.destination, keys) return logger.warning('No existing ssh host keys. Generating keys.') keys = generate_ssh_host_keys(args.destination) try: put_host_keys(k8s, keys) logger.info('Host keys saved to Kubernetes.') except KubernetesError as e: if e.httperror.response.status_code == 409: logger.error( 'Conflict while writing ssh keys to Kubernetes, retrying...') return run(args) else: logger.exception('Unexpected error while writing ssh host keys.') raise
def delete_app_command(args): """Deletes an app and all cluster resources associated with it.""" args.app = args.app.lower() k8s = Kubernetes(args.kubernetes_url, namespace='noelapp') deployer.delete_app(k8s, args.app) logger.info('Application {} deleted'.format(args.app))
def add_git_remote_command(args): """Adds the remote builder as a git remote to the current repository.""" k8s = Kubernetes(args.kubernetes_url, namespace='noel') remote.add_builder_git_remote(k8s, args.app, args.remote_name) logger.info( 'Git remote added. Use `git push {} master` to deploy application {}.' .format(args.remote_name, args.app))
def deploy_image_command(args): """Updates an application with the given docker image.""" args.app = args.app.lower() k8s = Kubernetes(args.kubernetes_url, namespace='noelapp') deployer.deploy_app(k8s, args.app, image=args.image) logger.info('Application {} updated with image {}'.format( args.app, args.image))
def deploy_image_command(args): """Updates an application with the given docker image.""" args.app = args.app.lower() k8s = Kubernetes(args.kubernetes_url, namespace='noelapp') deployer.deploy_app(k8s, args.app, image=args.image) logger.info( 'Application {} updated with image {}'.format(args.app, args.image))
def add_git_remote_command(args): """Adds the remote builder as a git remote to the current repository.""" k8s = Kubernetes(args.kubernetes_url, namespace='noel') remote.add_builder_git_remote(k8s, args.app, args.remote_name) logger.info( 'Git remote added. Use `git push {} master` to deploy application {}.'. format(args.remote_name, args.app))
def add_ssh_key_command(args): """Add an authorized SSH key to the remote builder.""" with open(os.path.expanduser(args.ssh_key), 'r') as f: ssh_key = f.read() k8s = Kubernetes(args.kubernetes_url, namespace='noel') ssh_keys.add_key(k8s, args.hostname, ssh_key) logger.info('SSH Key {} added for as {}'.format(args.ssh_key, args.hostname))
def add_ssh_key_command(args): """Add an authorized SSH key to the remote builder.""" with open(os.path.expanduser(args.ssh_key), 'r') as f: ssh_key = f.read() k8s = Kubernetes(args.kubernetes_url, namespace='noel') ssh_keys.add_key(k8s, args.hostname, ssh_key) logger.info( 'SSH Key {} added for as {}'.format(args.ssh_key, args.hostname))
def set_config_command(args): """Sets the current configuration values for an application.""" args.app = args.app.lower() data = {pair[0]: pair[1] for pair in [x.split('=', 1) for x in args.pairs]} k8s = Kubernetes(args.kubernetes_url, namespace='noelapp') config = deployer.update_config(k8s, args.app, data) deployer.deploy_app(k8s, args.app, config=config) logger.info('Config updated for app {}'.format(args.app))
def run(args): k8s = Kubernetes(args.kubernetes_url, namespace='noel') resource_version = None try: secret = k8s.get_secret('ssh-keys') keys = secret['data'] resource_version = secret['metadata']['resourceVersion'] write_authorized_keys_file(keys, args.destination) logger.info('Wrote authorized keys. {} known keys.'.format( len(keys))) except KubernetesError as e: if e.httperror.response.status_code == 404: logger.warning('No ssh keys found, will watch for more.') else: logger.exception( 'Unexpected error while retrieving initial ssh keys.') while True: try: params = { 'labelSelector': 'type=ssh-keys', 'resourceVersion': resource_version } for change in k8s.watch_secrets(params=params): if change['type'] not in ['CREATED', 'ADDED', 'MODIFIED']: continue secret = change['object'] if secret['metadata']['name'] != 'ssh-keys': continue keys = k8s.decode_secret_data(secret['data']) write_authorized_keys_file(keys, args.destination) logger.info('Updated authorized keys. {} known keys.'.format( len(keys))) # Set the resource version param, so that any exception occurs # we only get the changes since the last one we saw. resource_version = secret['metadata']['resourceVersion'] except Exception: logger.exception( 'Error while refreshing ssh keys, waiting 30 seconds.') time.sleep(30)
def scale_command(args): """Scales the number of replicas for an application.""" args.app = args.app.lower() k8s = Kubernetes(args.kubernetes_url, namespace='noelapp') rc = deployer.get_replication_controller(k8s, args.app) if not rc: logger.error( 'No replication controller found for app {}.'.format(args.app)) return False k8s.scale(rc['metadata']['name'], replicas=args.replicas) logger.info( 'Scaled app {} to {} replicas.'.format(args.app, args.replicas))
def scale_command(args): """Scales the number of replicas for an application.""" args.app = args.app.lower() k8s = Kubernetes(args.kubernetes_url, namespace='noelapp') rc = deployer.get_replication_controller(k8s, args.app) if not rc: logger.error('No replication controller found for app {}.'.format( args.app)) return False k8s.scale(rc['metadata']['name'], replicas=args.replicas) logger.info('Scaled app {} to {} replicas.'.format(args.app, args.replicas))
def post_receive_hook_command(): repo_name = os.path.basename(os.getcwd()) _, sha, ref = read_push_info_from_stdin() if ref != 'refs/heads/master': logger.error('Received ref {}, not deploying. \n' 'Please push master to deploy.'.format(ref)) return False logger.info('Got request to build project {}.'.format(repo_name)) staging_dir = os.path.join(STAGING_ROOT, repo_name) logger.info('Staging code at {}'.format(staging_dir)) checkout_repo(staging_dir) args = argparse.Namespace( dir=staging_dir, app=repo_name, version=sha[:6], kubernetes_url='http://localhost:8001') return build_and_deploy_command(args)
def build(dir, app, version): project_id = gcp.get_project_id() logger.info('Using Google Cloud Project ID {}'.format(project_id)) logger.info('Building app {} at {}'.format(app, dir)) image = 'gcr.io/{}/noel-app-{}:{}'.format(project_id, app, version) docker.build(image, dir) logger.info('Finished building image, pushing image to registry.') docker_auth_token = gcp.get_gce_auth_token() if docker_auth_token: docker.login('https://gcr.io', docker_auth_token) docker.push(image, use_gcloud=True if not docker_auth_token else False) logger.info('Image {} successfully built and pushed.'.format(image)) return image