Initial commit

This commit is contained in:
Sérgio Ramos 2016-10-10 16:37:26 +01:00 committed by Tom Gallacher
commit dd718e1135
64 changed files with 3050 additions and 0 deletions

13
triton-graphql/.eslintrc Normal file
View File

@ -0,0 +1,13 @@
{
"extends": "semistandard",
"rules": {
"no-unused-vars": "error",
"space-before-function-paren": [2, "never"],
"object-curly-newline": ["error", {
"minProperties": 1
}],
"sort-vars": ["error", {
"ignoreCase": true
}]
}
}

50
triton-graphql/.gitignore vendored Normal file
View File

@ -0,0 +1,50 @@
# Logs
logs
*.log
npm-debug.log*
# Runtime data
pids
*.pid
*.seed
*.pid.lock
# Directory for instrumented libs generated by jscoverage/JSCover
lib-cov
# Coverage directory used by tools like istanbul
coverage
# nyc test coverage
.nyc_output
# Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files)
.grunt
# node-waf configuration
.lock-wscript
# Compiled binary addons (http://nodejs.org/api/addons.html)
build/Release
# Dependency directories
node_modules
jspm_packages
# Optional npm cache directory
.npm
# Optional eslint cache
.eslintcache
# Optional REPL history
.node_repl_history
# Output of 'npm pack'
*.tgz
# Vim files:
*.sw*
# Mac OS dirty files
.DS_Store

144
triton-graphql/README.md Normal file
View File

@ -0,0 +1,144 @@
# triton-graphql
Proof-of-Concept of the Triton API running on GraphQL.
### install dependencies
```bash
$ npm install
```
### setup credentials
Edit `credentials.json`
```json
{
"url": "https://us-sw-1.api.joyentcloud.com",
"keyId": "", //public key fingerprint ex: 35:jh:42:56...
"account": "", // account ex: raoulmillais
"user": "" // sub-account ex: ramitos
}
```
## api
- [x] Account
- [x] GetAccount
- [x] UpdateAccount
- [x] Keys
- [x] ListKeys
- [x] GetKey
- [x] CreateKey
- [x] DeleteKey
- [x] Users
- [x] ListUsers
- [x] GetUser
- [x] CreateUser
- [x] UpdateUser
- [-] ChangeUserPassword
- [x] DeleteUser
- [x] Roles
- [x] ListRoles
- [x] GetRole
- [x] CreateRole
- [x] UpdateRole
- [x] DeleteRole
- [x] Role Tags
- [x] SetRoleTags
- [x] Policies
- [x] ListPolicies
- [x] GetPolicy
- [x] CreatePolicy
- [x] UpdatePolicy
- [x] DeletePolicy
- [x] User SSH Keys
- [x] ListUserKeys
- [x] GetUserKey
- [x] CreateUserKey
- [x] DeleteUserKey
- [-] Config
- [-] GetConfig
- [-] UpdateConfig
- [x] Datacenters
- [x] ListDatacenters
- [x] GetDatacenter
- [x] Services
- [x] ListServices
- [x] Images
- [x] ListImages
- [x] GetImage
- [x] DeleteImage
- [x] ExportImage
- [x] CreateImageFromMachine
- [-] UpdateImage
- [x] Packages
- [x] ListPackages
- [x] GetPackage
- [x] Instances
- [x] ListMachines
- [x] GetMachine
- [x] CreateMachine
- [x] StopMachine
- [x] StartMachine
- [x] RebootMachine
- [-] ResizeMachine
- [-] RenameMachine
- [x] EnableMachineFirewall
- [x] DisableMachineFirewall
- [x] CreateMachineSnapshot
- [x] StartMachineFromSnapshot
- [x] ListMachineSnapshots
- [x] GetMachineSnapshot
- [x] DeleteMachineSnapshot
- [-] UpdateMachineMetadata
- [-] ListMachineMetadata
- [-] GetMachineMetadata
- [-] DeleteMachineMetadata
- [-] DeleteAllMachineMetadata
- [x] AddMachineTags
- [x] ReplaceMachineTags
- [ ] ListMachineTags
- [x] GetMachineTag
- [x] DeleteMachineTag
- [x] DeleteMachineTags
- [x] DeleteMachine
- [x] MachineAudit
- [-] Analytics
- [-] DescribeAnalytics
- [-] ListInstrumentations
- [-] GetInstrumentation
- [-] GetInstrumentationValue
- [-] GetInstrumentationHeatmap
- [-] GetInstrumentationHeatmapDetails
- [-] CreateInstrumentation
- [-] DeleteInstrumentation
- [x] FirewallRules
- [x] Firewall Rule Syntax
- [x] ListFirewallRules
- [x] GetFirewallRule
- [x] CreateFirewallRule
- [x] UpdateFirewallRule
- [x] EnableFirewallRule
- [x] DisableFirewallRule
- [x] DeleteFirewallRule
- [x] ListMachineFirewallRules
- [x] ListFirewallRuleMachines
- [-] Fabrics
- [-] ListFabricVLANs
- [-] CreateFabricVLAN
- [-] GetFabricVLAN
- [-] UpdateFabricVLAN
- [-] DeleteFabricVLAN
- [-] ListFabricNetworks
- [-] CreateFabricNetwork
- [-] GetFabricNetwork
- [-] DeleteFabricNetwork
- [x] Networks
- [x] ListNetworks
- [x] GetNetwork
- [-] Nics
- [-] ListNics
- [-] GetNic
- [-] AddNic
- [-] RemoveNic

View File

@ -0,0 +1,25 @@
{
"name": "triton-graphql",
"private": true,
"license": "Apache-2.0",
"version": "1.0.0",
"main": "src/index.js",
"dependencies": {
"bunyan": "^1.8.1",
"express": "^4.14.0",
"express-graphql": "^0.5.4",
"got": "^6.5.0",
"graphql": "^0.7.1",
"moment": "^2.15.1",
"smartdc-auth": "^2.5.2",
"triton": "^4.14.0",
"user-home": "^2.0.0"
},
"devDependencies": {
"eslint": "3.7.0",
"eslint-config-semistandard": "^7.0.0",
"eslint-config-standard": "^6.2.0",
"eslint-plugin-promise": "^2.0.1",
"eslint-plugin-standard": "^2.0.1"
}
}

View File

@ -0,0 +1,9 @@
const request = require('./request');
module.exports.get = () => {
return request('getAccount');
};
module.exports.update = (ctx) => {
return request('updateAccount', ctx);
};

View File

@ -0,0 +1,5 @@
// const request = require('./request');
module.exports.get = (ctx) => {
// return request('', ctx);
};

View File

@ -0,0 +1,5 @@
const request = require('./request');
module.exports = () => {
return request('listDatacenters');
};

View File

@ -0,0 +1,9 @@
const request = require('./request');
module.exports.list = () => {
return request('listFirewallRules', {});
};
module.exports.get = (ctx) => {
return request('getFirewallRule', ctx);
};

View File

@ -0,0 +1,37 @@
const request = require('./request');
module.exports.list = () => {
return request('listFirewallRules', {});
};
module.exports.listByMachine = (ctx) => {
return request('listMachineFirewallRules', ctx);
};
module.exports.listMachines = (ctx) => {
return request('listFirewallRuleMachines', ctx);
};
module.exports.get = (ctx) => {
return request('getFirewallRule', ctx);
};
module.exports.create = (ctx) => {
return request('createFirewallRule', ctx);
};
module.exports.update = (ctx) => {
return request('updateFirewallRule', ctx);
};
module.exports.enable = (ctx) => {
return request('enableFirewallRule', ctx);
};
module.exports.disable = (ctx) => {
return request('disableFirewallRule', ctx);
};
module.exports.destroy = (ctx) => {
return request('deleteFirewallRule', ctx);
};

View File

@ -0,0 +1,25 @@
const request = require('./request');
module.exports.list = (ctx) => {
return request('listImages', ctx);
};
module.exports.get = (ctx) => {
return request('getImage', ctx);
};
module.exports.create = (ctx) => {
return request('createImageFromMachine', ctx);
};
// module.exports.update = (ctx) => {
// return request('UpdateImage', ctx);
// };
module.exports.destroy = (uuid) => {
return request('deleteImage', uuid);
};
// module.exports.xport = (uuid) => {
// return request('deleteImage', uuid);
// };

View File

