Skip to content

Commit

Permalink
fix: stackUtils.changeRegion, add tests
Browse files Browse the repository at this point in the history
  • Loading branch information
mvayngrib committed Jul 27, 2018
1 parent 2b195f5 commit 0e3b88c
Show file tree
Hide file tree
Showing 6 changed files with 20,439 additions and 13 deletions.
41 changes: 37 additions & 4 deletions src/stack-utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import {
import Errors from './errors'
import * as utils from './utils'
import { randomString } from './crypto'
import { splitCamelCaseToArray, replaceAll } from './string-utils'
import {
LAUNCH_STACK_BASE_URL
} from './constants'
Expand Down Expand Up @@ -520,17 +521,47 @@ export default class StackUtils {
}

public static changeRegion = ({ template, from, to }) => {
const toChange = _.omit(template, 'Mappings')
const str = JSON.stringify(toChange)
const { Mappings, ...toChange } = template
let changed = StackUtils.changeAutoScalingRegion({
template: toChange,
from, to
})

const hacked = JSON.stringify(changed)
.replace(new RegExp(from, 'ig'), to)
.replace(new RegExp(normalizePathPart(from), 'g'), normalizePathPart(to))

return {
...JSON.parse(str),
Mappings: template.Mappings
...JSON.parse(hacked),
Mappings
}
}

public static changeAutoScalingRegion = ({ template, from, to }) => {
const cleanFrom = toAutoScalingRegionFormat(from)
const cleanTo = toAutoScalingRegionFormat(to)
let str = JSON.stringify(template)
const toReplace = _.map(template.Resources, (resource: any, key: string) => {
const { Type } = resource
if (Type && Type.startsWith('AWS::ApplicationAutoScaling')) {
return key
}
})
.filter(_.identity)
.sort((a, b) => b.length - a.length)

toReplace.forEach(key => {
const parts = splitCamelCaseToArray(key)
const cleanRegion = parts.pop()
if (cleanRegion === cleanTo) return

const newKey = parts.join('') + cleanTo
str = replaceAll(str, key, newKey)
})

return JSON.parse(str)
}

// public static changeAdminEmail = ({ template, to }) => {
// return {
// ...template,
Expand Down Expand Up @@ -651,3 +682,5 @@ const normalizePathPart = path => _.upperFirst(
.replace(/\{(.*)\}/g, '$1Var')
.replace(/[^0-9A-Za-z]/g, '')
)

const toAutoScalingRegionFormat = (region: string) => _.upperFirst(region.replace(/[^a-zA-Z0-9]/ig, ''))
36 changes: 27 additions & 9 deletions src/string-utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,32 +2,54 @@

// lazy('stableStringify', 'json-stable-stringify')

import upperFirst from 'lodash/upperFirst'
export const stableStringify = require('json-stable-stringify')
export const safeStringify = require('json-stringify-safe')
export const format = require('string-format')
export const toCamelCase = (str, delimiter, upperFirst) => {

export { upperFirst }
export const toCamelCase = (str, delimiter, upFirst) => {
return str
.split(delimiter)
.map((part, i) => {
if (i === 0 && !upperFirst) {
if (i === 0 && !upFirst) {
return part.toLowerCase()
}

return upperCaseFirstCharacter(part)
return upperFirst(part)
})
.join('')
}

// https://stackoverflow.com/questions/4149276/javascript-camelcase-to-regular-form
export const splitCamelCase = (str, delimiter=' ', upperFirst) => {
export const splitCamelCase = (str, delimiter=' ', upFirst) => {
const split = str.slice(0, 1) + str.slice(1)
// insert a space before all caps
.replace(/([A-Z])/g, delimiter + '$1')
.trim()

return upperFirst ? upperCaseFirstCharacter(split) : split
return upFirst ? upperFirst(split) : split
}

export const splitCamelCaseToArray = (str: string) => {
let lowerCasePrefix = ''
for (let i = 0; i < str.length; i++) {
let ch = str[i]
if (isUpperCase(ch)) break

lowerCasePrefix += ch
}

const rest = str.match(/[A-Z][^A-Z]*/g).slice()
return lowerCasePrefix ? [lowerCasePrefix, ...rest] : rest
}

const isUpperCase = (ch: string) => ch.toUpperCase() === ch
const isLowerCase = (ch: string) => ch.toLowerCase() === ch

export const replaceAll = (str: string, search: string, replacement: string) => {
return str.split(search).join(replacement)
}

export const prettify = (obj) => {
return JSON.stringify(obj, bufferReplacer, 2)
Expand All @@ -42,10 +64,6 @@ export const alphabetical = (a, b) => {
const HEX_REGEX = /^[0-9A-F]+$/i
export const isHex = str => HEX_REGEX.test(str)

function upperCaseFirstCharacter (str) {
return str[0].toUpperCase() + str.slice(1).toLowerCase()
}

function bufferReplacer (key, value) {
// Filtering out properties
if (isLikeBuffer(value)) {
Expand Down
6,777 changes: 6,777 additions & 0 deletions src/test/fixtures/cloudformation-template-ap-southeast-2.json

Large diffs are not rendered by default.

6,777 changes: 6,777 additions & 0 deletions src/test/fixtures/cloudformation-template-yossarian.json

Large diffs are not rendered by default.

6,777 changes: 6,777 additions & 0 deletions src/test/fixtures/cloudformation-template.json

Large diffs are not rendered by default.

44 changes: 44 additions & 0 deletions src/test/stack-utils.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@

require('./env').install()

// import fs from 'fs'
// import path from 'path'
import test from 'tape'
import _ from 'lodash'

import { stableStringify } from '../string-utils'
import {
loudAsync,
} from '../utils'

import { StackUtils } from '../stack-utils'

const virginia = require('./fixtures/cloudformation-template.json')
const sydney = require('./fixtures/cloudformation-template-ap-southeast-2.json')
const yossarian = require('./fixtures/cloudformation-template-yossarian.json')

test('change region', t => {
const hopefullySydney = StackUtils.changeRegion({
template: virginia,
from: 'us-east-1',
to: 'ap-southeast-2',
})

// fs.writeFileSync(path.resolve(__dirname, '../../src/test/fixtures/cloudformation-template-ap-southeast-2.json'), stableStringify(hopefullySydney, { space: 2 }))
// fs.writeFileSync(path.resolve(__dirname, './fixtures/cloudformation-template-ap-southeast-2.json'), stableStringify(hopefullySydney, { space: 2 }))
t.same(hopefullySydney, sydney)
t.end()
})

test('change service name', t => {
const hopefullyYossarian = StackUtils.changeServiceName({
template: virginia,
from: 'tdl-tradle-ltd',
to: 'tdl-yossarian-ltd',
})

// fs.writeFileSync(path.resolve(__dirname, '../../src/test/fixtures/cloudformation-template-yossarian.json'), stableStringify(hopefullyYossarian, { space: 2 }))
// fs.writeFileSync(path.resolve(__dirname, './fixtures/cloudformation-template-yossarian.json'), stableStringify(hopefullyYossarian, { space: 2 }))
t.same(hopefullyYossarian, yossarian)
t.end()
})

0 comments on commit 0e3b88c

Please sign in to comment.