Skip to content

Commit dbce9ff

Browse files
committed
fix: Fixed bug with ssh config resource not handling comments
1 parent a009fce commit dbce9ff

File tree

4 files changed

+65
-28
lines changed

4 files changed

+65
-28
lines changed

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@
2323
"ajv": "^8.12.0",
2424
"ajv-formats": "^2.1.1",
2525
"semver": "^7.6.0",
26-
"codify-plugin-lib": "1.0.174",
26+
"codify-plugin-lib": "1.0.175",
2727
"codify-schemas": "1.0.63",
2828
"chalk": "^5.3.0",
2929
"debug": "^4.3.4",

src/resources/ssh/ssh-config-hosts-parameter.ts

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,7 @@ export class SshConfigHostsParameter extends StatefulParameter<SshConfig, SshCon
6161
async refresh(): Promise<SshConfigOptions[] | null> {
6262
const filePath = path.resolve(os.homedir(), '.ssh', 'config');
6363

64-
const sshConfigFile = await fs.readFile(filePath, 'utf8');
64+
const sshConfigFile = await fs.readFile(filePath, 'utf8')
6565
const hostBlocks = this.parseHostBlocks(sshConfigFile);
6666

6767
return this.parseHostObjects(hostBlocks);
@@ -171,7 +171,9 @@ export class SshConfigHostsParameter extends StatefulParameter<SshConfig, SshCon
171171
}
172172

173173
private parseHostBlocks(sshConfigFile: string): string[] {
174-
return sshConfigFile.split(SSH_CONFIG_REGEX)
174+
return sshConfigFile
175+
.replaceAll(/#(.*)[\n\r]/g, '') // Remove all comments
176+
.split(SSH_CONFIG_REGEX)
175177
.filter(Boolean)
176178
}
177179

Lines changed: 22 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import { describe, expect, it } from 'vitest';
2-
import { SshKeyResource } from './ssh-key.js';
32
import { SshConfigFileResource } from './ssh-config.js';
3+
import { SshConfigHostsParameter } from './ssh-config-hosts-parameter';
44

55
describe('Ssh config unit test', () => {
66
it('Can parse a ssh config file', async () => {
@@ -11,35 +11,32 @@ describe('Ssh config unit test', () => {
1111
})
1212

1313
it('Can remap the input hosts objects', async () => {
14-
const resource = new SshConfigFileResource();
15-
const transformedInput = resource.getSettings().transformation?.to({
16-
hosts: [
17-
{
18-
Host: '*',
19-
HostName: 'test',
20-
IdentityFile: '~/.ssh/id_ed25519',
21-
AddKeysToAgent: true
22-
},
23-
{
24-
Host: '192.168.0.1',
25-
User: 'pi'
26-
}
27-
]
28-
})
14+
const resource = new SshConfigHostsParameter();
15+
const transformedInput = resource.getSettings().transformation?.to([
16+
{
17+
Host: '*',
18+
HostName: 'test',
19+
IdentityFile: '~/.ssh/id_ed25519',
20+
AddKeysToAgent: true
21+
},
22+
{
23+
Host: '192.168.0.1',
24+
User: 'pi'
25+
}
26+
])
2927

30-
expect(transformedInput).toMatchObject({
31-
"hosts": [
28+
expect(transformedInput).toMatchObject([
3229
{
33-
"Host": "*",
34-
"HostName": "test",
35-
"IdentityFile": "~/.ssh/id_ed25519",
36-
"AddKeysToAgent": "yes"
30+
'Host': '*',
31+
'HostName': 'test',
32+
'IdentityFile': '~/.ssh/id_ed25519',
33+
'AddKeysToAgent': 'yes'
3734
},
3835
{
39-
"Host": "192.168.0.1",
40-
"User": "pi"
36+
'Host': '192.168.0.1',
37+
'User': 'pi'
4138
}
4239
]
43-
})
40+
)
4441
})
4542
})

test/ssh/ssh-config.test.ts

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@ import { PluginTester } from 'codify-plugin-test';
33
import * as path from 'node:path';
44
import * as fs from 'node:fs/promises';
55
import * as os from 'node:os';
6+
import { PluginProcess } from 'codify-plugin-test/dist/plugin-process';
7+
import { ResourceOperation } from 'codify-schemas';
68

79
describe('Ssh config tests', () => {
810
const pluginPath = path.resolve('./src/index.ts');
@@ -92,6 +94,42 @@ Host github.com
9294
})
9395
})
9496

97+
it('Can handle a file with comments', { timeout: 300000 }, async () => {
98+
const configPath = path.join(os.homedir(), '.ssh', 'config');
99+
100+
const existingFile = await fs.readFile(configPath, 'utf8')
101+
await fs.writeFile(configPath, '# This is a comment\n' + existingFile, 'utf8');
102+
103+
const plugin = new PluginProcess(pluginPath);
104+
const plan = await plugin.plan({
105+
core: {
106+
type: 'ssh-config'
107+
},
108+
desired: {
109+
hosts: [
110+
{
111+
Host: 'new.com',
112+
AddKeysToAgent: true,
113+
IdentityFile: 'id_ed25519'
114+
},
115+
{
116+
Host: 'github.com',
117+
AddKeysToAgent: true,
118+
UseKeychain: true,
119+
},
120+
{
121+
Match: 'User bob,joe,phil',
122+
PasswordAuthentication: true,
123+
}
124+
],
125+
},
126+
state: undefined,
127+
isStateful: false
128+
})
129+
130+
expect(plan.operation).to.eq(ResourceOperation.NOOP)
131+
})
132+
95133
it('Can match similar host names + destroy a .ssh/config file by renaming it', { timeout: 300000 }, async () => {
96134
await PluginTester.fullTest(pluginPath, [
97135
{

0 commit comments

Comments
 (0)