text:
__version__ = "0.8"

# Requirements
#   python3, kops, ssh-keygen, awscli, packaging, appdirs, gcloud, azure-cli, helm, kubectl, kubernetes.tar.gz

# References:
#   https://github.com/kubernetes-incubator/client-python/blob/master/kubernetes/README.md
#   https://github.com/kubernetes/kops/blob/master/docs/aws.md

import warnings
import requests
import fire
import tarfile
import os
import sys
import kubernetes.client as kubeclient
from kubernetes.client.rest import ApiException
import kubernetes.config as kubeconfig
import yaml
import json
from pprint import pprint
import subprocess
from datetime import timedelta
import importlib.util
from jinja2 import Template

class PipelineCli(object):
    _kube_deploy_registry = {'jupyter': (['jupyterhub.ml/jupyterhub-deploy.yaml'], []),
                            'jupyterhub': (['jupyterhub.ml/jupyterhub-deploy.yaml'], []),
                            'spark': (['apachespark.ml/master-deploy.yaml'], ['spark-worker', 'metastore']),
                            'spark-worker': (['apachespark.ml/worker-deploy.yaml'], []),
                            'metastore': (['metastore.ml/metastore-deploy.yaml'], ['mysql']),
                            'hdfs': (['hdfs.ml/namenode-deploy.yaml'], []),
                            'redis': (['keyvalue.ml/redis-master-deploy.yaml'], []),
                            'presto': (['presto.ml/master-deploy.yaml',
                                        'presto.ml/worker-deploy.yaml'], ['metastore']),
                            'presto-ui': (['presto.ml/ui-deploy.yaml'], ['presto']),
                            'airflow': (['scheduler.ml/airflow-deploy.yaml'], ['mysql', 'redis']),
                            'mysql': (['sql.ml/mysql-master-deploy.yaml'], []),
                            'web-home': (['web.ml/home-deploy.yaml'], []),
                            'zeppelin': (['zeppelin.ml/zeppelin-deploy.yaml'], []),
                            'zookeeper': (['zookeeper.ml/zookeeper-deploy.yaml'], []),
                            'elasticsearch': (['elasticsearch.ml/elasticsearch-2-3-0-deploy.yaml'], []),
                            'kibana': (['kibana.ml/kibana-4-5-0-deploy.yaml'], ['elasticsearch'], []),
                            'kafka': (['stream.ml/kafka-0.10-deploy.yaml'], ['zookeeper']),
                            'cassandra': (['cassandra.ml/cassandra-deploy.yaml'], []),
                            'jenkins': (['jenkins/jenkins-deploy.yaml'], []),
                            'prediction-java': (['prediction.ml/java-deploy.yaml'], []),
                            'prediction-python3': (['prediction.ml/python3-deploy.yaml'], []),
                            'prediction-scikit': (['prediction.ml/scikit-deploy.yaml'], []),
                            'prediction-pmml': (['prediction.ml/pmml-deploy.yaml'], []),
                            'prediction-spark': (['prediction.ml/spark-deploy.yaml'], []),
                            'prediction-tensorflow': (['prediction.ml/tensorflow-deploy.yaml'], []),
                            'prediction-tensorflow-gpu': (['prediction.ml/tensorflow-gpu-deploy.yaml'], []),
                            'turbine': (['dashboard.ml/turbine-deploy.yaml'], []),
                            'hystrix': (['dashboard.ml/hystrix-deploy.yaml'], []),
                            'weave-scope-app': (['dashboard.ml/weavescope/scope-1.3.0.yaml'], []),
                            'kubernetes-dashboard': (['dashboard.ml/kubernetes-dashboard/v1.6.0.yaml'], []),
                            'heapster': (['metrics.ml/monitoring-standalone/v1.3.0.yaml'], []),
                            'route53-mapper': (['dashboard.ml/route53-mapper/v1.3.0.yml'], []),
                            'kubernetes-logging': (['dashboard.ml/logging-elasticsearch/v1.5.0.yaml'], []),
                           }
    _kube_svc_registry = {'jupyter': (['jupyterhub.ml/jupyterhub-svc.yaml'], []),
                         'jupyterhub': (['jupyterhub.ml/jupyterhub-svc.yaml'], []),
                         'spark': (['apachespark.ml/master-svc.yaml'], ['spark-worker', 'metastore']),
                         'spark-worker': (['apachespark.ml/worker-svc.yaml'], []),
                         'metastore': (['metastore.ml/metastore-svc.yaml'], ['mysql']),
                         'hdfs': (['hdfs.ml/namenode-svc.yaml'], []),
                         'redis': (['keyvalue.ml/redis-master-svc.yaml'], []),
                         'presto': (['presto.ml/master-svc.yaml',
                                     'presto.ml/worker-svc.yaml'], ['metastore']),
                         'presto-ui': (['presto.ml/ui-svc.yaml'], ['presto']),
                         'airflow': (['scheduler.ml/airflow-svc.yaml'], ['mysql', 'redis']),
                         'mysql': (['sql.ml/mysql-master-svc.yaml'], []),
                         'web-home': (['web.ml/home-svc.yaml'], []),
                         'zeppelin': (['zeppelin.ml/zeppelin-svc.yaml'], []),
                         'zookeeper': (['zookeeper.ml/zookeeper-svc.yaml'], []),
                         'elasticsearch': (['elasticsearch.ml/elasticsearch-2-3-0-svc.yaml'], []),
                         'kibana': (['kibana.ml/kibana-4-5-0-svc.yaml'], ['elasticsearch'], []),
                         'kafka': (['stream.ml/kafka-0.10-svc.yaml'], ['zookeeper']),
                         'cassandra': (['cassandra.ml/cassandra-svc.yaml'], []),
                         'jenkins': (['jenkins/jenkins-svc.yaml'], []),
                         'prediction-java': (['prediction.ml/java-svc.yaml'], []),
                         'prediction-python3': (['prediction.ml/python3-svc.yaml'], []),
                         'prediction-scikit': (['prediction.ml/scikit-svc.yaml'], []),
                         'prediction-spark': (['prediction.ml/spark-svc.yaml'], []),
                         'prediction-pmml': (['prediction.ml/pmml-svc.yaml'], []),
                         'prediction-tensorflow': (['prediction.ml/tensorflow-svc.yaml'], []),
                         'prediction-tensorflow-gpu': (['prediction.ml/tensorflow-gpu-svc.yaml'], []),
                         'turbine': (['dashboard.ml/turbine-svc.yaml'], []),
                         'hystrix': (['dashboard.ml/hystrix-svc.yaml'], []),
                        }

    _kube_deploy_template_registry = {'predict': (['templates/model-deploy.yaml.template'], [])}
    _kube_svc_template_registry = {'predict': (['templates/model-svc.yaml.template'], [])}

    def _get_default_pipeline_api_version(self):
        return 'v1'

    def _get_default_pipeline_git_home(self):
        return 'https://github.com/fluxcapacitor/source.ml/'

    def _get_default_pipeline_git_version(self):
        return 'master'

    def _get_current_context_from_kube_config(self):
        cmd = 'kubectl config current-context'
        process = subprocess.Popen(cmd.split(), stdout=subprocess.PIPE)
        (output, error) = process.communicate()
        return output.rstrip().decode('utf-8')

    def version(self):
        print(__version__)

    def conda_view(self,
              environment):
        print("Dumping dependencies for conda env '%s'" % environment)
        cmd = 'conda -n %s list' % environment
        process = subprocess.Popen(cmd.split(), stdout=subprocess.PIPE)
        (output, error) = process.communicate()
        return output.rstrip().decode('utf-8')

    def config_get(self,
                   config_key):
        print("")
        pprint(self._get_full_config())
        print("")
        return self._get_full_config()[config_key]

    def config_set(self,
                   config_key,
                   config_value):
        print("config_key: '%s'" % config_key)
        self._merge_dict({config_key: config_value})
        print("config_value: '%s'" % self._get_full_config()[config_key])
        self._merge_dict({config_key: config_value})
        print("")
        pprint(self._get_full_config())
        print("")

    def _merge_dict(self,
                    new_dict):

        pipeline_api_version = self._get_full_config()['pipeline_api_version']
        config_file_base_path = "~/.pipeline/"
        config_file_base_path = os.path.expandvars(config_file_base_path)
        config_file_base_path = os.path.expanduser(config_file_base_path)
        config_file_base_path = os.path.abspath(config_file_base_path)
        config_file_path = os.path.join(config_file_base_path, 'config')

        existing_config_dict = self._get_full_config()

        # >= Python3.5
        # {**existing_config_dict, **new_dict}
        existing_config_dict.update(new_dict)

        new_config_yaml = yaml.dump(existing_config_dict, default_flow_style=False, explicit_start=True)

        with open(config_file_path, 'w') as fh:
            fh.write(new_config_yaml)

    def _get_full_config(self):
        config_file_base_path = "~/.pipeline/"
        config_file_base_path = os.path.expandvars(config_file_base_path)
        config_file_base_path = os.path.expanduser(config_file_base_path)
        config_file_base_path = os.path.abspath(config_file_base_path)
        config_file_filename = os.path.join(config_file_base_path, 'config')

        if not os.path.exists(config_file_filename):
            if not os.path.exists(config_file_base_path):
                os.makedirs(config_file_base_path)
            initial_config_dict = {'pipeline_api_version': self._get_default_pipeline_api_version(),
                                   'pipeline_git_home': self._get_default_pipeline_git_home(),
                                   'pipeline_git_version': self._get_default_pipeline_git_version()}
            initial_config_yaml =  yaml.dump(initial_config_dict, default_flow_style=False, explicit_start=True)
            print("")
            print("Default config created at '%s'.  Override with 'pipeline init'" % config_file_filename)
            print("")
            with open(config_file_filename, 'w') as fh:
                fh.write(initial_config_yaml)

        # Load the YAML
        with open(config_file_filename, 'r') as fh:
            existing_config_dict = yaml.load(fh)
            return existing_config_dict

    def config(self):
        print(yaml.dump(self._get_full_config(), default_flow_style=False, explicit_start=True))
        print("")

    def service_list(self):
        self.cluster_view()

    def service_proxy(self,
              app_name,
              local_port=None,
              app_port=None):

        self.service_tunnel(app_name, local_port, app_port)

    def service_tunnel(self,
               app_name,
               local_port=None,
               app_port=None):

        pipeline_api_version = self._get_full_config()['pipeline_api_version']
        try:
            kube_cluster_context = self._get_full_config()['kube_cluster_context']
            kube_namespace = self._get_full_config()['kube_namespace']
        except:
            print("")
            print("Cluster needs to be configured with 'pipeline cluster-init'.")
            print("")
            return

        pod = self._get_pod_by_app_name(app_name)
        if not pod:
            print("")
            print("App '%s' is not running." % app_name)
            print("")
            return
        if not app_port:
            svc = self._get_svc_by_app_name(app_name)
            if not svc:
                print("")
                print("App '%s' proxy port cannot be found." % app_name)
                print("")
                return
            app_port = svc.spec.ports[0].target_port

        if not local_port:
            print("")
            print("Proxying local port '<randomly-chosen>' to app '%s' port '%s' using pod '%s'." % (app_port, app_name, pod.metadata.name))
            print("")
            print("Use 'http://127.0.0.1:<randomly-chosen>' to access app '%s' on port '%s'." % (app_name, app_port))
            print("")
            print("If you break out of this terminal, your proxy session will end.")
            print("")
            subprocess.call('kubectl port-forward %s :%s' % (pod.metadata.name, app_port), shell=True)
            print("")
        else:
            print("")
            print("Proxying local port '%s' to app '%s' port '%s' using pod '%s'." % (local_port, app_port, app_name, pod.metadata.name))
            print("")
            print("Use 'http://127.0.0.1:%s' to access app '%s' on port '%s'." % (local_port, app_name, app_port))
            print("")
            print("If you break out of this terminal, your proxy session will end.")
            print("")
            subprocess.call('kubectl port-forward %s %s:%s' % (pod.metadata.name, local_port, app_port), shell=True)
            print("")

    # TODO:  Start an airflow job
    def job_flow(self,
             flow_name):
        print("")
        print("Submit airflow coming soon!")

    # TODO:  Submit a spark job
    def job_submit(self,
               replicas):
        print("Submit spark job coming soon!")

    def top(self,
            app_name=None):

        self.metrics_system(app_name)

    def metrics_system(self,
               app_name=None):

        pipeline_api_version = self._get_full_config()['pipeline_api_version']

        try:
            kube_cluster_context = self._get_full_config()['kube_cluster_context']
            kube_namespace = self._get_full_config()['kube_namespace']
        except:
            print("")
            print("Cluster needs to be configured 'pipeline cluster-init'.")
            print("")
            return

        if (app_name):
