Skip to content

Commit

Permalink
Merge pull request #483 from SquirrelCorporation/feat-add-repo-supports
Browse files Browse the repository at this point in the history
[FEAT] Add support for multiple Git services
  • Loading branch information
SquirrelDeveloper authored Nov 15, 2024
2 parents 88c778d + bbc6e9f commit d3eb8f5
Show file tree
Hide file tree
Showing 32 changed files with 370 additions and 96 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import React, { useState } from 'react';
import { API } from 'ssm-shared-lib';

type DirectoryExclusionFormProps = {
selectedRecord: Partial<API.LocalRepository>;
selectedRecord: Partial<API.LocalPlaybooksRepository>;
};

const DirectoryExclusionForm: React.FC<DirectoryExclusionFormProps> = (
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,11 @@
import { ProForm, ProFormText } from '@ant-design/pro-components';
import { capitalizeFirstLetter } from '@/utils/strings';
import {
ProForm,
ProFormSelect,
ProFormText,
} from '@ant-design/pro-components';
import React from 'react';
import { API } from 'ssm-shared-lib';
import { API, SsmGit } from 'ssm-shared-lib';

export type GitFormProps = {
selectedRecord: Partial<
Expand Down Expand Up @@ -33,6 +38,17 @@ const GitForm: React.FC<GitFormProps> = ({ selectedRecord, repositories }) => (
},
]}
/>
<ProFormSelect
width={'md'}
name={'gitService'}
label={'Git Service'}
options={Object.values(SsmGit.Services).map((e) => ({
label: capitalizeFirstLetter(e),
value: e,
}))}
rules={[{ required: true }]}
initialValue={selectedRecord?.gitService || SsmGit.Services.Github}
/>
<ProFormText
width={'md'}
name={'email'}
Expand Down
33 changes: 11 additions & 22 deletions server/src/controllers/rest/containers-stacks-repository/git.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { API } from 'ssm-shared-lib';
import ContainerCustomStackRepositoryRepo from '../../../data/database/repository/ContainerCustomStackRepositoryRepo';
import { NotFoundError } from '../../../middlewares/api/ApiError';
import { SuccessResponse } from '../../../middlewares/api/ApiResponse';
Expand All @@ -15,22 +16,16 @@ export const addGitRepository = async (req, res) => {
userName,
remoteUrl,
matchesList,
}: {
name: string;
accessToken: string;
branch: string;
email: string;
userName: string;
remoteUrl: string;
matchesList?: string[];
} = req.body;
gitService,
}: API.GitContainerStacksRepository = req.body;
await GitRepositoryUseCases.addGitRepository(
name,
await vaultEncrypt(accessToken, DEFAULT_VAULT_ID),
await vaultEncrypt(accessToken as string, DEFAULT_VAULT_ID),
branch,
email,
userName,
remoteUrl,
gitService,
matchesList,
);
new SuccessResponse('Added container stacks git repository').send(res);
Expand All @@ -52,26 +47,20 @@ export const updateGitRepository = async (req, res) => {
accessToken,
branch,
email,
gitUserName,
userName,
remoteUrl,
matchesList,
}: {
name: string;
accessToken: string;
branch: string;
email: string;
gitUserName: string;
remoteUrl: string;
matchesList?: string[];
} = req.body;
gitService,
}: API.GitContainerStacksRepository = req.body;
await GitRepositoryUseCases.updateGitRepository(
uuid,
name,
await vaultEncrypt(accessToken, DEFAULT_VAULT_ID),
await vaultEncrypt(accessToken as string, DEFAULT_VAULT_ID),
branch,
email,
gitUserName,
userName,
remoteUrl,
gitService,
matchesList,
);
new SuccessResponse('Updated container stacks git repository').send(res);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { body, param } from 'express-validator';
import { SsmGit } from 'ssm-shared-lib';
import validator from '../../../middlewares/Validator';