@ -0,0 +1,16 @@
module.exports = {
account: require('./account'),
users: require('./users'),
policies: require('./policies'),
roles: require('./roles'),
keys: require('./keys'),
datacenters: require('./datacenters'),
services: require('./services'),
images: require('./images'),
packages: require('./packages'),
machines: require('./machines'),
firewallRules: require('./firewall-rules'),
// fabrics: require('./fabrics'),
networks: require('./networks'),
nics: require('./nics')
};

View File

@ -0,0 +1,35 @@
const request = require('./request');
module.exports = {
user: {
list: (ctx) => {
return request('listUserKeys', ctx);
},
get: (ctx) => {
return request('getUserKey', ctx);
},
create: (ctx) => {
return request('createUserKey', ctx);
},
destroy: (ctx) => {
return request('deleteUserKey', ctx);
}
},
account: {
list: () => {
return request('listKeys', {});
},
get: (ctx) => {
return request('getKey', ctx);
},
create: (ctx) => {
return request('createKey', ctx);
},
destroy: (ctx) => {
return request('deleteKey', ctx);
}
}
};

View File

@ -0,0 +1,108 @@
const request = require('./request');
const snapshots = {
list: (ctx) => {
return request('listMachineSnapshots', ctx);
},
get: (ctx) => {
return request('getMachineSnapshot', ctx);
},
create: (ctx) => {
return request('createMachineSnapshot', ctx);
},
destroy: (ctx) => {
return request('deleteMachineSnapshot', ctx);
}
};
const metadata = {
list: (ctx) => {
return request('', ctx);
},
get: (ctx) => {
return request('', ctx);
},
update: (ctx) => {
return request('', ctx);
},
destroy: (ctx) => {
return request('', ctx);
}
};
const firewall = {
enable: (ctx) => {
return request('enableMachineFirewall', ctx);
},
disable: (ctx) => {
return request('disableMachineFirewall', ctx);
}
};
const tags = {
list: (ctx) => {
return request('listMachineTags', ctx);
},
get: (ctx) => {
return request('getMachineTag', ctx);
},
add: (ctx) => {
return request('addMachineTags', ctx);
},
replace: (ctx) => {
return request('replaceMachineTags', ctx);
},
destroy: (ctx) => {
const method = ctx.tag ? 'deleteMachineTag' : 'deleteMachineTags';
return request(method, ctx);
}
};
module.exports.list = (ctx) => {
return request('listMachines', ctx);
};
module.exports.get = (ctx) => {
return request('getMachine', ctx);
};
module.exports.create = (ctx) => {
return request('createMachine', ctx);
};
module.exports.stop = (ctx) => {
return request('stopMachine', ctx);
};
module.exports.start = (uuid) => {
return request('startMachine', uuid);
};
module.exports.startFromSnapshot = (ctx) => {
return request('startMachineFromSnapshot', ctx);
};
module.exports.reboot = (ctx) => {
return request('rebootMachine', ctx);
};
module.exports.resize = (ctx) => {
return request('', ctx);
};
module.exports.rename = (ctx) => {
return request('', ctx);
};
module.exports.destroy = (ctx) => {
return request('deleteMachine', ctx);
};
module.exports.audit = (ctx) => {
return request('machineAudit', ctx);
};
module.exports.snapshots = snapshots;
module.exports.metadata = metadata;
module.exports.firewall = firewall;
module.exports.tags = tags;

View File

@ -0,0 +1,9 @@
const request = require('./request');
module.exports.list = () => {
return request('listNetworks');
};
module.exports.get = (ctx) => {
return request('getNetwork', ctx);
};

View File

@ -0,0 +1,9 @@
const request = require('./request');
module.exports.list = () => {
return request('listNics');
};
module.exports.get = (ctx) => {
return request('getNic', ctx);
};

View File

@ -0,0 +1,9 @@
const request = require('./request');
module.exports.list = (ctx) => {
return request('listPackages', ctx);
};
module.exports.get = (ctx) => {
return request('getPackage', ctx);
};

View File

@ -0,0 +1,21 @@
const request = require('./request');
module.exports.list = (ctx) => {
return request('listPolicies');
};
module.exports.get = (ctx) => {
return request('getPolicy', ctx);
};
module.exports.create = (ctx) => {
return request('createPolicy', ctx);
};
module.exports.update = (ctx) => {
return request('updatePolicy', ctx);
};
module.exports.destroy = (ctx) => {
return request('deletePolicy', ctx);
};

View File

@ -0,0 +1,40 @@
const credentials = require('../../credentials.json');
const auth = require('smartdc-auth');
const cloudapi = require('triton/lib/cloudapi2');
const bunyan = require('bunyan');
var log = bunyan.createLogger({
name: 'triton-graphql'
});
var client = cloudapi.createClient({
log: log,
url: credentials.url,
account: credentials.account,
user: credentials.user,
sign: auth.cliSigner({
log: log,
keyId: credentials.keyId,
user: credentials.account,
subuser: credentials.user
})
});
module.exports = (method, args) => {
return new Promise((resolve, reject) => {
const fn = client[method].bind(client);
const cb = (err, res) => {
if (err) {
return reject(err);
}
resolve(res);
};
return args ? fn(args, cb) : fn(cb);
});
};
module.exports.client = client;

View File

@ -0,0 +1,31 @@
const request = require('./request');
module.exports.list = (ctx) => {
return request('listRoles');
};
module.exports.get = (ctx) => {
return request('getRole', ctx);
};
module.exports.create = (ctx) => {
return request('createRole', ctx);
};
module.exports.set = (ctx) => {
const id = ctx.id ? `/${id}` : '';
const resource = `/${request.client.account}/${ctx.resource}${id}`;
return request('setRoleTags', {
roleTags: ctx.role,
resource
});
};
module.exports.update = (ctx) => {
return request('updateRole', ctx);
};
module.exports.destroy = (ctx) => {
return request('deleteRole', ctx);
};

View File

@ -0,0 +1,5 @@
const request = require('./request');
module.exports = () => {
return request('listServices');
};

View File

@ -0,0 +1,21 @@
const request = require('./request');
module.exports.list = () => {
return request('listUsers');
};
module.exports.get = (ctx) => {
return request('getUser', ctx);
};
module.exports.create = (ctx) => {
return request('createUser', ctx);
};
module.exports.destroy = (ctx) => {
return request('deleteUser', ctx);
};
module.exports.update = (ctx) => {
return request('updateUser', ctx);
};

View File

@ -0,0 +1,20 @@
const express = require('express');
const graphqlHTTP = require('express-graphql');
const schema = require('./schema');
const app = express();
app.use('/graphql', graphqlHTTP(() => ({
schema: schema,
graphiql: true,
pretty: true
})));
app.listen(3000, (err) => {
if (err) {
console.log(err);
throw err;
}
console.log('Listening at localhost:3000');
});

View File

@ -0,0 +1,12 @@
const graphql = require('graphql');
const mutation = require('./mutations');
const query = require('./queries');
const {
GraphQLSchema
} = graphql;
module.exports = new GraphQLSchema({
query,
mutation
});

View File

@ -0,0 +1,57 @@
const AccountType = require('../types/login');
const api = require('../../api');
const {
GraphQLBoolean,
GraphQLString
} = require('graphql');
module.exports.updateAccount = {
type: AccountType,
description: 'Update your account details',
args: {
email: {
type: GraphQLString
},
company_name: {
type: GraphQLString
},
first_name: {
type: GraphQLString
},
last_name: {
type: GraphQLString
},
address: {
type: GraphQLString
},
postal_code: {
type: GraphQLString
},
city: {
type: GraphQLString
},
state: {
type: GraphQLString
},
country: {
type: GraphQLString
},
phone: {
type: GraphQLString
},
cns_enabled: {
type: GraphQLBoolean
}
},
resolve: (root, args) => {
return api.account.get().then((account) => {
return api.account.update(Object.assign(account, args, {
firstName: args.first_name || account.firstName,
lastName: args.first_name || account.lastName,
companyName: args.company_name || account.companyName,
postalCode: args.postal_code || account.postalCode
}));
});
}
};

View File