#            print("")
#            print("Retrieving system metrics for app '%s'." % app_name)
#            print("")
            self._get_app_resources(app_name)
#            print("")
#            print("Retrieving system metrics for cluster.")
            print("")
            self._get_cluster_resources()
        else:
            print("")
            print("Retrieving only system resources for cluster.  Use '--app-name' for app-level, as well.")
            print("")
            self._get_cluster_resources()

        print("")
        print("If you see an error above, you need to start Heapster with 'pipeline start heapster'.")
        print("")

    def _get_cluster_resources(self):
        subprocess.call("kubectl top node", shell=True)
        print("")

    def _get_app_resources(self,
                           app_name):

        pipeline_api_version = self._get_full_config()['pipeline_api_version']

        try:
            kube_cluster_context = self._get_full_config()['kube_cluster_context']
            kube_namespace = self._get_full_config()['kube_namespace']
        except:
            print("")
            print("Cluster needs to be configured 'pipeline cluster-init'.")
            print("")
            return

        kubeconfig.load_kube_config()
        kubeclient_v1 = kubeclient.CoreV1Api()
        kubeclient_v1_beta1 = kubeclient.ExtensionsV1beta1Api()

        with warnings.catch_warnings():
            warnings.simplefilter("ignore")
            response = kubeclient_v1.list_pod_for_all_namespaces(watch=False,
                                                                 pretty=True)
            pods = response.items
            for pod in pods:
                if (app_name in pod.metadata.name):
                    subprocess.call('kubectl top pod %s' % pod.metadata.name, shell=True)
        print("")

    def cluster_join(self,
             federation):
        print("")
        print("Federation joining coming soon!")
        print("")

    def cluster_up(self,
           provider='aws',
           ssh_public_key='~/.ssh/id_rsa.pub',
           initial_worker_count='1',
#           min_worker_count='1',
#           max_worker_count='1',
           worker_zones='us-west-2a,us-west-2b',
           worker_type='r2.2xlarge',
           master_zones='us-west-2c',
           master_type='t2.medium',
#           dns_zone='',
#           vpc='',
           kubernetes_version='1.6.2',
           kubernetes_image='kope.io/k8s-1.5-debian-jessie-amd64-hvm-ebs-2017-01-09'):
        try:
            kops_cluster_name = self._get_full_config()['kops_cluster_name']
            kops_state_store = self._get_full_config()['kops_state_store']

            if not kops_ssh_public_key:
                subprocess.call("ssh-keygen -t rsa", shell=True)
                ssh_public_key = '~/.ssh/id_rsa.pub'

            subprocess.call("aws configure", shell=True)
            subprocess.call("aws s3 mb %s" % kops_state_store, shell=True)

            subprocess.call("kops create cluster --ssh-public-key %s --node-count %s --zones %s --master-zones %s --node-size %s --master-size %s --kubernetes-version %s --image %s --state %s --name %s" % (ssh_public_key, initial_worker_count, worker_zones, master_zones, worker_type, master_type, kubernetes_version, kubernetes_image, kops_state_store, kops_cluster_name), shell=True)
            subprocess.call("kops update --state %s cluster %s --yes" % (kops_state_store, kops_cluster_name), shell=True)
            subprocess.call("kubectl config set-cluster %s --insecure-skip-tls-verify=true" % kops_cluster_name)
            print("")
            print("Cluster is being created.  This may take a few mins.")
            print("")
            print("Once the cluster is up, run 'kubectl cluster-info' for the Kubernetes dashboard url.")
            print("Username is 'admin'.")
            print("Password can be retrieved with 'kops get secrets kube --type secret -oplaintext --state %s'" % kops_state_store)
        except:
            print("")
            print("Kops needs to be configured with 'pipeline kops-init'.")
            print("")
            return

    def kops_init(self,
                  kops_cluster_name,
                  kops_state_store):
        config_dict = {'kops_cluster_name': kops_cluster_name,
                       'kops_state_store': kops_state_store}
        self._merge_dict(config_dict)
        print("")
        pprint(self._get_full_config())
        print("")

    def instancegroup_list(self):
        try:
            kops_cluster_name = self._get_full_config()['kops_cluster_name']
            kops_state_store = self._get_full_config()['kops_state_store']

            subprocess.call("kops --state %s --name %s get instancegroups" % (kops_state_store, kops_cluster_name), shell=True)
            print("")
        except:
            print("")
            print("Kops needs to be configured with 'pipeline kops-init'.")
            print("")
            return

    def cluster_list(self):
        try:
            kops_cluster_name = self._get_full_config()['kops_cluster_name']
            kops_state_store = self._get_full_config()['kops_state_store']

            subprocess.call("kops --state %s --name %s get clusters" % (kops_state_store, kops_cluster_name), shell=True)
            print("")
        except:
            print("")
            print("Kops needs to be configured with 'pipeline kops-init'.")
            print("")
            return

    def federation_list(self):
        try:
            kops_cluster_name = self._get_full_config()['kops_cluster_name']
            kops_state_store = self._get_full_config()['kops_state_store']

            subprocess.call("kops --state %s --name %s get federations" % (kops_state_store, kops_cluster_name), shell=True)
            print("")
        except:
            print("")
            print("Kops needs to be configured with 'pipeline kops-init'.")
            print("")
            return

    def secret_list(self):
        try:
            kops_cluster_name = self._get_full_config()['kops_cluster_name']
            kops_state_store = self._get_full_config()['kops_state_store']

            subprocess.call("kops --state %s --name %s get secrets" % (kops_state_store, kops_cluster_name), shell=True)
            print("")
        except:
            print("")
            print("Kops needs to be configured with 'pipeline kops-init'.")
            print("")
            return

    def init(self,
             pipeline_api_version=None,
             pipeline_git_home=None,
             pipeline_git_version=None):

        if not pipeline_api_version:
             pipeline_api_version = self._get_default_pipeline_api_version()

        if not pipeline_git_home:
             pipeline_git_home = self._get_default_pipeline_git_home()

        if not pipeline_git_version:
             pipeline_git_version = self._get_default_pipeline_git_version()

        config_dict = {'pipeline_api_version': pipeline_api_version,
                       'pipeline_git_home': pipeline_git_home,
                       'pipeline_git_version': pipeline_git_version}

        self._merge_dict(config_dict)

        print("")
        print(yaml.dump(self._get_full_config(), default_flow_style=False, explicit_start=True))
        print("")

    def cluster_init(self,
                     kube_cluster_context=None,
                     kube_namespace=None):
        pipeline_api_version = self._get_full_config()['pipeline_api_version']

        if not kube_cluster_context:
            kube_cluster_context = self._get_current_context_from_kube_config()

        if not kube_namespace:
            kube_namespace = 'default'

        config_dict = {'kube_cluster_context': kube_cluster_context,
                       'kube_namespace': kube_namespace}
        self._merge_dict(config_dict)
        print("")
        pprint(self._get_full_config())
        print("")

    def model_init(self,
                   model_type,
                   model_name,
                   model_path,
                   model_server_url=None,
                   model_test_request_path=None,
                   model_request_mime_type='application/json',
                   model_response_mime_type='application/json'):

        pipeline_api_version = self._get_full_config()['pipeline_api_version']

        model_path = os.path.expandvars(model_path)
        model_path = os.path.expanduser(model_path)
        model_path = os.path.abspath(model_path)

        if model_test_request_path:
            model_test_request_path = os.path.expandvars(model_test_request_path)
            model_test_request_path = os.path.expanduser(model_test_request_path)
            model_test_request_path = os.path.abspath(model_test_request_path)
        else:
            model_test_request_path = os.path.join(model_path, 'data/test_request.json')

        if model_server_url:
            model_server_url.rstrip('/')

            config_dict = {
                           'model_server_url': model_server_url,
                           'model_type': model_type,
                           'model_name': model_name,
                           'model_path': model_path,
                           'model_test_request_path': model_test_request_path,
                           'model_request_mime_type': model_request_mime_type,
                           'model_response_mime_type': model_response_mime_type,
            }
        else:
            config_dict = {
                           'model_type': model_type,
                           'model_name': model_name,
                           'model_path': model_path,
                           'model_test_request_path': model_test_request_path,
                           'model_request_mime_type': model_request_mime_type,
                           'model_response_mime_type': model_response_mime_type,
            }

        self._merge_dict(config_dict)
        print("")
        pprint(self._get_full_config())
        print("")

    # TODO:  make package_path more clear (ie docker package, tar.gz package)
    def model_package(self,
                      model_type=None,
                      model_name=None,
                      model_path=None,
                      model_chip='cpu',
                      model_tag='master',
                      package_type='docker',
                      package_path='.'):

        if not model_type:
            model_type = self._get_full_config()['model_type']

        if not model_name:
            model_name = self._get_full_config()['model_name']

        if not model_path:
            model_path = self._get_full_config()['model_path']

        #model_path = os.path.expandvars(model_path)
        #model_path = os.path.expanduser(model_path)
        #model_path = os.path.abspath(model_path)

        #package_path = os.path.expandvars(package_path)
        #package_path = os.path.expanduser(package_path)
        #package_path = os.path.abspath(package_path)

        if package_type == 'docker':
            if model_chip == 'gpu':
                docker_cmd = 'nvidia-docker'
            else:
                docker_cmd = 'docker'

            # TODO:  Incorporate model_path
            cmd = '%s build -t fluxcapacitor/predict-%s-%s-%s:%s \
                     --build-arg model_type=%s \
                     --build-arg model_name=%s \
                     --build-arg model_path=%s \
                     --build-arg model_chip=%s \
                     -f Dockerfile %s' % (docker_cmd, model_type, model_name, model_chip, model_tag, model_type, model_name, model_path, model_chip, package_path)

            print(cmd)
            print("")
            process = subprocess.call(cmd, shell=True)

            model_predict_deploy_yaml_template_path = os.path.join(package_path, PipelineCli._kube_deploy_template_registry['predict'][0][0])
            model_predict_svc_yaml_template_path = os.path.join(package_path, PipelineCli._kube_svc_template_registry['predict'][0][0])

            #deploy_yaml_template = Template(model_predict_deploy_yaml_template_path)
            #deploy_yaml_rendered = deloy_yaml_template.render()

            #svc_yaml_template = Template(model_predict_svc_yaml_template_path)
            #svc_yaml_rendered = svc_yaml_template.render()
        else:
            self._model_package_tar(model_type,
                                    model_name,
                                    model_path,
                                    model_tag,
                                    package_path)

    def model_shell(self,
                    model_type=None,
                    model_name=None,
                    model_tag='master',
                    model_chip='cpu'):

        if not model_type:
            model_type = self._get_full_config()['model_type']

        if not model_name:
            model_name = self._get_full_config()['model_name']

        if model_chip == 'gpu':
            docker_cmd = 'nvidia-docker'
        else:
            docker_cmd = 'docker'

        cmd = '%s exec -it predict-%s-%s-%s-%s bash' % (docker_cmd, model_type, model_name, model_chip, model_tag)
        print(cmd)
        print("")
        process = subprocess.call(cmd, shell=True)

    def model_push(self,
                   model_type=None,
                   model_name=None,
                   model_chip='cpu',
                   model_tag='master'):

        if not model_type:
            model_type = self._get_full_config()['model_type']

        if not model_name:
            model_name = self._get_full_config()['model_name']

        if not model_tag:
            model_tag = self._get_full_config()['model_tag']

        if model_chip == 'gpu':
            docker_cmd = 'nvidia-docker'
        else:
            docker_cmd = 'docker'

        cmd = '%s push fluxcapacitor/predict-%s-%s-%s:%s' % (docker_cmd, model_type, model_name, model_chip, model_tag)
        process = subprocess.call(cmd, shell=True)

    def model_start(self,
                    package_type='docker',
                    model_type=None,
                    model_name=None,
                    model_chip='cpu',
                    model_tag='master',
                    memory_limit='2G'):

        if not model_type:
            model_type = self._get_full_config()['model_type']

        if not model_name:
            model_name = self._get_full_config()['model_name']

        if not model_tag:
            model_tag = self._get_full_config()['model_tag']

        if model_chip == 'gpu':
            docker_cmd = 'nvidia-docker'
        else:
            docker_cmd = 'docker'

        cmd = '%s run -itd --name=predict-%s-%s-%s-%s \
               -m %s -p 6969:6969 -p 7070:7070 -p 10254:10254 \
               -p 9876:9876 -p 9040:9040 -p 9090:9090 -p 3000:3000 \
               -p 6333:6333 -e "PIO_MODEL_TYPE=%s" -e "PIO_MODEL_NAME=%s" \
               fluxcapacitor/predict-%s-%s-%s:%s' % (docker_cmd, model_type, model_name, model_chip, model_tag, memory_limit, model_type, model_name, model_type, model_name, model_chip, model_tag)

        process = subprocess.call(cmd, shell=True)

    def model_stop(self,
                   package_type='docker',
                   model_type=None,
                   model_name=None,
                   model_chip='cpu',
                   model_tag='master'):

        if not model_type:
            model_type = self._get_full_config()['model_type']

        if not model_name:
            model_name = self._get_full_config()['model_name']

        if not model_tag:
            model_tag = self._get_full_config()['model_tag']

        if model_chip == 'gpu':
            docker_cmd = 'nvidia-docker'
        else:
            docker_cmd = 'docker'

        cmd = '%s rm -f predict-%s-%s-%s-%s' % (docker_cmd, model_type, model_name, model_chip, model_tag)

        process = subprocess.call(cmd, shell=True)

    def model_logs(self,
                   package_type='docker',
                   model_type=None,
                   model_name=None,
                   model_chip='cpu',
                   model_tag='master'):

        if not model_type:
            model_type = self._get_full_config()['model_type']

        if not model_name:
            model_name = self._get_full_config()['model_name']

        if not model_tag:
            model_tag = self._get_full_config()['model_tag']

        if model_chip == 'gpu':
            docker_cmd = 'nvidia-docker'
        else:
            docker_cmd = 'docker'

        cmd = '%s logs -f predict-%s-%s-%s-%s' % (docker_cmd, model_type, model_name, model_chip, model_tag)

        process = subprocess.call(cmd, shell=True)

    def service_upgrade(self,
                        app_name,
                        docker_image,
                        docker_tag):

        pipeline_api_version = self._get_full_config()['pipeline_api_version']

        try:
            kube_cluster_context = self._get_full_config()['kube_cluster_context']
            kube_namespace = self._get_full_config()['kube_namespace']
        except:
            print("")
            print("Cluster needs to be configured with 'pipeline cluster-init'.")
            print("")
            return

        kubeconfig.load_kube_config()
        kubeclient_v1 = kubeclient.CoreV1Api()
        kubeclient_v1_beta1 = kubeclient.ExtensionsV1beta1Api()

        with warnings.catch_warnings():
            warnings.simplefilter("ignore")
            response = kubeclient_v1_beta1.list_deployment_for_all_namespaces(watch=False,
                                                                              pretty=True)
            found = False
            deployments = response.items
            for deploy in deployments:
                if app_name in deploy.metadata.name:
                    found = True
                    break
            if found:
                print("")
                print("Upgrading app '%s' using Docker image '%s:%s'." % (deploy.metadata.name, docker_image, docker_tag))
                print("")
                cmd = "kubectl set image deploy %s %s=%s:%s" % (deploy.metadata.name, deploy.metadata.name, docker_image, docker_tag)
                print("Running '%s'." % cmd)
                print("")
                subprocess.call(cmd, shell=True)
                print("")
                cmd = "kubectl rollout status deploy %s" % deploy.metadata.name
                print("Running '%s'." % cmd)
                print("")
                subprocess.call(cmd, shell=True)
                print("")
                cmd = "kubectl rollout history deploy %s" % deploy.metadata.name
                print("Running '%s'." % cmd)
                print("")
                subprocess.call(cmd, shell=True)
                print("")
                print("Check status with 'pipeline cluster'.")
                print("")
            else:
                print("")
                print("App '%s' is not running." % app_name)
                print("")

    def service_rollback(self,
                         app_name,
                         to_revision=None):

        pipeline_api_version = self._get_full_config()['pipeline_api_version']

        try:
            kube_cluster_context = self._get_full_config()['kube_cluster_context']
            kube_namespace = self._get_full_config()['kube_namespace']
        except:
            print("")
            print("Cluster needs to be configured with 'pipeline cluster-init'.")
            print("")
            return

        kubeconfig.load_kube_config()
        kubeclient_v1 = kubeclient.CoreV1Api()
        kubeclient_v1_beta1 = kubeclient.ExtensionsV1beta1Api()

        with warnings.catch_warnings():
            warnings.simplefilter("ignore")
            response = kubeclient_v1_beta1.list_deployment_for_all_namespaces(watch=False,
                                                                              pretty=True)
            found = False
            deployments = response.items
            for deploy in deployments:
                if app_name in deploy.metadata.name:
                    found = True
                    break
            if found:
                print("")
                if to_revision:
                    print("Rolling back app '%s' to revision '%s'." % deploy.metadata.name, revision)
                    cmd = "kubectl rollout undo deploy %s --to-revision=%s" % (deploy.metadata.name, to_revision)
                else:
                    print("Rolling back app '%s'." % deploy.metadata.name)
                    cmd = "kubectl rollout undo deploy %s" % deploy.metadata.name
                print("")
                print("Running '%s'." % cmd)
                print("")
                subprocess.call(cmd, shell=True)
                print("")
                cmd = "kubectl rollout status deploy %s" % deploy.metadata.name
                print("Running '%s'." % cmd)
                print("")
                subprocess.call(cmd, shell=True)
                print("")
                cmd = "kubectl rollout history deploy %s" % deploy.metadata.name
                print("Running '%s'." % cmd)
                print("")
                subprocess.call(cmd, shell=True)
                print("")
                print("Check status with 'pipeline cluster'.")
                print("")
            else:
                print("")
                print("App '%s' is not running." % app_name)
                print("")

    def _filter_tar(self,
                    tarinfo):
        # TODO:  Load this from .pipelineignore
        ignore_list = []
        for ignore in ignore_list:
            if ignore in tarinfo.name:
                return None

        return tarinfo

    def _model_package_tar(self,
                           model_type,
                           model_name,
                           model_path,
                           model_tag,
                           package_path,
                           package_name,
                           filemode='w',
                           compression='gz'):

        model_path = os.path.expandvars(model_path)
        model_path = os.path.expanduser(model_path)
        model_path = os.path.abspath(model_path)

        package_path = os.path.expandvars(package_path)
        package_path = os.path.expanduser(package_path)
        package_path = os.path.abspath(package_path)

        package_absolute_path = os.path.join(package_path, package_name)

        # TODO:  Incorporate model_tag if relevant
        with tarfile.open(package_absolute_path, '%s:%s' % (filemode, compression)) as tar:
            tar.add(model_path, arcname='.', filter=self._filter_tar)

