blob: dbaa596f61be4db827a0378e7216e359417dbf4d [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 {
// SetEnvironment stores the ResultStore environment.
SetEnvironment(Environment) bool
// Environment is the ResultStore environment.
Environment() Environment
// 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 parent Target and
// Configuration IDs.
SetConfiguredTarget(targetID, configID string, name string) bool
// ConfiguredTarget returns a ConfiguredTarget's name, given its parent Target and
// Configuration IDs.
ConfiguredTarget(targetID, configID string) string
// SetTestAction stores a TestAction's name under its ancestor Target and Configuration
// IDs.
SetTestAction(targetID, configID, name string) bool
// TestAction returns a TestAction's name, given its ancestor Target and Configuration
// IDs.
TestAction(targetID, configID string) string
}
// NewContext returns a new Context.
func NewContext() Context {
return &rsContext{}
}
// The default Context implementation.
type rsContext struct {
EnvironmentValue Environment `json:"environment"`
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"`
TestActionNames map[string]string `json:"test_actions"`
}
func (c *rsContext) SetEnvironment(value Environment) bool {
if c.EnvironmentValue != "" && c.EnvironmentValue != value {
return false
}
c.EnvironmentValue = value
return true
}
func (c *rsContext) Environment() Environment {
return c.EnvironmentValue
}
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.combineTargetAndConfigIDs(targetID, configID)
c.ConfiguredTargetNames[id] = name
return true
}
func (c *rsContext) ConfiguredTarget(targetID, configID string) string {
c.ensureConfiguredTargets()
id := c.combineTargetAndConfigIDs(targetID, configID)
val, _ := c.ConfiguredTargetNames[id]
return val
}
func (c *rsContext) SetTestAction(targetID, configID, name string) bool {
c.ensureTestActions()
oldName := c.TestAction(targetID, configID)
if oldName != "" && oldName != name {
return false
}
id := c.combineTargetAndConfigIDs(targetID, configID)
c.TestActionNames[id] = name
return true
}
func (c *rsContext) TestAction(targetID, configID string) string {
c.ensureTestActions()
id := c.combineTargetAndConfigIDs(targetID, configID)
val, _ := c.TestActionNames[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) ensureTestActions() {
if c.TestActionNames == nil {
c.TestActionNames = make(map[string]string)
}
}
func (c rsContext) combineTargetAndConfigIDs(targetID, configID string) string {
return fmt.Sprintf("(target=%s,config=%s)", targetID, configID)
}