<commit_before>import docker
import os, sys, yaml, copy, string, StringIO
import maestro, template, utils
from requests.exceptions import HTTPError
from .container import Container

class ContainerError(Exception):
  pass

class Service:
  def __init__(self, conf_file=None, environment=None):
    self.log = utils.setupLogging()
    self.containers = {}
    self.templates = {}

    if environment:
      self.load(environment)      
    else:
      if not conf_file.startswith('/'):
        conf_file = os.path.join(os.path.dirname(sys.argv[0]), conf_file)

      data = open(conf_file, 'r')
      self.config = yaml.load(data)
      
    # On load, order templates into the proper startup sequence      
    self.start_order = utils.order(self.config['templates'])

  def get(self, container):
    return self.containers[container]

  def build(self, wait_time=60):
    for tmpl in self.start_order:      
      if not self.config['templates'][tmpl]:
        sys.stderr.write("Error: no configuration found for template: " + tmpl + "\n")
        exit(1)

      config = self.config['templates'][tmpl]

      self._handleRequire(tmpl, wait_time)
      
      # Create the template. The service name and version will be dynamic once the new config format is implemented
      utils.status("Building template %s" % (tmpl))
      tmpl_instance = template.Template(tmpl, config, 'service', '0.1')
      tmpl_instance.build()


      self.templates[tmpl] = tmpl_instance

      # If count is defined in the config then we're launching multiple instances of the same thing
      # and they'll need to be tagged accordingly. Count only applies on build.
      count = tag_name = 1
      if 'count' in config:
        count = tag_name = config['count']  
      
      while count > 0:      
        name = tmpl
        if tag_name > 1:
          name = name + "__" + str(count)

        utils.status("Launching instance of template %s named %s" % (tmpl, name))      
        instance = tmpl_instance.instantiate(name)
        instance.run()

        self.containers[name] = instance
        
        count = count - 1
      
  def destroy(self, timeout=None):
    for container in self.containers:
      self.containers[container].destroy(timeout)     

  def start(self, container=None, wait_time=60):
    # If a container is provided we just start that container
    # TODO: may need an abstraction here to handle names of multi-container groups
    if container:
      self.containers[container].start()  
    else:
      for container in self.start_order:  
        self._handleRequire(container, wait_time)
        
        self.containers[container].start()

  def stop(self, container=None, timeout=None):
    if container:
      self.containers[container].stop(timeout)
    else:
      for container in self.containers:     
        self.containers[container].stop(timeout)

  def load(self, filename='envrionment.yml'):
    self.log.info('Loading environment from: %s', filename)      
    
    with open(filename, 'r') as input_file:
      self.config = yaml.load(input_file)

      for tmpl in self.config['templates']:
        # TODO fix hardcoded service name and version
        self.templates[tmpl] = template.Template(tmpl, self.config['templates'][tmpl], 'service', '0.1')
      
      for container in self.config['containers']:
        self.containers[container] = Container(container, self.config['containers'][container], 
          self.config['containers'][container])
    
  def save(self, filename='environment.yml'):
    self.log.info('Saving environment state to: %s', filename)      
      
    with open(filename, 'w') as output_file:
      output_file.write(self.dump())

  def run(self, template, commandline=None):
    if template in self.templates:
      # TODO: name need to be dynamic here. Need to handle static and temporary cases.
      container = self.templates[template].instantiate(template + "32", commandline)
      container.run()

      # for dynamic runs there  needs to be a way to display the output of the command.

      return container
    else:
      # Should handle arbitrary containers
      raise ContainerError("Unknown template")

  def ps(self):
    columns = "{0:<14}{1:<19}{2:<44}{3:<11}{4:<15}\n" 
    result = columns.format("ID", "NODE", "COMMAND", "STATUS", "PORTS")
    for container in self.containers:
      container_id = self.containers[container].state['container_id']
      
      node_name = (container[:15] + '..') if len(container) > 17 else container

      command = ''
      status = 'Stopped'
      ports = ''
      try:
        state = docker.Client().inspect_container(container_id)
        command = string.join([state['Path']] + state['Args'])
        command = (command[:40] + '..') if len(command) > 42 else command
        p = state['NetworkSettings']['PortMapping']['Tcp']
        
        for port in p:
          if ports:
            ports += ", "
          ports += p[port] + "->" + port 
        if state['State']['Running']:<commit_msg>Fixing error running ps when environment is stopped<commit_after>import docker
import os, sys, yaml, copy, string, StringIO
import maestro, template, utils
from requests.exceptions import HTTPError
from .container import Container

class ContainerError(Exception):
  pass