@ -0,0 +1,102 @@
const FirewallRuleType = require('../types/firewall-rule');
const api = require('../../api');
const {
GraphQLID,
GraphQLBoolean,
GraphQLString
} = require('graphql');
module.exports.createFirewallRule = {
type: FirewallRuleType,
description: 'Adds a new firewall rule for the specified account. This rule will be added to all the account\'s instances where it may be necessary',
args: {
enabled: {
type: GraphQLBoolean,
description: 'Indicates if the rule is enabled (optional, false by default)'
},
rule: {
type: GraphQLString,
description: 'Firewall rule text'
},
description: {
type: GraphQLString,
description: 'Human-readable description for the rule (optional)'
}
},
resolve: (root, args) => {
return api.firewallRules.create({
rule: args.rule,
description: args.description,
enabled: !!args.enabled
});
}
};
module.exports.updateFirewallRule = {
type: FirewallRuleType,
description: 'Updates the given rule record and -- depending on rule contents -- adds/removes/updates the rule on all the required instances',
args: {
id: {
type: GraphQLID,
description: 'Firewall rule id'
},
enabled: {
type: GraphQLBoolean,
description: 'Indicates if the rule is enabled (optional, false by default)'
},
rule: {
type: GraphQLString,
description: 'Firewall rule text'
},
description: {
type: GraphQLString,
description: 'Human-readable description for the rule (optional)'
}
},
resolve: (root, args) => {
return api.firewallRules.update(args);
}
};
module.exports.enableFirewallRule = {
type: FirewallRuleType,
description: 'Enables the given firewall rule if it is disabled',
args: {
id: {
type: GraphQLID,
description: 'Firewall rule id'
}
},
resolve: (root, args) => {
return api.firewallRules.enable(args);
}
};
module.exports.disableFirewallRule = {
type: FirewallRuleType,
description: 'Disables the given firewall rule if it is enabled',
args: {
id: {
type: GraphQLID,
description: 'Firewall rule id'
}
},
resolve: (root, args) => {
return api.firewallRules.disable(args);
}
};
module.exports.deleteFirewallRule = {
type: FirewallRuleType,
description: 'Removes the given firewall rule from all the required instances',
args: {
id: {
type: GraphQLID,
description: 'Firewall rule id'
}
},
resolve: (root, args) => {
return api.firewallRules.destroy(args);
}
};

View File

@ -0,0 +1,56 @@
const AccountType = require('../types/login');
const DynamicObjectType = require('../types/dynamic-object');
const api = require('../../api');
const {
GraphQLString,
GraphQLList,
GraphQLNonNull,
GraphQLID
} = require('graphql');
module.exports.createImage = {
type: AccountType,
description: 'Create a new custom image from an instance',
args: {
machine: {
type: new GraphQLNonNull(GraphQLID),
description: 'The prepared and stopped instance UUID from which the image is to be created'
},
name: {
type: new GraphQLNonNull(GraphQLString),
description: 'The name of the custom image, e.g. "my-image". Maximum 512 characters. However, typical names should be much shorter, e.g. 5-20 characters'
},
version: {
type: new GraphQLNonNull(GraphQLString),
description: 'The version of the custom image, e.g. "1.0.0". Maximum 128 characters'
},
description: {
type: GraphQLString,
description: 'A short prose description of this image. Maximum 512 characters'
},
homepage: {
type: GraphQLString,
description: 'Homepage URL where users can find more information about the image. Maximum 128 characters'
},
eula: {
type: GraphQLString,
description: 'URL of the End User License Agreement (EULA) for the image. Maximum 128 characters'
},
acl: {
type: new GraphQLList(GraphQLID),
description: 'An array of user/account UUIDs to which to give read access to a private image. I.e. this is only relevant for images with public === false'
},
tags: {
type: DynamicObjectType,
description: 'An object of key/value pairs that allows clients to categorize images by any given criteria'
}
},
resolve: (root, args) => {
const {
create
} = api.images;
return create(args);
}
};

View File

@ -0,0 +1,18 @@
const {
GraphQLObjectType
} = require('graphql');
module.exports = new GraphQLObjectType({
name: 'RootMutationType',
fields: Object.assign(
require('./account'),
require('./keys'),
require('./users'),
require('./roles'),
require('./policies'),
require('./machines'),
require('./images'),
require('./firewall-rules'),
require('./snapshots')
)
});

View File

@ -0,0 +1,53 @@
const KeyType = require('../types/key');
const api = require('../../api');
const {
GraphQLNonNull,
GraphQLString,
GraphQLID
} = require('graphql');
module.exports.createKey = {
type: KeyType,
description: 'Uploads a new OpenSSH key to Triton for use in HTTP signing and SSH',
args: {
name: {
type: new GraphQLNonNull(GraphQLString)
},
key: {
type: new GraphQLNonNull(GraphQLString)
},
userId: {
type: GraphQLID,
description: 'UserId to add this key to. Leaving this in blank will add the key to the account'
}
},
resolve: (root, args) => {
const _api = args.userId ? api.keys.user : api.keys.account;
return _api.create(args);
}
};
module.exports.deleteKey = {
type: GraphQLID,
description: 'Deletes a single SSH key, by name or fingerprint',
args: {
name: {
type: GraphQLString
},
fingerprint: {
type: GraphQLString
},
userId: {
type: GraphQLID,
description: 'UserId who this key belongs to. Leaving this in blank will delete an account key'
}
},
resolve: (root, args) => {
const _api = args.userId ? api.keys.user : api.keys.account;
return _api.destroy(args).then(() => {
return args.name || args.fingerprint;
});
}
};

View File