#    def model_pickle(self,
#                     model_name='model',
#                     path_to_model='.'):

#        import cloudpickle as pickle

#        spec = importlib.util.spec_from_file_location(model_name, path_to_model)
#        model = importlib.util.module_from_spec(spec)
        # Note:  This will initialize all global vars defined inside of <path_to_model>/model.py
#        spec.loader.exec_module(model)

#        model_pkl_path = '%s.pkl' % model_name

#        with open(model_pkl_path, 'wb') as fh:
#            pickle.dump(model, fh)

#    def model_package(self,
#                      path_to_model,
#                      ):

#        pipeline_api_version = self._get_full_config()['pipeline_api_version']

#        try:
#            kube_cluster_context = self._get_full_config()['kube_cluster_context']
#            kube_namespace = self._get_full_config()['kube_namespace']
#        except:
#            print("")
#            print("Cluster needs to be configured with 'pipeline init-cluster'.")
#            print("")
#            return

#        try:
#            pipeline_git_home = self._get_full_config()['pipeline_git_home']

#            if 'http:' in pipeline_git_home or 'https:' in pipeline_git_home:
#                pass
#            else:
#                pipeline_git_home = os.path.expandvars(pipeline_git_home)
#                pipeline_git_home = os.path.expanduser(pipeline_git_home)
#                pipeline_git_home = os.path.abspath(pipeline_git_home)

