Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Commit 01410cf

Browse filesBrowse files
tyler-dunkelTyson Kunovsky
authored andcommitted
fix(readme): update readme with contribution guidelines.
1 parent 7fec9e1 commit 01410cf
Copy full SHA for 01410cf

9 files changed

+402-14Lines changed: 402 additions & 14 deletions
Expand file treeCollapse file tree
Open diff view settings
Collapse file

‎.cloud-graphrc.json.example‎

Copy file name to clipboard
+11Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
{
2+
"aws": {
3+
"regions": "us-east-1,us-east-2,us-west-1,us-west-2",
4+
"resources": "alb,vpc,cloudwatch,eip,ebs,ec2Instance,elb,igw,kms,lambda,nat,sg,networkInterface,apiGatewayRestApi,apiGatewayResource,apiGatewayStage"
5+
},
6+
"cloudGraph": {
7+
"dgraphHost": "http://localhost:8080",
8+
"directory": "cg",
9+
"queryEngine": "playground"
10+
}
11+
}
Collapse file

‎.eslintrc.json‎

Copy file name to clipboardExpand all lines: .eslintrc.json
+1-1Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,5 +7,5 @@
77
"rules": {
88
"no-console": "off"
99
},
10-
"ignorePatterns": ["src/plugins/"]
10+
"ignorePatterns": ["src/plugins/", "examples"]
1111
}
Collapse file

‎.gitignore‎

Copy file name to clipboardExpand all lines: .gitignore
+1-2Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,11 +7,10 @@
77
/tmp
88
node_modules
99
.cloud-graphrc.json
10-
*.graphql
1110
aws_*.json
1211
/.vscode
1312
/.yalc
1413
yalc.lock
1514
/src/plugins
16-
/cg-*
15+
/cg
1716
/dgraph
Collapse file

‎CONTRIBUTING.md‎