@ -0,0 +1,328 @@
const MachineType = require('../types/machine');
const DynamicObjectType = require('../types/dynamic-object');
const api = require('../../api');
const {
GraphQLNonNull,
GraphQLString,
GraphQLBoolean,
GraphQLID,
GraphQLList
} = require('graphql');
module.exports.createMachine = {
type: MachineType,
description: 'Allows you to provision an instance',
args: {
name: {
type: GraphQLString,
description: 'Friendly name for this instance; default is the first 8 characters of the machine id'
},
'package': {
type: new GraphQLNonNull(GraphQLString),
description: 'Id of the package to use on provisioning, obtained from ListPackages'
},
image: {
type: new GraphQLNonNull(GraphQLString),
description: 'The image UUID (from images { id })'
},
networks: {
type: new GraphQLList(GraphQLString),
description: 'Desired networks ids (from networks { id })'
},
locality: {
type: MachineType.locality,
description: 'Optionally specify which instances the new instance should be near or far from'
},
metadata: {
type: DynamicObjectType,
description: 'An arbitrary set of metadata key/value pairs can be set at provision time'
},
tags: {
type: DynamicObjectType,
description: 'An arbitrary set of tags can be set at provision time'
},
firewall_enabled: {
type: GraphQLBoolean,
description: 'Completely enable or disable firewall for this instance. Default is false'
}
},
resolve: (root, args) => {
const resolveNames = (obj = {}, namespace) => {
return Object.keys(obj).reduce((all, name) => {
return Object.assign(all, {
[`${namespace}.${name}`]: obj[name]
});
}, {});
};
const tags = resolveNames(args.tags, 'tag');
const metadata = resolveNames(args.tags, 'metadata');
const machine = Object.assign({
name: args.name,
'package': args['package'],
image: args.image,
networks: args.networks,
locality: args.locality,
firewall_enabled: args.firewall_enabled
}, tags, metadata);
return api.machines.create(machine);
}
};
module.exports.startMachine = {
type: MachineType,
description: 'Allows you to boot up an instance',
args: {
id: {
type: new GraphQLNonNull(GraphQLID),
description: 'The machine id'
}
},
resolve: (root, args) => {
return api.machines.start(args.id).then((machine) => {
if (machine) {
return machine;
}
return api.machines.get(args);
});
}
};
module.exports.startMachineFromSnapshot = {
type: MachineType,
description: 'If an instance is in the "stopped" state, you can choose to start the instance from the referenced snapshot',
args: {
id: {
type: new GraphQLNonNull(GraphQLID),
description: 'The machine id'
},
name: {
type: new GraphQLNonNull(GraphQLID),
description: 'The snapshot id'
}
},
resolve: (root, args) => {
return api.machines.startFromSnapshot(args).then((machine) => {
if (machine) {
return machine;
}
return api.machines.get(args);
});
}
};
module.exports.stopMachine = {
type: MachineType,
description: 'Allows you to shut down an instance',
args: {
id: {
type: new GraphQLNonNull(GraphQLID),
description: 'The machine id'
}
},
resolve: (root, args) => {
return api.machines.stop(args.id).then((machine) => {
if (machine) {
return machine;
}
return api.machines.get(args);
});
}
};
module.exports.rebootMachine = {
type: MachineType,
description: 'Allows you to reboot an instance',
args: {
id: {
type: new GraphQLNonNull(GraphQLID),
description: 'The machine id'
}
},
resolve: (root, args) => {
return api.machines.reboot(args.id).then((machine) => {
if (machine) {
return machine;
}
return api.machines.get(args);
});
}
};
module.exports.deleteMachine = {
type: DynamicObjectType,
description: 'Allows you to completely destroy an instance',
args: {
id: {
type: new GraphQLNonNull(GraphQLID),
description: 'The machine id'
}
},
resolve: (root, args) => {
return api.machines.destroy(args.id);
}
};
module.exports.auditMachine = {
type: new GraphQLList(DynamicObjectType),
description: 'Provides a list of an instance\'s accomplished actions. Results are sorted from newest to oldest action',
args: {
id: {
type: new GraphQLNonNull(GraphQLID),
description: 'The machine id'
}
},
resolve: (root, args) => {
return api.machines.destroy(args.id);
}
};
module.exports.setMachineFirewall = {
type: MachineType,
description: 'Allows you to set the firewall state for an instance',
args: {
id: {
type: new GraphQLNonNull(GraphQLID),
description: 'The machine id'
},
enabled: {
type: new GraphQLNonNull(GraphQLBoolean)
}
},
resolve: (root, args) => {
const {
firewall
} = api.machines;
const fn = args.enabled ? firewall.enable : firewall.disable;
return fn(args.id).then((machine) => {
if (machine) {
return machine;
}
return api.machines.get(args);
});
}
};
module.exports.enableMachineFirewall = {
type: MachineType,
description: 'Allows you to enable the firewall for an instance',
args: {
id: {
type: new GraphQLNonNull(GraphQLID),
description: 'The machine id'
}
},
resolve: (root, args) => {
const {
firewall
} = api.machines;
return firewall.enable(args.id).then((machine) => {
if (machine) {
return machine;
}
return api.machines.get(args);
});
}
};
module.exports.disableMachineFirewall = {
type: MachineType,
description: 'Allows you to completely disable the firewall of an instance',
args: {
id: {
type: new GraphQLNonNull(GraphQLID),
description: 'The machine id'
}
},
resolve: (root, args) => {
const {
firewall
} = api.machines;
return firewall.disable(args.id).then((machine) => {
if (machine) {
return machine;
}
return api.machines.get(args);
});
}
};
module.exports.addMachineTags = {
type: DynamicObjectType,
description: 'Set tags on the given instance',
args: {
id: {
type: new GraphQLNonNull(GraphQLID),
description: 'The machine id'
},
tags: {
type: new GraphQLNonNull(DynamicObjectType),
description: 'Tag name/value pairs'
}
},
resolve: (root, args) => {
const {
tags
} = api.machines;
return tags.add(args);
}
};
module.exports.replaceMachineTags = {
type: DynamicObjectType,
description: 'Fully replace all tags on an instance with the given tags',
args: {
id: {
type: new GraphQLNonNull(GraphQLID),
description: 'The machine id'
},
tags: {
type: new GraphQLNonNull(DynamicObjectType),
description: 'Tag name/value pairs'
}
},
resolve: (root, args) => {
const {
tags
} = api.machines;
return tags.replace(args);
}
};
module.exports.deleteMachineTags = {
type: DynamicObjectType,
description: 'Deletes tags from an instance',
args: {
id: {
type: new GraphQLNonNull(GraphQLID),
description: 'The machine id'
},
tag: {
type: GraphQLString,
description: 'Tag name to remove. If value is not supplied, all machine tags are removed'
}
},
resolve: (root, args) => {
const {
tags
} = api.machines;
return tags.destroy(args);
}
};

View File

@ -0,0 +1,71 @@
const PolicyType = require('../types/policy');
const api = require('../../api');
const {
GraphQLNonNull,
GraphQLString,
GraphQLID,
GraphQLList
} = require('graphql');
module.exports.createPolicy = {
type: PolicyType,
description: 'Creates a new account policy',
args: {
name: {
type: new GraphQLNonNull(GraphQLString),
description: 'The policy name'
},
rules: {
type: new GraphQLNonNull(new GraphQLList(GraphQLString)),
description: 'One or more Aperture sentences to be added to the current policy'
},
description: {
type: GraphQLString,
description: 'A description for this policy (Optional)'
}
},
resolve: (root, args) => {
return api.policies.create(args);
}
};
module.exports.updatePolicy = {
type: PolicyType,
description: 'Upgrades an existing account policy. Everything but id can be modified',
args: {
id: {
type: new GraphQLNonNull(GraphQLID)
},
name: {
type: new GraphQLNonNull(GraphQLString),
description: 'The policy name'
},
rules: {
type: new GraphQLNonNull(new GraphQLList(GraphQLString)),
description: 'One or more Aperture sentences to be added to the current policy'
},
description: {
type: GraphQLString,
description: 'A description for this policy (Optional)'
}
},
resolve: (root, args) => {
return api.policies.update(args);
}
};
module.exports.deletePolicy = {
type: GraphQLID,
description: 'Delete an RBAC policy',
args: {
id: {
type: new GraphQLNonNull(GraphQLID)
}
},
resolve: (root, args) => {
return api.policies.destroy(args).then(() => {
return args.id;
});
}
};

View File

@ -0,0 +1,105 @@
const RoleType = require('../types/role');
const api = require('../../api');
const {
GraphQLNonNull,
GraphQLString,
GraphQLID,
GraphQLList
} = require('graphql');
module.exports.createRole = {
type: RoleType,
description: 'Create a new role for your account',
args: {
name: {
type: new GraphQLNonNull(GraphQLString),
description: 'The role\'s name'
},
policies: {
type: new GraphQLList(GraphQLString),
description: 'This account\'s policies to be given to this role (Optional)'
},
members: {
type: new GraphQLList(GraphQLString),
description: 'This account\'s user logins to be added to this role (Optional)'
},
default_members: {
type: new GraphQLList(GraphQLString),
description: 'This account\'s user logins to be added to this role and have it enabled by default (Optional)'
}
},
resolve: (root, args) => {
return api.roles.create(args);
}
};
module.exports.updateRole = {
type: RoleType,
description: 'Modifies an account role. Anything but id can be modified',
args: {
id: {
type: new GraphQLNonNull(GraphQLID)
},
name: {
type: GraphQLString,
description: 'The role\'s name'
},
policies: {
type: new GraphQLList(GraphQLString),
description: 'This account\'s policies to be given to this role (Optional)'
},
members: {
type: new GraphQLList(GraphQLString),
description: 'This account\'s user logins to be added to this role (Optional)'
},
default_members: {
type: new GraphQLList(GraphQLString),
description: 'This account\'s user logins to be added to this role and have it enabled by default (Optional)'
}
},
resolve: (root, args) => {
return api.roles.update(args);
}
};
module.exports.deleteRole = {
type: GraphQLID,
description: 'Remove a role',
args: {
id: {
type: new GraphQLNonNull(GraphQLID)
}
},
resolve: (root, args) => {
return api.roles.destroy(args).then(() => {
return args.id;
});
}
};
module.exports.setRoleTags = {
type: RoleType.tag,
description: 'Sets the given role tags to the provided resource path. resource_path can be the path to any of the CloudAPI resources described in this document: account, keys, users, roles, policies, user\'s ssh keys, datacenters, images, packages, instances, analytics, instrumentations, firewall rules and networks.',
args: {
resource: {
type: new GraphQLNonNull(GraphQLString),
description: 'The resource type e.g. `machines`, `policies`...'
},
id: {
type: GraphQLID,
description: 'The resource id'
},
role: {
type: new GraphQLNonNull(new GraphQLList(GraphQLString)),
description: 'The list role-tags to be added to this resource'
}
},
resolve: (root, args) => {
const {
set
} = api.roles;
return set(args);
}
};

View File