#            pipeline_git_version = self._get_full_config()['pipeline_git_version']
#        except:
#            print("")
#            print("PipelineIO needs to be configured with 'pipeline init'.")
#            print("")
#            return

    def _model_deploy(self,
                      model_server_url=None,
                      model_type=None,
                      model_name=None,
                      model_path='.',
                      model_tag='master',
                      timeout=60):

        pipeline_api_version = self._get_full_config()['pipeline_api_version']

        if not model_server_url:
            try:
                model_server_url= self._get_full_config()['model_server_url']
            except:
                print("")
                print("Model needs to be configured with 'pipeline model-init'.")
                print("")
                return

        if not model_type:
            try:
                model_type = self._get_full_config()['model_type']
            except:
                print("")
                print("Model needs to be configured with 'pipeline model-init'.")
                print("")
                return

        if not model_name:
            try:
                model_name = self._get_full_config()['model_name']
            except:
                print("")
                print("Model needs to be configured with 'pipeline model-init'.")
                print("")
                return

        if not model_path:
            try:
                model_path = self._get_full_config()['model_path']
            except:
                print("")
                print("Model needs to be configured with 'pipeline model-init'.")
                print("")
                return

        if not model_tag:
            try:
                model_tag = self._get_full_config()['model_tag']
            except:
                print("")
                print("Model needs to be configured with 'pipeline model-init'.")
                print("")
                return

        model_path = os.path.expandvars(model_path)
        model_path = os.path.expanduser(model_path)
        model_path = os.path.abspath(model_path)

        print('model_server_url: %s' % model_server_url)
        print('model_type: %s' % model_type)
        print('model_name: %s' % model_name)
        print('model_path: %s' % model_path)
        print('model_tag: %s' % model_tag)

        if (os.path.isdir(model_path)):
            compressed_model_package_filename = 'pipeline.tar.gz'

            print("")
            print("Compressing model package '%s' into '%s'." % (model_path, compressed_model_package_filename))
            self.model_package(path_to_model=model_path,
                               package_name=compressed_model_package_filename,
                               filemode='w',
                               compression='gz')
            model_file = compressed_model_package_filename
            upload_key = 'file'
            upload_value = compressed_model_package_filename
        else:
            print("")
            print("Model path must be a directory.  All contents of the directory will be uploaded.")
            return

        full_model_url = "%s/api/%s/model/deploy/%s/%s" % (model_server_url.rstrip('/'), pipeline_api_version, model_type, model_name)

        with open(model_file, 'rb') as fh:
            files = [(upload_key, (upload_value, fh))]
            print("")
            print("Deploying model '%s' to '%s'." % (model_file, full_model_url))
            headers = {'Accept': 'application/json'}
            try:
                response = requests.post(url=full_model_url,
                                         headers=headers,
                                         files=files,
                                         timeout=timeout)
                #print("")
                #print(response)

                if response.status_code != requests.codes.ok:
                    if response.text:
                        print("")
                        pprint(response.text)

                if response.status_code == requests.codes.ok:
                    print("")
                    print("Success!")
                    print("")
                    print("curl -X POST -H 'Content-Type: [request_mime_type]' -d '[request_body]' %s" % full_model_url.replace('/deploy/','/predict/'))
                else:
                    response.raise_for_status()
                    print("")
            except requests.exceptions.HTTPError as hte:
                print("Error while deploying model.\nError: '%s'" % str(hte))
                print("")
            except IOError as ioe:
                print("Error while deploying model.\nError: '%s'" % str(ioe))
                print("")

        if (os.path.isdir(model_path)):
            print("")
            #print("Cleaning up compressed model package '%s'..." % model_file)
            #print("")
            os.remove(model_file)

    def _predict(self,
                model_server_url=None,
                model_type=None,
                model_name=None,
                model_tag='master',
                model_test_request_path=None,
                model_request_mime_type='application/json',
                model_response_mime_type='application/json',
                timeout=10):

        pipeline_api_version = self._get_full_config()['pipeline_api_version']

        if not model_server_url:
            try:
                model_server_url = self._get_full_config()['model_server_url']
            except:
                print("")
                print("Model needs to be configured with 'pipeline model-init'.")
                print("")
                return

        if not model_type:
            try:
                model_type = self._get_full_config()['model_type']
            except:
                print("")
                print("Model needs to be configured with 'pipeline model-init'.")
                print("")
                return

        if not model_name:
            try:
                model_name = self._get_full_config()['model_name']
            except:
                print("")
                print("Model needs to be configured with 'pipeline model-init'.")
                print("")
                return

        if not model_tag:
            try:
                model_tag = self._get_full_config()['model_tag']
            except:
                print("")
                print("Model needs to be configured with 'pipeline model-init'.")
                print("")
                return

        if not model_test_request_path:
            try:
                model_test_request_path = self._get_full_config()['model_test_request_path']
            except:
                print("")
                print("Model needs to be configured with 'pipeline model-init'.")
                print("")
                return

        if model_test_request_path:
            model_test_request_path = os.path.expandvars(model_test_request_path)
            model_test_request_path = os.path.expanduser(model_test_request_path)
            model_test_request_path = os.path.abspath(model_test_request_path)

        if not model_request_mime_type:
            try:
                model_request_mime_type = self._get_full_config()['model_request_mime_type']
            except:
                print("")
                print("Model needs to be configured with 'pipeline model-init'.")
                print("")
                return

        if not model_response_mime_type:
            try:
                model_response_mime_type = self._get_full_config()['model_response_mime_type']
            except:
                print("")
                print("Model needs to be configured with 'pipeline model-init'.")
                print("")
                return

        print('model_server_url: %s' % model_server_url)
        print('model_type: %s' % model_type)
        print('model_name: %s' % model_name)
        print('model_tag: %s' % model_tag)
        print('model_test_request_path: %s' % model_test_request_path)
        print('model_request_mime_type: %s' % model_request_mime_type)
        print('model_response_mime_type: %s' % model_response_mime_type)

        full_model_url = "%s/api/%s/model/predict/%s/%s" % (model_server_url.rstrip('/'), pipeline_api_version, model_type, model_name)
        print("")
        print("Predicting with file '%s' using '%s'" % (model_test_request_path, full_model_url))
        print("")

        with open(model_test_request_path, 'rb') as fh:
            model_input_binary = fh.read()

        headers = {'Content-type': model_request_mime_type, 'Accept': model_response_mime_type}
        from datetime import datetime

        begin_time = datetime.now()
        response = requests.post(url=full_model_url,
                                 headers=headers,
                                 data=model_input_binary,
                                 timeout=timeout)
        end_time = datetime.now()

        if response.text:
            print("")
            pprint(response.text)

        if response.status_code == requests.codes.ok:
            print("")
            print("Success!")

        total_time = end_time - begin_time
        print("")
        print("Request time: %s milliseconds" % (total_time.microseconds / 1000))
        print("")

    def model_predict(self,
                      concurrency=1,
                      model_server_url=None,
                      model_type=None,
                      model_name=None,
                      model_tag='master',
                      model_test_request_path=None,
                      model_request_mime_type='application/json',
                      model_response_mime_type='application/json'):

        from concurrent.futures import ThreadPoolExecutor, as_completed

        with ThreadPoolExecutor(max_workers=concurrency) as executor:
            for _ in range(concurrency):
                executor.submit(self._predict(model_server_url,
                                              model_type,
                                              model_name,
                                              model_tag,
                                              model_test_request_path,
                                              model_request_mime_type,
                                              model_response_mime_type))

    def cluster_view(self):
        pipeline_api_version = self._get_full_config()['pipeline_api_version']

        try:
            kube_cluster_context = self._get_full_config()['kube_cluster_context']
            kube_namespace = self._get_full_config()['kube_namespace']
        except:
            print("")
            print("Cluster needs to be configured with 'pipeline cluster-init'.")
            print("")
            return

        kubeconfig.load_kube_config()
        kubeclient_v1 = kubeclient.CoreV1Api()
        kubeclient_v1_beta1 = kubeclient.ExtensionsV1beta1Api()

        print("")
        print("Available Services")
        print("******************")
        self._get_all_available_apps()

        print("")
        print("DNS Internal (Public)")
        print("*********************")
        with warnings.catch_warnings():
            warnings.simplefilter("ignore")
            response = kubeclient_v1.list_service_for_all_namespaces(watch=False,
                                                                     pretty=True)
            services = response.items
            for svc in services:
                ingress = 'Not public'
                if svc.status.load_balancer.ingress and len(svc.status.load_balancer.ingress) > 0:
                    if (svc.status.load_balancer.ingress[0].hostname):
                        ingress = svc.status.load_balancer.ingress[0].hostname
                    if (svc.status.load_balancer.ingress[0].ip):
                        ingress = svc.status.load_balancer.ingress[0].ip
                print("%s (%s)" % (svc.metadata.name, ingress))

        print("")
        print("Containers (Pods)")
        print("****************")
        with warnings.catch_warnings():
            warnings.simplefilter("ignore")
            response = kubeclient_v1.list_pod_for_all_namespaces(watch=False,
                                                                 pretty=True)
            pods = response.items
            for pod in pods:
                print("%s (%s)" % (pod.metadata.name, pod.status.phase))

        print("")
        print("Nodes")
        print("*****")
        self._get_all_nodes()

        print("")
        print("Config")
        print("******")
        self.config()
        print("")

    def _get_pod_by_app_name(self,
                             app_name):

        pipeline_api_version = self._get_full_config()['pipeline_api_version']
        try:
            kube_cluster_context = self._get_full_config()['kube_cluster_context']
            kube_namespace = self._get_full_config()['kube_namespace']
        except:
            print("")
            print("Cluster needs to be configured with 'pipeline cluster-init'.")
            print("")
            return

        kubeconfig.load_kube_config()
        kubeclient_v1 = kubeclient.CoreV1Api()
        kubeclient_v1_beta1 = kubeclient.ExtensionsV1beta1Api()

        found = False
        with warnings.catch_warnings():
            warnings.simplefilter("ignore")
            response = kubeclient_v1.list_pod_for_all_namespaces(watch=False, pretty=True)
            pods = response.items
            for pod in pods:
                if app_name in pod.metadata.name:
                    found = True
                    break
        if found:
            return pod
        else:
            return None

    def _get_svc_by_app_name(self,
                             app_name):

        pipeline_api_version = self._get_full_config()['pipeline_api_version']
        try:
            kube_cluster_context = self._get_full_config()['kube_cluster_context']
            kube_namespace = self._get_full_config()['kube_namespace']
        except:
            print("")
            print("Cluster needs to be configured with 'pipeline cluster-init'.")
            print("")
            return

        kubeconfig.load_kube_config()
        kubeclient_v1 = kubeclient.CoreV1Api()
        kubeclient_v1_beta1 = kubeclient.ExtensionsV1beta1Api()

        found = False
        with warnings.catch_warnings():
            warnings.simplefilter("ignore")
            response = kubeclient_v1.list_service_for_all_namespaces(watch=False,
                                                                     pretty=True)
            services = response.items
            for svc in services:
                if app_name in svc.metadata.name:
                    found = True
                    break
        if found:
            return svc
        else:
            return None

    def _get_all_available_apps(self):
        pipeline_api_version = self._get_full_config()['pipeline_api_version']

        available_apps = list(PipelineCli._kube_deploy_registry.keys())
        available_apps.sort()
        for app in available_apps:
            print(app)

    def node_list(self):
        pipeline_api_version = self._get_full_config()['pipeline_api_version']

        try:
            kube_cluster_context = self._get_full_config()['kube_cluster_context']
            kube_namespace = self._get_full_config()['kube_namespace']
        except:
            print("")
            print("Cluster needs to be configured with 'pipeline cluster-init'.")
            print("")
            return

        print("")
        print("Nodes")
        print("*****")
        self._get_all_nodes()
        print("")

    def _get_all_nodes(self):
        pipeline_api_version = self._get_full_config()['pipeline_api_version']

        try:
            kube_cluster_context = self._get_full_config()['kube_cluster_context']
            kube_namespace = self._get_full_config()['kube_namespace']
        except:
            print("")
            print("Cluster needs to be configured with 'pipeline cluster-init'.")
            print("")
            return

        kubeconfig.load_kube_config()
        kubeclient_v1 = kubeclient.CoreV1Api()
        kubeclient_v1_beta1 = kubeclient.ExtensionsV1beta1Api()

        with warnings.catch_warnings():
            warnings.simplefilter("ignore")
            response = kubeclient_v1.list_node(watch=False, pretty=True)
            nodes = response.items
            for node in nodes:
                print("%s" % node.metadata.labels['kubernetes.io/hostname'])

    def services(self):
        self.cluster_view()

    def service_shell(self,
              app_name):

        self.service_connect(app_name)

    def service_connect(self,
                app_name):

        pipeline_api_version = self._get_full_config()['pipeline_api_version']

        try:
            kube_cluster_context = self._get_full_config()['kube_cluster_context']
            kube_namespace = self._get_full_config()['kube_namespace']
        except:
            print("")
            print("Cluster needs to be configured with 'pipeline cluster-init'.")
            print("")
            return

        kubeconfig.load_kube_config()
        kubeclient_v1 = kubeclient.CoreV1Api()
        kubeclient_v1_beta1 = kubeclient.ExtensionsV1beta1Api()

        with warnings.catch_warnings():
            warnings.simplefilter("ignore")
            response = kubeclient_v1.list_pod_for_all_namespaces(watch=False,
                                                                 pretty=True)
            pods = response.items
            for pod in pods:
                if app_name in pod.metadata.name:
                    break
            print("")
            print("Connecting to '%s'" % pod.metadata.name)
            print("")
            subprocess.call("kubectl exec -it %s bash" % pod.metadata.name, shell=True)
        print("")

    def service_logs(self,
                     app_name):

        pipeline_api_version = self._get_full_config()['pipeline_api_version']

        try:
            kube_cluster_context = self._get_full_config()['kube_cluster_context']
            kube_namespace = self._get_full_config()['kube_namespace']
        except:
            print("")
            print("Cluster needs to be configured with 'pipeline cluster-init'.")
            print("")
            return

        kubeconfig.load_kube_config()
        kubeclient_v1 = kubeclient.CoreV1Api()
        kubeclient_v1_beta1 = kubeclient.ExtensionsV1beta1Api()

        with warnings.catch_warnings():
            warnings.simplefilter("ignore")
            response = kubeclient_v1.list_pod_for_all_namespaces(watch=False,
                                                                 pretty=True)
            found = False
            pods = response.items
            for pod in pods:
                if app_name in pod.metadata.name:
                    found = True
                    break
            if found:
                print("")
                print("Tailing logs on '%s'." % pod.metadata.name)
                print("")
                subprocess.call("kubectl logs -f %s" % pod.metadata.name, shell=True)
                print("")
            else:
                print("")
                print("App '%s' is not running." % app_name)
                print("")

    def service_scale(self,
                      app_name,
                      replicas):

        pipeline_api_version = self._get_full_config()['pipeline_api_version']

        try:
            kube_cluster_context = self._get_full_config()['kube_cluster_context']
            kube_namespace = self._get_full_config()['kube_namespace']
        except:
            print("")
            print("Cluster needs to be configured with 'pipeline cluster-init'.")
            print("")
            return

        kubeconfig.load_kube_config()
        kubeclient_v1 = kubeclient.CoreV1Api()
        kubeclient_v1_beta1 = kubeclient.ExtensionsV1beta1Api()

        with warnings.catch_warnings():
            warnings.simplefilter("ignore")
            response = kubeclient_v1_beta1.list_deployment_for_all_namespaces(watch=False,
                                                                              pretty=True)
            found = False
            deployments = response.items
            for deploy in deployments:
                if app_name in deploy.metadata.name:
                    found = True
                    break
            if found:
                print("")
                print("Scaling app '%s' to '%s' replicas." % (deploy.metadata.name, replicas))
                print("")
                cmd = "kubectl scale deploy %s --replicas=%s" % (deploy.metadata.name, replicas)
                print("Running '%s'." % cmd)
                print("")
                subprocess.call(cmd, shell=True)
                print("")
                print("Check status with 'pipeline cluster'.")
                print("")
            else:
                print("")
                print("App '%s' is not running." % app_name)
                print("")

    def volume_list(self):

        pipeline_api_version = self._get_full_config()['pipeline_api_version']

        try:
            kube_cluster_context = self._get_full_config()['kube_cluster_context']
            kube_namespace = self._get_full_config()['kube_namespace']
        except:
            print("")
            print("Cluster needs to be configured with 'pipeline cluster-init'.")
            print("")
            return

        print("")
        print("Volumes")
        print("*******")
        self._get_all_volumes()

        print("")
        print("Volume Claims")
        print("*************")
        self._get_all_volume_claims()
        print("")

    def _get_all_volumes(self):

        pipeline_api_version = self._get_full_config()['pipeline_api_version']

        try:
            kube_cluster_context = self._get_full_config()['kube_cluster_context']
            kube_namespace = self._get_full_config()['kube_namespace']
        except:
            print("")
            print("Cluster needs to be configured with 'pipeline cluster-init'.")
            print("")
            return

        kubeconfig.load_kube_config()
        kubeclient_v1 = kubeclient.CoreV1Api()
        kubeclient_v1_beta1 = kubeclient.ExtensionsV1beta1Api()

        with warnings.catch_warnings():
            warnings.simplefilter("ignore")
            response = kubeclient_v1.list_persistent_volume(watch=False,
                                                            pretty=True)
            claims = response.items
            for claim in claims:
                print("%s" % (claim.metadata.name))
        print("")

    def _get_all_volume_claims(self):

        pipeline_api_version = self._get_full_config()['pipeline_api_version']

        try:
            kube_cluster_context = self._get_full_config()['kube_cluster_context']
            kube_namespace = self._get_full_config()['kube_namespace']
        except:
            print("")
            print("Cluster needs to be configured with 'pipeline cluster-init'.")
            print("")
            return

        kubeconfig.load_kube_config()
        kubeclient_v1 = kubeclient.CoreV1Api()
        kubeclient_v1_beta1 = kubeclient.ExtensionsV1beta1Api()

        with warnings.catch_warnings():
            warnings.simplefilter("ignore")
            response = kubeclient_v1.list_persistent_volume_claim_for_all_namespaces(watch=False,
                                                                                pretty=True)
            claims = response.items
            for claim in claims:
                print("%s" % (claim.metadata.name))
        print("")

    def _get_config_yamls(self,
                          app_name):
        return []

    def _get_secret_yamls(self,
                          app_name):
        return []

    def _get_deploy_yamls(self,
                          app_name):
        try:
            (deploy_yamls, dependencies) = PipelineCli._kube_deploy_registry[app_name]
        except:
            dependencies = []
            deploy_yamls = []

        if len(dependencies) > 0:
            for dependency in dependencies:
                deploy_yamls = deploy_yamls + self._get_deploy_yamls(dependency)
        return deploy_yamls

    def _get_svc_yamls(self,
                       app_name):
        try:
            (svc_yamls, dependencies) = PipelineCli._kube_svc_registry[app_name]
        except:
            dependencies = []
            svc_yamls = []

        if len(dependencies) > 0:
            for dependency in dependencies:
                svc_yamls = svc_yamls + self._get_svc_yamls(dependency)
        return svc_yamls

    def service_start(self,
                      app_name):

        pipeline_api_version = self._get_full_config()['pipeline_api_version']

        try:
            kube_cluster_context = self._get_full_config()['kube_cluster_context']
            kube_namespace = self._get_full_config()['kube_namespace']
        except:
            print("")
            print("Cluster needs to be configured with 'pipeline cluster-init'.")
            print("")
            return

        try:
            pipeline_git_home = self._get_full_config()['pipeline_git_home']

            if 'http:' in pipeline_git_home or 'https:' in pipeline_git_home:
                pass
            else:
                pipeline_git_home = os.path.expandvars(pipeline_git_home)
                pipeline_git_home = os.path.expanduser(pipeline_git_home)
                pipeline_git_home = os.path.abspath(pipeline_git_home)

            pipeline_git_version = self._get_full_config()['pipeline_git_version']
        except:
            print("")
            print("PipelineIO needs to be configured with 'pipeline init-pipeline'.")
            print("")
            return

        config_yaml_filenames = []
        secret_yaml_filenames = []
        deploy_yaml_filenames = []
        svc_yaml_filenames = []

        config_yaml_filenames = config_yaml_filenames + self._get_config_yamls(app_name)
        secret_yaml_filenames = secret_yaml_filenames + self._get_secret_yamls(app_name)
        deploy_yaml_filenames = deploy_yaml_filenames + self._get_deploy_yamls(app_name)
        print("Using '%s'" % deploy_yaml_filenames)

        svc_yaml_filenames = svc_yaml_filenames + self._get_svc_yamls(app_name)
        print(svc_yaml_filenames)
        print("Using '%s'" % svc_yaml_filenames)

        kubeconfig.load_kube_config()
        kubeclient_v1 = kubeclient.CoreV1Api()
        kubeclient_v1_beta1 = kubeclient.ExtensionsV1beta1Api()

        #for config_yaml_filename in config_yaml_filenames:
            # TODO
        #    return

        #for secret_yaml_filename in secret_yaml_filenames:
            # TODO
        #    return
        print("")
        print("Starting app '%s'." % app_name)
        print("")
        print("Kubernetes Deployments:")
        print("")
        for deploy_yaml_filename in deploy_yaml_filenames:
            try:
                if 'http:' in deploy_yaml_filename or 'https:' in deploy_yaml_filename:
                    deploy_yaml_filename = deploy_yaml_filename.replace('github.com', 'raw.githubusercontent.com')
                    cmd = "kubectl create -f %s --record" % deploy_yaml_filename
                    print("Running '%s'." % cmd)
                    print("")
                    subprocess.call(cmd, shell=True)
                    print("")
                else:
                    if 'http:' in pipeline_git_home or 'https:' in pipeline_git_home:
                        pipeline_git_home = pipeline_git_home.replace('github.com', 'raw.githubusercontent.com')
                        cmd = "kubectl create -f %s/%s/%s --record" % (pipeline_git_home.rstrip('/'), pipeline_git_version, deploy_yaml_filename)
                        print("Running '%s'." % cmd)
                        print("")
                        subprocess.call(cmd, shell=True)
                        print("")
                    else:
                        with open(os.path.join(pipeline_git_home, deploy_yaml_filename)) as fh:
                            deploy_yaml = yaml.load(fh)
                            with warnings.catch_warnings():
                                warnings.simplefilter("ignore")
                                response = kubeclient_v1_beta1.create_namespaced_deployment(body=deploy_yaml,
                                                                                namespace=kube_namespace,
                                                                                pretty=True)
                                pprint(response)
            except ApiException as e:
                print("")
                print("App '%s' did not start properly.\n%s" % (deploy_yaml_filename, str(e)))
                print("")

        print("")
        print("Kubernetes Services:")
        print("")
        for svc_yaml_filename in svc_yaml_filenames:
            try:
                if 'http:' in svc_yaml_filename or 'https:' in svc_yaml_filename:
                    svc_yaml_filename = svc_yaml_filename.replace('github.com', 'raw.githubusercontent.com')
                    cmd = "kubectl create -f %s --record" % svc_yaml_filename
                    print("Running '%s'." % cmd)
                    print("")
                    subprocess.call(cmd, shell=True)
                    print("")
                else:
                    if 'http:' in pipeline_git_home or 'https:' in pipeline_git_home:
                        pipeline_git_home = pipeline_git_home.replace('github.com', 'raw.githubusercontent.com')
                        cmd = "kubectl create -f %s/%s/%s --record" % (pipeline_git_home.rstrip('/'), pipeline_git_version, svc_yaml_filename)
                        print("Running '%s'." % cmd)
                        print("")
                        subprocess.call(cmd, shell=True)
                        print("")
                    else:
                        with open(os.path.join(pipeline_git_home, svc_yaml_filename)) as fh:
                            svc_yaml = yaml.load(fh)
                            with warnings.catch_warnings():
                                warnings.simplefilter("ignore")
                                response = kubeclient_v1.create_namespaced_service(body=svc_yaml,
                                                                                namespace=kube_namespace,
                                                                                pretty=True)
                                pprint(response)
            except ApiException as e:
                print("")
                print("App '%s' did not start properly.\n%s" % (svc_yaml_filename, str(e)))
                print("")

        print("")
        print("Ignore any 'Already Exists' errors.  These are OK.")
        print("")
        print("Check app status with 'pipeline apps' or 'pipeline cluster-init'.")
        print("")

    def service_kill(self,
                     app_name):

        self.service_stop(app_name)

    def service_delete(self,
                       app_name):

        self.service_stop(app_name)

    def service_stop(self,
                     app_name):

        pipeline_api_version = self._get_full_config()['pipeline_api_version']

        try:
            kube_cluster_context = self._get_full_config()['kube_cluster_context']
            kube_namespace = self._get_full_config()['kube_namespace']
        except:
            print("")
            print("Cluster needs to be configured with 'pipeline cluster-init'.")
            print("")
            return

        kubeconfig.load_kube_config()
        kubeclient_v1 = kubeclient.CoreV1Api()
        kubeclient_v1_beta1 = kubeclient.ExtensionsV1beta1Api()

        with warnings.catch_warnings():
            warnings.simplefilter("ignore")
            response = kubeclient_v1_beta1.list_deployment_for_all_namespaces(watch=False, pretty=True)
            found = False
            deployments = response.items
            for deploy in deployments:
                if app_name in deploy.metadata.name:
                    found = True
                    break
            if found:
                print("")
                print("Stopping app '%s'." % deploy.metadata.name)
                print("")
                cmd = "kubectl delete deploy %s" % deploy.metadata.name
                print("Running '%s'." % cmd)
                print("")
                subprocess.call(cmd, shell=True)
                print("")
                print("Check app status with 'pipeline apps' or 'pipeline cluster'.")
                print("")
            else:
                print("")
                print("App '%s' is not running." % app_name)
                print("")