Copy file name to clipboard
+312Lines changed: 312 additions & 0 deletions
  • Display the source diff
  • Display the rich diff
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,312 @@
1+
# Contribution Guidelines
2+
3+
<!-- contributionguidelines -->
4+
5+
<!-- toc -->
6+
7+
- [Creating A new provider](#creating-a-new-provider)
8+
9+
- [Adding A new entity to an existing provider](#Adding-a-new-entity-to-an-existing-provider)
10+
11+
- [Adding new data to an existing entity](#Adding-new-data-to-an-existing-entity)
12+
<!-- tocstop -->
13+
14+
## Getting Started
15+
16+
To setup `CloudGraph` in development mode, first clone the CLI repo.
17+
**TODO:** update to correct url
18+
19+
```bash
20+
git clone https://github.com/sindresorhus/ora
21+
```
22+
23+
Next, if you are doing updates to an **existing** provider module, clone that as well. For example `cg-provider-aws`
24+
**TODO:** update to correct url
25+
26+
```bash
27+
git clone https://github.com/sindresorhus/ora
28+
```
29+
30+
`cd` into the provider repo and run the repos build command. For `cg-provider-aws` this would be:
31+
32+
```
33+
yarn build
34+
```
35+
36+
In order to have the `CLI` pick up changes you have made locally, you must link the two repos. In the provider repo, run:
37+
38+
```bash
39+
yarn link
40+
```
41+
42+
The output of `yarn link` will tell you what command to run within the CLI repo. For example:
43+
44+
```bash
45+
yarn link cg-provider-aws
46+
```
47+
48+
Next, make your changes within the provider repo and run `yarn build` again. And that's it! Now the `CLI` will pick up your changes when it pulls in the provider client.
49+
50+
## Creating A New Provider
51+
52+
To create a new provider, you must create a new NPM module that is publicly available within the NPM registry and conforms to the naming convention `@${yourOrgName}/cg-provider-${providerName}`. For example `@myOrg/cg-provider-pivotal`. The module must export a client for your provider that extends the `Client` class found in `@cloudgraph/sdk` shown below and defines the functions `configure`, `getSchema`, and `getData` . We will describe what each function should do below.
53+
54+
```
55+
export default abstract class Provider {
56+
constructor(config: any) {
57+
this.logger = config.logger
58+
this.config = config.provider
59+
}
60+
61+
interface = inquirer
62+
63+
logger: Logger
64+
65+
config: any
66+
67+
68+
async configure(flags: any): Promise<any> {
69+
throw new Error('Function configure has not been defined')
70+
}
71+
72+
getSchema(): string {
73+
throw new Error('Function getSchema has not been defined')
74+
}
75+
76+
async getData({ opts }: { opts: Opts }): Promise<any> {
77+
throw new Error('Function getData has not been defined')
78+
}
79+
}
80+
```
81+
82+
### Configure
83+
84+
The `configure` function is called by `@cloudgraph/cli` in the `INIT` command to allow each provider to control its own configuration. This configuration will then be passed to the provider client's `constructor` as `config.provider`. The provider client must call `super(config)` within its `constructor` to allow the `@cloudgraph/sdk` client to set the `this.config` which can then be consumed within the provider. The `configure` function should return an `Object` containing all the properties and values the provider wants to allow the end user to set. Here is an example configuration for `aws`
85+
86+
```
87+
{
88+
"regions": "us-east-1,us-east-2,us-west-1",
89+
"resources": "alb,lambda,ebs"
90+
}
91+
```
92+
93+
You may prompt the user to enter values using `this.interface` which is an instance of `Inquirer.js` https://github.com/SBoudrias/Inquirer.js
94+
95+
### getSchema
96+
97+
The `getSchema` function should return the stringified GraphQL schema that will be used by your provider. You can add any valid [Dgraph directive](https://dgraph.io/docs/graphql/directives/) to your schema in order to control the results of the schema generated by Dgraph. Below is an example implementation of `getSchema` used in `@cloudgraph/cg-provider-aws`.
98+
99+
**NOTE**: You will only need to define the GraphQL **types** that describe your schema and Dgraph will automatically generate the queries and mutations to access those types.
100+
101+
```
102+
/**
103+
* getSchema is used to get the schema for provider
104+
* @returns A string of graphql sub schemas
105+
*/
106+
107+
getSchema(): string {
108+
const typesArray = loadFilesSync(path.join(__dirname), {
109+
recursive: true,
110+
extensions: ['graphql'],
111+
})
112+
113+
return print(mergeTypeDefs(typesArray))
114+
}
115+
```
116+
117+
## getData
118+
119+
The `getData` function is responsible for collecting and returning all the provider data that you would like to be query-able by the end user. `@cloudgraph/cli` creates **nodes** in the graph through the concept of `entities` and **edges** in the graph through the concept of `connections`. `entities` are the provider data objects themselves as described by the defined GraphQL schema for the provider. `connections` are objects that describe how the tool should make connections **between** entities in the provider data. The data structure returned by the `getData` function should match the `ProviderData` interface below:
120+
121+
**Note**: Please see the [`@cloudgraph/cg-template-provider`](https://github.com/sindresorhus/ora) (**TODO**: update with real link) for an example on how to create entities and connections for a provider
122+
123+
```
124+
export interface ServiceConnection {
125+
id: string // The id of the entity to make a connection to
126+
127+
resourceType?: string // [Optional] The name of the connection
128+
129+
relation?: string // [Optional] The relation beteen the entity and its connection
130+
131+
field: string // The property on the parent schema this connected entity should be added to
132+
}
133+
134+
135+
136+
export interface Entity {
137+
name: string, // The name of the entity
138+
139+
mutation: string, // The GraphQL mutation that should be called to push this entity to Dgraph
140+
141+
/**
142+
* An array of the entity data supplied by the provider
143+
* that matches the GraphQL schema of that entity
144+
* (except for connections)
145+
*/
146+
data: any[]
147+
}
148+
149+
150+
151+
export interface ProviderData {
152+
entities: Entity[], // An array of objects matching the Entity interface
153+
154+
/**
155+
* An object where the keys are the ids of parent entities
156+
* to make connections to and where the values are an array of ServiceConnection
157+
* objects denoting which child entities the parent is connected to.
158+
*/
159+
connections: {[key: string]: ServiceConnection[]}
160+
}
161+
```
162+
163+
## Adding a new entity to an existing provider
164+
165+
To add a new entity (i.e. adding RDS to AWS) to an existing provider, (i.e. `@cloudgraph/cg-provider-aws`), you must create a new GraphQL sub-schema for that entity. This GraphQL schema should define the **type(s)** for the new entity and add any directives wanted. You must then define the functions the provider requires to query, format, and form connections for the new entity. In the case of **officially** supported providers under the `@cloudgraph` org, this would be done by creating the functions defined in the `Service` interface below.
166+
167+
**NOTE**: community supported providers could handle entities differently, consult with the creators of those providers if the way to add new entities is unclear.
168+
169+
```
170+
export interface Service {
171+
/**
172+
* function that formats an entity to match the GraphQL schema for that entity
173+
*/
174+
format: ({
175+
service,
176+
region,
177+
account,
178+
}: {
179+
service: any
180+
region: string
181+
account: string
182+
}) => any
183+
184+
/**
185+
* [Optional] function that returns the connections for an entity
186+
*/
187+
getConnections?: ({
188+
service,
189+
region,
190+
account,
191+
data,
192+
}: {
193+
service: any
194+
region: string
195+
account: string
196+
data: any
197+
}) => {[key: string]: ServiceConnection[],
198+
199+
mutation: string, // GraphQL mutation used to insert this entity into the DB
200+
201+
/**
202+
* Function to get the RAW entity data from the provider (such as the aws-sdk)
203+
*/
204+
getData: ({
205+
regions,
206+
credentials,
207+
opts,
208+
}: {
209+
regions: string
210+
credentials: any
211+
opts: Opts
212+
}) => any
213+
}
214+
```
215+
216+
You then must ensure that the `getData` function for the provider client knows about the new entity. In the case of `@cloudgraph/cg-provider-aws` this would be done by updating the `ServiceMap` Object and `services.js` file to include the new entity. For example, if you created a new entity `MyEntity`, you would first update the `services.js` file to include your new entity.
217+
218+
```
219+
export default {
220+
alb: 'alb',
221+
cloudwatch: 'cloudwatch',
222+
ebs: 'ebs',
223+
224+
...
225+
226+
myEntity: 'myEntity', // The new entity you are adding
227+
228+
...
229+
230+
subnet: 'subnet',
231+
vpc: 'vpc',
232+
}
233+
```
234+
235+
You would then update the `ServiceMap` to point to the new entity's class as seen below:
236+
237+
```
238+
export const ServiceMap = {
239+
[services.alb]: ALB,
240+
[services.cloudwatch]: CloudWatch,
241+
242+
...
243+
244+
[services.myEntity]: MyEntity, // The new entity class you have created
245+
[services.vpc]: VPC,
246+
247+
...
248+
249+
[services.ebs]: EBS,
250+
}
251+
```
252+
253+
## Adding new data to an existing entity
254+
255+
In order to add new data to an existing entity for **Officially** supported providers, you must update the entity's `schema`, `format` function, and `getData` function. Lets say you have an entity called `MyEntity` with the following schema, `getData` and `format`.
256+
257+
```
258+
type MyEntity {
259+
id: String!
260+
name: String!
261+
someDataPoint: String
262+
}
263+
264+
function getData() => {
265+
return {
266+
id: 'fakeId',
267+
name: 'fakeName',
268+
someDataFieldToChange: 'isADataPoint'
269+
}
270+
}
271+
272+
function format(rawData) => {
273+
return {
274+
id: rawData.id,
275+
name: rawData.name,
276+
someDataPoint: rawData.someDataFieldToChange
277+
}
278+
}
279+
```
280+
281+
and you wanted to add a new attribute called `myNewData`. You would update the entity like so:
282+
283+
```
284+
type MyEntity {
285+
id: String!
286+
name: String!
287+
someDataPoint: String
288+
myNewData: String // or whatever type the new data is
289+
}
290+
291+
function getData() => {
292+
return {
293+
id: 'fakeId',
294+
name: 'fakeName',
295+
someDataFieldToChange: 'isADataPoint',
296+
myNewData: 'myNewDataToAdd'
297+
}
298+
}
299+
300+
function format(rawData) => {
301+
return {
302+
id: rawData.id,
303+
name: rawData.name,
304+
someDataPoint: rawData.someDataFieldToChange,
305+
myNewData: rawData.myNewData
306+
}
307+
}
308+
```
309+
310+
And that's it! The CLI will now pick up the new data point and push it to the DB.
311+
312+
If you have any ideas for how to make this contribution guide more effective or easier to work with please let us know, we would love to hear your feedback.

0 commit comments

Comments
0 (0)
Morty Proxy This is a proxified and sanitized view of the page, visit original site.