Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 18 additions & 0 deletions src/operations.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { parseProviderKind, parseWorkspaceMetadata, parseWorkspaceRecord } from './contracts.js';
import { readPolicy } from './policy.js';
import { readMetadata } from './metadata.js';
import { createDockerProvider } from './providers/docker.js';
import { createKubernetesProvider } from './providers/kubernetes.js';
import { createAppleContainerProvider } from './providers/apple-container.js';
Expand Down Expand Up @@ -120,6 +121,23 @@ export function createWorkspaceProviderOperations(options = {}) {
}
return { projectID, workspaces, failures, completeProviders };
},
/**
* Whether a workspace still matches the settings in force, read from its own
* metadata without contacting the provider. Kept separate from inspectWorkspace,
* which runs a health check: a surface labelling a list must not pay for one probe
* per row, and the answer here is already recorded in the workspace itself.
*/
async describeWorkspacePolicyState(workspace) {
parseWorkspaceRecord(workspace);
const provider = providerForWorkspace(workspace);
try {
readMetadata(workspace, provider.kind, policy);
return { provider: provider.kind, matchesPolicy: true };
} catch (error) {
if (error?.code === 'WORKSPACE_POLICY_MISMATCH') return { provider: provider.kind, matchesPolicy: false, code: error.code };
throw error;
}
},
async inspectWorkspace(workspace) {
workspace = await adoptWorkspace(workspace);
const provider = providerForWorkspace(workspace);
Expand Down
18 changes: 18 additions & 0 deletions src/operations.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,24 @@ describe('workspace provider recovery operations', () => {
await Promise.all([rm(stateDirectory, { recursive: true, force: true }), rm(sourceDirectory, { recursive: true, force: true })]);
});

it('reads policy state from the workspace itself without contacting the provider', async () => {
const operations = createWorkspaceProviderOperations({ policy, sourceDirectory });
const workspace = recoveredWorkspace();

await expect(operations.describeWorkspacePolicyState(workspace)).resolves.toMatchObject({ matchesPolicy: true });
// Labelling a list must not cost one provider probe per row.
expect(provider.list).not.toHaveBeenCalled();
expect(provider.reconcile).not.toHaveBeenCalled();
});

it('reports a workspace created under settings that are no longer in force', async () => {
const operations = createWorkspaceProviderOperations({ policy, sourceDirectory });
const workspace = recoveredWorkspace();
const drifted = { ...workspace, extra: { ...workspace.extra, policyFingerprint: 'b'.repeat(64) } };

await expect(operations.describeWorkspacePolicyState(drifted)).resolves.toMatchObject({ matchesPolicy: false, code: 'WORKSPACE_POLICY_MISMATCH' });
});

function recoveredWorkspace(overrides = {}) {
const identity = {
provider: 'docker',
Expand Down
Loading