Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix: active/standby support for environments with slash in the name #3214

Merged
merged 5 commits into from
Sep 6, 2022
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
2 changes: 1 addition & 1 deletion node-packages/commons/src/tasks.ts
Original file line number Diff line number Diff line change
Expand Up @@ -332,7 +332,7 @@ export const createTaskMonitor = async function(task: string, payload: any) {
}

// makes strings "safe" if it is to be used in something dns related
const makeSafe = string => string.toLocaleLowerCase().replace(/[^0-9a-z-]/g,'-')
export const makeSafe = string => string.toLocaleLowerCase().replace(/[^0-9a-z-]/g,'-')

// @TODO: make sure if it fails, it does so properly
export const getControllerBuildData = async function(deployData: any) {
Expand Down
92 changes: 65 additions & 27 deletions services/api/src/resources/deployment/resolvers.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,14 @@
// @ts-ignore
import * as R from 'ramda';
// @ts-ignore
import { sendToLagoonLogs } from '@lagoon/commons/dist/logs';
import {
createDeployTask,
createMiscTask,
createPromoteTask,
sendToLagoonActions
sendToLagoonActions,
makeSafe
// @ts-ignore
} from '@lagoon/commons/dist/tasks';
import { ResolverFn } from '../';
import {
Expand All @@ -18,18 +22,28 @@ import { Helpers } from './helpers';
import { EVENTS } from './events';
import { Helpers as environmentHelpers } from '../environment/helpers';
import { Helpers as projectHelpers } from '../project/helpers';
// @ts-ignore
import { addTask } from '@lagoon/commons/dist/api';
import { Sql as environmentSql } from '../environment/sql';
// @ts-ignore
import S3 from 'aws-sdk/clients/s3';
// @ts-ignore
import sha1 from 'sha1';
// @ts-ignore
import { generateBuildId, jsonMerge } from '@lagoon/commons/dist/util';
import { logger } from '../../loggers/logger';
// @ts-ignore
import uuid4 from 'uuid4';

// @ts-ignore
const accessKeyId = process.env.S3_FILES_ACCESS_KEY_ID || 'minio'
// @ts-ignore
const secretAccessKey = process.env.S3_FILES_SECRET_ACCESS_KEY || 'minio123'
// @ts-ignore
const bucket = process.env.S3_FILES_BUCKET || 'lagoon-files'
// @ts-ignore
const region = process.env.S3_FILES_REGION
// @ts-ignore
const s3Origin = process.env.S3_FILES_HOST || 'http://docker.for.mac.localhost:9000'

const config = {
Expand Down Expand Up @@ -88,6 +102,7 @@ export const getBuildLog: ResolverFn = async (
if (!data) {
return null;
}
// @ts-ignore
let logMsg = new Buffer(JSON.parse(JSON.stringify(data.Body)).data).toString('ascii');
return logMsg;
} catch (e) {
Expand Down Expand Up @@ -736,7 +751,6 @@ export const deployEnvironmentBranch: ResolverFn = async (
meta,
`*[${deployData.projectName}]* Error deploying \`${deployData.branchName}\`: ${error}`
);
console.log(error);
return `Error: ${error}`;
}
}
Expand Down Expand Up @@ -1008,28 +1022,52 @@ export const switchActiveStandby: ResolverFn = async (
);
return `Error: no standbyProductionEnvironment configured`;
}

var environmentStandbyId
var environmentProdId
var environmentProd
var environmentStandby
// we want the task to show in the standby environment, as this is where the task will be initiated.
const environmentRows = await query(
sqlClientPool,
environmentSql.selectEnvironmentByNameAndProject(
project.standbyProductionEnvironment,
project.id
)
);
const environment = environmentRows[0];
var environmentId = parseInt(environment.id);
// we need to pass some additional information about the production environment
const environmentRowsProd = await query(
sqlClientPool,
environmentSql.selectEnvironmentByNameAndProject(
project.productionEnvironment,
project.id
)
);
const environmentProd = environmentRowsProd[0];
var environmentProdId = parseInt(environmentProd.id);
try {
// maybe the environments have slashes in their names
// get all the environments for this project
const environmentsForProject = await query(
sqlClientPool,
environmentSql.selectEnvironmentsByProjectID(
project.id
)
);
for (const envForProject of environmentsForProject) {
// check the environments to see if their name when made "safe" matches what is defined in the `production` or `standbyProduction` environment
if (makeSafe(envForProject.name) == project.productionEnvironment) {
const environmentRowsProd = await query(
sqlClientPool,
environmentSql.selectEnvironmentByNameAndProject(
envForProject.name,
project.id
)
);
environmentProd = environmentRowsProd[0];
environmentProdId = parseInt(environmentProd.id);
}
if (makeSafe(envForProject.name) == project.standbyProductionEnvironment) {
const environmentRows = await query(
sqlClientPool,
environmentSql.selectEnvironmentByNameAndProject(
envForProject.name,
project.id
)
);
environmentStandby = environmentRows[0];
environmentStandbyId = parseInt(environmentStandby.id);
}
}
} catch (err) {
throw new Error(`Unable to determine active standby environments: ${err}`);
}

if (environmentStandbyId === undefined || environmentProdId === undefined) {
throw new Error(`Unable to determine active standby environments`);
}
// construct the data for the misc task
// set up the task data payload
const data = {
Expand All @@ -1045,9 +1083,9 @@ export const switchActiveStandby: ResolverFn = async (
openshiftProjectName: environmentProd.openshiftProjectName
},
environment: {
id: environmentId,
name: environment.name,
openshiftProjectName: environment.openshiftProjectName
id: environmentStandbyId,
name: environmentStandby.name,
openshiftProjectName: environmentStandby.openshiftProjectName
},
task: {
id: '0',
Expand All @@ -1064,7 +1102,7 @@ export const switchActiveStandby: ResolverFn = async (
'Active/Standby Switch',
'ACTIVE',
created,
environmentId,
environmentStandbyId,
null,
null,
null,
Expand All @@ -1081,7 +1119,7 @@ export const switchActiveStandby: ResolverFn = async (
// return the task id and remote id
var retData = {
id: data.task.id,
environment: environmentId
environment: environmentStandbyId
};
return retData;
} catch (error) {
Expand Down
5 changes: 5 additions & 0 deletions services/api/src/resources/environment/sql.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,11 @@ export const Sql = {
.where('name', '=', name)
.andWhere('project', '=', projectId)
.toString(),
selectEnvironmentsByProjectID: (projectId: number) =>
knex('environment')
.select('id', 'name')
.where('project', '=', projectId)
.toString(),
truncateEnvironment: () =>
knex('environment')
.truncate()
Expand Down
11 changes: 6 additions & 5 deletions services/ui/src/components/Environment/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import { bp, color } from 'lib/variables';
import Router from 'next/router';
import ActiveStandbyConfirm from 'components/ActiveStandbyConfirm';
import SwitchActiveStandbyMutation from 'lib/mutation/SwitchActiveStandby';
import { makeSafe } from 'lib/util';

/**
* Displays the environment information.
Expand All @@ -26,8 +27,8 @@ const Environment = ({ environment }) => {
<label>Environment Type</label>
<div className="field">
{environment.environmentType}
{environment.project.productionEnvironment && environment.project.standbyProductionEnvironment && environment.environmentType == 'production' && environment.project.productionEnvironment == environment.name &&
(" (active)")}{environment.project.productionEnvironment && environment.project.standbyProductionEnvironment && environment.environmentType == 'production' && environment.project.standbyProductionEnvironment == environment.name && (" (standby)")}
{environment.project.productionEnvironment && environment.project.standbyProductionEnvironment && environment.environmentType == 'production' && environment.project.productionEnvironment == makeSafe(environment.name) &&
(" (active)")}{environment.project.productionEnvironment && environment.project.standbyProductionEnvironment && environment.environmentType == 'production' && environment.project.standbyProductionEnvironment == makeSafe(environment.name) && (" (standby)")}
</div>
</div>
</div>
Expand Down Expand Up @@ -74,7 +75,7 @@ const Environment = ({ environment }) => {
</div>
</div>
<div className="field-wrapper routes">
{environment.project.productionEnvironment && environment.project.standbyProductionEnvironment && environment.environmentType == 'production' && environment.project.productionEnvironment == environment.name && (
{environment.project.productionEnvironment && environment.project.standbyProductionEnvironment && environment.environmentType == 'production' && environment.project.productionEnvironment == makeSafe(environment.name) && (
<div>
<label>Active Environment Routes</label>
<div className="field">
Expand All @@ -89,7 +90,7 @@ const Environment = ({ environment }) => {
: ''}
</div>
</div>)}
{environment.project.productionEnvironment && environment.project.standbyProductionEnvironment && environment.environmentType == 'production' && environment.project.standbyProductionEnvironment == environment.name && (
{environment.project.productionEnvironment && environment.project.standbyProductionEnvironment && environment.environmentType == 'production' && environment.project.standbyProductionEnvironment == makeSafe(environment.name) && (
<div>
<label>Standby Environment Routes</label>
<div className="field">
Expand Down Expand Up @@ -119,7 +120,7 @@ const Environment = ({ environment }) => {
</div>
</div>
</div>
{environment.project.productionEnvironment && environment.project.standbyProductionEnvironment && environment.environmentType == 'production' && environment.project.standbyProductionEnvironment == environment.name && (
{environment.project.productionEnvironment && environment.project.standbyProductionEnvironment && environment.environmentType == 'production' && environment.project.standbyProductionEnvironment == makeSafe(environment.name) && (
<Mutation mutation={SwitchActiveStandbyMutation}>
{(switchActiveStandby, { loading, called, error, data }) => {
const switchActiveBranch = () => {
Expand Down
5 changes: 3 additions & 2 deletions services/ui/src/components/Environments/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import css from 'styled-jsx/css';
import EnvironmentLink from 'components/link/Environment';
import Box from 'components/Box';
import { bp, color, fontSize } from 'lib/variables';
import { makeSafe } from 'lib/util';

const bgImages = {
branch: {
Expand Down Expand Up @@ -69,12 +70,12 @@ const Environments = ({ environments = [], project }) => {
<span>Production</span>
</div>
)}
{project.productionEnvironment && project.standbyProductionEnvironment && project.productionEnvironment == environment.name && (
{project.productionEnvironment && project.standbyProductionEnvironment && project.productionEnvironment == makeSafe(environment.name) && (
<div className="activeLabel">
<span>Active</span>
</div>
)}
{project.productionEnvironment && project.standbyProductionEnvironment && project.standbyProductionEnvironment == environment.name && (
{project.productionEnvironment && project.standbyProductionEnvironment && project.standbyProductionEnvironment == makeSafe(environment.name) && (
<div className="standbyLabel">
<span>Standby</span>
</div>
Expand Down
2 changes: 2 additions & 0 deletions services/ui/src/lib/util.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,3 +7,5 @@ export const queryStringToObject = R.pipe(
R.map(R.split('=')),
R.fromPairs
);

export const makeSafe = string => string.toLocaleLowerCase().replace(/[^0-9a-z-]/g,'-')