@ -0,0 +1,73 @@
const SnapshotType = require('../types/snapshot');
const api = require('../../api');
const {
GraphQLNonNull,
GraphQLString,
GraphQLID
} = require('graphql');
module.exports.createSnapshot = {
type: SnapshotType,
description: 'Allows you to take a snapshot of a machine instance',
args: {
machine: {
type: new GraphQLNonNull(GraphQLID),
description: 'The machine id'
},
name: {
type: GraphQLString,
description: 'The name to assign to the new snapshot'
}
},
resolve: (root, args) => {
const {
snapshot: {
create,
get
}
} = api.machines;
const newArgs = {
id: args.machine,
name: args.name
};
return create(newArgs).then((snapshot) => {
if (snapshot) {
return snapshot;
}
return get(newArgs);
});
}
};
module.exports.deleteSnapshot = {
type: GraphQLID,
description: 'Deletes the specified snapshot of an instance',
args: {
machine: {
type: new GraphQLNonNull(GraphQLID),
description: 'The machine id'
},
name: {
type: GraphQLString,
description: 'The name to assign to the new snapshot'
}
},
resolve: (root, args) => {
const {
snapshot: {
destroy
}
} = api.machines;
const newArgs = {
id: args.machine,
name: args.name
};
return destroy(newArgs).then(() => args.name);
}
};

View File

@ -0,0 +1,144 @@
const UserType = require('../types/login');
const api = require('../../api');
const {
GraphQLNonNull,
GraphQLString,
GraphQLID
} = require('graphql');
module.exports.createUser = {
type: UserType,
description: 'Creates a new user under an account',
args: {
login: {
type: new GraphQLNonNull(GraphQLString)
},
email: {
type: new GraphQLNonNull(GraphQLString)
},
password: {
type: new GraphQLNonNull(GraphQLString)
},
company_name: {
type: GraphQLString
},
first_name: {
type: GraphQLString
},
last_name: {
type: GraphQLString
},
address: {
type: GraphQLString
},
postal_code: {
type: GraphQLString
},
city: {
type: GraphQLString
},
state: {
type: GraphQLString
},
country: {
type: GraphQLString
},
phone: {
type: GraphQLString
}
},
resolve: (root, args) => {
return api.users.create(Object.assign(args, {
firstName: args.first_name,
lastName: args.first_name,
companyName: args.company_name,
postalCode: args.postal_code
}));
}
};
module.exports.deleteUser = {
type: GraphQLID,
description: 'Remove a user',
args: {
id: {
type: new GraphQLNonNull(GraphQLID)
}
},
resolve: (root, args) => {
return api.users.destroy(args).then(() => {
return args.id;
});
}
};
module.exports.updateUser = {
type: UserType,
description: 'Update a user\'s modifiable properties',
args: {
id: {
type: new GraphQLNonNull(GraphQLID)
},
login: {
type: GraphQLString
},
email: {
type: GraphQLString
},
company_name: {
type: GraphQLString
},
first_name: {
type: GraphQLString
},
last_name: {
type: GraphQLString
},
address: {
type: GraphQLString
},
postal_code: {
type: GraphQLString
},
city: {
type: GraphQLString
},
state: {
type: GraphQLString
},
country: {
type: GraphQLString
},
phone: {
type: GraphQLString
}
},
resolve: (root, args) => {
return api.users.update(Object.assign(args, {
firstName: args.first_name,
lastName: args.first_name,
companyName: args.company_name,
postalCode: args.postal_code
}));
}
};
// module.exports.changeUserPassword = {
// type: UserType,
// description: 'This is a separate rule for password changes, so different policies can be used for an user trying to modify other data, or only their own password',
// args: {
// id: {
// type: new GraphQLNonNull(GraphQLID)
// },
// password: {
// type: GraphQLString
// },
// password_confirmation: {
// type: GraphQLString
// }
// },
// resolve: (root, args) => {
// return api.users.updatePassword(args);
// }
// };

View File

@ -0,0 +1,13 @@
const AccountType = require('../types/login');
const api = require('../../api');
module.exports = {
type: AccountType,
resolve() {
return api.account.get().then((account) => {
return Object.assign(account, {
isUser: false
});
});
}
};

View File

@ -0,0 +1,21 @@
const DatacenterType = require('../types/datacenter');
const graphql = require('graphql');
const api = require('../../api');
const {
GraphQLList
} = graphql;
module.exports = {
type: new GraphQLList(DatacenterType),
resolve() {
return api.datacenters().then((datacenters) => {
return Object.keys(datacenters).map((name) => {
return {
url: datacenters[name],
name
};
});
});
}
};

View File

@ -0,0 +1,14 @@
const FabricType = require('../types/fabrics');
const graphql = require('graphql');
const api = require('../../api');
const {
GraphQLList
} = graphql;
module.exports = {
type: new GraphQLList(FabricType),
resolve() {
return api.fabrics.list();
}
};

View File

@ -0,0 +1,26 @@
const FirewallRuleType = require('../types/firewall-rule');
const graphql = require('graphql');
const api = require('../../api');
const {
GraphQLList,
GraphQLID
} = graphql;
module.exports = {
type: new GraphQLList(FirewallRuleType),
args: {
id: {
type: GraphQLID,
description: 'Filter on id'
}
},
resolve(root, args) {
const {
list,
get
} = api.firewallRules;
return !args.id ? list() : get(args.id).then((rule) => [rule]);
}
};

View File

@ -0,0 +1,58 @@
const ImageType = require('../types/image');
const graphql = require('graphql');
const api = require('../../api');
const {
GraphQLList,
GraphQLBoolean,
GraphQLString,
GraphQLID
} = graphql;
module.exports = {
type: new GraphQLList(ImageType),
args: {
id: {
type: GraphQLID,
description: 'Filter on id'
},
name: {
type: GraphQLString,
description: 'Filter on "friendly" name'
},
os: {
type: GraphQLString,
description: 'Filter on the underlying operating system'
},
version: {
type: GraphQLString,
description: 'Filter on the version'
},
'public': {
type: GraphQLBoolean,
description: 'Filter public/private images'
},
state: {
type: GraphQLString,
description: 'Filter on image state. By default only active images are shown. Use "all" to list all images'
},
owner: {
type: GraphQLString,
description: 'Filter on owner UUID'
},
type: {
type: GraphQLString,
description: 'Filter on image type'
}
},
resolve(root, args) {
const {
list,
get
} = api.images;
return args.id ? get({
id: args.id
}).then((img) => [img]) : list(args);
}
};

View File

@ -0,0 +1,22 @@
const {
GraphQLObjectType
} = require('graphql');
module.exports = new GraphQLObjectType({
name: 'RootQueryType',
fields: {
account: require('./account'),
users: require('./users'),
policies: require('./policies'),
roles: require('./roles'),
datacenters: require('./datacenters'),
services: require('./services'),
images: require('./images'),
packages: require('./packages'),
machines: require('./machines'),
firewallRules: require('./firewall-rules'),
// fabrics: require('./fabrics')
networks: require('./networks')
// nics: require('./nics')
}
});

View File

@ -0,0 +1,83 @@
const MachineType = require('../types/machine');
const graphql = require('graphql');
const api = require('../../api');
const {
GraphQLInt,
GraphQLList,
GraphQLString,
GraphQLID
} = graphql;
module.exports = {
type: new GraphQLList(MachineType),
args: {
id: {
type: GraphQLID
},
brand: {
type: GraphQLString,
description: 'Filter on the type of instance (e.g. lx)'
},
name: {
type: GraphQLString,
description: 'Machine name to find (will make your list size 1, or 0 if nothing found)'
},
image: {
type: GraphQLString,
description: 'Image id; returns instances provisioned with that image'
},
state: {
type: GraphQLString,
description: 'Filter on the current state (e.g. running)'
},
memory: {
type: GraphQLInt,
description: 'Filter on the current size of the RAM deployed (in MiB)'
},
tombstone: {
type: GraphQLInt,
description: 'Filter on instances destroyed in the last N minutes'
},
first: {
type: GraphQLInt,
description: 'Return a max of N instances; default is 1000 (which is also the maximum allowable result set size)'
},
after: {
type: GraphQLInt,
description: 'Get a `first` number of instances starting at this offset'
},
tags: {
type: new GraphQLList(GraphQLString),
description: 'Filter on existing tags'
},
docker: {
type: GraphQLString,
description: 'Whether to only list Docker instances, or only non-Docker instances, if present. Defaults to showing all instances.'
},
credentials: {
type: GraphQLString,
description: 'Whether to include the generated credentials for instances, if present. Defaults to false'
}
},
resolve(root, args, ctx) {
const {
list,
get
} = api.machines;
const {
after,
first
} = args;
const newArgs = Object.assign(args, {
limit: first,
offset: after
});
return args.id ? get({
id: args.id
}).then((machine) => [machine]) : list(newArgs);
}
};

