Implement getSharedStorage operation & use it in the add-on

Implement the `getSharedStorage` operation in the Manager, and use it in
the add-on to get the shared storage location in a way that makes sense
for the platform of the user.

Manifest task: T100196
This commit is contained in:
Sybren A. Stüvel 2022-08-31 11:44:37 +02:00
parent 31769bcdf2
commit 31cf0a4ecc
4 changed files with 115 additions and 10 deletions

View File

@ -4,6 +4,7 @@
import logging
import dataclasses
import platform
from typing import TYPE_CHECKING, Optional
from urllib3.exceptions import HTTPError, MaxRetryError
@ -16,20 +17,20 @@ if TYPE_CHECKING:
from flamenco.manager import ApiClient as _ApiClient
from flamenco.manager.models import (
FlamencoVersion as _FlamencoVersion,
ManagerConfiguration as _ManagerConfiguration,
SharedStorageLocation as _SharedStorageLocation,
)
from .preferences import FlamencoPreferences as _FlamencoPreferences
else:
_ApiClient = object
_FlamencoPreferences = object
_FlamencoVersion = object
_ManagerConfiguration = object
_SharedStorageLocation = object
@dataclasses.dataclass(frozen=True)
class ManagerInfo:
version: Optional[_FlamencoVersion] = None
config: Optional[_ManagerConfiguration] = None
storage: Optional[_SharedStorageLocation] = None
error: str = ""
@classmethod
@ -38,9 +39,9 @@ class ManagerInfo:
@classmethod
def with_info(
cls, version: _FlamencoVersion, config: _ManagerConfiguration
cls, version: _FlamencoVersion, storage: _SharedStorageLocation
) -> "ManagerInfo":
return cls(version=version, config=config)
return cls(version=version, storage=storage)
def flamenco_api_client(manager_url: str) -> _ApiClient:
@ -120,13 +121,14 @@ def ping_manager(
# Do a late import, so that the API is only imported when actually used.
from flamenco.manager import ApiException
from flamenco.manager.apis import MetaApi
from flamenco.manager.models import FlamencoVersion, ManagerConfiguration
from flamenco.manager.models import FlamencoVersion, SharedStorageLocation
meta_api = MetaApi(api_client)
error = ""
try:
version: FlamencoVersion = meta_api.get_version()
config: ManagerConfiguration = meta_api.get_configuration()
storage: SharedStorageLocation = meta_api.get_shared_storage(
"users", platform.system().lower())
except ApiException as ex:
error = "Manager cannot be reached: %s" % ex
except MaxRetryError as ex:
@ -142,10 +144,10 @@ def ping_manager(
return ManagerInfo.with_error(error)
# Store whether this Manager supports the Shaman API.
prefs.is_shaman_enabled = config.shaman_enabled
prefs.job_storage = config.storage_location
prefs.is_shaman_enabled = storage.shaman_enabled
prefs.job_storage = storage.location
report = "%s version %s found" % (version.name, version.version)
window_manager.flamenco_status_ping = report
return ManagerInfo.with_info(version, config)
return ManagerInfo.with_info(version, storage)

View File

@ -68,6 +68,24 @@ func (f *Flamenco) GetVariables(e echo.Context, audience api.ManagerVariableAudi
return e.JSON(http.StatusOK, apiVars)
}
func (f *Flamenco) GetSharedStorage(e echo.Context, audience api.ManagerVariableAudience, platform string) error {
location := f.config.EffectiveStoragePath()
feeder := make(chan string, 1)
receiver := make(chan string, 1)
feeder <- location
close(feeder)
f.config.ExpandVariables(feeder, receiver, config.VariableAudience(audience), config.VariablePlatform(platform))
return e.JSON(http.StatusOK, api.SharedStorageLocation{
Audience: audience,
Platform: platform,
Location: <-receiver,
ShamanEnabled: f.isShamanEnabled(),
})
}
func (f *Flamenco) CheckSharedStoragePath(e echo.Context) error {
logger := requestLogger(e)

View File

@ -15,6 +15,7 @@ import (
"github.com/golang/mock/gomock"
"github.com/labstack/echo/v4"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
func TestGetVariables(t *testing.T) {
@ -64,6 +65,89 @@ func TestGetVariables(t *testing.T) {
}
}
func TestGetSharedStorage(t *testing.T) {
mockCtrl := gomock.NewController(t)
defer mockCtrl.Finish()
mf := newMockedFlamenco(mockCtrl)
conf := config.GetTestConfig(func(c *config.Conf) {
// Test with a Manager on Windows.
c.MockCurrentGOOSForTests("windows")
// Set up a two-way variable to do the mapping.
c.Variables["shared_storage_mapping"] = config.Variable{
IsTwoWay: true,
Values: []config.VariableValue{
{Value: "/user/shared/storage", Platform: config.VariablePlatformLinux, Audience: config.VariableAudienceUsers},
{Value: "/worker/shared/storage", Platform: config.VariablePlatformLinux, Audience: config.VariableAudienceWorkers},
{Value: `S:\storage`, Platform: config.VariablePlatformWindows, Audience: config.VariableAudienceAll},
},
}
})
mf.config.EXPECT().Get().Return(&conf).AnyTimes()
mf.config.EXPECT().EffectiveStoragePath().Return(`S:\storage\flamenco`).AnyTimes()
{ // Test user client on Linux.
mf.config.EXPECT().
ExpandVariables(gomock.Any(), gomock.Any(), config.VariableAudienceUsers, config.VariablePlatformLinux).
Do(func(inputChannel <-chan string, outputChannel chan<- string, audience config.VariableAudience, platform config.VariablePlatform) {
// Defer to the actual ExpandVariables() implementation of the above config.
conf.ExpandVariables(inputChannel, outputChannel, audience, platform)
})
mf.shaman.EXPECT().IsEnabled().Return(false)
echoCtx := mf.prepareMockedRequest(nil)
err := mf.flamenco.GetSharedStorage(echoCtx, api.ManagerVariableAudienceUsers, "linux")
require.NoError(t, err)
assertResponseJSON(t, echoCtx, http.StatusOK, api.SharedStorageLocation{
Location: "/user/shared/storage/flamenco",
Audience: api.ManagerVariableAudienceUsers,
Platform: "linux",
})
}
{ // Test worker client on Linux with Shaman enabled.
mf.config.EXPECT().
ExpandVariables(gomock.Any(), gomock.Any(), config.VariableAudienceWorkers, config.VariablePlatformLinux).
Do(func(inputChannel <-chan string, outputChannel chan<- string, audience config.VariableAudience, platform config.VariablePlatform) {
// Defer to the actual ExpandVariables() implementation of the above config.
conf.ExpandVariables(inputChannel, outputChannel, audience, platform)
})
mf.shaman.EXPECT().IsEnabled().Return(true)
echoCtx := mf.prepareMockedRequest(nil)
err := mf.flamenco.GetSharedStorage(echoCtx, api.ManagerVariableAudienceWorkers, "linux")
require.NoError(t, err)
assertResponseJSON(t, echoCtx, http.StatusOK, api.SharedStorageLocation{
Location: "/worker/shared/storage/flamenco",
Audience: api.ManagerVariableAudienceWorkers,
Platform: "linux",
ShamanEnabled: true,
})
}
{ // Test user client on Windows.
mf.config.EXPECT().
ExpandVariables(gomock.Any(), gomock.Any(), config.VariableAudienceUsers, config.VariablePlatformWindows).
Do(func(inputChannel <-chan string, outputChannel chan<- string, audience config.VariableAudience, platform config.VariablePlatform) {
// Defer to the actual ExpandVariables() implementation of the above config.
conf.ExpandVariables(inputChannel, outputChannel, audience, platform)
})
mf.shaman.EXPECT().IsEnabled().Return(false)
echoCtx := mf.prepareMockedRequest(nil)
err := mf.flamenco.GetSharedStorage(echoCtx, api.ManagerVariableAudienceUsers, "windows")
require.NoError(t, err)
assertResponseJSON(t, echoCtx, http.StatusOK, api.SharedStorageLocation{
Location: `S:\storage\flamenco`,
Audience: api.ManagerVariableAudienceUsers,
Platform: "windows",
})
}
}
func TestCheckSharedStoragePath(t *testing.T) {
mf, finish := metaTestFixtures(t)
defer finish()

View File

@ -70,6 +70,7 @@ func newMockedFlamenco(mockCtrl *gomock.Controller) mockedFlamenco {
logStorage: logStore,
config: cs,
stateMachine: sm,
shaman: sha,
clock: clock,
lastRender: lr,
localStorage: localStore,