Manager: allow setup to finish without Blender
Add an option to the setup assistant to skip configuring the path to Blender. It will just use the `default` option, which causes the Workers to try and find Blender on their own. Fixes #104306 Reviewed-on: https://projects.blender.org/studio/flamenco/pulls/104306 Reviewed-by: Sybren A. Stüvel <sybren@blender.org>
This commit is contained in:
parent
0a98fd2b96
commit
6baa132c43
@ -21,6 +21,14 @@ import (
|
|||||||
"projects.blender.org/studio/flamenco/pkg/api"
|
"projects.blender.org/studio/flamenco/pkg/api"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
ErrSetupConfigUnusableSource = errors.New("sources should not have the 'is_usable' field set to false")
|
||||||
|
ErrSetupConfigEmptyStorageLocation = errors.New("'storageLocation' field must not be empty")
|
||||||
|
ErrSetupConfigEmptyPath = errors.New("'path' field must not be empty while using the 'file_association' source")
|
||||||
|
ErrSetupConfigEmptyPathOrInput = errors.New("'path' or 'input' fields must not be empty while using the 'input_path' or 'path_envvar' sources")
|
||||||
|
ErrSetupConfigEmptySource = errors.New("'source' field must not be empty")
|
||||||
|
)
|
||||||
|
|
||||||
func (f *Flamenco) GetVersion(e echo.Context) error {
|
func (f *Flamenco) GetVersion(e echo.Context) error {
|
||||||
return e.JSON(http.StatusOK, api.FlamencoVersion{
|
return e.JSON(http.StatusOK, api.FlamencoVersion{
|
||||||
Version: appinfo.ExtendedVersion(),
|
Version: appinfo.ExtendedVersion(),
|
||||||
@ -265,11 +273,9 @@ func (f *Flamenco) SaveSetupAssistantConfig(e echo.Context) error {
|
|||||||
|
|
||||||
logger = logger.With().Interface("config", setupAssistantCfg).Logger()
|
logger = logger.With().Interface("config", setupAssistantCfg).Logger()
|
||||||
|
|
||||||
if setupAssistantCfg.StorageLocation == "" ||
|
if err := checkSetupAssistantConfig(setupAssistantCfg); err != nil {
|
||||||
!setupAssistantCfg.BlenderExecutable.IsUsable ||
|
logger.Error().AnErr("cause", err).Msg("setup assistant: configuration is incomplete")
|
||||||
setupAssistantCfg.BlenderExecutable.Path == "" {
|
return sendAPIError(e, http.StatusBadRequest, "configuration is incomplete: %v", err)
|
||||||
logger.Warn().Msg("setup assistant: configuration is incomplete, unable to accept")
|
|
||||||
return sendAPIError(e, http.StatusBadRequest, "configuration is incomplete")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
conf := f.config.Get()
|
conf := f.config.Get()
|
||||||
@ -277,7 +283,7 @@ func (f *Flamenco) SaveSetupAssistantConfig(e echo.Context) error {
|
|||||||
|
|
||||||
var executable string
|
var executable string
|
||||||
switch setupAssistantCfg.BlenderExecutable.Source {
|
switch setupAssistantCfg.BlenderExecutable.Source {
|
||||||
case api.BlenderPathSourceFileAssociation:
|
case api.BlenderPathSourceFileAssociation, api.BlenderPathSourceDefault:
|
||||||
// The Worker will try to use the file association when the command is set
|
// The Worker will try to use the file association when the command is set
|
||||||
// to the string "blender".
|
// to the string "blender".
|
||||||
executable = "blender"
|
executable = "blender"
|
||||||
@ -336,3 +342,37 @@ func flamencoManagerDir() (string, error) {
|
|||||||
func commandNeedsQuoting(cmd string) bool {
|
func commandNeedsQuoting(cmd string) bool {
|
||||||
return strings.ContainsAny(cmd, "\n\t;()")
|
return strings.ContainsAny(cmd, "\n\t;()")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func checkSetupAssistantConfig(config api.SetupAssistantConfig) error {
|
||||||
|
if config.StorageLocation == "" {
|
||||||
|
return ErrSetupConfigEmptyStorageLocation
|
||||||
|
}
|
||||||
|
|
||||||
|
if !config.BlenderExecutable.IsUsable {
|
||||||
|
return ErrSetupConfigUnusableSource
|
||||||
|
}
|
||||||
|
|
||||||
|
switch config.BlenderExecutable.Source {
|
||||||
|
case api.BlenderPathSourceDefault:
|
||||||
|
return nil
|
||||||
|
|
||||||
|
case api.BlenderPathSourceFileAssociation:
|
||||||
|
if config.BlenderExecutable.Path == "" {
|
||||||
|
return ErrSetupConfigEmptyPath
|
||||||
|
}
|
||||||
|
|
||||||
|
case api.BlenderPathSourceInputPath, api.BlenderPathSourcePathEnvvar:
|
||||||
|
if config.BlenderExecutable.Path == "" ||
|
||||||
|
config.BlenderExecutable.Input == "" {
|
||||||
|
return ErrSetupConfigEmptyPathOrInput
|
||||||
|
}
|
||||||
|
|
||||||
|
case "":
|
||||||
|
return ErrSetupConfigEmptySource
|
||||||
|
|
||||||
|
default:
|
||||||
|
return fmt.Errorf("unknown 'source' field value: %v", config.BlenderExecutable.Source)
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
@ -363,6 +363,27 @@ func TestSaveSetupAssistantConfig(t *testing.T) {
|
|||||||
assert.Equal(t, expectBlenderVar, savedConfig.Variables["blender"])
|
assert.Equal(t, expectBlenderVar, savedConfig.Variables["blender"])
|
||||||
assert.Equal(t, defaultBlenderArgsVar, savedConfig.Variables["blenderArgs"])
|
assert.Equal(t, defaultBlenderArgsVar, savedConfig.Variables["blenderArgs"])
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Test situation where adding a blender executable was skipped.
|
||||||
|
{
|
||||||
|
savedConfig := doTest(api.SetupAssistantConfig{
|
||||||
|
StorageLocation: mf.tempdir,
|
||||||
|
BlenderExecutable: api.BlenderPathCheckResult{
|
||||||
|
IsUsable: true,
|
||||||
|
Source: api.BlenderPathSourceDefault,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
assert.Equal(t, mf.tempdir, savedConfig.SharedStoragePath)
|
||||||
|
expectBlenderVar := config.Variable{
|
||||||
|
Values: config.VariableValues{
|
||||||
|
{Platform: "linux", Value: "blender"},
|
||||||
|
{Platform: "windows", Value: "blender"},
|
||||||
|
{Platform: "darwin", Value: "blender"},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
assert.Equal(t, expectBlenderVar, savedConfig.Variables["blender"])
|
||||||
|
assert.Equal(t, defaultBlenderArgsVar, savedConfig.Variables["blenderArgs"])
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func metaTestFixtures(t *testing.T) (mockedFlamenco, func()) {
|
func metaTestFixtures(t *testing.T) (mockedFlamenco, func()) {
|
||||||
|
@ -114,7 +114,7 @@
|
|||||||
|
|
||||||
<p v-else>Choose how a Worker should invoke the Blender command when performing a task:</p>
|
<p v-else>Choose how a Worker should invoke the Blender command when performing a task:</p>
|
||||||
|
|
||||||
<fieldset v-if="autoFoundBlenders.length >= 1">
|
<fieldset>
|
||||||
<label v-if="autoFoundBlenderPathEnvvar" for="blender-path_envvar">
|
<label v-if="autoFoundBlenderPathEnvvar" for="blender-path_envvar">
|
||||||
<div>
|
<div>
|
||||||
<input
|
<input
|
||||||
@ -191,25 +191,19 @@
|
|||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
</label>
|
</label>
|
||||||
|
|
||||||
|
<label for="blender-default">
|
||||||
|
<div>
|
||||||
|
<input
|
||||||
|
type="radio"
|
||||||
|
v-model="selectedBlender"
|
||||||
|
name="blender"
|
||||||
|
:value="blenderFromDefaultSource"
|
||||||
|
id="blender-default" />
|
||||||
|
{{ sourceLabels['default'] }}
|
||||||
|
</div>
|
||||||
|
</label>
|
||||||
</fieldset>
|
</fieldset>
|
||||||
|
|
||||||
<div v-if="autoFoundBlenders.length === 0">
|
|
||||||
<input
|
|
||||||
v-model="customBlenderExe"
|
|
||||||
@keyup.enter="nextStepAfterCheckBlenderExePath"
|
|
||||||
:class="{
|
|
||||||
'is-invalid': blenderExeCheckResult != null && !blenderExeCheckResult.is_usable,
|
|
||||||
}"
|
|
||||||
type="text"
|
|
||||||
placeholder="Path to Blender executable" />
|
|
||||||
|
|
||||||
<p v-if="isBlenderExeChecking" class="is-in-progress">Checking...</p>
|
|
||||||
<p
|
|
||||||
v-if="blenderExeCheckResult != null && !blenderExeCheckResult.is_usable"
|
|
||||||
class="check-failed">
|
|
||||||
{{ blenderExeCheckResult.cause }}
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
</step-item>
|
</step-item>
|
||||||
|
|
||||||
<step-item
|
<step-item
|
||||||
@ -240,6 +234,9 @@
|
|||||||
The command you provided: "<code>{{ selectedBlender.path }}</code
|
The command you provided: "<code>{{ selectedBlender.path }}</code
|
||||||
>"
|
>"
|
||||||
</dd>
|
</dd>
|
||||||
|
<dd v-if="selectedBlender.source == 'default'">
|
||||||
|
You have chosen to skip adding a blender path.
|
||||||
|
</dd>
|
||||||
</dl>
|
</dl>
|
||||||
</div>
|
</div>
|
||||||
<p v-if="isConfirmed" class="check-ok">
|
<p v-if="isConfirmed" class="check-ok">
|
||||||
@ -291,7 +288,8 @@ export default {
|
|||||||
sourceLabels: {
|
sourceLabels: {
|
||||||
file_association: 'Blender that runs when you double-click a .blend file:',
|
file_association: 'Blender that runs when you double-click a .blend file:',
|
||||||
path_envvar: 'Blender found on the $PATH environment:',
|
path_envvar: 'Blender found on the $PATH environment:',
|
||||||
input_path: 'Another Blender executable:',
|
input_path: 'Specify a Blender executable:',
|
||||||
|
default: 'Skip, let the Workers use whatever Blender is available.',
|
||||||
},
|
},
|
||||||
isConfirming: false,
|
isConfirming: false,
|
||||||
isConfirmed: false,
|
isConfirmed: false,
|
||||||
@ -324,6 +322,15 @@ export default {
|
|||||||
blenderFromInputPath() {
|
blenderFromInputPath() {
|
||||||
return this.allBlenders.find((b) => b.source === 'input_path');
|
return this.allBlenders.find((b) => b.source === 'input_path');
|
||||||
},
|
},
|
||||||
|
blenderFromDefaultSource() {
|
||||||
|
return {
|
||||||
|
input: '',
|
||||||
|
path: '',
|
||||||
|
source: 'default',
|
||||||
|
is_usable: true,
|
||||||
|
cause: '',
|
||||||
|
};
|
||||||
|
},
|
||||||
setupConfirmIsClickable() {
|
setupConfirmIsClickable() {
|
||||||
if (this.isConfirming || this.isConfirmed) {
|
if (this.isConfirming || this.isConfirmed) {
|
||||||
return false;
|
return false;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user