View File

@ -0,0 +1,25 @@
const NetworkType = require('../types/network');
const graphql = require('graphql');
const api = require('../../api');
const {
GraphQLList,
GraphQLID
} = graphql;
module.exports = {
type: new GraphQLList(NetworkType),
args: {
id: {
type: GraphQLID
}
},
resolve(root, args) {
const {
list,
get
} = api.networks;
return !args.id ? list() : get(args).then((network) => [network]);
}
};

View File

@ -0,0 +1,25 @@
const NicType = require('../types/nic');
const graphql = require('graphql');
const api = require('../../api');
const {
GraphQLList,
GraphQLString
} = graphql;
module.exports = {
type: new GraphQLList(NicType),
args: {
mac: {
type: GraphQLString
}
},
resolve(root, args) {
const {
list,
get
} = api.nics;
return !args.id ? list() : get(args).then((nic) => [nic]);
}
};

View File

@ -0,0 +1,62 @@
const PackageType = require('../types/package');
const graphql = require('graphql');
const api = require('../../api');
const {
GraphQLInt,
GraphQLList,
GraphQLString,
GraphQLID
} = graphql;
module.exports = {
type: new GraphQLList(PackageType),
args: {
id: {
type: GraphQLID,
description: 'Filter on package id'
},
name: {
type: GraphQLString,
description: 'Filter on the "friendly" name'
},
memory: {
type: GraphQLInt,
description: 'Filter on how much memory will by available (in MiB)'
},
disk: {
type: GraphQLInt,
description: 'Filter on how much disk space will be available (in MiB)'
},
swap: {
type: GraphQLInt,
description: 'Filter on how much swap space will be available (in MiB)'
},
lwps: {
type: GraphQLInt,
description: 'Filter on maximum number of light-weight processes (threads) allowed'
},
vcpus: {
type: GraphQLInt,
description: 'Filter on number of vCPUs'
},
version: {
type: GraphQLString,
description: 'Filter on the version'
},
group: {
type: GraphQLString,
description: 'Filter on the group belonging to'
}
},
resolve(root, args) {
const {
list,
get
} = api.packages;
return args.id ? get({
id: args.id
}).then((pkg) => [pkg]) : list(args);
}
};

View File

@ -0,0 +1,26 @@
const PolicyType = require('../types/policy');
const graphql = require('graphql');
const api = require('../../api');
const {
GraphQLList,
GraphQLID
} = graphql;
module.exports = {
type: new GraphQLList(PolicyType),
args: {
id: {
type: GraphQLID,
description: '`id` of the `PolicyType` to filter'
}
},
resolve(root, args) {
const {
list,
get
} = api.policies;
return !args.id ? list() : get(args).then((policy) => [policy]);
}
};

View File

@ -0,0 +1,26 @@
const RoleType = require('../types/role');
const graphql = require('graphql');
const api = require('../../api');
const {
GraphQLList,
GraphQLID
} = graphql;
module.exports = {
type: new GraphQLList(RoleType),
args: {
id: {
type: GraphQLID,
description: '`id` or `name` of the `RoleType` to filter'
}
},
resolve(root, args) {
const {
list,
get
} = api.roles;
return !args.id ? list() : get(args).then((role) => [role]);
}
};

View File

@ -0,0 +1,21 @@
const ServiceType = require('../types/service');
const graphql = require('graphql');
const api = require('../../api');
const {
GraphQLList
} = graphql;
module.exports = {
type: new GraphQLList(ServiceType),
resolve() {
return api.services().then((services) => {
return Object.keys(services).map((name) => {
return {
url: services[name],
name
};
});
});
}
};

View File

@ -0,0 +1,30 @@
const UserType = require('../types/login');
const graphql = require('graphql');
const api = require('../../api');
const {
GraphQLList,
GraphQLID
} = graphql;
module.exports = {
type: new GraphQLList(UserType),
args: {
id: {
type: GraphQLID,
description: '`id` or `login` of the `UserType` to filter'
}
},
resolve(root, args, ctx) {
const {
list,
get
} = api.users;
return !args.id ? list() : get(args).then((user) => [user]).then((user) => {
return Object.assign(user, {
isUser: true
});
});
}
};

View File

@ -0,0 +1,58 @@
const DynamicObjectType = require('./dynamic-object');
const {
GraphQLString,
GraphQLObjectType,
GraphQLBoolean
} = require('graphql');
const CallerType = new GraphQLObjectType({
name: 'CallerType',
fields: {
type: {
type: GraphQLString,
description: 'Authentication type for the action request. One of "basic", "operator", "signature" or "token"'
},
user: {
type: GraphQLString,
description: 'When the authentication type is "basic", this member will be present and include user login'
},
ip: {
type: GraphQLString,
description: 'The IP addresses this from which the action was requested. Not present if type is "operator"'
},
keyId: {
type: GraphQLString,
description: 'When authentication type is either "signature" or "token", SSH key identifier'
}
}
});
module.exports = new GraphQLObjectType({
name: 'AuditType',
fields: {
action: {
type: GraphQLString,
description: 'The name of the action'
},
parameters: {
type: DynamicObjectType,
description: 'The original set of parameters sent when the action was requested'
},
success: {
type: GraphQLBoolean,
description: '`true` or `false`, depending on the action\'s success',
resolve: (root) => {
return root.success === 'yes';
}
},
caller: {
type: CallerType,
description: 'Account requesting the action'
},
time: {
type: GraphQLString,
description: 'When the action finished'
}
}
});

View File

@ -0,0 +1,17 @@
const {
GraphQLString,
GraphQLObjectType
} = require('graphql');
module.exports = new GraphQLObjectType({
name: 'DatacenterType',
fields: {
name: {
type: GraphQLString,
description: 'location of the datacenter'
},
url: {
type: GraphQLString
}
}
});

View File

@ -0,0 +1,44 @@
const {
GraphQLScalarType,
Kind
} = require('graphql');
const kinds = {
[Kind.STRING]: (ast) => {
return ast.value;
},
[Kind.BOOLEAN]: (ast) => {
return kinds[Kind.STRING](ast);
},
[Kind.INT]: (ast) => {
return Number(ast.value);
},
[Kind.FLOAT]: (ast) => {
return kinds[Kind.INT](ast);
},
[Kind.OBJECT]: (ast) => {
const value = Object.create(null);
ast.fields.forEach(field => {
value[field.name.value] = parseLiteral(field.value);
});
return value;
},
[Kind.LIST]: (ast) => {
return ast.values.map(parseLiteral);
}
};
// https://github.com/taion/graphql-type-json/blob/master/src/index.js
const parseLiteral = (ast) => {
const kind = kinds[ast.kind];
return kind ? kinds[ast.kind](ast) : null;
};
// from http://stackoverflow.com/a/34229603
module.exports = new GraphQLScalarType({
name: 'DynamicObjectType',
serialize: v => v,
parseValue: v => v,
parseLiteral: parseLiteral
});

View File

@ -0,0 +1,23 @@
const {
GraphQLString,
GraphQLObjectType,
GraphQLInt
} = require('graphql');
module.exports = new GraphQLObjectType({
name: 'FabricsType',
fields: {
name: {
type: GraphQLString,
description: 'A unique name to identify the VLAN'
},
vlan_id: {
type: GraphQLInt,
description: 'A number from 0-4095 that indicates the VLAN\'s id'
},
description: {
type: GraphQLString,
description: 'An optional description of the VLAN'
}
}
});

View File

