class Towel::Session

A session keeps track of an invocation throughout its lifespan. It is meant to be a helper to framework-specific implementations by providing a more convenient API over the raw gRPC calls.

Public Class Methods

new(config = nil) click to toggle source
# File lib/towel/session.rb, line 6
def initialize(config = nil)
    @config = config || Towel::Configuration.read
    @stub = create_stub
    @project = [
      "organizations",
      @config["collector"]["organization"],
      "projects",
      @config["collector"]["project"]
    ].join "/"
    @invocation = nil
    @groups = {}
    @group_id = -1
    @results = {}
    @result_id = -1
    @logs = {}
end

Public Instance Methods

cancel_invocation() click to toggle source

Mark an invocation as cancelled. Do not call this and `#finish` on a given Session.

# File lib/towel/session.rb, line 145
def cancel_invocation
  request = Towel::V1alpha::CancelInvocationRequest.new
  request.name = @invocation.name

  @stub.cancel_invocation(request)
end
create_invocation() click to toggle source

Creates a new invocation. Returns the invocation URL at which users may view results. This must be called before other methods.

# File lib/towel/session.rb, line 25
def create_invocation
    invocation = Towel::V1alpha::Invocation.new
    invocation.project = @project
    @config["labels"].each {|k, v| invocation.labels[k] = v }
    invocation.start_time = Time.now.utc

    # Add environment-specific information
    invocation.platform = Towel::Environment.platform
    invocation.hostname = Towel::Environment.hostname
    invocation.user = Towel::Environment.user
    invocation.working_dir = Towel::Environment.working_dir
    invocation.argv.concat(Towel::Environment.argv)
    Towel::Environment.env_vars.each do |name, value|
      invocation.env_vars[name] = value
    end
    invocation.revision = Towel::Environment.revision

    request = Towel::V1alpha::CreateInvocationRequest.new
    request.invocation = invocation

    @invocation = @stub.create_invocation(request)

    @invocation.url
end
create_log(name) click to toggle source

Create a new log with a given name. This can be used as-is or wrapped in a LogIO wrapper and used in place of a IO stream.

# File lib/towel/session.rb, line 124
def create_log(name)
  raise Error, "Log '#{name}' already exists" if @logs.key?(name)
  resource_name = [@invocation.name, "logs", name].join "/"
  @logs[name] = Log.new(resource_name, @stub)
end
create_result(group, name, display_name: nil) click to toggle source

Creates a result under a specified group and mark it as running. Returns the resource name of the result, which can be used to set a Log context.

# File lib/towel/session.rb, line 52
def create_result(group, name, display_name: nil)
  group_id = find_or_create_group(group)

  result = Towel::V1alpha::Result.new

  if @results.key?([group_id, name])
    raise Error, "Result already has been created for '#{name}'"
  else
    result_id = @result_id += 1
    @results[[group_id, name]] = result_id
  end

  result.name = [
    @invocation.name,
    "groups",
    group_id,
    "results",
    result_id
  ].join "/"
  result.display_name = display_name || name
  result.start_time = Time.now.utc
  result.state = Towel::V1alpha::ResultState::RUNNING

  request = Towel::V1alpha::CreateResultRequest.new
  request.result = result

  @stub.create_result(request)

  ["groups", group_id, "results", result_id].join "/"
end
finish_invocation() click to toggle source

Mark an invocation as finished (ran to termination without being cancelled). Do not call this and `#cancel` on a given Session. All outstanding logs will be flushed and closed as part of this.

# File lib/towel/session.rb, line 133
def finish_invocation
  @logs.each { |name, log| log.close }

  request = Towel::V1alpha::FinishInvocationRequest.new
  request.name = @invocation.name
  request.end_time = Time.now.utc

  @stub.finish_invocation(request)
end
update_result(group, name, state:, duration: nil, description: nil) click to toggle source

Updates a result with its outcome.

# File lib/towel/session.rb, line 84
def update_result(group, name, state:, duration: nil, description: nil)
  group_id = find_group(group)
  unless @results.key?([group_id, name])
    raise Error, "Cannot find result '#{name}'"
  end
  result_id = @results[[group_id, name]]

  result = Towel::V1alpha::Result.new
  update_mask = Google::Protobuf::FieldMask.new

  result.name = [
    @invocation.name,
    "groups",
    group_id,
    "results",
    result_id
  ].join "/"

  update_mask.paths << "state"
  result.state = state

  if !duration.nil?
    update_mask.paths << "duration"
    result.duration = duration
  end

  if !description.nil?
    update_mask.paths << "description"
    result.description = description
  end

  request = Towel::V1alpha::UpdateResultRequest.new
  request.result = result
  request.update_mask = update_mask

  @stub.update_result(request)
end

Private Instance Methods

create_stub() click to toggle source

Returns a Collector stub that the rest of this class can use to communicate with Towel.

# File lib/towel/session.rb, line 156
def create_stub
    ssl_credentials = GRPC::Core::ChannelCredentials.new
    bearer_credentials = GRPC::Core::CallCredentials.new(proc {
      { authorization: "Bearer #{@config["auth"]["api_key"]}" }
    })
    credentials = ssl_credentials.compose(bearer_credentials)

    Towel::V1alpha::Collector::Stub.new(
      @config["collector"]["address"],
      credentials
    )
end
find_group(name) click to toggle source

Finds a previously created group by name. Raises `Towel::Error` if the group does not exist.

# File lib/towel/session.rb, line 193
def find_group(name)
  raise Error, "Cannot find group '#{name}'" unless @groups.key?(name)
  @groups[name]
end
find_or_create_group(name) click to toggle source

Finds a group by name and attempts to create it if it does not exist. Returns the ID of the group. Most users of Session will call `#create_result` instead, which calls this behind the scenes.

# File lib/towel/session.rb, line 172
def find_or_create_group(name)
  if @groups.key?(name)
    @groups[name]
  else
    # This group doesn't exist yet, so let's create it.
    group_id = @group_id += 1

    group = Towel::V1alpha::Group.new
    group.name = [@invocation.name, "groups", group_id].join "/"
    group.display_name = name
    request = Towel::V1alpha::CreateGroupRequest.new
    request.group = group

    @stub.create_group(request)
    @groups[name] = group_id
    group_id
  end
end