def main():
    fire.Fire(PipelineCli)

if __name__ == '__main__':
    main()


text:
<?php

return [
    'title' => 'Home page',
    'header' => 'IIS Euganeo',
    'text' => 'Benvenuto nel sito dedicato agli studenti dell\'IIS Euganeo!',
    'inspire' => 'Vivi l\'evoluzione tecnologica del tuo Istituto!!!',
];

redpajama_set_name: RedPajamaGithub


text:
<link rel="import" href="../../bower_components/polymer/polymer.html">
<link rel="import" href="../../bower_components/core-icons/core-icons.html">

<polymer-element name="star-rate" attributes="stars value readOnly">

    <template>

            <template repeat="{{n in currentStars}}" >

                <core-icon icon="{{n <= value ? 'star' : 'star-outline'}}"  hidden?="{{(n-value)==0.5}}" data-item="{{n}}" on-mouseout="{{onMouseout}}" on-click="{{setvalue}}">

                </core-icon>

                <core-icon icon="star-half" hidden?="{{value!=n-0.5}}" on-click="{{setvalue}}" data-item="{{n-0.5}}" on-mouseout="{{onMouseout}}">

                </core-icon>

            </template>

    </template>

</polymer-element>


text:
<bill session="115" type="h" number="3260" updated="2017-09-11T02:54:50Z">
  <state datetime="2017-07-14">REFERRED</state>
  <status>
    <introduced datetime="2017-07-14"/>
  </status>
  <introduced datetime="2017-07-14"/>
  <titles>
    <title type="short" as="introduced">Airline Passenger Protection Act of 2017</title>
    <title type="short" as="introduced">Airline Passenger Protection Act of 2017</title>
    <title type="official" as="introduced">To provide passengers in air transportation with certain rights.</title>
    <title type="display">Airline Passenger Protection Act of 2017</title>
  </titles>
  <sponsor bioguide_id="T000460"/>
  <cosponsors/>
  <actions>
    <action datetime="2017-07-14">
      <text>Introduced in House</text>
    </action>
    <action datetime="2017-07-14" state="REFERRED">
      <text>Referred to the House Committee on Transportation and Infrastructure.</text>
    </action>
    <action datetime="2017-07-15">
      <text>Referred to the Subcommittee on Aviation.</text>
    </action>
  </actions>
  <committees>
    <committee subcommittee="" code="HSPW" name="House Transportation and Infrastructure" activity="Referral"/>
    <committee subcommittee="Aviation" code="HSPW05" name="House Transportation and Infrastructure" activity="Referral"/>
  </committees>
  <relatedbills/>
  <subjects>
    <term name="Transportation and public works"/>
  </subjects>
  <amendments/>
  <committee-reports/>
