Manager: implement the getVariables
OpenAPI operation
This commit is contained in:
parent
ae2cb281b4
commit
0ff8ed7585
@ -7,6 +7,7 @@ import (
|
|||||||
"net/http"
|
"net/http"
|
||||||
|
|
||||||
"git.blender.org/flamenco/internal/appinfo"
|
"git.blender.org/flamenco/internal/appinfo"
|
||||||
|
"git.blender.org/flamenco/internal/manager/config"
|
||||||
"git.blender.org/flamenco/pkg/api"
|
"git.blender.org/flamenco/pkg/api"
|
||||||
"github.com/labstack/echo/v4"
|
"github.com/labstack/echo/v4"
|
||||||
)
|
)
|
||||||
@ -24,3 +25,22 @@ func (f *Flamenco) GetConfiguration(e echo.Context) error {
|
|||||||
StorageLocation: f.config.EffectiveStoragePath(),
|
StorageLocation: f.config.EffectiveStoragePath(),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (f *Flamenco) GetVariables(e echo.Context, audience api.ManagerVariableAudience, platform string) error {
|
||||||
|
variables := f.config.ResolveVariables(
|
||||||
|
config.VariableAudience(audience),
|
||||||
|
config.VariablePlatform(platform),
|
||||||
|
)
|
||||||
|
|
||||||
|
apiVars := api.ManagerVariables{
|
||||||
|
AdditionalProperties: make(map[string]api.ManagerVariable),
|
||||||
|
}
|
||||||
|
for name, variable := range variables {
|
||||||
|
apiVars.AdditionalProperties[name] = api.ManagerVariable{
|
||||||
|
IsTwoway: variable.IsTwoWay,
|
||||||
|
Value: variable.Value,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return e.JSON(http.StatusOK, apiVars)
|
||||||
|
}
|
||||||
|
60
internal/manager/api_impl/meta_test.go
Normal file
60
internal/manager/api_impl/meta_test.go
Normal file
@ -0,0 +1,60 @@
|
|||||||
|
package api_impl
|
||||||
|
|
||||||
|
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
|
||||||
|
import (
|
||||||
|
"net/http"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"git.blender.org/flamenco/internal/manager/config"
|
||||||
|
"git.blender.org/flamenco/pkg/api"
|
||||||
|
"github.com/golang/mock/gomock"
|
||||||
|
"github.com/stretchr/testify/assert"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestGetVariables(t *testing.T) {
|
||||||
|
mockCtrl := gomock.NewController(t)
|
||||||
|
defer mockCtrl.Finish()
|
||||||
|
|
||||||
|
mf := newMockedFlamenco(mockCtrl)
|
||||||
|
|
||||||
|
// Test Linux Worker.
|
||||||
|
{
|
||||||
|
resolvedVarsLinuxWorker := make(map[string]config.ResolvedVariable)
|
||||||
|
resolvedVarsLinuxWorker["jobs"] = config.ResolvedVariable{
|
||||||
|
IsTwoWay: true,
|
||||||
|
Value: "Linux value",
|
||||||
|
}
|
||||||
|
resolvedVarsLinuxWorker["blender"] = config.ResolvedVariable{
|
||||||
|
IsTwoWay: false,
|
||||||
|
Value: "/usr/local/blender",
|
||||||
|
}
|
||||||
|
|
||||||
|
mf.config.EXPECT().
|
||||||
|
ResolveVariables(config.VariableAudienceWorkers, config.VariablePlatformLinux).
|
||||||
|
Return(resolvedVarsLinuxWorker)
|
||||||
|
|
||||||
|
echoCtx := mf.prepareMockedRequest(nil)
|
||||||
|
err := mf.flamenco.GetVariables(echoCtx, api.ManagerVariableAudienceWorkers, "linux")
|
||||||
|
assert.NoError(t, err)
|
||||||
|
assertResponseJSON(t, echoCtx, http.StatusOK, api.ManagerVariables{
|
||||||
|
AdditionalProperties: map[string]api.ManagerVariable{
|
||||||
|
"blender": {Value: "/usr/local/blender", IsTwoway: false},
|
||||||
|
"jobs": {Value: "Linux value", IsTwoway: true},
|
||||||
|
},
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// Test unknown platform User.
|
||||||
|
{
|
||||||
|
resolvedVarsUnknownPlatform := make(map[string]config.ResolvedVariable)
|
||||||
|
mf.config.EXPECT().
|
||||||
|
ResolveVariables(config.VariableAudienceUsers, config.VariablePlatform("troll")).
|
||||||
|
Return(resolvedVarsUnknownPlatform)
|
||||||
|
|
||||||
|
echoCtx := mf.prepareMockedRequest(nil)
|
||||||
|
err := mf.flamenco.GetVariables(echoCtx, api.ManagerVariableAudienceUsers, "troll")
|
||||||
|
assert.NoError(t, err)
|
||||||
|
assertResponseJSON(t, echoCtx, http.StatusOK, api.ManagerVariables{})
|
||||||
|
}
|
||||||
|
}
|
@ -699,6 +699,20 @@ func (mr *MockConfigServiceMockRecorder) Get() *gomock.Call {
|
|||||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Get", reflect.TypeOf((*MockConfigService)(nil).Get))
|
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Get", reflect.TypeOf((*MockConfigService)(nil).Get))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ResolveVariables mocks base method.
|
||||||
|
func (m *MockConfigService) ResolveVariables(arg0 config.VariableAudience, arg1 config.VariablePlatform) map[string]config.ResolvedVariable {
|
||||||
|
m.ctrl.T.Helper()
|
||||||
|
ret := m.ctrl.Call(m, "ResolveVariables", arg0, arg1)
|
||||||
|
ret0, _ := ret[0].(map[string]config.ResolvedVariable)
|
||||||
|
return ret0
|
||||||
|
}
|
||||||
|
|
||||||
|
// ResolveVariables indicates an expected call of ResolveVariables.
|
||||||
|
func (mr *MockConfigServiceMockRecorder) ResolveVariables(arg0, arg1 interface{}) *gomock.Call {
|
||||||
|
mr.mock.ctrl.T.Helper()
|
||||||
|
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ResolveVariables", reflect.TypeOf((*MockConfigService)(nil).ResolveVariables), arg0, arg1)
|
||||||
|
}
|
||||||
|
|
||||||
// MockTaskStateMachine is a mock of TaskStateMachine interface.
|
// MockTaskStateMachine is a mock of TaskStateMachine interface.
|
||||||
type MockTaskStateMachine struct {
|
type MockTaskStateMachine struct {
|
||||||
ctrl *gomock.Controller
|
ctrl *gomock.Controller
|
||||||
|
@ -10,6 +10,7 @@ import (
|
|||||||
|
|
||||||
type VariableReplacer interface {
|
type VariableReplacer interface {
|
||||||
ExpandVariables(valueToExpand string, audience config.VariableAudience, platform config.VariablePlatform) string
|
ExpandVariables(valueToExpand string, audience config.VariableAudience, platform config.VariablePlatform) string
|
||||||
|
ResolveVariables(audience config.VariableAudience, platform config.VariablePlatform) map[string]config.ResolvedVariable
|
||||||
}
|
}
|
||||||
|
|
||||||
// replaceTaskVariables performs variable replacement for worker tasks.
|
// replaceTaskVariables performs variable replacement for worker tasks.
|
||||||
|
@ -149,6 +149,12 @@ type VariableValue struct {
|
|||||||
Value string `yaml:"value" json:"value"`
|
Value string `yaml:"value" json:"value"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ResolvedVariable represents info about the variable, resolved for a specific platform & audience.
|
||||||
|
type ResolvedVariable struct {
|
||||||
|
IsTwoWay bool
|
||||||
|
Value string
|
||||||
|
}
|
||||||
|
|
||||||
// getConf parses flamenco-manager.yaml and returns its contents as a Conf object.
|
// getConf parses flamenco-manager.yaml and returns its contents as a Conf object.
|
||||||
func getConf() (Conf, error) {
|
func getConf() (Conf, error) {
|
||||||
return loadConf(configFilename)
|
return loadConf(configFilename)
|
||||||
@ -381,21 +387,8 @@ func updateMap[K comparable, V any](target map[K]V, updateWith map[K]V) {
|
|||||||
|
|
||||||
// ExpandVariables converts "{variable name}" to the value that belongs to the given audience and platform.
|
// ExpandVariables converts "{variable name}" to the value that belongs to the given audience and platform.
|
||||||
func (c *Conf) ExpandVariables(valueToExpand string, audience VariableAudience, platform VariablePlatform) string {
|
func (c *Conf) ExpandVariables(valueToExpand string, audience VariableAudience, platform VariablePlatform) string {
|
||||||
platformsForAudience := c.VariablesLookup[audience]
|
varsForPlatform := c.getVariables(audience, platform)
|
||||||
if platformsForAudience == nil {
|
if len(varsForPlatform) == 0 {
|
||||||
log.Warn().
|
|
||||||
Str("valueToExpand", valueToExpand).
|
|
||||||
Str("audience", string(audience)).
|
|
||||||
Str("platform", string(platform)).
|
|
||||||
Msg("no variables defined for this audience")
|
|
||||||
return valueToExpand
|
|
||||||
}
|
|
||||||
|
|
||||||
varsForPlatform := map[string]string{}
|
|
||||||
updateMap(varsForPlatform, platformsForAudience[VariablePlatformAll])
|
|
||||||
updateMap(varsForPlatform, platformsForAudience[platform])
|
|
||||||
|
|
||||||
if varsForPlatform == nil {
|
|
||||||
log.Warn().
|
log.Warn().
|
||||||
Str("valueToExpand", valueToExpand).
|
Str("valueToExpand", valueToExpand).
|
||||||
Str("audience", string(audience)).
|
Str("audience", string(audience)).
|
||||||
@ -410,9 +403,56 @@ func (c *Conf) ExpandVariables(valueToExpand string, audience VariableAudience,
|
|||||||
valueToExpand = strings.Replace(valueToExpand, placeholder, varvalue, -1)
|
valueToExpand = strings.Replace(valueToExpand, placeholder, varvalue, -1)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO: this needs to go through multiple variable replacements, to make sure
|
||||||
|
// that, for example, the `{jobs}` variable gets the two-way variables applied
|
||||||
|
// as well.
|
||||||
|
|
||||||
return valueToExpand
|
return valueToExpand
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// GetVariables returns the variable values for this (audience, platform) combination.
|
||||||
|
// If no variables are found, just returns an empty map. If a value is defined
|
||||||
|
// for both the "all" platform and specifically the given platform, the specific
|
||||||
|
// platform definition wins.
|
||||||
|
func (c *Conf) getVariables(audience VariableAudience, platform VariablePlatform) map[string]string {
|
||||||
|
platformsForAudience := c.VariablesLookup[audience]
|
||||||
|
if len(platformsForAudience) == 0 {
|
||||||
|
return make(map[string]string)
|
||||||
|
}
|
||||||
|
|
||||||
|
varsForPlatform := map[string]string{}
|
||||||
|
updateMap(varsForPlatform, platformsForAudience[VariablePlatformAll])
|
||||||
|
updateMap(varsForPlatform, platformsForAudience[platform])
|
||||||
|
return varsForPlatform
|
||||||
|
}
|
||||||
|
|
||||||
|
// ResolveVariables returns the variables for this (audience, platform) combination.
|
||||||
|
// If no variables are found, just returns an empty map. If a value is defined
|
||||||
|
// for both the "all" platform and specifically the given platform, the specific
|
||||||
|
// platform definition wins.
|
||||||
|
func (c *Conf) ResolveVariables(audience VariableAudience, platform VariablePlatform) map[string]ResolvedVariable {
|
||||||
|
varsForPlatform := c.getVariables(audience, platform)
|
||||||
|
|
||||||
|
resolvedVars := make(map[string]ResolvedVariable)
|
||||||
|
for name, value := range varsForPlatform {
|
||||||
|
resolvedVar := ResolvedVariable{Value: value}
|
||||||
|
|
||||||
|
// Find the 'IsTwoway' property by finding the actual foundVar, which can be
|
||||||
|
// defined in two places.
|
||||||
|
if foundVar, ok := c.Variables[name]; ok {
|
||||||
|
resolvedVar.IsTwoWay = foundVar.IsTwoWay
|
||||||
|
} else if foundVar, ok := c.implicitVariables[name]; ok {
|
||||||
|
resolvedVar.IsTwoWay = foundVar.IsTwoWay
|
||||||
|
} else {
|
||||||
|
log.Error().Str("variable", name).Msg("unable to find this variable, where did it come from?")
|
||||||
|
}
|
||||||
|
|
||||||
|
resolvedVars[name] = resolvedVar
|
||||||
|
}
|
||||||
|
|
||||||
|
return resolvedVars
|
||||||
|
}
|
||||||
|
|
||||||
// checkVariables performs some basic checks on variable definitions.
|
// checkVariables performs some basic checks on variable definitions.
|
||||||
// All errors are logged, not returned.
|
// All errors are logged, not returned.
|
||||||
func (c *Conf) checkVariables() {
|
func (c *Conf) checkVariables() {
|
||||||
|
@ -45,6 +45,9 @@ func (s *Service) Save() error {
|
|||||||
func (s *Service) ExpandVariables(valueToExpand string, audience VariableAudience, platform VariablePlatform) string {
|
func (s *Service) ExpandVariables(valueToExpand string, audience VariableAudience, platform VariablePlatform) string {
|
||||||
return s.config.ExpandVariables(valueToExpand, audience, platform)
|
return s.config.ExpandVariables(valueToExpand, audience, platform)
|
||||||
}
|
}
|
||||||
|
func (s *Service) ResolveVariables(audience VariableAudience, platform VariablePlatform) map[string]ResolvedVariable {
|
||||||
|
return s.config.ResolveVariables(audience, platform)
|
||||||
|
}
|
||||||
func (s *Service) EffectiveStoragePath() string {
|
func (s *Service) EffectiveStoragePath() string {
|
||||||
return s.config.EffectiveStoragePath()
|
return s.config.EffectiveStoragePath()
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user