blob: 0f68455257e757ad4161e0b07b403d65ef1153df [file] [log] [blame]
// Copyright 2018 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
package resultstore
import (
"fmt"
)
// Context stores information necessary to create an Invocation. It is used to support
// tilo clients that use a distributed execution model, where multiple processes
// participate in creating, modifying, and finishing an Invocation. This can be
// accomplished by serializing the Context as a JSON object and passing it to another
// process.
//
// When creating ResultStore entities, the name of the entity's parent must be provided
// for ResultStore to make the parent-child association. The entity name is created by
// the ResultStore backend and returned from the UploadApi methods. This cache is used to
// store those names as they are returned.
//
// All requests to modify an Invocation require an authorization token, which is specified
// when the Invocation is created. This cache also stores that token.
//
// Context getters return false if values are not present, or empty. Setters return false
// when values are already set. Attempting to ovewrite a value should always be
// considered a bug. For example: if the auth token is ovewritten, we can no longer upload
// to an invocation. If an entity name is ovewritten, we can no longer associate children
// with that entity.
//
// Please do not add information to this interface unless it is necessary to support
// creating Invocations in a distributed manner.
type Context interface {
// SetAuthToken stores the Invocation's auth token.
SetAuthToken(string) bool
// AuthToken is the Invocation's auth token.
AuthToken() string
// SetInvocationID Stores the name of the Invocation.
SetInvocationID(id string) bool
// SetInvocationName Stores the name of the Invocation.
SetInvocationName(name string) bool
// InvocationID is the Invocation's ID.
InvocationID() string
// InvocationName is the Invocation's name.
InvocationName() string
// SetTarget stores a Target's name under its ID.
SetTarget(id, name string) bool
// Target returns a Target's name, given its ID.
Target(id string) string
// SetConfiguredTarget stores a ConfiguredTarget's name under its ID.
SetConfiguredTarget(targetID, configID string, name string) bool
// ConfiguredTarget returns a ConfiguredTarget's name, given its ID.
ConfiguredTarget(targetID, configID string) string
}
// NewContext returns a new Context.
func NewContext() Context {
return &rsContext{}
}
// The default Context implementation.
type rsContext struct {
AuthTokenValue string `json:"auth_token"`
InvocationNameValue string `json:"invocation_name"`
InvocationIDValue string `json:"invocation_id"`
TargetNames map[string]string `json:"targets"`
ConfiguredTargetNames map[string]string `json:"configured_targets"`
}
func (c *rsContext) SetAuthToken(value string) bool {
if c.AuthTokenValue != "" && c.AuthTokenValue != value {
return false
}
c.AuthTokenValue = value
return true
}
func (c *rsContext) AuthToken() string {
return c.AuthTokenValue
}
func (c *rsContext) SetInvocationName(name string) bool {
if c.InvocationNameValue != "" && c.InvocationNameValue != name {
return false
}
c.InvocationNameValue = name
return true
}
func (c *rsContext) InvocationName() string {
return c.InvocationNameValue
}
func (c *rsContext) SetInvocationID(name string) bool {
if c.InvocationIDValue != "" && c.InvocationIDValue != name {
return false
}
c.InvocationIDValue = name
return true
}
func (c *rsContext) InvocationID() string {
return c.InvocationIDValue
}
func (c *rsContext) SetTarget(id, name string) bool {
c.ensureTargets()
oldName := c.Target(id)
if oldName != "" && oldName != name {
return false
}
c.TargetNames[id] = name
return true
}
func (c *rsContext) Target(id string) string {
c.ensureTargets()
val, _ := c.TargetNames[id]
return val
}
func (c *rsContext) SetConfiguredTarget(targetID, configID string, name string) bool {
c.ensureConfiguredTargets()
oldName := c.ConfiguredTarget(targetID, configID)
if oldName != "" && oldName != name {
return false
}
ID := c.createConfiguredTargetID(targetID, configID)
c.ConfiguredTargetNames[ID] = name
return true
}
func (c *rsContext) ConfiguredTarget(targetID, configID string) string {
c.ensureConfiguredTargets()
ID := c.createConfiguredTargetID(targetID, configID)
val, _ := c.ConfiguredTargetNames[ID]
return val
}
func (c *rsContext) ensureTargets() {
if c.TargetNames == nil {
c.TargetNames = make(map[string]string)
}
}
func (c *rsContext) ensureConfiguredTargets() {
if c.ConfiguredTargetNames == nil {
c.ConfiguredTargetNames = make(map[string]string)
}
}
func (c rsContext) createConfiguredTargetID(targetID, configID string) string {
return fmt.Sprintf("(target=%s,config=%s)", targetID, configID)
}