</bill>


text:
<meta charset="UTF-8">
<title>KettleScreen.dispose - api</title>
<link rel="stylesheet" href="..\..\..\style.css">

api / io.github.restioson.kettle.api.screen / KettleScreen / dispose

dispose

open fun dispose(): Unit (source)

Dispose of assets internally used by screen


text:
title: "context update"
description: "The context update command description and usage"
keywords: "context, update"
---

# context update

```markdown
Usage:  docker context update [OPTIONS] CONTEXT

Update a context

Docker endpoint config:

NAME                DESCRIPTION
from                Copy Docker endpoint configuration from an existing context
host                Docker endpoint on which to connect
ca                  Trust certs signed only by this CA
cert                Path to TLS certificate file
key                 Path to TLS key file
skip-tls-verify     Skip TLS certificate validation

Example:

$ docker context update my-context --description "some description" --docker "host=tcp://myserver:2376,ca=~/ca-file,cert=~/cert-file,key=~/key-file"

Options:
      --description string                  Description of the context
      --docker stringToString               set the docker endpoint
                                            (default [])
```

## Description

Updates an existing `context`.
See [context create](context_create.md).

## Examples

### Update an existing context

```console
$ docker context update \
    --description "some description" \
    --docker "host=tcp://myserver:2376,ca=~/ca-file,cert=~/cert-file,key=~/key-file" \
    my-context
```


