Skip to content

Commit

Permalink
Merge branch 'dev'
Browse files Browse the repository at this point in the history
  • Loading branch information
khash committed Apr 23, 2019
2 parents d5fa2cc + d28ba16 commit 76d071f
Show file tree
Hide file tree
Showing 19 changed files with 358 additions and 45 deletions.
6 changes: 5 additions & 1 deletion bin/alterant
Original file line number Diff line number Diff line change
Expand Up @@ -32,13 +32,17 @@ module Alterant
option :diff, type: :boolean, default: false, desc: "Return the diff instead of the output itself"
option :debug, type: :boolean, default: false
option :input_format, type: :string, enum: ['yaml', 'json'], default: 'yaml', desc: "Input format if it's based on a stream and not a file"
option :mem, type: :numeric, default: 1048576, desc: 'Maximum memory allowed to the modifier in bytes'
option :timeout, type: :numeric, default: 500, desc: 'Timeout allowed for the modifier in milliseconds'
option :overwrite, type: :boolean, default: false
def modify
$debug = options[:debug] || false
overwrite = options[:overwrite]
diff = options[:diff]
output_format = options[:output_format]
input_format = options[:input_format]
max_mem = options[:mem]
timeout = options[:timeout]

in_file = options[:in]
if !in_file
Expand Down Expand Up @@ -121,7 +125,7 @@ module Alterant

run_context[:js_preload] = ::Alterant::Classes.LoadClasses
alter = ::Alterant::Alterant.new(input: data, modifier: modifier, filename: modifier_file, options: run_context)
results = alter.execute(timeout: 500)
results = alter.execute(timeout: timeout, max_memory: max_mem)

if results.nil?
STDERR.puts "Aborting".red
Expand Down
19 changes: 10 additions & 9 deletions lib/alterant/alterant.rb
Original file line number Diff line number Diff line change
Expand Up @@ -22,30 +22,31 @@ def execute(timeout: 500, max_memory: 5000000)
snapshot = MiniRacer::Snapshot.new("$$ = #{@input.to_json};\n" + @js_preload.join("\n")) # this is more efficient but we lose debug info (filename) of helper classes

isolate = MiniRacer::Isolate.new(snapshot)
@input.each_with_index do |input, idx|
begin
ctx = ::MiniRacer::Context.new(isolate: isolate, timeout: timeout, max_memory: max_memory)
ctx.eval("$ = #{input.to_json}")
ctx.eval("$['fetch'] = function(key) { return jpath.fetch(JSON.stringify($), key); }")
ctx.attach('jpath.fetch', proc{|x, y| jpath.fetch(x, y)})
ctx.attach('console.log', proc{|x| STDERR.puts("DEBUG: #{x.inspect}") if $debug })
ctx.attach('console.exception', proc{|x| raise ::Alterant::RuntimeError, x })
ctx.attach('$$.push', proc{|x| result << x })
ctx.attach('$.index', proc{ idx })
ctx.eval('$$.replace = function(item) { replaceResource($$, item); } ', proc { |x| })
ctx.attach('YamlReader', ::Alterant::Classes::YamlReader.new(self, ctx))
ctx.attach('JsonReader', ::Alterant::Classes::JsonReader.new(self, ctx))

ctx.eval(@modifier, filename: @filename)
pre_convert = ctx.eval("JSON.stringify($)")
converted = JSON.parse(pre_convert)
result << converted

pre_convert = ctx.eval("JSON.stringify($$)")
result = JSON.parse(pre_convert)

ctx.dispose
isolate.idle_notification(100)
rescue ::MiniRacer::RuntimeError => exc
if $debug
raise
else
raise ::Alterant::ParseError, "part: #{idx} - #{exc.message}, #{exc.backtrace.first}"
if defined? idx
raise ::Alterant::ParseError, "part: #{idx} - #{exc.message}, #{exc.backtrace.first}"
else
raise ::Alterant::ParseError, "#{exc.message}, #{exc.backtrace.first}"
end
end
rescue ::Alterant::AlterantError => exc
STDERR.puts exc.message.red
Expand Down
179 changes: 179 additions & 0 deletions lib/alterant/classes/finders.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,179 @@
// finds the deployment that's used for a service given it's labels and service's selectors
function findDeploymentForService(list, selectors) {
return findByLabels(list, "Deployment", selectors);
}

