Merge branch 'gometalinter' of https://github.com/bforsyth927/lumi into bforsyth927-gometalinter

This commit is contained in:
Luke Hoban 2017-06-13 16:15:12 -07:00
commit cdd5471cfe
35 changed files with 570 additions and 282 deletions

View file

@ -30,8 +30,6 @@ install:
.PHONY: lint
lint:
@echo "\033[0;32mLINT:\033[0m"
@gometalinter pkg/...
@gometalinter cmd/lumi/...
@gometalinter cmd/lumidl/...

View file

@ -1023,11 +1023,14 @@ export class Transformer {
contract.assert(!!idsym, `Expected an ID symbol for '${id.ident}', but it is missing`);
tok = await this.resolveTokenFromSymbol(idsym);
// note that we intentionally leave object blank, since the token is fully qualified.
if ((idsym.flags & ts.SymbolFlags.Alias) === 0) {
// Mark as dynamic unless this is an alias to a module import.
isDynamic = true;
}
}
if (isDynamic) {
// If the target type is `dynamic`, we cannot perform static lookups; devolve into a dynamic load.
contract.assert(!!object);
return this.withLocation(node, <ast.TryLoadDynamicExpression>{
kind: ast.tryLoadDynamicExpressionKind,
object: object,

View file

@ -1215,10 +1215,10 @@
"right": {
"kind": "TryLoadDynamicExpression",
"object": {
"kind": "LoadLocationExpression",
"kind": "TryLoadDynamicExpression",
"name": {
"kind": "Token",
"tok": "basic/arrays:index:a2",
"kind": "StringLiteral",
"value": "a2",
"loc": {
"file": "index.ts",
"start": {
@ -1303,10 +1303,10 @@
"left": {
"kind": "TryLoadDynamicExpression",
"object": {
"kind": "LoadLocationExpression",
"kind": "TryLoadDynamicExpression",
"name": {
"kind": "Token",
"tok": "basic/arrays:index:a2",
"kind": "StringLiteral",
"value": "a2",
"loc": {
"file": "index.ts",
"start": {
@ -1436,10 +1436,10 @@
"right": {
"kind": "TryLoadDynamicExpression",
"object": {
"kind": "LoadLocationExpression",
"kind": "TryLoadDynamicExpression",
"name": {
"kind": "Token",
"tok": "basic/arrays:index:a2",
"kind": "StringLiteral",
"value": "a2",
"loc": {
"file": "index.ts",
"start": {
@ -1524,10 +1524,10 @@
"left": {
"kind": "TryLoadDynamicExpression",
"object": {
"kind": "LoadLocationExpression",
"kind": "TryLoadDynamicExpression",
"name": {
"kind": "Token",
"tok": "basic/arrays:index:a2",
"kind": "StringLiteral",
"value": "a2",
"loc": {
"file": "index.ts",
"start": {
@ -1657,10 +1657,10 @@
"right": {
"kind": "TryLoadDynamicExpression",
"object": {
"kind": "LoadLocationExpression",
"kind": "TryLoadDynamicExpression",
"name": {
"kind": "Token",
"tok": "basic/arrays:index:a2",
"kind": "StringLiteral",
"value": "a2",
"loc": {
"file": "index.ts",
"start": {
@ -1745,10 +1745,10 @@
"left": {
"kind": "TryLoadDynamicExpression",
"object": {
"kind": "LoadLocationExpression",
"kind": "TryLoadDynamicExpression",
"name": {
"kind": "Token",
"tok": "basic/arrays:index:a2",
"kind": "StringLiteral",
"value": "a2",
"loc": {
"file": "index.ts",
"start": {
@ -2004,10 +2004,10 @@
"right": {
"kind": "TryLoadDynamicExpression",
"object": {
"kind": "LoadLocationExpression",
"kind": "TryLoadDynamicExpression",
"name": {
"kind": "Token",
"tok": "basic/arrays:index:a3",
"kind": "StringLiteral",
"value": "a3",
"loc": {
"file": "index.ts",
"start": {
@ -2121,10 +2121,10 @@
"right": {
"kind": "TryLoadDynamicExpression",
"object": {
"kind": "LoadLocationExpression",
"kind": "TryLoadDynamicExpression",
"name": {
"kind": "Token",
"tok": "basic/arrays:index:a3",
"kind": "StringLiteral",
"value": "a3",
"loc": {
"file": "index.ts",
"start": {
@ -2238,10 +2238,10 @@
"right": {
"kind": "TryLoadDynamicExpression",
"object": {
"kind": "LoadLocationExpression",
"kind": "TryLoadDynamicExpression",
"name": {
"kind": "Token",
"tok": "basic/arrays:index:a3",
"kind": "StringLiteral",
"value": "a3",
"loc": {
"file": "index.ts",
"start": {
@ -2859,10 +2859,10 @@
"right": {
"kind": "TryLoadDynamicExpression",
"object": {
"kind": "LoadLocationExpression",
"kind": "TryLoadDynamicExpression",
"name": {
"kind": "Token",
"tok": "basic/arrays:index:a6",
"kind": "StringLiteral",
"value": "a6",
"loc": {
"file": "index.ts",
"start": {
@ -2978,10 +2978,10 @@
"object": {
"kind": "TryLoadDynamicExpression",
"object": {
"kind": "LoadLocationExpression",
"kind": "TryLoadDynamicExpression",
"name": {
"kind": "Token",
"tok": "basic/arrays:index:a6",
"kind": "StringLiteral",
"value": "a6",
"loc": {
"file": "index.ts",
"start": {
@ -3125,10 +3125,10 @@
"object": {
"kind": "TryLoadDynamicExpression",
"object": {
"kind": "LoadLocationExpression",
"kind": "TryLoadDynamicExpression",
"name": {
"kind": "Token",
"tok": "basic/arrays:index:a6",
"kind": "StringLiteral",
"value": "a6",
"loc": {
"file": "index.ts",
"start": {
@ -3272,10 +3272,10 @@
"object": {
"kind": "TryLoadDynamicExpression",
"object": {
"kind": "LoadLocationExpression",
"kind": "TryLoadDynamicExpression",
"name": {
"kind": "Token",
"tok": "basic/arrays:index:a6",
"kind": "StringLiteral",
"value": "a6",
"loc": {
"file": "index.ts",
"start": {
@ -3417,10 +3417,10 @@
"right": {
"kind": "TryLoadDynamicExpression",
"object": {
"kind": "LoadLocationExpression",
"kind": "TryLoadDynamicExpression",
"name": {
"kind": "Token",
"tok": "basic/arrays:index:a6",
"kind": "StringLiteral",
"value": "a6",
"loc": {
"file": "index.ts",
"start": {
@ -3536,10 +3536,10 @@
"object": {
"kind": "TryLoadDynamicExpression",
"object": {
"kind": "LoadLocationExpression",
"kind": "TryLoadDynamicExpression",
"name": {
"kind": "Token",
"tok": "basic/arrays:index:a6",
"kind": "StringLiteral",
"value": "a6",
"loc": {
"file": "index.ts",
"start": {
@ -3683,10 +3683,10 @@
"object": {
"kind": "TryLoadDynamicExpression",
"object": {
"kind": "LoadLocationExpression",
"kind": "TryLoadDynamicExpression",
"name": {
"kind": "Token",
"tok": "basic/arrays:index:a6",
"kind": "StringLiteral",
"value": "a6",
"loc": {
"file": "index.ts",
"start": {
@ -3830,10 +3830,10 @@
"object": {
"kind": "TryLoadDynamicExpression",
"object": {
"kind": "LoadLocationExpression",
"kind": "TryLoadDynamicExpression",
"name": {
"kind": "Token",
"tok": "basic/arrays:index:a6",
"kind": "StringLiteral",
"value": "a6",
"loc": {
"file": "index.ts",
"start": {
@ -4189,10 +4189,10 @@
"right": {
"kind": "TryLoadDynamicExpression",
"object": {
"kind": "LoadLocationExpression",
"kind": "TryLoadDynamicExpression",
"name": {
"kind": "Token",
"tok": "basic/arrays:index:a6",
"kind": "StringLiteral",
"value": "a6",
"loc": {
"file": "index.ts",
"start": {
@ -4308,10 +4308,10 @@
"object": {
"kind": "TryLoadDynamicExpression",
"object": {
"kind": "LoadLocationExpression",
"kind": "TryLoadDynamicExpression",
"name": {
"kind": "Token",
"tok": "basic/arrays:index:a6",
"kind": "StringLiteral",
"value": "a6",
"loc": {
"file": "index.ts",
"start": {
@ -4455,10 +4455,10 @@
"object": {
"kind": "TryLoadDynamicExpression",
"object": {
"kind": "LoadLocationExpression",
"kind": "TryLoadDynamicExpression",
"name": {
"kind": "Token",
"tok": "basic/arrays:index:a6",
"kind": "StringLiteral",
"value": "a6",
"loc": {
"file": "index.ts",
"start": {
@ -4602,10 +4602,10 @@
"object": {
"kind": "TryLoadDynamicExpression",
"object": {
"kind": "LoadLocationExpression",
"kind": "TryLoadDynamicExpression",
"name": {
"kind": "Token",
"tok": "basic/arrays:index:a6",
"kind": "StringLiteral",
"value": "a6",
"loc": {
"file": "index.ts",
"start": {
@ -4747,10 +4747,10 @@
"right": {
"kind": "TryLoadDynamicExpression",
"object": {
"kind": "LoadLocationExpression",
"kind": "TryLoadDynamicExpression",
"name": {
"kind": "Token",
"tok": "basic/arrays:index:a6",
"kind": "StringLiteral",
"value": "a6",
"loc": {
"file": "index.ts",
"start": {
@ -4866,10 +4866,10 @@
"object": {
"kind": "TryLoadDynamicExpression",
"object": {
"kind": "LoadLocationExpression",
"kind": "TryLoadDynamicExpression",
"name": {
"kind": "Token",
"tok": "basic/arrays:index:a6",
"kind": "StringLiteral",
"value": "a6",
"loc": {
"file": "index.ts",
"start": {
@ -5013,10 +5013,10 @@
"object": {
"kind": "TryLoadDynamicExpression",
"object": {
"kind": "LoadLocationExpression",
"kind": "TryLoadDynamicExpression",
"name": {
"kind": "Token",
"tok": "basic/arrays:index:a6",
"kind": "StringLiteral",
"value": "a6",
"loc": {
"file": "index.ts",
"start": {
@ -5160,10 +5160,10 @@
"object": {
"kind": "TryLoadDynamicExpression",
"object": {
"kind": "LoadLocationExpression",
"kind": "TryLoadDynamicExpression",
"name": {
"kind": "Token",
"tok": "basic/arrays:index:a6",
"kind": "StringLiteral",
"value": "a6",
"loc": {
"file": "index.ts",
"start": {

View file

@ -942,10 +942,10 @@
"expression": {
"kind": "InvokeFunctionExpression",
"function": {
"kind": "LoadLocationExpression",
"kind": "TryLoadDynamicExpression",
"name": {
"kind": "Token",
"tok": "basic/undefined:index:f",
"kind": "StringLiteral",
"value": "f",
"loc": {
"file": "index.ts",
"start": {
@ -1237,10 +1237,10 @@
"expression": {
"kind": "InvokeFunctionExpression",
"function": {
"kind": "LoadLocationExpression",
"kind": "TryLoadDynamicExpression",
"name": {
"kind": "Token",
"tok": "basic/undefined:index:g",
"kind": "StringLiteral",
"value": "g",
"loc": {
"file": "index.ts",
"start": {

View file

@ -1023,10 +1023,10 @@
},
"operator": "=",
"right": {
"kind": "LoadLocationExpression",
"kind": "TryLoadDynamicExpression",
"name": {
"kind": "Token",
"tok": "basic/props:index:modprop",
"kind": "StringLiteral",
"value": "modprop",
"loc": {
"file": "index.ts",
"start": {
@ -1256,10 +1256,10 @@
"kind": "BinaryOperatorExpression",
"operator": "!=",
"left": {
"kind": "LoadLocationExpression",
"kind": "TryLoadDynamicExpression",
"name": {
"kind": "Token",
"tok": "basic/props:index:c",
"kind": "StringLiteral",
"value": "c",
"loc": {
"file": "index.ts",
"start": {
@ -1389,10 +1389,10 @@
"right": {
"kind": "LoadLocationExpression",
"object": {
"kind": "LoadLocationExpression",
"kind": "TryLoadDynamicExpression",
"name": {
"kind": "Token",
"tok": "basic/props:index:c",
"kind": "StringLiteral",
"value": "c",
"loc": {
"file": "index.ts",
"start": {
@ -1568,10 +1568,10 @@
"tok": "f"
},
"value": {
"kind": "LoadLocationExpression",
"kind": "TryLoadDynamicExpression",
"name": {
"kind": "Token",
"tok": "basic/props:index:modprop",
"kind": "StringLiteral",
"value": "modprop",
"loc": {
"file": "index.ts",
"start": {
@ -1664,10 +1664,10 @@
"value": {
"kind": "LoadLocationExpression",
"object": {
"kind": "LoadLocationExpression",
"kind": "TryLoadDynamicExpression",
"name": {
"kind": "Token",
"tok": "basic/props:index:c",
"kind": "StringLiteral",
"value": "c",
"loc": {
"file": "index.ts",
"start": {
@ -1770,10 +1770,10 @@
"property": {
"kind": "InvokeFunctionExpression",
"function": {
"kind": "LoadLocationExpression",
"kind": "TryLoadDynamicExpression",
"name": {
"kind": "Token",
"tok": "basic/props:index:j",
"kind": "StringLiteral",
"value": "j",
"loc": {
"file": "index.ts",
"start": {
@ -1965,10 +1965,10 @@
"right": {
"kind": "LoadLocationExpression",
"object": {
"kind": "LoadLocationExpression",
"kind": "TryLoadDynamicExpression",
"name": {
"kind": "Token",
"tok": "basic/props:index:c",
"kind": "StringLiteral",
"value": "c",
"loc": {
"file": "index.ts",
"start": {
@ -2065,10 +2065,10 @@
"left": {
"kind": "LoadLocationExpression",
"object": {
"kind": "LoadLocationExpression",
"kind": "TryLoadDynamicExpression",
"name": {
"kind": "Token",
"tok": "basic/props:index:c",
"kind": "StringLiteral",
"value": "c",
"loc": {
"file": "index.ts",
"start": {

View file

@ -1164,10 +1164,10 @@
"function": {
"kind": "LoadLocationExpression",
"object": {
"kind": "LoadLocationExpression",
"kind": "TryLoadDynamicExpression",
"name": {
"kind": "Token",
"tok": "basic/super:index:b",
"kind": "StringLiteral",
"value": "b",
"loc": {
"file": "index.ts",
"start": {
@ -1262,10 +1262,10 @@
"kind": "BinaryOperatorExpression",
"operator": "!=",
"left": {
"kind": "LoadLocationExpression",
"kind": "TryLoadDynamicExpression",
"name": {
"kind": "Token",
"tok": "basic/super:index:bgx",
"kind": "StringLiteral",
"value": "bgx",
"loc": {
"file": "index.ts",
"start": {
@ -1363,10 +1363,10 @@
}
},
"right": {
"kind": "LoadLocationExpression",
"kind": "TryLoadDynamicExpression",
"name": {
"kind": "Token",
"tok": "basic/super:index:bgx",
"kind": "StringLiteral",
"value": "bgx",
"loc": {
"file": "index.ts",
"start": {
@ -1581,10 +1581,10 @@
"function": {
"kind": "LoadLocationExpression",
"object": {
"kind": "LoadLocationExpression",
"kind": "TryLoadDynamicExpression",
"name": {
"kind": "Token",
"tok": "basic/super:index:c",
"kind": "StringLiteral",
"value": "c",
"loc": {
"file": "index.ts",
"start": {
@ -1679,10 +1679,10 @@
"kind": "BinaryOperatorExpression",
"operator": "!=",
"left": {
"kind": "LoadLocationExpression",
"kind": "TryLoadDynamicExpression",
"name": {
"kind": "Token",
"tok": "basic/super:index:cgx",
"kind": "StringLiteral",
"value": "cgx",
"loc": {
"file": "index.ts",
"start": {
@ -1780,10 +1780,10 @@
}
},
"right": {
"kind": "LoadLocationExpression",
"kind": "TryLoadDynamicExpression",
"name": {
"kind": "Token",
"tok": "basic/super:index:cgx",
"kind": "StringLiteral",
"value": "cgx",
"loc": {
"file": "index.ts",
"start": {
@ -1910,10 +1910,10 @@
"function": {
"kind": "LoadLocationExpression",
"object": {
"kind": "LoadLocationExpression",
"kind": "TryLoadDynamicExpression",
"name": {
"kind": "Token",
"tok": "basic/super:index:c",
"kind": "StringLiteral",
"value": "c",
"loc": {
"file": "index.ts",
"start": {
@ -2008,10 +2008,10 @@
"kind": "BinaryOperatorExpression",
"operator": "!=",
"left": {
"kind": "LoadLocationExpression",
"kind": "TryLoadDynamicExpression",
"name": {
"kind": "Token",
"tok": "basic/super:index:cgy",
"kind": "StringLiteral",
"value": "cgy",
"loc": {
"file": "index.ts",
"start": {
@ -2109,10 +2109,10 @@
}
},
"right": {
"kind": "LoadLocationExpression",
"kind": "TryLoadDynamicExpression",
"name": {
"kind": "Token",
"tok": "basic/super:index:cgy",
"kind": "StringLiteral",
"value": "cgy",
"loc": {
"file": "index.ts",
"start": {

View file

@ -2,5 +2,6 @@ name: serverless
description: Basic example of a serverless AWS application.
dependencies:
lumi: "*"
lumijs: "*"
aws: "*"

View file

@ -49,34 +49,17 @@ let music = new aws.dynamodb.Table("music", {
],
})
// TODO[pulumi/lumi#174] Until we have global definitions available in Lumi for these APIs that are expected
// by runtime code, we'll declare variables that should be available on the global scope of the lambda to keep
// TypeScript type checking happy.
let console: any
function createLambda() {
// TODO[pulumi/lumi#175] Currently, we can only capture local variables, not module scope variables,
// so we keep this inside a helper function.
let hello = "Hello, world!"
let num = 3
let obj = { x: 42 }
let mus = music
let lambda = new aws.serverless.Function(
"mylambda",
[aws.iam.AWSLambdaFullAccess],
(event, context, callback) => {
console.log(hello);
console.log(obj.x);
console.log("Music table hash key is: " + mus.hashKey);
console.log("Invoked function: " + context.invokedFunctionArn);
callback(null, "Succeeed with " + context.getRemainingTimeInMillis() + "ms remaining.");
}
);
return lambda;
}
let lambda = createLambda();
let hello = "Hello, world!"
let lambda = new aws.serverless.Function(
"mylambda",
[aws.iam.AWSLambdaFullAccess],
(event, context, callback) => {
console.log(hello);
console.log("Music table hash key is: " + music.hashKey);
console.log("Invoked function: " + context.invokedFunctionArn);
callback(null, "Succeeed with " + context.getRemainingTimeInMillis() + "ms remaining.");
}
);
let api = new aws.serverless.API("frontend")
api.route("GET", "/bambam", lambda)

View file

@ -9,6 +9,7 @@
"typescript": "^2.1.4"
},
"peerDependencies": {
"@lumi/lumi": "*",
"@lumi/aws": "*"
}
}

View file

@ -13,11 +13,9 @@
// See the License for the specific language governing permissions and
// limitations under the License.
/* tslint:disable: ordered-imports */
import * as slack from "@slack/client";
import {builders, providers} from "./cicd";
import * as github from "./github";
import * as slack from "@slack/client";
// On pushes or PR merges,
// - In master, build and deploy the bits to production.

View file

@ -78,7 +78,7 @@ function createPathSpec(lambdaARN: string): SwaggerOperation {
}
function createSourceARN(region: string, account: string, apiid: string, functionName: string): string {
return "arn:aws:execute-api:"+region+":"+account+":"+apiid+"/*/*/"+ functionName;
return "arn:aws:execute-api:" + region + ":" + account + ":" + apiid + "/*/*/" + functionName;
}
// API is a higher level abstraction for working with AWS APIGateway reources.
@ -117,9 +117,8 @@ export class API {
default:
throw new Error("Method not supported: " + method);
}
<<<<<<< HEAD
let apiName = "";
if(this.api.apiName !== undefined) {
if (this.api.apiName !== undefined) {
apiName = this.api.apiName;
}
let invokePermission = new Permission(this.apiName + "_invoke_" + sha1hash(method + path), {
@ -129,9 +128,6 @@ export class API {
sourceARN: createSourceARN("us-east-1", "490047557317", apiName, "webapi-test-func"),
});
// TODO[pulumi/lumi#90]: Once we suport output properties, we can use `lambda.lambda.arn` as input
=======
// TODO[pulumi/lumi#90]: Once we suport output properties, we can use `lambda.lambda.arn` as input
>>>>>>> 13dbcdbafc96be49e509c618194cd649ba6d0817
// to constructing this apigateway lambda invocation uri.
// this.swaggerSpec.paths[path][swaggerMethod] = createPathSpec(lambda.lambda.arn);
this.swaggerSpec.paths[path][swaggerMethod] = createPathSpec(

View file

@ -13,12 +13,11 @@
// See the License for the specific language governing permissions and
// limitations under the License.
/* tslint:disable: ordered-imports align*/
import { AssetArchive, String } from "@lumi/lumi/asset";
import { serializeClosure, jsonStringify } from "@lumi/lumi/runtime";
import { jsonStringify, serializeClosure} from "@lumi/lumi/runtime";
import { Role } from "../iam/role";
import { Function as LambdaFunction } from "../lambda/function";
import { ARN } from "../types";
import { Role } from "../iam/role";
// Context is the shape of the context object passed to a Function callback.
export interface Context {
@ -56,7 +55,7 @@ export class Function {
public role: Role;
constructor(name: string, policies: ARN[],
func: (event: any, context: Context, callback: (error: any, result: any) => void) => any) {
func: (event: any, context: Context, callback: (error: any, result: any) => void) => any) {
if (name === undefined) {
throw new Error("Missing required resource name");

View file

@ -13,12 +13,8 @@
// See the License for the specific language governing permissions and
// limitations under the License.
/* tslint:disable:no-empty */
// Asset represents a blob of text or data that is managed as a first class entity.
export abstract class Asset {
constructor() {
}
}
// Blob is a kind of asset produced from an in-memory blob represented as a byte array.

View file

@ -12,10 +12,8 @@
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
/* tslint:disable:no-empty*/
// Resource represents a class whose CRUD operations are implemented by a provider plugin.
export abstract class Resource {
constructor() {
}
}

View file

@ -1,3 +1,5 @@
name: lumijs
description: The LumiJS runtime library.
dependencies:
lumi: "*"

25
lib/lumijs/lib/console.ts Normal file
View file

@ -0,0 +1,25 @@
// Licensed to Pulumi Corporation ("Pulumi") under one or more
// contributor license agreements. See the NOTICE file distributed with
// this work for additional information regarding copyright ownership.
// Pulumi licenses this file to You under the Apache License, Version 2.0
// (the "License"); you may not use this file except in compliance with
// the License. You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
import { printf } from "@lumi/lumi/runtime"
export class Console {
log(message: any) {
printf(message);
printf("\n");
}
}
export let console = new Console();

View file

@ -17,4 +17,5 @@
export * from "./errors";
export * from "./types";
export * from "./console";

View file

@ -13,12 +13,12 @@
// See the License for the specific language governing permissions and
// limitations under the License.
/* tslint:disable: variable-name */
// The available cloud providers.
export const AWS = "aws"; // Amazon Web Services.
export const GCP = "gcp"; // Google Cloud Platform.
export const Azure = "azure"; // Microsoft Azure.
export const VMWare = "vmware"; // VMWare vSphere, etc.
export const aws = "aws"; // Amazon Web Services.
export const gcp = "gcp"; // Google Cloud Platform.
export const azure = "azure"; // Microsoft Azure.
export const vmware = "vmware"; // VMWare vSphere, etc.

View file

@ -13,12 +13,9 @@
// See the License for the specific language governing permissions and
// limitations under the License.
/* tslint:disable:ordered-imports */
export * from "./arch";
import * as clouds from "./clouds";
import * as schedulers from "./schedulers";
import * as runtimes from "./runtimes";
import * as schedulers from "./schedulers";
export {clouds, schedulers, runtimes};

View file

@ -13,15 +13,12 @@
// See the License for the specific language governing permissions and
// limitations under the License.
/* tslint:disable:variable-name */
// The available language runtimes.
export const NodeJS = "nodejs";
export const Python = "python";
export const nodejs = "nodejs";
export const python = "python";
export let ext: {[lang: string]: string} = {
NodeJS: ".js",
Python: ".py",
nodejs: ".js",
python: ".py",
};

View file

@ -13,14 +13,11 @@
// See the License for the specific language governing permissions and
// limitations under the License.
/* tslint:disable:variable-name */
// The available container scheduler/runtimes.
export const Swarm = "swarm"; // Docker Swarm.
export const Kubernetes = "kubernetes"; // Kubernetes.
export const Mesos = "mesos"; // Apache Mesos.
export const ECS = "ecs"; // Amazon Elastic Container Service (only valid for AWS clouds).
export const GKE = "gke"; // Google Container Engine (only valid for GCP clouds).
export const ACS = "acs"; // Microsoft Azure Container Service (only valid for Azure).
export const swarm = "swarm"; // Docker Swarm.
export const kubernetes = "kubernetes"; // Kubernetes.
export const mesos = "mesos"; // Apache Mesos.
export const ecs = "ecs"; // Amazon Elastic Container Service (only valid for AWS clouds).
export const gke = "gke"; // Google Container Engine (only valid for GCP clouds).
export const acs = "acs"; // Microsoft Azure Container Service (only valid for Azure).

View file

@ -13,14 +13,12 @@
// See the License for the specific language governing permissions and
// limitations under the License.
/* tslint:disable:ordered-imports */
import * as arch from "../arch";
import * as config from "../config";
import * as runtime from "../runtime";
import * as aws from "@lumi/aws";
import * as kubefission from "@lumi/kubefission";
import {asset} from "@lumi/lumi";
import * as arch from "../arch";
import * as config from "../config";
import * as runtime from "../runtime";
// Function is a cross-cloud function abstraction whose source code is taken from a string, file, or network asset.
// For example, `https://gist.github.com/pulumi/fe8a5ae322ffe63fac90535eb554237f` will use a Gist published on GitHub,
@ -48,16 +46,16 @@ export class Function {
// initCloudResources sets up the right resources for the given cloud and scheduler target.
private initCloudResources(): any {
let target: arch.Arch = config.requireArch();
if (target.scheduler === arch.schedulers.Kubernetes) {
if (target.scheduler === arch.schedulers.kubernetes) {
return this.initKubernetesResources();
}
else {
switch (target.cloud) {
case arch.clouds.AWS:
case arch.clouds.aws:
return this.initAWSResources();
case arch.clouds.GCP:
case arch.clouds.gcp:
return this.initGCPResources();
case arch.clouds.Azure:
case arch.clouds.azure:
return this.initAzureResources();
default:
throw new Error("Unsupported target cloud: " + target.cloud);

View file

@ -0,0 +1,107 @@
// Licensed to Pulumi Corporation ("Pulumi") under one or more
// contributor license agreements. See the NOTICE file distributed with
// this work for additional information regarding copyright ownership.
// Pulumi licenses this file to You under the Apache License, Version 2.0
// (the "License"); you may not use this file except in compliance with
// the License. You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package binder
import (
"github.com/pulumi/lumi/pkg/compiler/ast"
"github.com/pulumi/lumi/pkg/tokens"
"github.com/pulumi/lumi/pkg/util/contract"
)
// FreeVars computes the free variables referenced inside a function body.
// The free variables for a function will be either simple identifier tokens or tokens
// referencing module-scope variables.
func FreeVars(fnc ast.Function) []tokens.Token {
visitor := &freeVarsVisitor{
freeVars: map[tokens.Token]bool{},
}
ast.Walk(visitor, fnc)
params := fnc.GetParameters()
if params != nil {
for _, lv := range *params {
visitor.removeLocalVariable(lv)
}
}
var vars []tokens.Token
for k := range visitor.freeVars {
vars = append(vars, k)
}
return vars
}
type freeVarsVisitor struct {
freeVars map[tokens.Token]bool
}
var _ ast.Visitor = (*freeVarsVisitor)(nil)
func (visitor *freeVarsVisitor) Visit(node ast.Node) ast.Visitor {
return visitor
}
// We walk the AST and process each node after visiting it in depth first order. There are two cases we care about:
// 1) After visiting a leaf node which is a reference to a local variable (`n.Object == nil``), we add it to our set.
// 2) After visiting a LocalVariableDeclaration or a Lambda, we remove the declared variables from our set.
func (visitor *freeVarsVisitor) After(node ast.Node) {
switch n := node.(type) {
case *ast.LoadLocationExpression:
if n.Object == nil {
visitor.addToken(n.Name.Tok)
}
case *ast.LoadDynamicExpression:
if n.Object == nil {
switch e := n.Name.(type) {
case *ast.StringLiteral:
visitor.addToken(tokens.Token(e.Value))
default:
contract.Failf("expected LoadDynamicExpression with Object == nil to have a StringLiteral expression")
}
}
case *ast.TryLoadDynamicExpression:
if n.Object == nil {
switch e := n.Name.(type) {
case *ast.StringLiteral:
visitor.addToken(tokens.Token(e.Value))
default:
contract.Failf("expected LoadDynamicExpression with Object == nil to have a StringLiteral expression")
}
}
case *ast.LambdaExpression:
if n.Parameters != nil {
for _, param := range *n.Parameters {
visitor.removeLocalVariable(param)
}
}
case *ast.Block:
for _, stmt := range n.Statements {
switch s := stmt.(type) {
case *ast.LocalVariableDeclaration:
visitor.removeLocalVariable(s.Local)
}
}
}
}
func (visitor *freeVarsVisitor) addToken(tok tokens.Token) {
visitor.freeVars[tok] = true
}
func (visitor *freeVarsVisitor) removeLocalVariable(lv *ast.LocalVariable) {
delete(visitor.freeVars, tokens.Token(lv.Name.Ident))
}

View file

@ -0,0 +1,192 @@
// Licensed to Pulumi Corporation ("Pulumi") under one or more
// contributor license agreements. See the NOTICE file distributed with
// this work for additional information regarding copyright ownership.
// Pulumi licenses this file to You under the Apache License, Version 2.0
// (the "License"); you may not use this file except in compliance with
// the License. You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package binder
import (
"testing"
"github.com/pulumi/lumi/pkg/compiler/ast"
"github.com/pulumi/lumi/pkg/compiler/types"
"github.com/pulumi/lumi/pkg/tokens"
"github.com/stretchr/testify/assert"
)
func makeLocalVariable(name string) *ast.LocalVariable {
return &ast.LocalVariable{
DefinitionNode: ast.DefinitionNode{
Name: &ast.Identifier{
Ident: tokens.Name(name),
},
},
VariableNode: ast.VariableNode{
Type: &ast.TypeToken{
Tok: types.Object.TypeToken(),
},
},
}
}
func expressionRef(expr ast.Expression) *ast.Expression {
return &expr
}
func TestFreeVars_Parameter(t *testing.T) {
// function(foo) foo
fun := ast.ModuleMethod{
FunctionNode: ast.FunctionNode{
Parameters: &[]*ast.LocalVariable{
makeLocalVariable("foo"),
},
Body: &ast.ExpressionStatement{
Expression: &ast.LoadLocationExpression{
Name: &ast.Token{
Tok: tokens.Token("foo"),
},
},
},
},
}
freeVars := FreeVars(&fun)
assert.Len(t, freeVars, 0, "expected no free variables")
}
func TestFreeVars_Dynamic(t *testing.T) {
// function(foo) foo
fun := ast.ModuleMethod{
FunctionNode: ast.FunctionNode{
Parameters: &[]*ast.LocalVariable{},
Body: &ast.ExpressionStatement{
Expression: &ast.LoadDynamicExpression{
Name: &ast.StringLiteral{
Value: "foo",
},
},
},
},
}
freeVars := FreeVars(&fun)
assert.Len(t, freeVars, 1, "expected one free variable")
assert.Equal(t, tokens.Name("foo"), freeVars[0].Name())
}
func TestFreeVars_LocalVariable(t *testing.T) {
// function(foo) { var bar; foo; bar; baz; }
fun := ast.ModuleMethod{
FunctionNode: ast.FunctionNode{
Parameters: &[]*ast.LocalVariable{
makeLocalVariable("foo"),
},
Body: &ast.Block{
Statements: []ast.Statement{
&ast.LocalVariableDeclaration{
Local: makeLocalVariable("bar"),
},
&ast.ExpressionStatement{
Expression: &ast.LoadLocationExpression{
Name: &ast.Token{
Tok: tokens.Token("foo"),
},
},
},
&ast.ExpressionStatement{
Expression: &ast.LoadLocationExpression{
Name: &ast.Token{
Tok: tokens.Token("bar"),
},
},
},
&ast.ExpressionStatement{
Expression: &ast.TryLoadDynamicExpression{
Name: &ast.StringLiteral{
Value: "baz",
},
},
},
},
},
},
}
freeVars := FreeVars(&fun)
assert.Len(t, freeVars, 1, "expected one free variable")
assert.Equal(t, tokens.Name("baz"), freeVars[0].Name())
}
func TestFreeVars_Member(t *testing.T) {
// function(foo) foo.bar
fun := ast.ModuleMethod{
FunctionNode: ast.FunctionNode{
Parameters: &[]*ast.LocalVariable{
makeLocalVariable("foo"),
},
Body: &ast.ExpressionStatement{
Expression: &ast.LoadLocationExpression{
Object: expressionRef(&ast.LoadLocationExpression{
Name: &ast.Token{
Tok: tokens.Token("foo"),
},
}),
Name: &ast.Token{
Tok: tokens.Token("bar"),
},
},
},
},
}
freeVars := FreeVars(&fun)
assert.Len(t, freeVars, 0, "expected no free variables")
}
func TestFreeVars_Lambda(t *testing.T) {
// function(foo) ((bar) => bar)(foo)
fun := ast.ModuleMethod{
FunctionNode: ast.FunctionNode{
Parameters: &[]*ast.LocalVariable{
makeLocalVariable("foo"),
},
Body: &ast.ExpressionStatement{
Expression: &ast.InvokeFunctionExpression{
Function: &ast.LambdaExpression{
FunctionNode: ast.FunctionNode{
Parameters: &[]*ast.LocalVariable{
makeLocalVariable("bar"),
},
Body: &ast.ExpressionStatement{
Expression: &ast.LoadLocationExpression{
Name: &ast.Token{
Tok: tokens.Token("bar"),
},
},
},
},
},
CallExpressionNode: ast.CallExpressionNode{
Arguments: &[]*ast.CallArgument{
&ast.CallArgument{
Expr: &ast.LoadLocationExpression{
Name: &ast.Token{
Tok: tokens.Token("foo"),
},
},
},
},
},
},
},
},
}
freeVars := FreeVars(&fun)
assert.Len(t, freeVars, 0, "expected no free variables")
}

View file

@ -1730,22 +1730,23 @@ func (e *evaluator) evalLoadDynamicCore(node ast.Node, objexpr *ast.Expression,
}, nil
}
func (e *evaluator) getDynamicNameAddr(key tokens.Name, lval bool) *rt.Pointer {
var pv *rt.Pointer
// If there's no object, look in the current localsment.
pkey := rt.PropertyKey(key)
globals := e.getModuleGlobals(e.ctx.Currmodule)
if loc := e.locals.Lookup(key); loc != nil {
pv = e.locals.GetValueAddr(loc, true) // create a slot, we know the declaration exists.
} else {
// If it didn't exist in the lexical scope, check the module's globals.
pv = globals.Properties().GetAddr(pkey) // look for a global by this name, but don't allocate one.
func getDynamicNameAddrCore(locals rt.Environment, globals *rt.Object, key tokens.Name) *rt.Pointer {
if loc := locals.Lookup(key); loc != nil {
return locals.GetValueAddr(loc, true) // create a slot, we know the declaration exists.
}
// If it didn't exist in the lexical scope, check the module's globals.
pkey := rt.PropertyKey(key)
return globals.Properties().GetAddr(pkey) // look for a global by this name, but don't allocate one.
}
// Finally, if neither of those existed, and this is the target of a load, allocate a slot.
func (e *evaluator) getDynamicNameAddr(key tokens.Name, lval bool) *rt.Pointer {
globals := e.getModuleGlobals(e.ctx.Currmodule)
pv := getDynamicNameAddrCore(e.locals, globals, key)
// If not found and this is the target of a load, allocate a slot.
if pv == nil && lval {
if e.fnc != nil && e.fnc.SpecialModInit() && e.locals.Activation() {
pkey := rt.PropertyKey(key)
pv = globals.Properties().GetInitAddr(pkey)
} else {
loc := symbols.NewSpecialVariableSym(key, types.Dynamic)
@ -1870,7 +1871,8 @@ func (e *evaluator) evalLambdaExpression(node *ast.LambdaExpression) (*rt.Object
// To create a lambda object we will simply produce a function object that can invoke it. Lambdas also uniquely
// capture the current environment, including the this variable.
sig := e.ctx.RequireType(node).(*symbols.FunctionType)
obj := rt.NewFunctionObjectFromLambda(node, sig, e.locals)
moduleObject := e.getModuleGlobals(e.ctx.Currmodule)
obj := rt.NewFunctionObjectFromLambda(node, sig, e.locals, moduleObject)
return obj, nil
}

View file

@ -19,14 +19,15 @@ import (
"crypto/sha1"
"encoding/hex"
"fmt"
"sort"
"strconv"
"strings"
"github.com/pulumi/lumi/pkg/compiler/ast"
"github.com/pulumi/lumi/pkg/compiler/binder"
"github.com/pulumi/lumi/pkg/compiler/symbols"
"github.com/pulumi/lumi/pkg/compiler/types"
"github.com/pulumi/lumi/pkg/eval/rt"
"github.com/pulumi/lumi/pkg/tokens"
"github.com/pulumi/lumi/pkg/util/contract"
)
@ -108,21 +109,24 @@ func serializeClosure(intrin *rt.Intrinsic, e *evaluator, this *rt.Object, args
return e.NewException(intrin.Tree(), "Expected argument 'func' to be a lambda expression.")
}
// TODO[pulumi/lumi#177]: We are using the full environment available at execution time here, we should
// instead capture only the free variables referenced in the function itself.
// Insert environment variables into a PropertyMap with stable ordering
envPropMap := rt.NewPropertyMap()
slots := stub.Env.Slots()
var keys []*symbols.LocalVariable
for key := range slots {
keys = append(keys, key)
}
sort.SliceStable(keys, func(i, j int) bool {
return keys[i].Name() < keys[j].Name()
})
for _, key := range keys {
envPropMap.Set(rt.PropertyKey(key.Name()), slots[key].Obj())
for _, tok := range binder.FreeVars(stub.Func) {
var name tokens.Name
contract.Assertf(tok.Simple() || (tok.HasModule() && tok.HasModuleMember() && !tok.HasClassMember()),
"Expected free variable to be simple name or reference to top-level module name")
if tok.Simple() {
name = tok.Name()
} else {
name = tokens.Name(tok.ModuleMember().Name())
}
pv := getDynamicNameAddrCore(stub.Env, stub.Module, name)
if pv != nil {
envPropMap.Set(rt.PropertyKey(name), pv.Obj())
}
// Else the variable was not found, so we skip serializing it.
// This will be true for references to globals which are not known to Lumi but
// will be available within the runtime environment.
}
envObj := e.alloc.New(intrin.Tree(), types.Dynamic, envPropMap, nil)

View file

@ -452,21 +452,23 @@ func NewFunctionObjectFromSymbol(fnc symbols.Function, this *Object) *Object {
}
// NewFunctionObjectFromLambda creates a new function object with very specific underlying parts.
func NewFunctionObjectFromLambda(fnc ast.Function, sig *symbols.FunctionType, env Environment) *Object {
func NewFunctionObjectFromLambda(fnc ast.Function, sig *symbols.FunctionType, env Environment, module *Object) *Object {
return NewFunctionObject(FuncStub{
Func: fnc,
Sig: sig,
Env: env,
Func: fnc,
Sig: sig,
Env: env,
Module: module,
})
}
// FuncStub is a stub that captures a symbol plus an optional instance 'this' object.
type FuncStub struct {
Func ast.Function // the function whose body AST to evaluate.
Sym symbols.Function // an optional function symbol that this AST belongs to.
Sig *symbols.FunctionType // the function type representing this function's signature.
This *Object // an optional "this" pointer to bind when invoking this function.
Env Environment // an optional environment to evaluate this function inside.
Func ast.Function // the function whose body AST to evaluate.
Sym symbols.Function // an optional function symbol that this AST belongs to.
Sig *symbols.FunctionType // the function type representing this function's signature.
This *Object // an optional "this" pointer to bind when invoking this function.
Env Environment // an optional environment to evaluate this function inside.
Module *Object // an optional module object to use for module variable lookups inside this function.
}
// NewPointerObject allocates a new pointer-like object that wraps the given reference.
@ -641,11 +643,12 @@ func adjustPointerForThis(parent *Object, this *Object, prop *Pointer) *Pointer
stub := value.FunctionValue()
contract.Assert(stub.This == parent)
value = NewFunctionObject(FuncStub{
Func: stub.Func,
Sym: stub.Sym,
Sig: stub.Sig,
This: this,
Env: stub.Env,
Func: stub.Func,
Sym: stub.Sym,
Sig: stub.Sig,
This: this,
Env: stub.Env,
Module: stub.Module,
})
prop = NewPointer(value, prop.Readonly(), prop.Getter(), prop.Setter())
case *symbols.ComputedType:
@ -684,7 +687,7 @@ func (intrin *Intrinsic) SpecialModInit() bool { return false }
func (intrin *Intrinsic) Tree() diag.Diagable { return intrin.node }
func (intrin *Intrinsic) Function() ast.Function { return intrin.node }
func (intrin *Intrinsic) Signature() *symbols.FunctionType { return intrin.sig }
func (intrin *Intrinsic) String() string { return string(intrin.Name()) }
func (intrin *Intrinsic) String() string { return string(intrin.Token()) }
func (intrin *Intrinsic) UnderlyingSymbol() symbols.Function { return intrin.fnc }

View file

@ -28,8 +28,8 @@ import (
"github.com/pulumi/lumi/pkg/util/contract"
)
// Print prints a LumiGL graph.
func Print(g graph.Graph, w io.Writer) error {
var err error
// Allocate a new writer. In general, we will ignore write errors throughout this function, for simplicity, opting
// instead to return the result of flushing the buffer at the end, which is generally latching.

View file

@ -346,12 +346,11 @@ func (a Archive) openURLStream(url *url.URL) (io.ReadCloser, error) {
// Bytes fetches the archive contents as a byte slices. This is almost certainly the least efficient way to deal with
// the underlying streaming capabilities offered by assets and archives, but can be used in a pinch to interact with
// APIs that demand []bytes.
func (a Archive) Bytes(format ArchiveFormat) []byte {
func (a Archive) Bytes(format ArchiveFormat) ([]byte, error) {
var data bytes.Buffer
err := a.Archive(format, &data)
contract.Assert(err == nil)
return data.Bytes()
var err error
err = a.Archive(format, &data)
return data.Bytes(), err
}
// Archive produces a single archive stream in the desired format. It prefers to return the archive with as little

View file

@ -95,13 +95,13 @@ func newPlugin(ctx *Context, bins []string, prefix string) (*plugin, error) {
var port string
b := make([]byte, 1)
for {
n, stderr := plug.Stdout.Read(b)
if stderr != nil {
n, readerr := plug.Stdout.Read(b)
if readerr != nil {
plug.Proc.Kill()
if port == "" {
return nil, errors.Wrapf(stderr, "could not read plugin [%v] stdout", foundbin)
return nil, errors.Wrapf(readerr, "could not read plugin [%v] stdout", foundbin)
}
return nil, errors.Wrapf(stderr, "failure reading plugin [%v] stdout (read '%v')", foundbin, port)
return nil, errors.Wrapf(readerr, "failure reading plugin [%v] stdout (read '%v')", foundbin, port)
}
if n > 0 && b[0] == '\n' {
break

View file

@ -37,7 +37,6 @@ func writefmtln(w *bufio.Writer, msg string, args ...interface{}) {
func emitHeaderWarning(w *bufio.Writer) {
writefmtln(w, "// *** WARNING: this file was generated by the Lumi IDL Compiler (LUMIDL). ***")
writefmtln(w, "// *** Do not edit by hand unless you're certain you know what you are doing! ***")
writefmtln(w, "/* tslint:disable:ordered-imports variable-name */")
writefmtln(w, "")
}

View file

@ -126,6 +126,7 @@ func (g *PackGenerator) emitFileContents(file string, body string) error {
// Emit a header into the file.
emitHeaderWarning(w)
writefmtln(w, "/* tslint:disable:ordered-imports variable-name */")
// If there are any resources, import the Lumi package.
if g.FileHadRes {

View file

@ -38,15 +38,10 @@ func InitLogging(logToStderr bool, verbose int, logFlow bool) {
flag.Parse()
if logToStderr {
err := flag.Lookup("logtostderr").Value.Set("true")
if err != nil {
contract.Assert(err != nil)
}
contract.Assert(err != nil)
}
if verbose > 0 {
err := flag.Lookup("v").Value.Set(strconv.Itoa(verbose))
if err != nil {
contract.Assert(err != nil)
}
contract.Assert(err != nil)
}
}

View file

@ -178,11 +178,6 @@ func (w *workspace) DepCandidates(dep pack.PackageURL) []string {
return cands
}
// namePath just cleans a name and makes sure it's appropriate to use as a path.
func namePath(nm tokens.Name) string { //nolint
return stringNamePath(string(nm))
}
// qnamePath just cleans a name and makes sure it's appropriate to use as a path.
func qnamePath(nm tokens.QName) string {
return stringNamePath(string(nm))

View file

@ -120,5 +120,6 @@
"check-separator",
"check-type"
]
}
}