text:
package ru.HomeworkAdress;

public class ContactData {
    private final String firstname;
    private final String lastname;
    private final String nickname;
    private final String company;
    private final String home;

    public ContactData(String firstname, String lastname, String nickname, String company, String home) {
        this.firstname = firstname;
        this.lastname = lastname;
        this.nickname = nickname;
        this.company = company;
        this.home = home;
    }

    public String getFirstname() {
        return firstname;
    }

    public String getLastname() {
        return lastname;
    }

    public String getNickname() {
        return nickname;
    }

    public String getCompany() {
        return company;
    }

    public String getHome() {
        return home;
    }
}


text:
class LoginClient : public Client {
    public:
        LoginClient(std::unique_ptr<Core::INetwork> sock);
        virtual ~LoginClient() = default;

        uint32_t sessionId() const;

        std::string ip() const;

        uint16_t port() const;

    private:
        uint32_t sessionId_;
        std::string ip_;
        uint16_t port_;
        RoseCommon::PacketDispatcher<> dispatcher;

        virtual bool handlePacket(uint8_t *buffer) override;

        template <typename T>
        void register_dispatcher(std::function<void(const T&)>&& func) {
            dispatcher.add_dispatcher(T::PACKET_ID, std::move(func));
        }

        void accept_reply(const RoseCommon::Packet::SrvAcceptReply&);
        void login_reply(const RoseCommon::Packet::SrvLoginReply& reply);
        void channel_list_reply(const RoseCommon::Packet::SrvChannelListReply& reply);
        void srv_select_reply(const RoseCommon::Packet::SrvSrvSelectReply& reply);
};


text:
`Sequencer` is a jQuery-dependent Javascript object used to edit the content of multiple HTML elements in reference to a single timeline.