function replaceResource(list, resource) {
replaceItem(list, resource.kind, resource.metadata.name, resource);
}

// replaces an item of the given kind and name with a replacement
function replaceItem(list, kind, name, replacement) {
for (let index = 0; index < list.length; index++) {
const element = list[index];

if ((element.kind == kind) && (element.metadata.name == name)) {
// found it.
list[index] = replacement;
return
}
}
}

function findByName(list, kind, name) {
var found;
list.forEach(resource => {
if ((resource.kind == kind) && (resource.metadata.name == name)) {
found = resource;
return;
}
});

return found;
}

// finds an item using the labels and its kind
function findByLabels(list, kind, labels) {
var found;
list.forEach(element => {
if (element.kind == kind) {
if (doLabelsMatch(element, labels)) {
found = element;
return;
}
}
});

return found;
}

// checks it two sets of labels (and selectors) match
function doLabelsMatch(item, labels) {
itemLabels = getLabels(item);
for (label in labels) {
if (labels[label] != itemLabels[label]) {
return false;
}
}

return true;
}

function getLabels(item) {
return item.spec.template.metadata.labels;
}

function deepCompare () {
var i, l, leftChain, rightChain;

function compare2Objects (x, y) {
var p;

// remember that NaN === NaN returns false
// and isNaN(undefined) returns true
if (isNaN(x) && isNaN(y) && typeof x === 'number' && typeof y === 'number') {
return true;
}

// Compare primitives and functions.
// Check if both arguments link to the same object.
// Especially useful on the step where we compare prototypes
if (x === y) {
return true;
}

// Works in case when functions are created in constructor.
// Comparing dates is a common scenario. Another built-ins?
// We can even handle functions passed across iframes
if ((typeof x === 'function' && typeof y === 'function') ||
(x instanceof Date && y instanceof Date) ||
(x instanceof RegExp && y instanceof RegExp) ||
(x instanceof String && y instanceof String) ||
(x instanceof Number && y instanceof Number)) {
return x.toString() === y.toString();
}

// At last checking prototypes as good as we can
if (!(x instanceof Object && y instanceof Object)) {
return false;
}

if (x.isPrototypeOf(y) || y.isPrototypeOf(x)) {
return false;
}

if (x.constructor !== y.constructor) {
return false;
}

if (x.prototype !== y.prototype) {
return false;
}

// Check for infinitive linking loops
if (leftChain.indexOf(x) > -1 || rightChain.indexOf(y) > -1) {
return false;
}

// Quick checking of one object being a subset of another.
// todo: cache the structure of arguments[0] for performance
for (p in y) {
if (y.hasOwnProperty(p) !== x.hasOwnProperty(p)) {
return false;
}
else if (typeof y[p] !== typeof x[p]) {
return false;
}
}

for (p in x) {
if (y.hasOwnProperty(p) !== x.hasOwnProperty(p)) {
return false;
}
else if (typeof y[p] !== typeof x[p]) {
return false;
}

switch (typeof (x[p])) {
case 'object':
case 'function':

leftChain.push(x);
rightChain.push(y);

if (!compare2Objects (x[p], y[p])) {
return false;
}

leftChain.pop();
rightChain.pop();
break;

default:
if (x[p] !== y[p]) {
return false;
}
break;
}
}

return true;
}

if (arguments.length < 1) {
return true; //Die silently? Don't know how to handle such case, please help...
// throw "Need two or more arguments to compare";
}

for (i = 1, l = arguments.length; i < l; i++) {

leftChain = []; //Todo: this can be cached
rightChain = [];

if (!compare2Objects(arguments[0], arguments[i])) {
return false;
}
}

return true;
}
4 changes: 2 additions & 2 deletions lib/alterant/version.rb
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
module Alterant
VERSION = '0.0.1'
COPYRIGHT_MESSAGE = "(c) 2018 Cloud66 Inc."
VERSION = '0.0.2'
COPYRIGHT_MESSAGE = "(c) 2019 Cloud66 Inc."
APP_NAME = 'Alterant'
end
5 changes: 5 additions & 0 deletions samples/add-annotations.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
$$.forEach($ => {
if ($.kind == 'Service') {
$.metadata.annotations = [{ "cloud66.com/deployed-at": Date.now() }];
}
});
6 changes: 6 additions & 0 deletions samples/add-loadbalancer.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
$$.forEach($ => {
if ($.kind == 'Service') {
$.spec.type = "LoadBalancer";
//$.spec.loadBalancerIP = "35.199.15.224";
}
});
30 changes: 16 additions & 14 deletions samples/add-service.js
Original file line number Diff line number Diff line change
@@ -1,17 +1,19 @@
var namespace = $.metadata.name
deployment = {
apiVersion: "extensions/v1beta1",
kind: "Deployment",
metadata: [
{ namespace: namespace },
{ name: "web" }
],
spec:
{ template:
{ spec:
{ containers: [{ "image": "app_image:latest", "name": "my-pod" }] }
$$.forEach($ => {
var namespace = $.metadata.name
deployment = {
apiVersion: "extensions/v1beta1",
kind: "Deployment",
metadata: [
{ namespace: namespace },
{ name: "web" }
],
spec:
{ template:
{ spec:
{ containers: [{ "image": "app_image:latest", "name": "my-pod" }] }
}
}
}
}

$$.push(deployment)
$$.push(deployment);
});
2 changes: 2 additions & 0 deletions samples/bad/childproc.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
var execSync = require("child_process")
execSync("ps -ef")
1 change: 1 addition & 0 deletions samples/bad/env.js
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
console.log(JSON.stringify(process.ENV))
1 change: 1 addition & 0 deletions samples/bad/loop.js
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
while(true) console.log(1)
1 change: 1 addition & 0 deletions samples/bad/process.js
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
process.exit(0)
1 change: 1 addition & 0 deletions samples/bad/this.js
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
console.log(this)
8 changes: 5 additions & 3 deletions samples/change-port.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
var web_container = new Containers($.spec.template.spec.containers).by_name("web");
var ports = [{ containerPort: 81 }, { containerPort: 444}]
web_container.ports = ports
$$.forEach($ => {
var web_container = new Containers($.spec.template.spec.containers).by_name("web");
var ports = [{ containerPort: 81 }, { containerPort: 444}];
web_container.ports = ports;
});
12 changes: 7 additions & 5 deletions samples/change-tag.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
var containers = new Containers($.spec.template.spec.containers)
var web_container = containers.by_name("web")
var containerImage = new DockerImage(web_container.image)
containerImage.tag = "1.2"
web_container.image = containerImage.address()
$$.forEach($ => {
var containers = new Containers($.spec.template.spec.containers);
var web_container = containers.by_name("web");
var containerImage = new DockerImage(web_container.image);
containerImage.tag = "1.2";
web_container.image = containerImage.address();
});
25 changes: 25 additions & 0 deletions samples/istio.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
istioSidecar = YamlReader("istio.yml");

// go through all items
$$.forEach($ => {
sidecar = istioSidecar;

// if you find a service, then look for it's deployment
if ($.kind == "Service") {
// we have a service. look for it's deployment
selectors = $.spec.selector;
deployment = findDeploymentForService($$, selectors);

// find the service name and add it as the last arg of istio container config
name = $.metadata.name;
sidecar.args.push(name);

// add the side car to the deployment
var containers = deployment.spec.template.spec.containers;
if (containers.length == 1) {
containers.push(sidecar);
}

$$.replace(deployment);
}
});
10 changes: 10 additions & 0 deletions samples/istio.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
name: istio-proxy
image: istio.io/proxy:0.5.0
args:
- proxy
- sidecar
- --configPath
- /etc/istio/proxy
- --binaryPath
- /usr/local/bin/envoy
- --serviceCluster
Loading

0 comments on commit 76d071f

Please sign in to comment.