export const addGitRepositoryValidator = [
Expand All @@ -9,6 +10,10 @@ export const addGitRepositoryValidator = [
body('userName').exists().isString().withMessage('userName is incorrect'),
body('remoteUrl').exists().isURL().withMessage('remoteUrl is incorrect'),
body('matchesList').exists().isArray().withMessage('matchesList is incorrect'),
body('gitService')
.exists()
.isIn(Object.values(SsmGit.Services))
.withMessage('Git service is required'),
validator,
];

Expand All @@ -21,6 +26,10 @@ export const updateGitRepositoryValidator = [
body('userName').exists().isString().withMessage('userName is incorrect'),
body('remoteUrl').exists().isURL().withMessage('remoteUrl is incorrect'),
body('matchesList').exists().isArray().withMessage('matchesListis incorrect'),
body('gitService')
.exists()
.isIn(Object.values(SsmGit.Services))
.withMessage('Git service is required'),
validator,
];

Expand Down
34 changes: 11 additions & 23 deletions server/src/controllers/rest/playbooks-repository/git.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { Repositories } from 'ssm-shared-lib';
import { API, Repositories } from 'ssm-shared-lib';
import PlaybooksRepositoryRepo from '../../../data/database/repository/PlaybooksRepositoryRepo';
import { NotFoundError } from '../../../middlewares/api/ApiError';
import { SuccessResponse } from '../../../middlewares/api/ApiResponse';
Expand All @@ -17,22 +17,16 @@ export const addGitRepository = async (req, res) => {
userName,
remoteUrl,
directoryExclusionList,
}: {
name: string;
accessToken: string;
branch: string;
email: string;
userName: string;
remoteUrl: string;
directoryExclusionList?: string[];
} = req.body;
gitService,
}: API.GitPlaybooksRepository = req.body;
await GitRepositoryUseCases.addGitRepository(
name,
await vaultEncrypt(accessToken, DEFAULT_VAULT_ID),
await vaultEncrypt(accessToken as string, DEFAULT_VAULT_ID),
branch,
email,
userName,
remoteUrl,
gitService,
directoryExclusionList,
);
new SuccessResponse('Added playbooks git repository').send(res);
Expand All @@ -56,27 +50,21 @@ export const updateGitRepository = async (req, res) => {
accessToken,
branch,
email,
gitUserName,
userName,
remoteUrl,
directoryExclusionList,
}: {
name: string;
accessToken: string;
branch: string;
email: string;
gitUserName: string;
remoteUrl: string;
directoryExclusionList?: string[];
} = req.body;
gitService,
}: API.GitPlaybooksRepository = req.body;

await GitRepositoryUseCases.updateGitRepository(
uuid,
name,
await vaultEncrypt(accessToken, DEFAULT_VAULT_ID),
await vaultEncrypt(accessToken as string, DEFAULT_VAULT_ID),
branch,
email,
gitUserName,
userName,
remoteUrl,
gitService,
directoryExclusionList,
);
new SuccessResponse('Updated playbooks git repository').send(res);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { body, param } from 'express-validator';
import { SsmGit } from 'ssm-shared-lib';
import validator from '../../../middlewares/Validator';