The `Sequencer` is best understood by example. [Go to this JSFiddle](http://jsfiddle.net/zyrolasting/7xgqc694/2/) and watch its execution on the following markup:

**HTML:**
```
<p data-seq-id="A">X</p>

<div class="hidden">
    <div data-sequence="A">
        <div data-seq-index="0">X</div>
        <div data-seq-index="1">Y</div>
        <div data-seq-index="2">Z</div>
    </div>
</div>
```

**Javascript:**
```
seq = new Sequencer(['A'], 1000);
seq.advance();
seq.play();
```

The paragraph contains content for a sequence titled `A`. The sequence data is contained in the hidden `div` below the paragraph. In this simple example, the paragraph reads "X," "Y" and "Z," and each letter stays visible for one second.

Each letter is read from the div with the attribute `data-sequence="A"` in the order specified by `data-seq-index` (starting from zero). `data-seq-index` defines the frames in which the content is meant to appear. So, if you swapped the `data-seq-index` for the elements containing "X" and "Y," "X" would appear first and "Y" would appear second.

## So what happened?

Let's break down the example code.

Sequence markup is arbitrary HTML identified by the `data-sequence` attribute. You can name the sequence anything you want, so long as its a legal HTML attribute value. Each "frame" of the sequence is identified by `data-seq-index` in children containers, and those must be integer values.

All sequence markup must be hidden.

**HTML:**
```
<div class="hidden">
    <div data-sequence="A">
        <div data-seq-index="0">X</div>
        <div data-seq-index="1">Y</div>
        <div data-seq-index="2">Z</div>
    </div>
</div>
```

To use the sequence, you need an HTML element to which you can output the current frame.

That's where this guy comes in.

```
<p data-seq-id="A"></p>
```

This element holds the current frame of the sequence. Notice that it uses `data-seq-id`, and its value `"A"` matches the `"A"` in the `data-sequence` attribute containing all of the frames. This is how you associate the two.

This brings us to the Javascript:

```
seq = new Sequencer(['A'], 1000);
seq.advance();
seq.play();
```

The `Sequencer` constructor takes three parameters, but only two are shown here. First, it takes an array of strings that identify sequences. Since we only have one sequence, namely `A`, we pass an array with only that value. The second parameter is the delay between frames in milliseconds.

Frames are zero-based, which means Frame 0 is the first frame in the sequence. When you instantiate a `Sequencer`, it's internal frame is set to `-1`. This is because the `Sequencer` does not try to mess with your target HTML container by setting it to Frame 0 until you explicitly tell it to. `seq.advance()` advances one frame, which puts the `Sequencer` at frame 0 and puts the `X` in the `<p>` element.

`seq.play()` sets the sequencer to advance frames according to the delay passed in the constructor.

You can use `seq.stop()` to stop playback.

# Multiple Sequences

You can prepare multiple sequences. See [this fiddle](http://jsfiddle.net/zyrolasting/7xgqc694/3/).

```
<p data-seq-id="A">X</p>
<p data-seq-id="B">Q</p>
<p data-seq-id="C">T</p>

<div class="hidden">
    <div data-sequence="A">
        <div data-seq-index="0">X</div>
        <div data-seq-index="1">Y</div>
        <div data-seq-index="2">Z</div>
    </div>
    <div data-sequence="B">
        <div data-seq-index="0">Q</div>
        <div data-seq-index="1">R</div>
        <div data-seq-index="2">S</div>
    </div>
    <div data-sequence="C">
        <div data-seq-index="0 3">T</div>
        <div data-seq-index="1 2">U</div>
    </div>
</div>
```

The same Javascript applies.

```
seq = new Sequencer(['A', 'B', 'C', 'X'], 1000);
seq.play();
```

There are two interesting things about this version. One, we pass a sequence `X` that does not exist. The Sequencer will notice and will simply not try to play anything by that name.

Second, look at the `data-seq-index` values in sequence `C`. Again, `data-seq-index` **defines the frames in which the content is meant to appear.** The content `T` appears in frames 0 and 3, and U appears in frames 1 and 2.

## Callbacks

[Here's another example fiddle](http://jsfiddle.net/zyrolasting/7xgqc694/4/)

You can define callbacks when `Sequencer` reaches certain frames, or when a specific sequence is updated.

```

var callbackMap = {
    'A': function(container, frame) {
        var r = Math.floor(Math.random() * 255);
        var g = Math.floor(Math.random() * 255);
        var b = Math.floor(Math.random() * 255);

        container.css('background-color', 'rgb(' + r + ',' + g + ',' + b + ')');
    },

    'frame4': function() {
         alert('on frame 4');
    }
};

seq = new Sequencer(['A'], 1000, callbackMap);
seq.play();
```

In this example, the sequence `A` is associated with a callback that sets a random background color on the container (Note that the container is the target where frames appear, and that it is a jQuery object).

You can also set callbacks for specific frames, regardless of sequence. Notice that in the fiddle example, sequence `A` visually only has frames containing `X`, `Y` and `Z`. These are frames 0, 1 and 2, respectively. But the sequencer will **continue to play**, and you will eventually see the frame 4 callback get called.

This is an important fact: `Sequencer` will continue playing until `seq.stop()` is called.


text:
<!DOCTYPE html>

<link rel="import" href="/base/base.html">
<link rel="import" href="/ui/analysis/analysis_sub_view.html">
<link rel="import" href="/ui/analysis/selection_summary_table.html">
<link rel="import" href="/ui/analysis/multi_event_summary_table.html">
<link rel="import" href="/ui/analysis/multi_event_details_table.html">
<link rel="import" href="/ui/base/ui.html">
<link rel="import" href="/ui/base/table.html">

<polymer-element name="tr-ui-a-multi-event-sub-view"
    extends="tr-ui-a-sub-view">
  <template>

  </template>

</polymer-element>


text:
package com.facebook.litho.testing.specmodels;

import static com.facebook.litho.testing.assertj.LegacyLithoAssertions.assertThat;
import static com.facebook.litho.testing.assertj.SubComponentDeepExtractor.deepSubComponentWith;
import static org.hamcrest.CoreMatchers.is;
import static org.junit.Assume.assumeThat;

import com.facebook.litho.ComponentContext;
import com.facebook.litho.config.ComponentsConfiguration;
import com.facebook.litho.testing.LegacyLithoViewRule;
import com.facebook.litho.testing.subcomponents.InspectableComponent;
import com.facebook.litho.testing.testrunner.LithoTestRunner;
import com.facebook.litho.widget.TestText;
import com.facebook.litho.widget.Text;
import org.assertj.core.api.Condition;
import org.hamcrest.CustomTypeSafeMatcher;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.robolectric.annotation.LooperMode;

@LooperMode(LooperMode.Mode.LEGACY)
@RunWith(LithoTestRunner.class)
public class InjectPropMatcherGenerationTest {
  @Rule public LegacyLithoViewRule mLegacyLithoViewRule = new LegacyLithoViewRule();

  @Before
  public void setUp() {
    assumeThat(
        "These tests can only be run in debug mode.",
        ComponentsConfiguration.IS_INTERNAL_BUILD,
        is(true));
  }

  @Test
  public void testInjectPropMatching() {
    final ComponentContext c = mLegacyLithoViewRule.getContext();
    final MyInjectProp component =
        new MyInjectProp(c.getAndroidContext()).create(c).normalString("normal string").build();
    // Faking some DI mechanism doing its thing.
    component.injectedString = "injected string";
    component.injectedKettle = new MyInjectPropSpec.Kettle(92f);
    component.injectedComponent = Text.create(c).text("injected text").build();

    final Condition<InspectableComponent> matcher =
        TestMyInjectProp.matcher(c)
            .normalString("normal string")
            .injectedString("injected string")
            .injectedKettle(
                new CustomTypeSafeMatcher<MyInjectPropSpec.Kettle>("matches temperature") {
                  @Override
                  protected boolean matchesSafely(MyInjectPropSpec.Kettle item) {
                    return Math.abs(item.temperatureCelsius - 92f) < 0.1;
                  }
                })
            .injectedComponent(TestText.matcher(c).text("injected text").build())
            .build();

    assertThat(c, component).has(deepSubComponentWith(c, matcher));
  }
}


text:
package com.cwenao.trying.graph;

import java.util.Stack;

/**
 * @author cwenao
 * @version $Id DepthFirstSearchTrying.java, v 0.1 2017-10-11 13:33 cwenao Exp $$
 */
public class DepthFirstSearchTrying {

    private boolean[] marked;
    private GraphTrying<Integer> graphTrying;
    private int v;

    public DepthFirstSearchTrying(GraphTrying graphTrying, int v) {
        this.graphTrying = graphTrying;
        marked = new boolean[graphTrying.getV()];
        this.v = v;
    }

    public void dfsWithStack(int v) {
        Stack<Integer> dfsStack = new Stack<>();
        dfsStack.push(v);
        marked[v] = true;
        while (!dfsStack.isEmpty()) {
            int x = dfsStack.peek();
            dfsStack.pop();

            System.out.println("this is the x: " + x);
            for (Integer w : graphTrying.adj(x)) {
                if (!marked[w]) {
                    System.out.println("this is the w: " + w);
                    dfsStack.push(w);
                    marked[w] = true;
                }
            }
        }
    }

    public static void main(String[] args) {
        GraphTrying<Integer> graphTrying = new GraphTrying<>(7);
        graphTrying.addEdge(0, 1);
        graphTrying.addEdge(0, 2);
        graphTrying.addEdge(1, 4);
        graphTrying.addEdge(2, 3);
        graphTrying.addEdge(4, 6);

        DepthFirstSearchTrying depthFirstSearchTrying = new DepthFirstSearchTrying(graphTrying, 0);
        depthFirstSearchTrying.dfsWithStack(0);

    }
}


text:
package stroom.legacy.model_6_1;

import java.util.Date;

/**
 *

 * Class that represents a period. May have null upper or lower bounds to
 * indicate before or after a time rather than between 2 times.
 *

 *

 *

 * The upper bound is not part of the period. E.g. 1/1/2001 to 1/1/2002 does not
 * include 1/1/2002.
 *

 */
@Deprecated
public class Period extends Range<Long> {
    private static final int N3 = 3;

    private static final long serialVersionUID = -7978314234943698113L;
    private static final long MS_IN_SECOND = 1000;
    private static final long MS_IN_MINUTE = 1000 * 60;
    private static final long MS_IN_HOUR = 1000 * 60 * 60;
    private static final long MS_IN_DAY = 1000 * 60 * 60 * 24;

    public Period() {
        // Default constructor necessary for GWT serialisation.
    }

    public Period(final Long fromMs, final Long toMs) {
        super(fromMs, toMs);
    }

    public static final Period clone(Period period) {
        if (period == null) {
            return null;
        }
        return new Period(period.getFromMs(), period.getToMs());
    }

    /**
     * Create a period just covering 1 ms.
     */
    public static final Period createMsPeriod(final long fromMs) {
        return new Period(fromMs, fromMs + 1);
    }

    /**
     * Create a period just covering 1 ms.
     */
    public static final Period createNullPeriod() {
        Period period = new Period();
        period.setMatchNull(true);
        return period;
    }

    private static String zeroPad(final int amount, final String in) {
        final int left = amount - in.length();
        final StringBuilder out = new StringBuilder();
        for (int i = 0; i < left; i++) {
            out.append("0");
        }
        out.append(in);
        return out.toString();
    }

    public Period doublePeriod() {
        if (!isBounded()) {
            throw new RuntimeException("Cannot double unbounded period.");
        }

        long duration = getTo() - getFrom();
        long half = duration / 2;
        return new Period(getFrom() - half, getTo() + half);
    }

    /**
     * @return whole hours in this period
     */
    public Long getHoursInPeriod() {
        if (isBounded()) {
            long duration = getTo() - getFrom();
            return duration / MS_IN_HOUR;
        }
        return null;
    }

    public int getPrecision(int pointsRequired) {
        if (!isBounded()) {
            return 0;
        }
        if (pointsRequired == 0) {
            return 0;
        }
        long duration = getTo() - getFrom();

        long scale = duration / pointsRequired;

        return (int) Math.log10(scale);
    }

    /**
     * @return whole days in period
     */
    public Long getDaysInPeriod() {
        if (isBounded()) {
            long duration = getTo() - getFrom();
            long days = (duration / MS_IN_DAY);
            return days;

        }
        return null;
    }

    // Here for XML serialisation.
    public Long getFromMs() {
        return super.getFrom();
    }

    // Here for XML serialisation.
    public void setFromMs(Long from) {
        super.setFrom(from);
    }

    // Here for XML serialisation.
    public Long getToMs() {
        return super.getTo();
    }

    // Here for XML serialisation.
    public void setToMs(Long to) {
        super.setTo(to);
    }

    /**
     * Gets the duration as a user readable string.
     */
    public String getDuration() {
        if (!isBounded()) {
            return null;
        }
        long duration = getTo() - getFrom();
        int hours = (int) (duration / MS_IN_HOUR);
        duration = duration - (hours * MS_IN_HOUR);
        int minutes = (int) (duration / MS_IN_MINUTE);
        duration = duration - (minutes * MS_IN_MINUTE);
        int seconds = (int) (duration / MS_IN_SECOND);
        duration = duration - (seconds * MS_IN_SECOND);

        final StringBuilder sb = new StringBuilder();
        sb.append(zeroPad(2, Integer.toString(hours)));
        sb.append(":");
        sb.append(zeroPad(2, Integer.toString(minutes)));
        sb.append(":");
        sb.append(zeroPad(2, Integer.toString(seconds)));
        sb.append(".");
        sb.append(zeroPad(N3, Long.toString(duration)));

        return sb.toString();
    }

    public Long duration() {
        if (getFrom() != null && getTo() != null) {
            return getTo() - getFrom();
        }
        return null;
    }

    @Override
    public String toString() {
        StringBuilder builder = new StringBuilder();
        builder.append("[");
        builder.append("From: ");
        if (getFrom() == null) {
            builder.append("null");
        } else {
            builder.append(new Date(getFrom()));
        }
        builder.append(", To: ");
        if (getTo() == null) {
            builder.append("null");
        } else {
            builder.append(new Date(getTo()));
        }
        builder.append(", Duration: ");
        builder.append(getDuration());
        builder.append("]");
        return builder.toString();
    }

}


text:
        <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
        <title>W29583_text</title>
        <link rel="stylesheet" type="text/css" href="style.css" />

                «

    <p class="styleSans1.0000<enum PANGO_WEIGHT_NORMAL of type PangoWeight><enum PANGO_STYLE_NORMAL of type PangoStyle>">

    <p class="styleSans12000<enum PANGO_WEIGHT_NORMAL of type PangoWeight><enum PANGO_STYLE_NORMAL of type PangoStyle>">

    <p class="styleSans46.0000<enum PANGO_WEIGHT_NORMAL of type PangoWeight><enum PANGO_STYLE_NORMAL of type PangoStyle>">Sin WI Grade Conn Collaps- Bum Tun-Ion 4.! 13.! P410 8T 1mm 1M1. "3,000 "It. my Poem: f." 1.30 10'
. 0'! 11 111" Mala-up'l'oruuomclflcasom: «marm- Mafia-fl
MparAPISpedflcamm,MmmcasmwmmngluumnWimmmommmemmdmmmm. Recommvaaluasmachmtheummstormfln10p Mummbeummamwuwbmevmm makmgupherealofmecuhq. AflormmhgafmujuwflhmiIWm.mmmmMmhgiuulmmwmm bomm otmuumod triangle (Knot. tome vaiues may modmbolqum. mummmnummmwu neededSeemo madpmaoelmv.

Lola mutations:

    <p class="styleSans6.0000<enum PANGO_WEIGHT_NORMAL of type PangoWeight><enum PANGO_STYLE_NORMAL of type PangoStyle>">n \w,m uvvlwn mun mum wlnmq

Flmllzc w." »» Circuum chm 9 B ~10ppu SW. LDDP Run GRICBL and Run 40-."- Caliper (,XTO don not My M I Inc who) ND BOP and NU In; RDMO.

    <p class="styleSans4.0000<enum PANGO_WEIGHT_NORMAL of type PangoWeight><enum PANGO_STYLE_NORMAL of type PangoStyle>">M It. MW v0.41."
W 4444 um Fauna-nun awn ~WA'I vblL'LMGF-IV'W

    <p class="styleSans93.0000<enum PANGO_WEIGHT_NORMAL of type PangoWeight><enum PANGO_STYLE_NORMAL of type PangoStyle>">
BASIC TRIANG LE
STAMP

    <p class="styleSans5.0000<enum PANGO_WEIGHT_NORMAL of type PangoWeight><enum PANGO_STYLE_NORMAL of type PangoStyle>">Pug-3

    <p class="styleSans5.0000<enum PANGO_WEIGHT_NORMAL of type PangoWeight><enum PANGO_STYLE_NORMAL of type PangoStyle>">Salt" ZlX-lF "mm Pi; (llAZLIfl'ILfl


text:
<?php
class C {
	const a = 'hello from C';
}
class D extends C {
}
class E extends D {
}
class F extends E {
	const a = 'hello from F';
}
class X {
}

$classes = array('C', 'D', 'E', 'F', 'X');
foreach($classes as $class) {
	echo "Constants from class $class: \n";
	$rc = new ReflectionClass($class);
	var_dump($rc->getConstants());
}
?>


text:
export interface IUser {
    id: number;
    username: string;
}