def generate
      if @yaml.has_key?("version")
        @yaml = @yaml.fetch("services")
      end

      # Generate JSON for our containers.
      containers = @yaml.map do |name, fields|
        # Skip this service if we've been given a list to emit, and
        # this service isn't on the list.
        begin
          mount_points = (fields["volumes"] || []).map do |v|
            host, container, ro = v.split(':')
            {
              "sourceVolume" => path_to_vol_name(host),
              "containerPath" => container,
              "readOnly" => (ro == "ro")
            }
          end

          json = {
            "name" => name,
            "image" => fields.fetch("image"),
            # Default to a tiny guaranteed CPU share.  Currently, 2 is the
            # smallest meaningful value, and various ECS tools will round
            # smaller numbers up.
            "cpu" => fields["cpu_shares"] || 2,
            "memory" => mem_limit_to_mb(fields.fetch("mem_limit")),
            "links" => fields["links"] || [],
            "portMappings" =>
              (fields["ports"] || []).map {|pm| port_mapping(pm) },
            "essential" => true,
            "environment" => environment(fields["environment"] || {}),
            "mountPoints" => mount_points,
            "volumesFrom" => [],
            "dockerLabels" => fields.fetch("labels", {}),
          }
          if fields.has_key?("entrypoint")
            json["entryPoint"] = command_line(fields.fetch("entrypoint"))
          end
          if fields.has_key?("command")
            json["command"] = command_line(fields.fetch("command"))
          end
          if fields.has_key?("privileged")
            json["privileged"] = fields.fetch("privileged")
          end
          if fields.has_key?("ulimits")
            json["ulimits"] = fields.fetch("ulimits").map do |name, limits|
              case limits
              when Hash
                softLimit = limits.fetch("soft")
                hardLimit = limits.fetch("hard")
              else
                softLimit = limits
                hardLimit = limits
              end
              { "name" => name,
                "softLimit" => softLimit,
                "hardLimit" => hardLimit }
            end
          end
          json

        rescue KeyError => e
          # This makes it a lot easier to localize errors a bit.
          raise ContainerKeyError.new("#{e.message} processing container \"#{name}\"")
        end
      end

      # Generate our top-level volume declarations.
      volumes = @yaml.map do |name, fields|
        (fields["volumes"] || []).map {|v| v.split(':')[0] }
      end.flatten.sort.uniq.map do |host_path|
        {
          "name" => path_to_vol_name(host_path),
          "host" => { "sourcePath" => host_path }
        }
      end

      # Return our final JSON.
      {
        "family" => @family,
        "containerDefinitions" => containers,
        "volumes" => volumes
      }
    end
def generate
      if @yaml.has_key?("version")
        @yaml = @yaml.fetch("services")
      end

      # Generate JSON for our containers.
      containers = @yaml.map do |name, fields|
        # Skip this service if we've been given a list to emit, and
        # this service isn't on the list.
        begin
          mount_points = (fields["volumes"] || []).map do |v|
            host, container, ro = v.split(':')
            {
              "sourceVolume" => path_to_vol_name(host),
              "containerPath" => container,
              "readOnly" => (ro == "ro")
            }
          end

          json = {
            "name" => name,
            "image" => fields.fetch("image"),
            # Default to a tiny guaranteed CPU share.  Currently, 2 is the
            # smallest meaningful value, and various ECS tools will round
            # smaller numbers up.
            "cpu" => fields["cpu_shares"] || 2,
            "memory" => mem_limit_to_mb(fields.fetch("mem_limit")),
            "links" => fields["links"] || [],
            "portMappings" =>
              (fields["ports"] || []).map {|pm| port_mapping(pm) },
            "essential" => true,
            "environment" => environment(fields["environment"] || {}),
            "mountPoints" => mount_points,
            "volumesFrom" => [],
            "dockerLabels" => fields.fetch("labels", {}),
          }
          if fields.has_key?("entrypoint")
            json["entryPoint"] = command_line(fields.fetch("entrypoint"))
          end
          if fields.has_key?("command")
            json["command"] = command_line(fields.fetch("command"))
          end
          if fields.has_key?("privileged")
            json["privileged"] = fields.fetch("privileged")
          end
          if fields.has_key?("ulimits")
            json["ulimits"] = fields.fetch("ulimits").map do |name, limits|
              case limits
              when Hash
                softLimit = limits.fetch("soft")
                hardLimit = limits.fetch("hard")
              else
                softLimit = limits
                hardLimit = limits
              end
              { "name" => name,
                "softLimit" => softLimit,
                "hardLimit" => hardLimit }
            end
          end
          json

        rescue KeyError => e
          # This makes it a lot easier to localize errors a bit.
          raise ContainerKeyError.new("#{e.message} processing container \"#{name}\"")
        end
      end

      # Generate our top-level volume declarations.
      volumes = @yaml.map do |name, fields|
        (fields["volumes"] || []).map {|v| v.split(':')[0] }
      end.flatten.sort.uniq.map do |host_path|
        {
          "name" => path_to_vol_name(host_path),
          "host" => { "sourcePath" => host_path }
        }
      end

      # Return our final JSON.
      {
        "family" => @family,
        "containerDefinitions" => containers,
        "volumes" => volumes
      }
    end
Create a new generator, specifying the family name to use, and the
 raw YAML input.
 Generate an ECS task definition as a raw Ruby hash.