class Service:
  def __init__(self, conf_file=None, environment=None):
    self.log = utils.setupLogging()
    self.containers = {}
    self.templates = {}

    if environment:
      self.load(environment)      
    else:
      if not conf_file.startswith('/'):
        conf_file = os.path.join(os.path.dirname(sys.argv[0]), conf_file)

      data = open(conf_file, 'r')
      self.config = yaml.load(data)
      
    # On load, order templates into the proper startup sequence      
    self.start_order = utils.order(self.config['templates'])

  def get(self, container):
    return self.containers[container]

  def build(self, wait_time=60):
    for tmpl in self.start_order:      
      if not self.config['templates'][tmpl]:
        sys.stderr.write("Error: no configuration found for template: " + tmpl + "\n")
        exit(1)

      config = self.config['templates'][tmpl]

      self._handleRequire(tmpl, wait_time)
      
      # Create the template. The service name and version will be dynamic once the new config format is implemented
      utils.status("Building template %s" % (tmpl))
      tmpl_instance = template.Template(tmpl, config, 'service', '0.1')
      tmpl_instance.build()


      self.templates[tmpl] = tmpl_instance

      # If count is defined in the config then we're launching multiple instances of the same thing
      # and they'll need to be tagged accordingly. Count only applies on build.
      count = tag_name = 1
      if 'count' in config:
        count = tag_name = config['count']  
      
      while count > 0:      
        name = tmpl
        if tag_name > 1:
          name = name + "__" + str(count)

        utils.status("Launching instance of template %s named %s" % (tmpl, name))      
        instance = tmpl_instance.instantiate(name)
        instance.run()

        self.containers[name] = instance
        
        count = count - 1
      
  def destroy(self, timeout=None):
    for container in self.containers:
      self.containers[container].destroy(timeout)     

  def start(self, container=None, wait_time=60):
    # If a container is provided we just start that container
    # TODO: may need an abstraction here to handle names of multi-container groups
    if container:
      self.containers[container].start()  
    else:
      for container in self.start_order:  
        self._handleRequire(container, wait_time)
        
        self.containers[container].start()

  def stop(self, container=None, timeout=None):
    if container:
      self.containers[container].stop(timeout)
    else:
      for container in self.containers:     
        self.containers[container].stop(timeout)

  def load(self, filename='envrionment.yml'):
    self.log.info('Loading environment from: %s', filename)      
    
    with open(filename, 'r') as input_file:
      self.config = yaml.load(input_file)

      for tmpl in self.config['templates']:
        # TODO fix hardcoded service name and version
        self.templates[tmpl] = template.Template(tmpl, self.config['templates'][tmpl], 'service', '0.1')
      
      for container in self.config['containers']:
        self.containers[container] = Container(container, self.config['containers'][container], 
          self.config['containers'][container])
    
  def save(self, filename='environment.yml'):
    self.log.info('Saving environment state to: %s', filename)      
      
    with open(filename, 'w') as output_file:
      output_file.write(self.dump())

  def run(self, template, commandline=None):
    if template in self.templates:
      # TODO: name need to be dynamic here. Need to handle static and temporary cases.
      container = self.templates[template].instantiate(template + "32", commandline)
      container.run()

      # for dynamic runs there  needs to be a way to display the output of the command.

      return container
    else:
      # Should handle arbitrary containers
      raise ContainerError("Unknown template")

  def ps(self):
    columns = "{0:<14}{1:<19}{2:<44}{3:<11}{4:<15}\n" 
    result = columns.format("ID", "NODE", "COMMAND", "STATUS", "PORTS")
    for container in self.containers:
      container_id = self.containers[container].state['container_id']
      
      node_name = (container[:15] + '..') if len(container) > 17 else container

      command = ''
      status = 'Stopped'
      ports = ''
      try:
        state = docker.Client().inspect_container(container_id)
        command = string.join([state['Path']] + state['Args'])
        command = (command[:40] + '..') if len(command) > 42 else command
        p = []
        if state['NetworkSettings']['PortMapping']:
          p = state['NetworkSettings']['PortMapping']['Tcp']
        
        for port in p:
          if ports:
            ports += ", "
          ports += p[port] + "->" + port 
        if state['State']['Running']:
{'fraction_non_alphanumeric': 0.11659281142294436, 'fraction_numerical': 0.007680945347119645, 'mean_word_length': 2.7684601113172542, 'pattern_counts': {'":': 0, '<': 13, '<?xml version=': 0, '>': 13, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '7204373', 'n_tokens_mistral': 2964, 'n_tokens_neox': 2873, 'n_words': 815}