@ -0,0 +1,93 @@
const MachineType = require('../types/machine');
const api = require('../../api');
console.log(MachineType);
const {
GraphQLString,
GraphQLBoolean,
GraphQLObjectType,
GraphQLList,
GraphQLID,
GraphQLInt
} = require('graphql');
const FirewallRuleSyntaxType = new GraphQLObjectType({
name: 'FirewallRuleSyntaxType',
fields: {
text: {
type: GraphQLString
},
'from': {
type: GraphQLString
},
'to': {
type: GraphQLString
},
action: {
type: GraphQLString
},
protocol: {
type: GraphQLString
},
port: {
type: GraphQLInt
}
}
});
module.exports = new GraphQLObjectType({
name: 'FirewallRuleType',
fields: {
id: {
type: GraphQLID,
description: 'Unique identifier for this rule'
},
enabled: {
type: GraphQLBoolean,
description: 'Indicates if the rule is enabled',
resolve: (root) => {
return !!root.enabled;
}
},
rule: {
type: FirewallRuleSyntaxType,
description: 'Firewall rule',
resolve: ({
rule
}) => {
const regex = /from (.*?) to (.*?) (allow|deny) (.*?) port (\d*)/i;
const tokens = rule.match(regex);
return {
'from': tokens[1],
'to': tokens[2],
action: tokens[3],
protocol: tokens[4],
port: tokens[5],
text: rule
};
}
},
global: {
type: GraphQLBoolean,
description: 'Indicates if the rule is global',
resolve: (root) => {
return !!root.global;
}
},
description: {
type: GraphQLString,
description: 'Human-readable description for the rule'
}
// machines: {
// type: new GraphQLList(MachineType),
// description: 'Lists all instances a firewall rule is applied to',
// resolve: (root) => {
// return api.firewallRules.listMachines({
// id: root.id
// });
// }
// }
}
});

View File

@ -0,0 +1,116 @@
const DynamicObjectType = require('./dynamic-object');
const {
GraphQLBoolean,
GraphQLString,
GraphQLObjectType,
GraphQLInt,
GraphQLList,
GraphQLID
} = require('graphql');
const ErrorType = new GraphQLObjectType({
name: 'ErrorType',
fields: {
code: {
type: GraphQLString,
description: 'A CamelCase string code for this error, e.g. "PrepareImageDidNotRun". See GetImage docs for a table of error.code values'
},
message: {
type: GraphQLString,
description: 'A short description of the image creation failure'
}
}
});
const ImageFileType = new GraphQLObjectType({
name: 'ImageFileType',
fields: {
compression: {
type: GraphQLString,
description: 'The type of file compression used for the image file. One of "bzip2", "gzip", "none"'
},
sha1: {
type: GraphQLString,
description: 'SHA-1 hex digest of the file content. Used for corruption checking'
},
size: {
type: GraphQLInt,
description: 'File size in bytes'
}
}
});
module.exports = new GraphQLObjectType({
name: 'ImageType',
description: 'An image contains the software packages that will be available on newly-provisioned instance. In the case of hardware virtual machines, the image also includes the operating system',
fields: {
id: {
type: GraphQLID,
description: 'Unique id for this image'
},
name: {
type: GraphQLString,
description: 'The "friendly" name for this image'
},
os: {
type: GraphQLString,
description: 'The underlying operating system for this image'
},
version: {
type: GraphQLString,
description: 'The version for this image'
},
type: {
type: GraphQLString,
description: 'What kind of image this is. The values differ after v8.0.0+'
},
requirements: {
type: DynamicObjectType,
description: 'Contains a grouping of various minimum requirements for provisioning an instance with this image. For example "password" indicates that a password must be provided'
},
homepage: {
type: GraphQLString,
description: 'The URL for a web page with more detailed information for this image'
},
files: {
type: new GraphQLList(ImageFileType),
description: 'An array of image files that make up each image. Currently only a single file per image is supported'
},
published_at: {
type: GraphQLString,
description: 'The time this image has been made publicly available'
},
owner: {
type: GraphQLString,
description: 'The UUID of the user who owns this image'
},
'public': {
type: GraphQLBoolean,
description: 'Indicates if this image is publicly available',
resolve: (root) => {
return !!root['public'];
}
},
state: {
type: GraphQLString,
description: 'The current state of the image. One of "active", "unactivated", "disabled", "creating", "failed"'
},
tags: {
type: DynamicObjectType,
description: 'An object of key/value pairs that allows clients to categorize images by any given criteria'
},
eula: {
type: GraphQLString,
description: 'URL of the End User License Agreement (EULA) for the image'
},
acl: {
type: new GraphQLList(GraphQLString),
description: 'Access Control List. An array of account UUIDs given access to a private image. The field is only relevant to private images'
},
error: {
type: ErrorType,
description: 'If state=="failed", resulting from CreateImageFromMachine failure, then there may be an error object of the form {"code": "<string error code>", "message": "<string desc>"}'
}
}
});

View File

@ -0,0 +1,19 @@
const {
GraphQLString,
GraphQLObjectType
} = require('graphql');
module.exports = new GraphQLObjectType({
name: 'KeyType',
fields: {
name: {
type: GraphQLString
},
fingerprint: {
type: GraphQLString
},
key: {
type: GraphQLString
}
}
});

View File

@ -0,0 +1,111 @@
const KeyType = require('./key');
const api = require('../../api');
const {
GraphQLBoolean,
GraphQLString,
GraphQLList,
GraphQLObjectType,
GraphQLID
} = require('graphql');
module.exports = new GraphQLObjectType({
name: 'LoginType',
fields: {
id: {
type: GraphQLID,
description: 'Unique id for this user/account'
},
login: {
type: GraphQLString,
description: 'Account/Sub-user login name'
},
email: {
type: GraphQLString,
description: 'Email address'
},
company_name: {
type: GraphQLString,
resolve: (root) => {
return !!root.company_name || root.companyName;
}
},
first_name: {
type: GraphQLString,
resolve: (root) => {
return !!root.first_name || root.firstName;
}
},
last_name: {
type: GraphQLString,
resolve: (root) => {
return !!root.last_name || root.lastName;
}
},
address: {
type: GraphQLString
},
postal_code: {
type: GraphQLString,
resolve: (root) => {
return !!root.postal_code || root.postalCode;
}
},
city: {
type: GraphQLString
},
state: {
type: GraphQLString
},
country: {
type: GraphQLString
},
phone: {
type: GraphQLString
},
cns_enabled: {
type: GraphQLBoolean,
description: 'true if Triton CNS is enabled for account',
resolve: (root) => {
return root.isUser ? null : !!root.triton_cns_enabled;
}
},
keys: {
type: new GraphQLList(KeyType),
description: 'Get keys for user/account',
args: {
name: {
type: GraphQLString,
description: 'Filter on key name'
},
fingerprint: {
type: GraphQLString,
description: 'Filter on key fingerprint'
}
},
resolve(root, args) {
const _api = root.isUser ? api.keys.user : api.keys.account;
const {
list,
get
} = _api;
const newArgs = Object.assign(args, {
userId: root.id
});
const filtered = args.name || args.fingerprint;
return !filtered ? list(newArgs) : get(newArgs).then((key) => [key]);
}
},
updated: {
type: GraphQLString,
description: 'When this user/account\'s details was last updated'
},
created: {
type: GraphQLString,
description: 'When this user/account was created'
}
}
});

View File