export const addGitRepositoryValidator = [
Expand All @@ -12,6 +13,10 @@ export const addGitRepositoryValidator = [
.optional()
.isArray()
.withMessage('Directory exclusion list is incorrect'),
body('gitService')
.exists()
.isIn(Object.values(SsmGit.Services))
.withMessage('Git service is required'),
validator,
];

Expand All @@ -27,6 +32,10 @@ export const updateGitRepositoryValidator = [
.optional()
.isArray()
.withMessage('Directory exclusion list is incorrect'),
body('gitService')
.exists()
.isIn(Object.values(SsmGit.Services))
.withMessage('Git service is required'),
validator,
];

Expand Down
141 changes: 119 additions & 22 deletions server/src/core/startup/index.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
import { Repositories, SettingsKeys } from 'ssm-shared-lib';
import { Repositories, SettingsKeys, SsmGit } from 'ssm-shared-lib';
import { v4 as uuidv4 } from 'uuid';
import { getFromCache, setToCache } from '../../data/cache';
import initRedisValues from '../../data/cache/defaults';
import { ContainerCustomStackModel } from '../../data/database/model/ContainerCustomStack';
import { ContainerCustomStacksRepositoryModel } from '../../data/database/model/ContainerCustomStackRepository';
import { ContainerVolumeModel } from '../../data/database/model/ContainerVolume';
import { DeviceModel } from '../../data/database/model/Device';
import { PlaybookModel } from '../../data/database/model/Playbook';
import { PlaybooksRepositoryModel } from '../../data/database/model/PlaybooksRepository';
import { copyAnsibleCfgFileIfDoesntExist } from '../../helpers/ansible/AnsibleConfigurationHelper';
import PinoLogger from '../../logger';
import AutomationEngine from '../../modules/automations/AutomationEngine';
Expand All @@ -27,10 +29,10 @@ class Startup {
async init() {
this.logger.info(`Initializing...`);
const schemeVersion = await this.initializeSchemeVersion();
await this.initializeModules();
if (this.isSchemeVersionDifferent(schemeVersion)) {
await this.updateScheme();
}
await this.initializeModules();
}

private async initializeSchemeVersion(): Promise<string | null> {
Expand All @@ -51,27 +53,122 @@ class Startup {
}

private async updateScheme() {
this.logger.warn(`updateScheme- Scheme version differed, starting applying updates...`);
await PlaybookModel.syncIndexes();
await DeviceModel.syncIndexes();
await createADefaultLocalUserRepository();
await initRedisValues();
void setAnsibleVersions();
await PlaybooksRepositoryEngine.syncAllRegistered();
this.registerPersistedProviders();
copyAnsibleCfgFileIfDoesntExist();
const masterNodeUrl = await getFromCache('_ssm_masterNodeUrl');
if (!masterNodeUrl) {
await setToCache('_ssm_masterNodeUrl', (await getFromCache('ansible-master-node-url')) || '');
this.logger.warn('updateScheme - Scheme version differed, starting applying updates...');
try {
await PlaybookModel.syncIndexes();
this.logger.info('PlaybookModel indexes synchronized successfully.');
} catch (error: any) {
this.logger.error(`Error synchronizing PlaybookModel indexes: ${error.message}`);
}

try {
await DeviceModel.syncIndexes();
this.logger.info('DeviceModel indexes synchronized successfully.');
} catch (error: any) {
this.logger.error(`Error synchronizing DeviceModel indexes: ${error.message}`);
}

try {
await createADefaultLocalUserRepository();
this.logger.info('Created default local user repository successfully.');
} catch (error: any) {
this.logger.error(`Error creating default local user repository: ${error.message}`);
}

try {
await initRedisValues();
this.logger.info('Initialized Redis values successfully.');
} catch (error: any) {
this.logger.error(`Error initializing Redis values: ${error.message}`);
}

try {
void setAnsibleVersions(); // Setting versions asynchronously without waiting
this.logger.info('Ansible versions set successfully.');
} catch (error: any) {
this.logger.error(`Error setting Ansible versions: ${error.message}`);
}

try {
await PlaybooksRepositoryEngine.syncAllRegistered();
this.logger.info('All registered playbooks synced successfully.');
} catch (error: any) {
this.logger.error(`Error syncing all registered playbooks: ${error.message}`);
}

try {
this.registerPersistedProviders();
this.logger.info('Persisted providers registered successfully.');
} catch (error: any) {
this.logger.error(`Error registering persisted providers: ${error.message}`);
}
await ContainerCustomStackModel.updateMany(
{ type: { $exists: false } },
{ $set: { type: Repositories.RepositoryType.LOCAL } },
);
const containerVolumes = await ContainerVolumeModel.find({ uuid: { $exists: false } });
for (const volume of containerVolumes) {
volume.uuid = uuidv4();
await volume.save();

try {
copyAnsibleCfgFileIfDoesntExist();
this.logger.info("Ansible configuration file copied if it didn't exist.");
} catch (error: any) {
this.logger.error(`Error copying Ansible configuration file: ${error.message}`);
}

try {
const masterNodeUrl = await getFromCache('_ssm_masterNodeUrl');
if (!masterNodeUrl) {
await setToCache(
'_ssm_masterNodeUrl',
(await getFromCache('ansible-master-node-url')) || '',
);
this.logger.info('Master Node URL set in cache successfully.');
}
} catch (error: any) {
this.logger.error(`Error managing master node URL in cache: ${error.message}`);
}

try {
await ContainerCustomStackModel.updateMany(
{ type: { $exists: false } },
{ $set: { type: Repositories.RepositoryType.LOCAL } },
);
this.logger.info('Container custom stack models updated successfully.');
} catch (error: any) {
this.logger.error(`Error updating container custom stack models: ${error.message}`);
}

try {
const containerVolumes = await ContainerVolumeModel.find({ uuid: { $exists: false } });
for (const volume of containerVolumes) {
volume.uuid = uuidv4();
await volume.save();
}
this.logger.info('Container volumes updated successfully.');
} catch (error: any) {
this.logger.error(`Error updating container volumes: ${error.message}`);
}

try {
const containerCustomStackRepositories = await ContainerCustomStacksRepositoryModel.find({
gitService: { $exists: false },
});
for (const repo of containerCustomStackRepositories) {
repo.gitService = SsmGit.Services.Github;
await repo.save();
}
this.logger.info('Container custom stack repositories updated successfully.');
} catch (error: any) {
this.logger.error(`Error updating container custom stack repositories: ${error.message}`);
}

try {
const playbookGitRepositories = await PlaybooksRepositoryModel.find({
gitService: { $exists: false },
type: Repositories.RepositoryType.GIT,
});
for (const repo of playbookGitRepositories) {
repo.gitService = SsmGit.Services.Github;
await repo.save();
}
this.logger.info('Playbook Git repositories updated successfully.');
} catch (error: any) {
this.logger.error(`Error updating playbook Git repositories: ${error.message}`);
}
}

Expand Down
Loading

0 comments on commit d3eb8f5

Please sign in to comment.