@codifycli/plugin-core 1.0.0-beta1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.eslintignore +2 -0
- package/.eslintrc.json +30 -0
- package/.github/workflows/release.yaml +19 -0
- package/.github/workflows/unit-test-ci.yaml +18 -0
- package/.prettierrc.json +1 -0
- package/bin/build.js +189 -0
- package/dist/bin/build.d.ts +1 -0
- package/dist/bin/build.js +80 -0
- package/dist/bin/deploy-plugin.d.ts +2 -0
- package/dist/bin/deploy-plugin.js +8 -0
- package/dist/common/errors.d.ts +8 -0
- package/dist/common/errors.js +24 -0
- package/dist/entities/change-set.d.ts +24 -0
- package/dist/entities/change-set.js +152 -0
- package/dist/entities/errors.d.ts +4 -0
- package/dist/entities/errors.js +7 -0
- package/dist/entities/plan-types.d.ts +25 -0
- package/dist/entities/plan-types.js +1 -0
- package/dist/entities/plan.d.ts +15 -0
- package/dist/entities/plan.js +127 -0
- package/dist/entities/plugin.d.ts +16 -0
- package/dist/entities/plugin.js +80 -0
- package/dist/entities/resource-options.d.ts +31 -0
- package/dist/entities/resource-options.js +76 -0
- package/dist/entities/resource-types.d.ts +11 -0
- package/dist/entities/resource-types.js +1 -0
- package/dist/entities/resource.d.ts +42 -0
- package/dist/entities/resource.js +303 -0
- package/dist/entities/stateful-parameter.d.ts +29 -0
- package/dist/entities/stateful-parameter.js +46 -0
- package/dist/entities/transform-parameter.d.ts +4 -0
- package/dist/entities/transform-parameter.js +2 -0
- package/dist/errors.d.ts +4 -0
- package/dist/errors.js +7 -0
- package/dist/index.d.ts +20 -0
- package/dist/index.js +26 -0
- package/dist/messages/handlers.d.ts +14 -0
- package/dist/messages/handlers.js +134 -0
- package/dist/messages/sender.d.ts +11 -0
- package/dist/messages/sender.js +57 -0
- package/dist/plan/change-set.d.ts +53 -0
- package/dist/plan/change-set.js +153 -0
- package/dist/plan/plan-types.d.ts +23 -0
- package/dist/plan/plan-types.js +1 -0
- package/dist/plan/plan.d.ts +66 -0
- package/dist/plan/plan.js +328 -0
- package/dist/plugin/plugin.d.ts +24 -0
- package/dist/plugin/plugin.js +200 -0
- package/dist/pty/background-pty.d.ts +21 -0
- package/dist/pty/background-pty.js +127 -0
- package/dist/pty/index.d.ts +50 -0
- package/dist/pty/index.js +20 -0
- package/dist/pty/promise-queue.d.ts +5 -0
- package/dist/pty/promise-queue.js +26 -0
- package/dist/pty/seqeuntial-pty.d.ts +17 -0
- package/dist/pty/seqeuntial-pty.js +119 -0
- package/dist/pty/vitest.config.d.ts +2 -0
- package/dist/pty/vitest.config.js +11 -0
- package/dist/resource/config-parser.d.ts +11 -0
- package/dist/resource/config-parser.js +21 -0
- package/dist/resource/parsed-resource-settings.d.ts +47 -0
- package/dist/resource/parsed-resource-settings.js +196 -0
- package/dist/resource/resource-controller.d.ts +36 -0
- package/dist/resource/resource-controller.js +402 -0
- package/dist/resource/resource-settings.d.ts +303 -0
- package/dist/resource/resource-settings.js +147 -0
- package/dist/resource/resource.d.ts +144 -0
- package/dist/resource/resource.js +44 -0
- package/dist/resource/stateful-parameter.d.ts +165 -0
- package/dist/resource/stateful-parameter.js +94 -0
- package/dist/scripts/deploy.d.ts +1 -0
- package/dist/scripts/deploy.js +2 -0
- package/dist/stateful-parameter/stateful-parameter-controller.d.ts +21 -0
- package/dist/stateful-parameter/stateful-parameter-controller.js +81 -0
- package/dist/stateful-parameter/stateful-parameter.d.ts +144 -0
- package/dist/stateful-parameter/stateful-parameter.js +43 -0
- package/dist/test.d.ts +1 -0
- package/dist/test.js +5 -0
- package/dist/utils/codify-spawn.d.ts +29 -0
- package/dist/utils/codify-spawn.js +136 -0
- package/dist/utils/debug.d.ts +2 -0
- package/dist/utils/debug.js +10 -0
- package/dist/utils/file-utils.d.ts +23 -0
- package/dist/utils/file-utils.js +186 -0
- package/dist/utils/functions.d.ts +12 -0
- package/dist/utils/functions.js +74 -0
- package/dist/utils/index.d.ts +46 -0
- package/dist/utils/index.js +271 -0
- package/dist/utils/internal-utils.d.ts +12 -0
- package/dist/utils/internal-utils.js +74 -0
- package/dist/utils/load-resources.d.ts +1 -0
- package/dist/utils/load-resources.js +46 -0
- package/dist/utils/package-json-utils.d.ts +12 -0
- package/dist/utils/package-json-utils.js +34 -0
- package/dist/utils/pty-local-storage.d.ts +2 -0
- package/dist/utils/pty-local-storage.js +2 -0
- package/dist/utils/spawn-2.d.ts +5 -0
- package/dist/utils/spawn-2.js +7 -0
- package/dist/utils/spawn.d.ts +29 -0
- package/dist/utils/spawn.js +124 -0
- package/dist/utils/utils.d.ts +18 -0
- package/dist/utils/utils.js +86 -0
- package/dist/utils/verbosity-level.d.ts +5 -0
- package/dist/utils/verbosity-level.js +9 -0
- package/package.json +59 -0
- package/rollup.config.js +24 -0
- package/src/common/errors.test.ts +43 -0
- package/src/common/errors.ts +31 -0
- package/src/errors.ts +8 -0
- package/src/index.test.ts +6 -0
- package/src/index.ts +30 -0
- package/src/messages/handlers.test.ts +329 -0
- package/src/messages/handlers.ts +181 -0
- package/src/messages/sender.ts +69 -0
- package/src/plan/change-set.test.ts +280 -0
- package/src/plan/change-set.ts +236 -0
- package/src/plan/plan-types.ts +27 -0
- package/src/plan/plan.test.ts +413 -0
- package/src/plan/plan.ts +499 -0
- package/src/plugin/plugin.test.ts +533 -0
- package/src/plugin/plugin.ts +291 -0
- package/src/pty/background-pty.test.ts +69 -0
- package/src/pty/background-pty.ts +154 -0
- package/src/pty/index.test.ts +129 -0
- package/src/pty/index.ts +66 -0
- package/src/pty/promise-queue.ts +33 -0
- package/src/pty/seqeuntial-pty.ts +151 -0
- package/src/pty/sequential-pty.test.ts +194 -0
- package/src/resource/config-parser.ts +42 -0
- package/src/resource/parsed-resource-settings.test.ts +186 -0
- package/src/resource/parsed-resource-settings.ts +307 -0
- package/src/resource/resource-controller-stateful-mode.test.ts +253 -0
- package/src/resource/resource-controller.test.ts +1081 -0
- package/src/resource/resource-controller.ts +563 -0
- package/src/resource/resource-settings.test.ts +1213 -0
- package/src/resource/resource-settings.ts +545 -0
- package/src/resource/resource.ts +157 -0
- package/src/stateful-parameter/stateful-parameter-controller.test.ts +244 -0
- package/src/stateful-parameter/stateful-parameter-controller.ts +111 -0
- package/src/stateful-parameter/stateful-parameter.ts +160 -0
- package/src/utils/debug.ts +11 -0
- package/src/utils/file-utils.test.ts +7 -0
- package/src/utils/file-utils.ts +231 -0
- package/src/utils/functions.ts +103 -0
- package/src/utils/index.ts +340 -0
- package/src/utils/internal-utils.test.ts +52 -0
- package/src/utils/pty-local-storage.ts +3 -0
- package/src/utils/test-utils.test.ts +96 -0
- package/src/utils/verbosity-level.ts +11 -0
- package/tsconfig.json +26 -0
- package/tsconfig.test.json +9 -0
- package/vitest.config.ts +10 -0
|
@@ -0,0 +1,533 @@
|
|
|
1
|
+
import { describe, expect, it } from 'vitest';
|
|
2
|
+
import { Plugin } from './plugin.js';
|
|
3
|
+
import { ApplyRequestData, OS, ParameterOperation, ResourceOperation, StringIndexedObject } from 'codify-schemas';
|
|
4
|
+
import { Resource } from '../resource/resource.js';
|
|
5
|
+
import { Plan } from '../plan/plan.js';
|
|
6
|
+
import { spy } from 'sinon';
|
|
7
|
+
import { ResourceSettings } from '../resource/resource-settings.js';
|
|
8
|
+
import { TestConfig, TestStatefulParameter } from '../utils/test-utils.test.js';
|
|
9
|
+
import { getPty } from '../pty/index.js';
|
|
10
|
+
import { z } from 'zod';
|
|
11
|
+
|
|
12
|
+
interface TestConfig extends StringIndexedObject {
|
|
13
|
+
propA: string;
|
|
14
|
+
propB: number;
|
|
15
|
+
propC?: string;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
class TestResource extends Resource<TestConfig> {
|
|
19
|
+
getSettings(): ResourceSettings<TestConfig> {
|
|
20
|
+
return {
|
|
21
|
+
id: 'testResource',
|
|
22
|
+
operatingSystems: [OS.Darwin],
|
|
23
|
+
};
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
create(plan: Plan<TestConfig>): Promise<void> {
|
|
27
|
+
return Promise.resolve(undefined);
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
destroy(plan: Plan<TestConfig>): Promise<void> {
|
|
31
|
+
return Promise.resolve(undefined);
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
async refresh(): Promise<Partial<TestConfig> | null> {
|
|
35
|
+
return {
|
|
36
|
+
propA: 'a',
|
|
37
|
+
propB: 10,
|
|
38
|
+
propC: 'c',
|
|
39
|
+
};
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
describe('Plugin tests', () => {
|
|
44
|
+
it('Can apply resource', async () => {
|
|
45
|
+
const resource = spy(new class extends TestResource {
|
|
46
|
+
async refresh(): Promise<Partial<TestConfig> | null> {
|
|
47
|
+
return {
|
|
48
|
+
propA: 'abc',
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
})
|
|
52
|
+
const plugin = Plugin.create('testPlugin', [resource as any])
|
|
53
|
+
|
|
54
|
+
const plan: ApplyRequestData['plan'] = {
|
|
55
|
+
operation: ResourceOperation.CREATE,
|
|
56
|
+
resourceType: 'testResource',
|
|
57
|
+
parameters: [
|
|
58
|
+
{ name: 'propA', operation: ParameterOperation.ADD, newValue: 'abc', previousValue: null },
|
|
59
|
+
],
|
|
60
|
+
isStateful: false,
|
|
61
|
+
};
|
|
62
|
+
|
|
63
|
+
await plugin.apply({ plan });
|
|
64
|
+
expect(resource.create.calledOnce).to.be.true;
|
|
65
|
+
});
|
|
66
|
+
|
|
67
|
+
it('Can destroy resource', async () => {
|
|
68
|
+
const resource = spy(new class extends TestResource {
|
|
69
|
+
async refresh(): Promise<Partial<TestConfig> | null> {
|
|
70
|
+
return null;
|
|
71
|
+
}
|
|
72
|
+
});
|
|
73
|
+
const testPlugin = Plugin.create('testPlugin', [resource as any])
|
|
74
|
+
|
|
75
|
+
const plan: ApplyRequestData['plan'] = {
|
|
76
|
+
operation: ResourceOperation.DESTROY,
|
|
77
|
+
resourceType: 'testResource',
|
|
78
|
+
parameters: [
|
|
79
|
+
{ name: 'propA', operation: ParameterOperation.REMOVE, newValue: null, previousValue: 'abc' },
|
|
80
|
+
],
|
|
81
|
+
isStateful: true,
|
|
82
|
+
};
|
|
83
|
+
|
|
84
|
+
await testPlugin.apply({ plan })
|
|
85
|
+
expect(resource.destroy.calledOnce).to.be.true;
|
|
86
|
+
});
|
|
87
|
+
|
|
88
|
+
it('Can re-create resource', async () => {
|
|
89
|
+
const resource = spy(new class extends TestResource {
|
|
90
|
+
async refresh(): Promise<Partial<TestConfig> | null> {
|
|
91
|
+
return {
|
|
92
|
+
propA: 'def',
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
})
|
|
96
|
+
const testPlugin = Plugin.create('testPlugin', [resource as any])
|
|
97
|
+
|
|
98
|
+
const plan: ApplyRequestData['plan'] = {
|
|
99
|
+
operation: ResourceOperation.RECREATE,
|
|
100
|
+
resourceType: 'testResource',
|
|
101
|
+
parameters: [
|
|
102
|
+
{ name: 'propA', operation: ParameterOperation.MODIFY, newValue: 'def', previousValue: 'abc' },
|
|
103
|
+
],
|
|
104
|
+
isStateful: false,
|
|
105
|
+
};
|
|
106
|
+
|
|
107
|
+
await testPlugin.apply({ plan })
|
|
108
|
+
expect(resource.destroy.calledOnce).to.be.true;
|
|
109
|
+
expect(resource.create.calledOnce).to.be.true;
|
|
110
|
+
});
|
|
111
|
+
|
|
112
|
+
it('Can modify resource', async () => {
|
|
113
|
+
const resource = spy(new class extends TestResource {
|
|
114
|
+
async refresh(): Promise<Partial<TestConfig> | null> {
|
|
115
|
+
return {
|
|
116
|
+
propA: 'def',
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
})
|
|
120
|
+
const testPlugin = Plugin.create('testPlugin', [resource as any])
|
|
121
|
+
|
|
122
|
+
const plan: ApplyRequestData['plan'] = {
|
|
123
|
+
operation: ResourceOperation.MODIFY,
|
|
124
|
+
resourceType: 'testResource',
|
|
125
|
+
parameters: [
|
|
126
|
+
{ name: 'propA', operation: ParameterOperation.MODIFY, newValue: 'def', previousValue: 'abc' },
|
|
127
|
+
],
|
|
128
|
+
isStateful: false,
|
|
129
|
+
};
|
|
130
|
+
|
|
131
|
+
await testPlugin.apply({ plan })
|
|
132
|
+
expect(resource.modify.calledOnce).to.be.true;
|
|
133
|
+
});
|
|
134
|
+
|
|
135
|
+
it('Can get resource info', async () => {
|
|
136
|
+
const schema = {
|
|
137
|
+
'$schema': 'http://json-schema.org/draft-07/schema',
|
|
138
|
+
'$id': 'https://www.codifycli.com/asdf-schema.json',
|
|
139
|
+
'title': 'Asdf resource',
|
|
140
|
+
'type': 'object',
|
|
141
|
+
'properties': {
|
|
142
|
+
'plugins': {
|
|
143
|
+
'type': 'array',
|
|
144
|
+
'description': 'Asdf plugins to install. See: https://github.com/asdf-community for a full list',
|
|
145
|
+
'items': {
|
|
146
|
+
'type': 'string'
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
},
|
|
150
|
+
'required': ['plugins'],
|
|
151
|
+
'additionalProperties': false
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
|
|
155
|
+
const resource = new class extends TestResource {
|
|
156
|
+
getSettings(): ResourceSettings<TestConfig> {
|
|
157
|
+
return {
|
|
158
|
+
id: 'typeId',
|
|
159
|
+
operatingSystems: [OS.Darwin],
|
|
160
|
+
schema,
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
const testPlugin = Plugin.create('testPlugin', [resource as any])
|
|
165
|
+
|
|
166
|
+
const resourceInfo = await testPlugin.getResourceInfo({ type: 'typeId' })
|
|
167
|
+
expect(resourceInfo.import).toMatchObject({
|
|
168
|
+
requiredParameters: [
|
|
169
|
+
'plugins'
|
|
170
|
+
]
|
|
171
|
+
})
|
|
172
|
+
})
|
|
173
|
+
|
|
174
|
+
it('Can get resource info (zod schema)', async () => {
|
|
175
|
+
const schema = z
|
|
176
|
+
.object({
|
|
177
|
+
plugins: z
|
|
178
|
+
.array(z.string())
|
|
179
|
+
.describe(
|
|
180
|
+
'Asdf plugins to install. See: https://github.com/asdf-community for a full list'
|
|
181
|
+
)
|
|
182
|
+
})
|
|
183
|
+
.strict()
|
|
184
|
+
|
|
185
|
+
const resource = new class extends TestResource {
|
|
186
|
+
getSettings(): ResourceSettings<TestConfig> {
|
|
187
|
+
return {
|
|
188
|
+
id: 'typeId',
|
|
189
|
+
operatingSystems: [OS.Darwin],
|
|
190
|
+
schema,
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
const testPlugin = Plugin.create('testPlugin', [resource as any])
|
|
195
|
+
|
|
196
|
+
const resourceInfo = await testPlugin.getResourceInfo({ type: 'typeId' })
|
|
197
|
+
expect(resourceInfo.import).toMatchObject({
|
|
198
|
+
requiredParameters: [
|
|
199
|
+
'plugins'
|
|
200
|
+
]
|
|
201
|
+
})
|
|
202
|
+
})
|
|
203
|
+
|
|
204
|
+
it('Get resource info to default import to the one specified in the resource settings', async () => {
|
|
205
|
+
const schema = {
|
|
206
|
+
'$schema': 'http://json-schema.org/draft-07/schema',
|
|
207
|
+
'$id': 'https://www.codifycli.com/asdf-schema.json',
|
|
208
|
+
'title': 'Asdf resource',
|
|
209
|
+
'type': 'object',
|
|
210
|
+
'properties': {
|
|
211
|
+
'plugins': {
|
|
212
|
+
'type': 'array',
|
|
213
|
+
'description': 'Asdf plugins to install. See: https://github.com/asdf-community for a full list',
|
|
214
|
+
'items': {
|
|
215
|
+
'type': 'string'
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
},
|
|
219
|
+
'required': ['plugins'],
|
|
220
|
+
'additionalProperties': false
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
|
|
224
|
+
const resource = new class extends TestResource {
|
|
225
|
+
getSettings(): ResourceSettings<TestConfig> {
|
|
226
|
+
return {
|
|
227
|
+
id: 'typeId',
|
|
228
|
+
operatingSystems: [OS.Darwin],
|
|
229
|
+
schema,
|
|
230
|
+
importAndDestroy: {
|
|
231
|
+
requiredParameters: []
|
|
232
|
+
}
|
|
233
|
+
}
|
|
234
|
+
}
|
|
235
|
+
}
|
|
236
|
+
const testPlugin = Plugin.create('testPlugin', [resource as any])
|
|
237
|
+
|
|
238
|
+
const resourceInfo = await testPlugin.getResourceInfo({ type: 'typeId' })
|
|
239
|
+
expect(resourceInfo.import).toMatchObject({
|
|
240
|
+
requiredParameters: []
|
|
241
|
+
})
|
|
242
|
+
})
|
|
243
|
+
|
|
244
|
+
it('Fails an apply if the validation fails', async () => {
|
|
245
|
+
const resource = spy(new class extends TestResource {
|
|
246
|
+
async refresh(): Promise<Partial<TestConfig> | null> {
|
|
247
|
+
return {
|
|
248
|
+
propA: 'abc',
|
|
249
|
+
}
|
|
250
|
+
}
|
|
251
|
+
})
|
|
252
|
+
const testPlugin = Plugin.create('testPlugin', [resource as any])
|
|
253
|
+
|
|
254
|
+
const plan: ApplyRequestData['plan'] = {
|
|
255
|
+
operation: ResourceOperation.MODIFY,
|
|
256
|
+
resourceType: 'testResource',
|
|
257
|
+
parameters: [
|
|
258
|
+
{ name: 'propA', operation: ParameterOperation.MODIFY, newValue: 'def', previousValue: 'abc' },
|
|
259
|
+
],
|
|
260
|
+
isStateful: false,
|
|
261
|
+
};
|
|
262
|
+
|
|
263
|
+
await expect(() => testPlugin.apply({ plan }))
|
|
264
|
+
.rejects
|
|
265
|
+
.toThrowError();
|
|
266
|
+
expect(resource.modify.calledOnce).to.be.true;
|
|
267
|
+
})
|
|
268
|
+
|
|
269
|
+
it('Allows the usage of pty in refresh (plan)', async () => {
|
|
270
|
+
const resource = spy(new class extends TestResource {
|
|
271
|
+
async refresh(): Promise<Partial<TestConfig> | null> {
|
|
272
|
+
expect(getPty()).to.not.be.undefined;
|
|
273
|
+
expect(getPty()).to.not.be.null;
|
|
274
|
+
|
|
275
|
+
return null;
|
|
276
|
+
}
|
|
277
|
+
})
|
|
278
|
+
|
|
279
|
+
const testPlugin = Plugin.create('testPlugin', [resource as any]);
|
|
280
|
+
await testPlugin.plan({
|
|
281
|
+
core: { type: 'testResource' },
|
|
282
|
+
desired: {},
|
|
283
|
+
state: undefined,
|
|
284
|
+
isStateful: false,
|
|
285
|
+
})
|
|
286
|
+
|
|
287
|
+
expect(resource.refresh.calledOnce).to.be.true;
|
|
288
|
+
});
|
|
289
|
+
|
|
290
|
+
it('Allows the usage of pty in validation refresh (apply)', async () => {
|
|
291
|
+
const resource = spy(new class extends TestResource {
|
|
292
|
+
async refresh(): Promise<Partial<TestConfig> | null> {
|
|
293
|
+
expect(getPty()).to.not.be.undefined;
|
|
294
|
+
expect(getPty()).to.not.be.null;
|
|
295
|
+
|
|
296
|
+
return {
|
|
297
|
+
propA: 'abc'
|
|
298
|
+
};
|
|
299
|
+
}
|
|
300
|
+
})
|
|
301
|
+
|
|
302
|
+
const testPlugin = Plugin.create('testPlugin', [resource as any]);
|
|
303
|
+
|
|
304
|
+
const plan: ApplyRequestData['plan'] = {
|
|
305
|
+
operation: ResourceOperation.CREATE,
|
|
306
|
+
resourceType: 'testResource',
|
|
307
|
+
parameters: [
|
|
308
|
+
{ name: 'propA', operation: ParameterOperation.ADD, newValue: 'abc', previousValue: null },
|
|
309
|
+
],
|
|
310
|
+
isStateful: false,
|
|
311
|
+
};
|
|
312
|
+
|
|
313
|
+
await testPlugin.apply({ plan })
|
|
314
|
+
expect(resource.refresh.calledOnce).to.be.true;
|
|
315
|
+
})
|
|
316
|
+
|
|
317
|
+
it('Maintains types for validate', async () => {
|
|
318
|
+
const resource = new class extends TestResource {
|
|
319
|
+
getSettings(): ResourceSettings<TestConfig> {
|
|
320
|
+
return {
|
|
321
|
+
id: 'type',
|
|
322
|
+
operatingSystems: [OS.Darwin],
|
|
323
|
+
schema: {
|
|
324
|
+
'$schema': 'http://json-schema.org/draft-07/schema',
|
|
325
|
+
'$id': 'https://www.codifycli.com/ssh-config.json',
|
|
326
|
+
'type': 'object',
|
|
327
|
+
'properties': {
|
|
328
|
+
'hosts': {
|
|
329
|
+
'description': 'The host blocks inside of the ~/.ssh/config file. See http://man.openbsd.org/OpenBSD-current/man5/ssh_config.5 ',
|
|
330
|
+
'type': 'array',
|
|
331
|
+
'items': {
|
|
332
|
+
'type': 'object',
|
|
333
|
+
'description': 'The individual host blocks inside of the ~/.ssh/config file',
|
|
334
|
+
'properties': {
|
|
335
|
+
'UseKeychain': {
|
|
336
|
+
'type': 'boolean',
|
|
337
|
+
'description': 'A UseKeychain option was introduced in macOS Sierra allowing users to specify whether they would like for the passphrase to be stored in the keychain'
|
|
338
|
+
},
|
|
339
|
+
}
|
|
340
|
+
}
|
|
341
|
+
}
|
|
342
|
+
}
|
|
343
|
+
}
|
|
344
|
+
}
|
|
345
|
+
};
|
|
346
|
+
}
|
|
347
|
+
|
|
348
|
+
const plugin = Plugin.create('testPlugin', [resource as any]);
|
|
349
|
+
const result = await plugin.validate({
|
|
350
|
+
configs: [{
|
|
351
|
+
core: { type: 'type' },
|
|
352
|
+
parameters: {
|
|
353
|
+
hosts: [{
|
|
354
|
+
UseKeychain: true,
|
|
355
|
+
}]
|
|
356
|
+
}
|
|
357
|
+
}]
|
|
358
|
+
})
|
|
359
|
+
|
|
360
|
+
console.log(result);
|
|
361
|
+
})
|
|
362
|
+
|
|
363
|
+
it('Returns allowMultiple for getResourceInfo', async () => {
|
|
364
|
+
const resource = spy(new class extends TestResource {
|
|
365
|
+
getSettings(): ResourceSettings<TestConfig> {
|
|
366
|
+
return {
|
|
367
|
+
...super.getSettings(),
|
|
368
|
+
operatingSystems: [OS.Darwin],
|
|
369
|
+
allowMultiple: {
|
|
370
|
+
identifyingParameters: ['path', 'paths']
|
|
371
|
+
}
|
|
372
|
+
}
|
|
373
|
+
}
|
|
374
|
+
})
|
|
375
|
+
|
|
376
|
+
const testPlugin = Plugin.create('testPlugin', [resource as any]);
|
|
377
|
+
|
|
378
|
+
const resourceInfo = await testPlugin.getResourceInfo({
|
|
379
|
+
type: 'testResource',
|
|
380
|
+
})
|
|
381
|
+
|
|
382
|
+
expect(resourceInfo.allowMultiple).to.be.true;
|
|
383
|
+
})
|
|
384
|
+
|
|
385
|
+
it('Can match resources together', async () => {
|
|
386
|
+
const resource = spy(new class extends TestResource {
|
|
387
|
+
getSettings(): ResourceSettings<TestConfig> {
|
|
388
|
+
return {
|
|
389
|
+
...super.getSettings(),
|
|
390
|
+
operatingSystems: [OS.Darwin],
|
|
391
|
+
parameterSettings: {
|
|
392
|
+
path: { type: 'directory' },
|
|
393
|
+
paths: { type: 'array', itemType: 'directory' }
|
|
394
|
+
},
|
|
395
|
+
allowMultiple: {
|
|
396
|
+
identifyingParameters: ['path', 'paths']
|
|
397
|
+
}
|
|
398
|
+
}
|
|
399
|
+
}
|
|
400
|
+
})
|
|
401
|
+
|
|
402
|
+
const testPlugin = Plugin.create('testPlugin', [resource as any]);
|
|
403
|
+
|
|
404
|
+
const { match } = await testPlugin.match({
|
|
405
|
+
resource: {
|
|
406
|
+
core: { type: 'testResource' },
|
|
407
|
+
parameters: { path: '/my/path', propA: 'abc' },
|
|
408
|
+
},
|
|
409
|
+
array: [
|
|
410
|
+
{
|
|
411
|
+
core: { type: 'testResource' },
|
|
412
|
+
parameters: { path: '/my/other/path', propA: 'abc' },
|
|
413
|
+
},
|
|
414
|
+
{
|
|
415
|
+
core: { type: 'testResource' },
|
|
416
|
+
parameters: { paths: ['/my/path'], propA: 'def' },
|
|
417
|
+
},
|
|
418
|
+
{
|
|
419
|
+
core: { type: 'testResource' },
|
|
420
|
+
parameters: { path: '/my/path', propA: 'hig' },
|
|
421
|
+
},
|
|
422
|
+
]
|
|
423
|
+
})
|
|
424
|
+
expect(match).toMatchObject({
|
|
425
|
+
core: { type: 'testResource' },
|
|
426
|
+
parameters: { path: '/my/path', propA: 'hig' },
|
|
427
|
+
})
|
|
428
|
+
|
|
429
|
+
const match2 = await testPlugin.match({
|
|
430
|
+
resource: {
|
|
431
|
+
core: { type: 'testResource' },
|
|
432
|
+
parameters: { path: '/my/path', propA: 'abc' },
|
|
433
|
+
},
|
|
434
|
+
array: []
|
|
435
|
+
})
|
|
436
|
+
|
|
437
|
+
expect(match2).toMatchObject({
|
|
438
|
+
match: undefined,
|
|
439
|
+
})
|
|
440
|
+
})
|
|
441
|
+
|
|
442
|
+
it('Can match resources together 2', { timeout: 3000000 }, async () => {
|
|
443
|
+
const resource = spy(new class extends TestResource {
|
|
444
|
+
getSettings(): ResourceSettings<TestConfig> {
|
|
445
|
+
return {
|
|
446
|
+
id: 'ssh-config',
|
|
447
|
+
operatingSystems: [OS.Darwin],
|
|
448
|
+
parameterSettings: {
|
|
449
|
+
hosts: { type: 'stateful', definition: new TestStatefulParameter() }
|
|
450
|
+
},
|
|
451
|
+
importAndDestroy: {
|
|
452
|
+
refreshKeys: ['hosts'],
|
|
453
|
+
defaultRefreshValues: { hosts: [] },
|
|
454
|
+
requiredParameters: []
|
|
455
|
+
},
|
|
456
|
+
dependencies: ['ssh-key'],
|
|
457
|
+
allowMultiple: {
|
|
458
|
+
matcher: (a, b) => a.hosts === b.hosts
|
|
459
|
+
}
|
|
460
|
+
}
|
|
461
|
+
}
|
|
462
|
+
})
|
|
463
|
+
|
|
464
|
+
const testPlugin = Plugin.create('testPlugin', [resource as any]);
|
|
465
|
+
|
|
466
|
+
const { match } = await testPlugin.match({
|
|
467
|
+
resource: {
|
|
468
|
+
core: { type: 'ssh-config' },
|
|
469
|
+
parameters: { hosts: 'a' },
|
|
470
|
+
},
|
|
471
|
+
array: [
|
|
472
|
+
{
|
|
473
|
+
core: { type: 'ssh-config' },
|
|
474
|
+
parameters: { hosts: 'b' },
|
|
475
|
+
},
|
|
476
|
+
{
|
|
477
|
+
core: { type: 'ssh-config' },
|
|
478
|
+
parameters: { hosts: 'a' },
|
|
479
|
+
},
|
|
480
|
+
{
|
|
481
|
+
core: { type: 'ssh-config' },
|
|
482
|
+
parameters: { hosts: 'c' },
|
|
483
|
+
},
|
|
484
|
+
]
|
|
485
|
+
})
|
|
486
|
+
|
|
487
|
+
console.log(match)
|
|
488
|
+
})
|
|
489
|
+
|
|
490
|
+
it('Validates that a config correctly allows multiple of a config when allowMultiple is true', async () => {
|
|
491
|
+
const resource = spy(new class extends TestResource {
|
|
492
|
+
getSettings(): ResourceSettings<TestConfig> {
|
|
493
|
+
return {
|
|
494
|
+
id: 'ssh-config',
|
|
495
|
+
operatingSystems: [OS.Darwin],
|
|
496
|
+
allowMultiple: true
|
|
497
|
+
}
|
|
498
|
+
}
|
|
499
|
+
})
|
|
500
|
+
|
|
501
|
+
const testPlugin = Plugin.create('testPlugin', [resource as any]);
|
|
502
|
+
|
|
503
|
+
const validate1 = await testPlugin.validate({
|
|
504
|
+
configs: [{ core: { type: 'ssh-config' }, parameters: { propA: 'a' } }, {
|
|
505
|
+
core: { type: 'ssh-config' },
|
|
506
|
+
parameters: { propB: 'b' }
|
|
507
|
+
}]
|
|
508
|
+
})
|
|
509
|
+
|
|
510
|
+
expect(validate1.resourceValidations.every((r) => r.isValid)).to.be.true;
|
|
511
|
+
})
|
|
512
|
+
|
|
513
|
+
it('Validates that a config correctly dis-allows multiple of a config when allowMultiple is false', async () => {
|
|
514
|
+
const resource = spy(new class extends TestResource {
|
|
515
|
+
getSettings(): ResourceSettings<TestConfig> {
|
|
516
|
+
return {
|
|
517
|
+
id: 'ssh-config',
|
|
518
|
+
operatingSystems: [OS.Darwin],
|
|
519
|
+
}
|
|
520
|
+
}
|
|
521
|
+
})
|
|
522
|
+
|
|
523
|
+
const testPlugin = Plugin.create('testPlugin', [resource as any]);
|
|
524
|
+
|
|
525
|
+
await expect(() => testPlugin.validate({
|
|
526
|
+
configs: [{ core: { type: 'ssh-config' }, parameters: { propA: 'a' } }, {
|
|
527
|
+
core: { type: 'ssh-config' },
|
|
528
|
+
parameters: { propB: 'b' }
|
|
529
|
+
}]
|
|
530
|
+
})
|
|
531
|
+
).rejects.toThrowError();
|
|
532
|
+
})
|
|
533
|
+
});
|