@ -0,0 +1,169 @@
const FirewallRuleType = require('./firewall-rule');
const DynamicObjectType = require('./dynamic-object');
const SnapshotType = require('./snapshot');
const api = require('../../api');
const {
GraphQLBoolean,
GraphQLString,
GraphQLInputObjectType,
GraphQLObjectType,
GraphQLInt,
GraphQLList,
GraphQLID
} = require('graphql');
module.exports = new GraphQLObjectType({
name: 'MachineType',
description: 'An image contains the software packages that will be available on newly-provisioned instance. In the case of hardware virtual machines, the image also includes the operating system',
fields: {
id: {
type: GraphQLID,
description: 'Unique id for this instance'
},
name: {
type: GraphQLString,
description: 'The "friendly" name for this instance'
},
brand: {
type: GraphQLString,
description: 'The type of instance (e.g. lx)'
},
state: {
type: GraphQLString,
description: 'The current state of this instance (e.g. running)'
},
image: {
type: GraphQLString,
description: 'The image id this instance was provisioned with'
},
memory: {
type: GraphQLInt,
description: 'The amount of RAM this instance has (in MiB)'
},
disk: {
type: GraphQLInt,
description: 'The amount of disk this instance has (in MiB)'
},
metadata: {
type: DynamicObjectType,
description: 'Any additional metadata this instance has'
},
tags: {
type: DynamicObjectType,
description: 'Any tags this instance has',
args: {
name: {
type: GraphQLString,
description: 'Filter on the name of the tag'
}
},
resolve: (root, args) => {
const {
tags: {
get
}
} = api.machines;
return !args.name ? root.tags : get({
id: root.id,
tag: args.name
}).then((value) => {
return {
[args.name]: value
};
});
}
},
created: {
type: GraphQLString,
description: 'When this instance was created'
},
updated: {
type: GraphQLString,
description: 'When this instance\'s details was last updated'
},
docker: {
type: GraphQLBoolean,
description: 'Whether this instance is a Docker container, if present',
resolve: (root) => {
return !!root.docker;
}
},
ips: {
type: new GraphQLList(GraphQLString),
description: 'The IP addresses this instance has'
},
networks: {
type: new GraphQLList(GraphQLString),
description: 'The network UUIDs of the nics this instance has'
},
primaryIp: {
type: GraphQLString,
description: 'IP address of the primary nic of this instance'
},
firewall_enabled: {
type: GraphQLBoolean,
description: 'Whether firewall rules are enforced on this instance',
resolve: (root) => {
return !!root.firewall_enabled;
}
},
firewall_rules: {
type: new GraphQLList(FirewallRuleType),
description: 'List of FirewallRules affecting this machine',
resolve: (root) => {
return api.firewallRules.listByMachine(root.id);
}
},
compute_node: {
type: GraphQLString,
description: 'UUID of the server on which the instance is located'
},
'package': {
type: GraphQLString,
description: 'The id or name of the package used to create this instance'
},
snapshots: {
type: new GraphQLList(SnapshotType),
description: 'The snapshots based on this instance',
args: {
name: {
type: GraphQLString,
description: 'Filter on the name of the snapshot'
}
},
resolve: (root, args) => {
const {
snapshot: {
list,
get
}
} = api.machines;
return !args.id ? list(root) : get({
id: root.id,
name: args.name
});
}
}
}
});
module.exports.locality = new GraphQLInputObjectType({
name: 'LocalityType',
fields: {
strict: {
type: GraphQLBoolean,
resolve: (root) => {
return !!root.strict;
}
},
near: {
type: new GraphQLList(GraphQLID)
},
far: {
type: new GraphQLList(GraphQLID)
}
}
});

View File

@ -0,0 +1,73 @@
const DynamicObjectType = require('./dynamic-object');
const {
GraphQLBoolean,
GraphQLString,
GraphQLObjectType,
GraphQLList,
GraphQLID
} = require('graphql');
module.exports = new GraphQLObjectType({
name: 'NetworkType',
description: 'Logical networks in Triton model core network configurations to enable Triton to define Virtual Network Interfaces and IP addresses for instances',
fields: {
id: {
type: GraphQLID,
description: 'Unique id for this network'
},
name: {
type: GraphQLString,
description: 'The network name'
},
'public': {
type: GraphQLBoolean,
description: 'Whether this a public or private (rfc1918) network',
resolve: (root) => {
return !!root['public'];
}
},
fabric: {
type: GraphQLBoolean,
description: 'Whether this network is created on a fabric',
resolve: (root) => {
return !!root.fabric;
}
},
description: {
type: GraphQLString,
description: 'Description of this network'
},
subnet: {
type: GraphQLString,
description: 'A CIDR formatted string that describes the network'
},
provision_start_ip: {
type: GraphQLString,
description: 'The first IP on the network that may be assigned'
},
provision_end_ip: {
type: GraphQLString,
description: 'The last IP on the network that may be assigned'
},
gateway: {
type: GraphQLString,
description: 'Optional Gateway IP address'
},
resolvers: {
type: new GraphQLList(GraphQLString),
description: 'Optional Resolver IP addresses'
},
routes: {
type: DynamicObjectType,
description: 'Optional Static routes for hosts on this network'
},
internet_nat: {
type: GraphQLBoolean,
description: 'Provision internet NAT zone on gateway address',
resolve: (root) => {
return !!root.internet_nat;
}
}
}
});

View File

@ -0,0 +1,43 @@
const {
GraphQLBoolean,
GraphQLObjectType,
GraphQLString
} = require('graphql');
module.exports = new GraphQLObjectType({
name: 'NicType',
description: 'Logical networks are used both on head nodes and compute nodes, and are associated with physical interfaces by using a system called NIC Tags',
fields: {
ip: {
type: GraphQLString,
description: 'NIC\'s IPv4 address'
},
mac: {
type: GraphQLString,
description: 'NIC\'s MAC address'
},
primary: {
type: GraphQLBoolean,
description: 'Whether this is the instance\'s primary NIC',
resolve: (root) => {
return root.primary;
}
},
netmask: {
type: GraphQLString,
description: 'IPv4 netmask'
},
gateway: {
type: GraphQLString,
description: 'IPv4 gateway'
},
state: {
type: GraphQLString,
description: 'Describes the state of the NIC (e.g. provisioning, running, or stopped)'
},
network: {
type: GraphQLString,
description: 'The NIC\'s network id (see ListNetworks)'
}
}
});

View File

@ -0,0 +1,52 @@
const {
GraphQLString,
GraphQLObjectType,
GraphQLInt,
GraphQLID
} = require('graphql');
module.exports = new GraphQLObjectType({
name: 'PackageType',
fields: {
id: {
type: GraphQLID,
description: 'Unique id for this package'
},
name: {
type: GraphQLString,
description: 'The "friendly" name for this package'
},
memory: {
type: GraphQLInt,
description: 'How much memory will by available (in MiB)'
},
disk: {
type: GraphQLInt,
description: 'How much disk space will be available (in MiB)'
},
swap: {
type: GraphQLInt,
description: 'How much swap space will be available (in MiB)'
},
lwps: {
type: GraphQLInt,
description: 'Maximum number of light-weight processes (threads) allowed'
},
vcpus: {
type: GraphQLInt,
description: 'Number of vCPUs for this package'
},
version: {
type: GraphQLString,
description: 'The version of this package'
},
group: {
type: GraphQLString,
description: 'The group this package belongs to'
},
description: {
type: GraphQLString,
description: 'A human-friendly description about this package'
}
}
});

View File

@ -0,0 +1,29 @@
const {
GraphQLString,
GraphQLObjectType,
GraphQLList,
GraphQLID
} = require('graphql');
module.exports = new GraphQLObjectType({
name: 'PolicyType',
description: 'Policies are lists of rules that describe access to resources',
fields: {
id: {
type: GraphQLID,
description: 'Unique id for this policy'
},
name: {
type: GraphQLString,
description: 'The policy name'
},
rules: {
type: new GraphQLList(GraphQLString),
description: 'One or more Aperture sentences applying to the policy'
},
description: {
type: GraphQLString,
description: 'A description for this policy'
}
}
});

View File

@ -0,0 +1,50 @@
const {
GraphQLString,
GraphQLObjectType,
GraphQLList,
GraphQLID
} = require('graphql');
module.exports = new GraphQLObjectType({
name: 'RoleType',
description: 'Roles are lists of users and policies. Roles describe which users are allowed access according to the policies',
fields: {
id: {
type: GraphQLID,
description: 'Unique id for this role'
},
name: {
type: GraphQLString,
description: 'The role name'
},
policies: {
type: new GraphQLList(GraphQLString),
description: 'This account\'s policies which this role obeys (Optional)'
},
members: {
type: new GraphQLList(GraphQLString),
description: 'This account\'s user logins this role applies to (Optional)'
},
default_members: {
type: new GraphQLList(GraphQLString),
description: 'This account\'s user logins this role applies to by default (Optional)'
}
}
});
module.exports.tag = new GraphQLObjectType({
name: 'RoleTagType',
fields: {
name: {
type: GraphQLString,
description: 'Path to the resource'
},
role_tag: {
type: new GraphQLList(GraphQLString),
description: 'The role name',
resolve: (root) => {
return root['role-tag'] || root.role_tag;
}
}
}
});

View File

@ -0,0 +1,16 @@
const {
GraphQLString,
GraphQLObjectType
} = require('graphql');
module.exports = new GraphQLObjectType({
name: 'ServiceType',
fields: {
name: {
type: GraphQLString
},
url: {
type: GraphQLString
}
}
});

View File

@ -0,0 +1,20 @@
const {
GraphQLString,
GraphQLObjectType,
GraphQLID
} = require('graphql');
module.exports = new GraphQLObjectType({
name: 'SnapshotType',
description: 'Policies are lists of rules that describe access to resources',
fields: {
name: {
type: GraphQLID,
description: 'The name of this snapshot'
},
state: {
type: GraphQLString,
description: 'The current state of the snapshot'
}
}
});

View File