├── .gitignore
├── .gitmodules
├── .travis.yml
├── Gruntfile.js
├── LICENSE
├── README.md
├── apiproxy
├── forecastweather-grunt-plugin-api.xml
├── policies
│ ├── Assign-Message-Remove-Suffix.xml
│ ├── JSON-to-XML.xml
│ ├── Script-External-Variables.xml
│ ├── SimpleJavaCallout.xml.bak
│ └── XMLtoJSON-Common.xml
├── proxies
│ └── default.xml
├── resources
│ └── jsc
│ │ ├── js_external_vars.js
│ │ ├── search-and-replace-example.js
│ │ └── search-and-replace-example2.js
└── targets
│ ├── default.xml
│ └── node.xml
├── config
└── kvm
│ └── testmyapi
│ ├── passwords.json
│ ├── passwords.json.encrypted
│ ├── testmyapi-prod
│ ├── passwords.json
│ ├── passwords.json.encrypted
│ ├── passwords2.json.encrypted
│ ├── targets.json
│ └── targets.json.encrypted
│ └── testmyapi-test
│ ├── passwords.json
│ ├── passwords.json.encrypted
│ ├── targets.json
│ └── targets.json.encrypted
├── grunt
├── apigee-config.js
├── conf
│ ├── eslint.json
│ └── rules
│ │ └── if-curly-formatting.js
├── lib
│ └── helper-functions.js
├── search-and-replace-files.js
└── tasks
│ ├── apigeeGruntPluginBanner.js
│ ├── compressAlias.js
│ ├── deleteApiRevision.js
│ ├── deployApiRevision.js
│ ├── deployApiRevisionAlias.js
│ ├── executeTests.js
│ ├── force.js
│ ├── getAllApiRevisions.js
│ ├── getDeployedApiRevisions.js
│ ├── installNpmRevision.js
│ ├── installNpmRevisionAlias.js
│ ├── saveGitRevision.js
│ ├── undeployApiRevision.js
│ └── updateApiRevision.js
├── java
├── lib
│ ├── expressions-1.0.0.jar
│ └── message-flow-1.0.0.jar
└── src
│ └── com
│ └── example
│ └── SimpleJavaCallout.java
├── node
├── .gitignore
├── app.js
├── node_modules
│ └── path
│ │ ├── package.json
│ │ └── path.js
├── package.json
├── public
│ ├── images
│ │ └── tree.jpg
│ └── tree.jpg
└── resources
│ └── forecastweather_node.js
├── package.json
├── tests
├── diego-forecastweather-grunt-plugin-api-test-data.js
├── forecastweather-grunt-plugin-api-prod-data.js
├── forecastweather-grunt-plugin-api-test-data.js
└── forecastweather-grunt-plugin-api.js
└── tools
├── CommonProxy
└── apiproxy
│ ├── policies
│ ├── Script-External-Variables.xml
│ └── xmltojson-1.xml
│ ├── proxies
│ ├── common-js-vars.flowfrag
│ └── xmltojson.flowfrag
│ └── resources
│ └── jsc
│ └── js_external_vars.js
├── forecastweather-jmeter-example
├── README.md
├── pom.xml
└── tests
│ ├── weather.jmx
│ ├── weather_prod.csv
│ └── weather_test.csv
└── proxy-dependency-maven-plugin
├── CommonProxy
└── apiproxy
│ ├── policies
│ ├── Script-External-Variables.xml
│ └── xmltojson-1.xml
│ ├── proxies
│ ├── common-js-vars.flowfrag
│ └── xmltojson.flowfrag
│ └── resources
│ └── jsc
│ └── js_external_vars.js
├── Gruntfile.js
├── README.md
├── apiproxy
├── forecastweather-grunt-plugin-api.xml
├── policies
│ ├── Assign-Message-Remove-Suffix.xml
│ ├── JSON-to-XML.xml
│ ├── Script-External-Variables.xml
│ ├── SimpleJavaCallout.xml.bak
│ └── XMLtoJSON-Common.xml
├── proxies
│ └── default.xml
├── resources
│ └── jsc
│ │ ├── js_external_vars.js
│ │ ├── search-and-replace-example.js
│ │ └── search-and-replace-example2.js
└── targets
│ ├── default.xml
│ └── node.xml
└── pom.xml
/.gitignore:
--------------------------------------------------------------------------------
1 |
2 | /node_modules
3 | target/
4 | report.xml
5 | checkstyle.xml
6 | results.html
7 | results.txt
8 | /config/kvm/**/*.decrypted
9 | /config/kvm/**/*.json
--------------------------------------------------------------------------------
/.gitmodules:
--------------------------------------------------------------------------------
1 | [submodule "common"]
2 | path = common
3 | url = https://github.com/apigeecs/apigee-deploy-grunt-plugin.git
4 |
--------------------------------------------------------------------------------
/.travis.yml:
--------------------------------------------------------------------------------
1 | language: node_js
2 | node_js:
3 | - "0.10"
4 | before_install: npm install -g grunt-cli
5 | install: npm install
6 | # step pending until Apigee credentials are encrypted in Travis by following these steps: http://docs.travis-ci.com/user/encryption-keys/
7 | before_script: grunt default -env=test -username=$ae_username -password=$ae_password -debug --upload-modules
8 | # Travis will look for scripts in the package.json, there I indicated the test step should run grunt mochaTest -env=test
9 | # based on answer from SO http://stackoverflow.com/questions/21128478/run-grunt-build-command-on-travis-ci
10 |
--------------------------------------------------------------------------------
/Gruntfile.js:
--------------------------------------------------------------------------------
1 | /*jslint node: true */
2 |
3 | /************************************************************************
4 | The MIT License (MIT)
5 |
6 | Copyright (c) 2014
7 |
8 | Permission is hereby granted, free of charge, to any person obtaining a copy
9 | of this software and associated documentation files (the "Software"), to deal
10 | in the Software without restriction, including without limitation the rights
11 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
12 | copies of the Software, and to permit persons to whom the Software is
13 | furnished to do so, subject to the following conditions:
14 |
15 | The above copyright notice and this permission notice shall be included in all
16 | copies or substantial portions of the Software.
17 |
18 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
24 | SOFTWARE.
25 | **************************************************************************/
26 |
27 | module.exports = function(grunt) {
28 | "use strict";
29 | var apigee_conf = require('./grunt/apigee-config.js')
30 | var helper = require('./grunt/lib/helper-functions.js');
31 | var searchNReplace = require('./grunt/search-and-replace-files.js');
32 | require('time-grunt')(grunt);
33 | // Project configuration.
34 | grunt.initConfig({
35 | pkg: grunt.file.readJSON('package.json'),
36 | apigee_profiles : apigee_conf.profiles(grunt),//{
37 | availabletasks: {
38 | tasks: {}
39 | },
40 | clean: ["target"],
41 | mkdir: {
42 | all: {
43 | options: {
44 | create: ['target', 'target/apiproxy/resources/java/', 'target/java/bin']
45 | },
46 | },
47 | },
48 | copy: {
49 | "java-jar" : {
50 | src: ['java/lib/*.jar', '!java/lib/expressions-1.0.0.jar', '!java/lib/message-flow-1.0.0.jar'],
51 | dest: 'target/apiproxy/resources/java/', filter: 'isFile', flatten: true, expand : true,
52 | },
53 | apiproxy: {
54 | src: 'apiproxy/**',
55 | dest: './target/',
56 | },
57 | "node-target": { // copy node folder to target for search and replace
58 | src: './node/**',
59 | dest: './target/'
60 | },
61 | "node-js-root": { //copy app.js and package.json
62 | expand : true,
63 | src: './target/node/*',
64 | dest: './target/apiproxy/resources/node/', filter: 'isFile', flatten: true
65 | },
66 | },
67 | // make a zipfile
68 | compress: {
69 | "node-modules": helper.setNodeResources('./target/node/node_modules/' ,{
70 | mode : 'zip',
71 | archive: './target/apiproxy/resources/node/node_modules.zip'
72 | }, [
73 | {expand: true, cwd: './target/node/node_modules/', src: ['**'], dest: 'node_modules/' } // makes all src relative to cwd
74 | ]),
75 |
76 | "node-public": helper.setNodeResources('./target/node/public/', {
77 | mode : 'zip',
78 | archive: './target/apiproxy/resources/node/public.zip'
79 | },[
80 | {expand: true, cwd: './target/node/public/', src: ['**'], dest: 'public/' }, // makes all src relative to cwd
81 | ]),
82 |
83 | "node-resources": helper.setNodeResources('./target/node/resources/', {
84 | mode : 'zip',
85 | archive: './target/apiproxy/resources/node/resources.zip'
86 | },[
87 | {expand: true, cwd: './target/node/resources/', src: ['**'], dest: 'resources/' }, // makes all src relative to cwd
88 | ]),
89 | main: {
90 | options: {
91 | mode : 'zip',
92 | archive: "target/<%= apigee_profiles[grunt.option('env')].apiproxy %>.zip"
93 | },
94 | files: [
95 | {expand: true, cwd: 'target/apiproxy/', src: ['**'], dest: 'apiproxy/' }, // makes all src relative to cwd
96 | ]
97 | }
98 | },
99 | // task for configuration management: search and replace elements within XML files
100 | xmlpoke: apigee_conf.xmlconfig(grunt.option('env'), grunt),
101 | // Configure a mochaTest task
102 | mochaTest: {
103 | test: {
104 | options: {
105 | reporter: 'spec', //supported reporters: tap
106 | timeout : 5000,
107 | quiet: false // Optionally suppress output to standard out (defaults to false)
108 | },
109 | src: ["tests/<%= apigee_profiles[grunt.option('env')].apiproxy %>**.js"]
110 | }
111 | },
112 | jshint: {
113 | options: { //see options reference http://www.jshint.com/docs/options/
114 | curly: true,
115 | eqeqeq: true,
116 | eqnull: true,
117 | browser: true,
118 | asi : true,
119 | debug : true,
120 | undef : true,
121 | unused : true,
122 | maxcomplexity : 5,
123 | reporter: require('jshint-stylish')
124 | },
125 | all: ['Gruntfile.js', 'apiproxy/**/*.js', 'tests/**/*.js', 'tasks/*.js']
126 | },
127 | eslint: { // task
128 | options: {
129 | config: 'grunt/conf/eslint.json', // custom config
130 | rulesdir: ['grunt/conf/rules'] // custom rules
131 | },
132 | target: ['Gruntfile.js', 'target/apiproxy/**/*.js', 'tests/**/*.js', 'tasks/*.js'] // array of files
133 | },
134 | 'string-replace': {
135 | dist : searchNReplace.searchAndReplaceFiles(grunt.option('env'), grunt)
136 | },
137 | shell: {
138 | options: {
139 | stderr: false,
140 | failOnError : true
141 | },
142 | // Remove comments to enable JavaCallout Policy
143 | // javaCompile: {
144 | // command: 'javac -sourcepath ./java/src/**/*.java -d ./target/java/bin -cp java/lib/expressions-1.0.0.jar:java/lib/message-flow-1.0.0.jar:jar:java/lib/message-flow-1.0.1.jar java/src/com/example/SimpleJavaCallout.java',
145 | // },
146 | // javaJar : {
147 | // command: 'jar cvf target/apiproxy/resources/java/javaCallouts.jar -C target/java/bin .',
148 | // },
149 |
150 | //run jmeter tests from Grunt
151 | /* "run_jmeter_tests" : {
152 | command: 'mvn install -P <%= grunt.option("env") %>',
153 | },*/
154 | },
155 | notify: {
156 | task_name: {
157 | options: {
158 | // Task-specific options go here.
159 | }
160 | },
161 | ApiDeployed: {
162 | options: {
163 | message: 'Deployment is ready!'
164 | }
165 | }
166 | },
167 | complexity: {
168 | generic: {
169 | src: ['target/apiproxy/**/*.js', 'tests/**/*.js', 'tasks/*.js'],
170 | exclude: ['doNotTest.js'],
171 | options: {
172 | breakOnErrors: true,
173 | jsLintXML: 'report.xml', // create XML JSLint-like report
174 | checkstyleXML: 'checkstyle.xml', // create checkstyle report
175 | errorsOnly: false, // show only maintainability errors
176 | cyclomatic: [3, 7, 12], // or optionally a single value, like 3
177 | halstead: [8, 13, 20], // or optionally a single value, like 8
178 | maintainability: 100,
179 | hideComplexFunctions: false, // only display maintainability
180 | broadcast: false // broadcast data over event-bus
181 | }
182 | },
183 | },
184 | prompt: helper.prompts(grunt)
185 | // Configure this task to support KVM data config migrations
186 | /* "apigee_kvm": {
187 | "testmyapi-test" : {
188 | options: {
189 | type: "env"
190 | },
191 | files: [{src: ['config/kvm/testmyapi/testmyapi-test/*.json']},
192 | ]
193 | },
194 | "testmyapi-prod" : {
195 | options: {
196 | type: "env"
197 | },
198 | files: [{src: ['config/kvm/testmyapi/testmyapi-prod/*.json']},
199 | ]
200 | },
201 | "testmyapi" : {
202 | options: {
203 | type: "org"
204 | },
205 | files: [{src: ['config/kvm/testmyapi/*.json']},
206 | ]
207 | }
208 | },*/
209 | })
210 |
211 | require('load-grunt-tasks')(grunt);
212 |
213 | // importKVM at Organization and Environment level. See apigee_kvm task above
214 | grunt.registerTask('importKVMs', ['apigee_kvm:' + grunt.config.get("apigee_profiles")[grunt.option('env')].org + '-' + grunt.option("env"), 'apigee_kvm:' + grunt.config.get("apigee_profiles")[grunt.option('env')].org]);
215 |
216 | grunt.registerTask('buildApiBundle', 'Build zip without importing it to Edge', ['apigeeGruntPluginBanner', 'prompt', 'clean', 'saveGitRevision', 'mkdir','copy', 'xmlpoke', 'string-replace', 'jshint', 'eslint', 'complexity', /*'shell'*/ 'compressAlias']);
217 | //1. import revision bumping revision id
218 | grunt.registerTask('IMPORT_DEPLOY_BUMP_REVISION', [ 'buildApiBundle', 'getDeployedApiRevisions', 'undeployApiRevision',
219 | 'apigee_import_api_bundle', 'installNpmRevisionAlias', 'deployApiRevisionAlias', 'executeTests', /*'shell:run_jmeter_tests',*/ 'notify:ApiDeployed']);
220 |
221 | //2. update revision keeping same id
222 | grunt.registerTask('UPDATE_CURRENT_REVISION', [ 'buildApiBundle', 'getDeployedApiRevisions', 'undeployApiRevision',
223 | 'updateApiRevision', 'installNpmRevisionAlias', 'deployApiRevisionAlias', 'executeTests', 'notify:ApiDeployed']);
224 |
225 | //3. import revision and run seamless deployment
226 | grunt.registerTask('DEPLOY_IMPORT_BUMP_SEAMLESS_REVISION', [ 'buildApiBundle', 'getDeployedApiRevisions', 'apigee_import_api_bundle',
227 | 'installNpmRevisionAlias', 'deployApiRevisionAlias', 'executeTests', /*'shell:run_jmeter_tests',*/ 'notify:ApiDeployed']);
228 |
229 | //set to DEPLOY_IMPORT_BUMP_SEAMLESS_REVISION by default. This is critical for production for seamless deploymen and not lose traffic
230 | grunt.registerTask('default', [ /*'importKVMs',*/'DEPLOY_IMPORT_BUMP_SEAMLESS_REVISION' ]);
231 |
232 | grunt.loadTasks('grunt/tasks');
233 | if(grunt.option.flags().indexOf('--help') === -1 && !grunt.option('env')) {
234 | grunt.fail.fatal('Invalid environment --env={env}.')
235 | }
236 | };
237 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | Apache License
2 | Version 2.0, January 2004
3 | http://www.apache.org/licenses/
4 |
5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
6 |
7 | 1. Definitions.
8 |
9 | "License" shall mean the terms and conditions for use, reproduction,
10 | and distribution as defined by Sections 1 through 9 of this document.
11 |
12 | "Licensor" shall mean the copyright owner or entity authorized by
13 | the copyright owner that is granting the License.
14 |
15 | "Legal Entity" shall mean the union of the acting entity and all
16 | other entities that control, are controlled by, or are under common
17 | control with that entity. For the purposes of this definition,
18 | "control" means (i) the power, direct or indirect, to cause the
19 | direction or management of such entity, whether by contract or
20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the
21 | outstanding shares, or (iii) beneficial ownership of such entity.
22 |
23 | "You" (or "Your") shall mean an individual or Legal Entity
24 | exercising permissions granted by this License.
25 |
26 | "Source" form shall mean the preferred form for making modifications,
27 | including but not limited to software source code, documentation
28 | source, and configuration files.
29 |
30 | "Object" form shall mean any form resulting from mechanical
31 | transformation or translation of a Source form, including but
32 | not limited to compiled object code, generated documentation,
33 | and conversions to other media types.
34 |
35 | "Work" shall mean the work of authorship, whether in Source or
36 | Object form, made available under the License, as indicated by a
37 | copyright notice that is included in or attached to the work
38 | (an example is provided in the Appendix below).
39 |
40 | "Derivative Works" shall mean any work, whether in Source or Object
41 | form, that is based on (or derived from) the Work and for which the
42 | editorial revisions, annotations, elaborations, or other modifications
43 | represent, as a whole, an original work of authorship. For the purposes
44 | of this License, Derivative Works shall not include works that remain
45 | separable from, or merely link (or bind by name) to the interfaces of,
46 | the Work and Derivative Works thereof.
47 |
48 | "Contribution" shall mean any work of authorship, including
49 | the original version of the Work and any modifications or additions
50 | to that Work or Derivative Works thereof, that is intentionally
51 | submitted to Licensor for inclusion in the Work by the copyright owner
52 | or by an individual or Legal Entity authorized to submit on behalf of
53 | the copyright owner. For the purposes of this definition, "submitted"
54 | means any form of electronic, verbal, or written communication sent
55 | to the Licensor or its representatives, including but not limited to
56 | communication on electronic mailing lists, source code control systems,
57 | and issue tracking systems that are managed by, or on behalf of, the
58 | Licensor for the purpose of discussing and improving the Work, but
59 | excluding communication that is conspicuously marked or otherwise
60 | designated in writing by the copyright owner as "Not a Contribution."
61 |
62 | "Contributor" shall mean Licensor and any individual or Legal Entity
63 | on behalf of whom a Contribution has been received by Licensor and
64 | subsequently incorporated within the Work.
65 |
66 | 2. Grant of Copyright License. Subject to the terms and conditions of
67 | this License, each Contributor hereby grants to You a perpetual,
68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable
69 | copyright license to reproduce, prepare Derivative Works of,
70 | publicly display, publicly perform, sublicense, and distribute the
71 | Work and such Derivative Works in Source or Object form.
72 |
73 | 3. Grant of Patent License. Subject to the terms and conditions of
74 | this License, each Contributor hereby grants to You a perpetual,
75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable
76 | (except as stated in this section) patent license to make, have made,
77 | use, offer to sell, sell, import, and otherwise transfer the Work,
78 | where such license applies only to those patent claims licensable
79 | by such Contributor that are necessarily infringed by their
80 | Contribution(s) alone or by combination of their Contribution(s)
81 | with the Work to which such Contribution(s) was submitted. If You
82 | institute patent litigation against any entity (including a
83 | cross-claim or counterclaim in a lawsuit) alleging that the Work
84 | or a Contribution incorporated within the Work constitutes direct
85 | or contributory patent infringement, then any patent licenses
86 | granted to You under this License for that Work shall terminate
87 | as of the date such litigation is filed.
88 |
89 | 4. Redistribution. You may reproduce and distribute copies of the
90 | Work or Derivative Works thereof in any medium, with or without
91 | modifications, and in Source or Object form, provided that You
92 | meet the following conditions:
93 |
94 | (a) You must give any other recipients of the Work or
95 | Derivative Works a copy of this License; and
96 |
97 | (b) You must cause any modified files to carry prominent notices
98 | stating that You changed the files; and
99 |
100 | (c) You must retain, in the Source form of any Derivative Works
101 | that You distribute, all copyright, patent, trademark, and
102 | attribution notices from the Source form of the Work,
103 | excluding those notices that do not pertain to any part of
104 | the Derivative Works; and
105 |
106 | (d) If the Work includes a "NOTICE" text file as part of its
107 | distribution, then any Derivative Works that You distribute must
108 | include a readable copy of the attribution notices contained
109 | within such NOTICE file, excluding those notices that do not
110 | pertain to any part of the Derivative Works, in at least one
111 | of the following places: within a NOTICE text file distributed
112 | as part of the Derivative Works; within the Source form or
113 | documentation, if provided along with the Derivative Works; or,
114 | within a display generated by the Derivative Works, if and
115 | wherever such third-party notices normally appear. The contents
116 | of the NOTICE file are for informational purposes only and
117 | do not modify the License. You may add Your own attribution
118 | notices within Derivative Works that You distribute, alongside
119 | or as an addendum to the NOTICE text from the Work, provided
120 | that such additional attribution notices cannot be construed
121 | as modifying the License.
122 |
123 | You may add Your own copyright statement to Your modifications and
124 | may provide additional or different license terms and conditions
125 | for use, reproduction, or distribution of Your modifications, or
126 | for any such Derivative Works as a whole, provided Your use,
127 | reproduction, and distribution of the Work otherwise complies with
128 | the conditions stated in this License.
129 |
130 | 5. Submission of Contributions. Unless You explicitly state otherwise,
131 | any Contribution intentionally submitted for inclusion in the Work
132 | by You to the Licensor shall be under the terms and conditions of
133 | this License, without any additional terms or conditions.
134 | Notwithstanding the above, nothing herein shall supersede or modify
135 | the terms of any separate license agreement you may have executed
136 | with Licensor regarding such Contributions.
137 |
138 | 6. Trademarks. This License does not grant permission to use the trade
139 | names, trademarks, service marks, or product names of the Licensor,
140 | except as required for reasonable and customary use in describing the
141 | origin of the Work and reproducing the content of the NOTICE file.
142 |
143 | 7. Disclaimer of Warranty. Unless required by applicable law or
144 | agreed to in writing, Licensor provides the Work (and each
145 | Contributor provides its Contributions) on an "AS IS" BASIS,
146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
147 | implied, including, without limitation, any warranties or conditions
148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
149 | PARTICULAR PURPOSE. You are solely responsible for determining the
150 | appropriateness of using or redistributing the Work and assume any
151 | risks associated with Your exercise of permissions under this License.
152 |
153 | 8. Limitation of Liability. In no event and under no legal theory,
154 | whether in tort (including negligence), contract, or otherwise,
155 | unless required by applicable law (such as deliberate and grossly
156 | negligent acts) or agreed to in writing, shall any Contributor be
157 | liable to You for damages, including any direct, indirect, special,
158 | incidental, or consequential damages of any character arising as a
159 | result of this License or out of the use or inability to use the
160 | Work (including but not limited to damages for loss of goodwill,
161 | work stoppage, computer failure or malfunction, or any and all
162 | other commercial damages or losses), even if such Contributor
163 | has been advised of the possibility of such damages.
164 |
165 | 9. Accepting Warranty or Additional Liability. While redistributing
166 | the Work or Derivative Works thereof, You may choose to offer,
167 | and charge a fee for, acceptance of support, warranty, indemnity,
168 | or other liability obligations and/or rights consistent with this
169 | License. However, in accepting such obligations, You may act only
170 | on Your own behalf and on Your sole responsibility, not on behalf
171 | of any other Contributor, and only if You agree to indemnify,
172 | defend, and hold each Contributor harmless for any liability
173 | incurred by, or claims asserted against, such Contributor by reason
174 | of your accepting any such warranty or additional liability.
175 |
176 | END OF TERMS AND CONDITIONS
177 |
178 | APPENDIX: How to apply the Apache License to your work.
179 |
180 | To apply the Apache License to your work, attach the following
181 | boilerplate notice, with the fields enclosed by brackets "{}"
182 | replaced with your own identifying information. (Don't include
183 | the brackets!) The text should be enclosed in the appropriate
184 | comment syntax for the file format. We also recommend that a
185 | file or class name and description of purpose be included on the
186 | same "printed page" as the copyright notice for easier
187 | identification within third-party archives.
188 |
189 | Copyright 2015 Apigee Corporation
190 |
191 | Licensed under the Apache License, Version 2.0 (the "License");
192 | you may not use this file except in compliance with the License.
193 | You may obtain a copy of the License at
194 |
195 | http://www.apache.org/licenses/LICENSE-2.0
196 |
197 | Unless required by applicable law or agreed to in writing, software
198 | distributed under the License is distributed on an "AS IS" BASIS,
199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
200 | See the License for the specific language governing permissions and
201 | limitations under the License.
202 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | [](https://travis-ci.org/apigeecs/apigee-deploy-grunt-plugin)
2 |
3 | 
4 |
5 | 
6 |
7 |
8 |
9 | **Table of Contents** *generated with [DocToc](http://doctoc.herokuapp.com/)*
10 |
11 | - [Why do we need a tool to manage the API Development Lifecycle for Apigee?](#why-do-we-need-a-tool-to-manage-the-api-development-lifecycle-for-apigee)
12 | - [Getting Started](#getting-started)
13 | - [Steps to get started (deprecated)](#steps-to-get-started-deprecated)
14 | - [Supported tasks](#supported-tasks)
15 | - [Most Important Tasks](#most-important-tasks)
16 | - [Default task : DEPLOY_IMPORT_BUMP_SEAMLESS_REVISION](#default-task--deploy_import_bump_seamless_revision)
17 | - [IMPORT_DEPLOY_BUMP_REVISION Task](#import_deploy_bump_revision-task)
18 | - [UPDATE_CURRENT_REVISION Task](#update_current_revision-task)
19 | - [Test what you just deployed](#test-what-you-just-deployed)
20 | - [Use apigee gateway and with Yahoo Weather standard Target](#use-apigee-gateway-and-with-yahoo-weather-standard-target)
21 | - [Use apigee gateway calling Yahoo Weather through Apigee Node.js as Target](#use-apigee-gateway-calling-yahoo-weather-through-apigee-nodejs-as-target)
22 | - [Use apigee gateway retrieving static content through Node.js as Target](#use-apigee-gateway-retrieving-static-content-through-nodejs-as-target)
23 | - [Use apigee gateway retrieving static content through Node.js as Target (nested folder)](#use-apigee-gateway-retrieving-static-content-through-nodejs-as-target-nested-folder)
24 | - [Use apigee gateway leveraging a JavaCallout policy](#use-apigee-gateway-leveraging-a-javacallout-policy)
25 | - [Complementary Tasks](#complementary-tasks)
26 | - [get all deployed api revisions](#get-all-deployed-api-revisions)
27 | - [undeploy api revision](#undeploy-api-revision)
28 | - [import API bundle without deploying it](#import-api-bundle-without-deploying-it)
29 | - [configuration management](#configuration-management)
30 | - [builds zip bundle under target directory](#builds-zip-bundle-under-target-directory)
31 | - [check all tasks available](#check-all-tasks-available)
32 | - [Node.js Deployment](#nodejs-deployment)
33 | - [JavaCallout Policy Support](#javacallout-policy-support)
34 | - [Search and Replace Functionality](#search-and-replace-functionality)
35 | - [Continuous Integration with Jenkins](#continuous-integration-with-jenkins)
36 | - [API Static Code Analysis](#api-static-code-analysis)
37 | - [JSHint](#jshint)
38 | - [ESLint](#eslint)
39 | - [Reusability of code with Maven Plugins and shell scripts/command line tools](#reusability-of-code-with-maven-plugins-and-shell-scriptscommand-line-tools)
40 | - [Contributing](#contributing)
41 |
42 |
43 |
44 | # Why do we need a tool to manage the API Development Lifecycle for Apigee?
45 |
46 | [](https://gitter.im/apigeecs/apigee-deploy-grunt-plugin?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
47 |
48 | * Pluggable environment (thousands of npm and grunt modules and plugins)
49 | * Grunt is perfect for applying continuous improvement by easily adding custom tasks. See [Tasks directory](https://github.com/apigeecs/apigee-deploy-grunt-plugin/tree/master/grunt/tasks)
50 | * It's pure JavaScript running on Node.js. Enough said, right :-)
51 | * Deploys Node.js API Proxies (node_modules, resources, and public directories) see [Gruntfile.js compress task](https://github.com/apigeecs/apigee-deploy-grunt-plugin/blob/master/Gruntfile.js). Also support of [Apigee NPM API](http://apigee.com/docs/management/apis/post/organizations/%7Borg_name%7D/apis/%7Bapi_name%7D/revisions/%7Brevision_num%7D/npm)
52 | * Supports JavaCallout Policies. Compiles, package and include Java library dependencies.
53 | * It's ready for TDD with Mocha.js and Chai. See [tests directory](https://github.com/apigeecs/apigee-deploy-grunt-plugin/tree/master/tests).
54 | * Does static code analysis with [JSHint](http://www.jshint.com/) and [ESLint](http://eslint.org/). So, out-of-the-box, you get the ability to add custom rules that promote coding best practices in JavaScript. See [ESLint custom rules](https://gist.github.com/jareware/7179093)
55 | * Reviews JavaScript file complexity by leveraging [Grunt-Complexity](https://github.com/vigetlabs/grunt-complexity#grunt-complexity)
56 | * Suppports Apigee KVM migration see Gruntfile.js for configuration task or please visit [grunt-apigee-kvm](https://github.com/grunt-apigee/grunt-apigee-kvm)
57 | * It's easier to troubleshoot. cURL command support. Just pass ```--curl=true```
58 | * Searches and replace files content with RegEx, string patterns, or XPath. See string-replace and xmlpoke tasks in Gruntfile.js
59 | * Includes files dynamically from common git submodule to promote DRY (Don't Repeat Yourself) principle (check search-and-replace.js entries)
60 | * It's compatible with most CI tools Jenkins, Bamboo, Go, and Travis
61 | * Sends automatic desktop notifications with [Grunt Notify](https://github.com/dylang/grunt-notify#screenshots)
62 | * It's compatible with IDEs. See [Chrome Grunt Dev Tools](https://chrome.google.com/webstore/detail/grunt-devtools/fbiodiodggnlakggeeckkjccjhhjndnb?hl=en) and [Grunt Task Runner for Web Storm](http://www.jetbrains.com/webstorm/webhelp/using-grunt-task-runner.html)
63 | * It's Compatible with Maven. So you can still run JMeter tests or single Maven tasks, if Mocha doesn't suit you needs, see **shell:run_jmeter_tests** target. [tools examples](https://github.com/apigeecs/apigee-deploy-grunt-plugin/tree/master/tools/forecastweather-jmeter-example).
64 |
65 | # Getting Started
66 | The easiest way to use this plugin is by leveraging Yeoman. Follow Getting Started from [Apigee API Proxy Generator](https://github.com/dzuluaga/generator-apigee-deploy-grunt-api#getting-started).
67 |
68 | # Steps to get started (deprecated)
69 | Getting started with Yeoman is much easier than following steps above. You no longer need to folow these steps unless you want learn how to use Git Submodules.
70 |
71 | **Prerequisites: Node.js and NPM**
72 |
73 | **Optional tools: Git. You can still use this plugin without Git, however manual steps will be required to initialize common folder.**
74 |
75 | * **Step 1:** Clone this repo with Git. ```git clone https://github.com/apigeecs/apigee-deploy-grunt-plugin.git```
76 | If you don't have Git is installed, download this repo as a zip file and expand it somewhere in the filesytem.
77 | * **Step 2:** ```cd apigee-deploy-grunt-plugin```
78 | * **Step 3:** open apigee-deploy-grunt-plugin folder and execute the two commands:
79 | ```
80 | git submodule init
81 | git submodule update
82 |
83 | ```
84 | **These two commands initialize Git Submodules by downloading source to Common folder from common branch. Installation without Git requires to download common branch as a zip file and expand its content into common folder (common/apiproxy)**
85 |
86 | * **Step 4:** setup Apigee Edge credentials as system environment variables ae_username and ae_password or just pass credentials as arguments
87 | * **Step 5:** install [grunt cli](http://gruntjs.com/getting-started#installing-the-cli) ```sudo npm install grunt-cli -g```
88 | * **Step 6:** execute ```npm install``` to install all grunt dependencies
89 | * **Step 7:** Edit and add environment to grunt/apigee-config.js file. Each environment will be referenced below as a flag e.g. --env={test, prod}
90 | * **Step 8:** Edit and add environments to grunt/search-and-replace-files.js for string replacements.
91 | * **Step 9:** run ```grunt --env=test --username={apigee_edge_email_address} --password={apigee_edge_password} --debug```
92 |
93 | # Supported tasks
94 |
95 | ### Most Important Tasks
96 |
97 | ##### Default task : DEPLOY_IMPORT_BUMP_SEAMLESS_REVISION
98 | One of the cool features of Apigee is seamless deployment or zero downtime. By default Grunt deploys in that mode. The following command will deploy api bundles with that mode:
99 | ```bash
100 | $ grunt --env=test --username={apigee_edge_email_address} --password={apigee_edge_password} --debug --curl=true
101 | ```
102 | **Note: Pass --debug flag to display Management API responses.**
103 |
104 | ##### IMPORT_DEPLOY_BUMP_REVISION Task
105 | The following command will undeploy is similar to the default task, however it undeploys the bundle, so there's some downtime. import, and deploy the api bundle:
106 | ```bash
107 | $ grunt IMPORT_DEPLOY_BUMP_REVISION --env=test --username={apigee_edge_email_address} --password={apigee_edge_password} --debug --curl=true
108 | ```
109 |
110 | ##### UPDATE_CURRENT_REVISION Task
111 | The following command will update current revision. Please be aware that it undeploys the current revision, so task is more suitable for development to avoid creating new revisions:
112 | ```bash
113 | $ grunt UPDATE_CURRENT_REVISION --env=test --username={apigee_edge_email_address} --password={apigee_edge_password} --debug --curl=true
114 | ```
115 |
116 | ### Test what you just deployed
117 | Once previous is executed, you should be able to try the following calls:
118 |
119 | ##### Use apigee gateway and with Yahoo Weather standard Target
120 | ```
121 | https://{org-env}.apigee.net/{api-basepath}/apigee/forecastrss?w=2502265
122 | ```
123 |
124 | Example ```https://testmyapi-test.apigee.net/weathergrunt/apigee/forecastrss?w=2502265```
125 |
126 | ##### Use apigee gateway calling Yahoo Weather through Apigee Node.js as Target
127 | ```
128 | https://{org-env}.apigee.net/{api-basepath}/forecastweather_node/2502265
129 | ```
130 |
131 | Example ```https://testmyapi-test.apigee.net/weathergrunt/forecastweather_node/2502265```
132 |
133 | ##### Use apigee gateway retrieving static content through Node.js as Target
134 | ```
135 | https://{org-env}.apigee.net/{api-basepath}/images/tree.jpg
136 | ```
137 |
138 | Example ```https://testmyapi-test.apigee.net/weathergrunt/images/tree.jpg```
139 |
140 | ##### Use apigee gateway retrieving static content through Node.js as Target (nested folder)
141 | ```
142 | https://{org-env}.apigee.net/{api-basepath}/tree.jpg
143 | ```
144 |
145 | Example ```https://testmyapi-test.apigee.net/weathergrunt/tree.jpg```
146 |
147 | ##### Use apigee gateway leveraging a JavaCallout policy
148 | **Disabled by default. Read section below for enabling directions.**
149 | ```
150 | https://{org-env}.apigee.net/{api-basepath}/javacallout
151 | ```
152 |
153 | Example ```curl https://testmyapi-test.apigee.net/weathergrunt/javacallout```
154 |
155 | ### Complementary Tasks
156 |
157 | #### get all deployed api revisions
158 | ```grunt getDeployedApiRevisions --env=test --debug```
159 |
160 | #### undeploy api revision
161 | ```grunt undeployApiRevision:{revision_id} --env=test --debug```
162 |
163 | #### undeploy api revision
164 | ```grunt deployApiRevision:{revision_id} --env=test --debug```
165 |
166 | #### get all api revisions
167 | ```grunt getAllApiRevisions --env=test --debug```
168 |
169 | #### import API build bundle without deploying it
170 | ```grunt importApiBundle --env=test --debug --debug```
171 |
172 | #### delete a revision
173 | ```grunt deleteApiRevision:{revision_id} --env=test --debug```
174 |
175 | #### update a revision with build bundle
176 | ```
177 | $ grunt updateApiRevision:{revision_id} --env=test
178 | ```
179 | #### configuration management
180 | See grunt/apigee-config.js file.
181 |
182 | #### builds zip bundle under target directory
183 | ```grunt compress --env=test```
184 |
185 | #### clean Target directory
186 | ```grunt clean --env=test```
187 |
188 | #### check all tasks available
189 | ```grunt --help``` or ```grunt availabletasks --env=test``` will display a nicer colored output.
190 |
191 | #### supported arguments and flags
192 | ```
193 | --username={apigee_edge_username}
194 | ```
195 |
196 | ```
197 | --password={apigee_edge_password}
198 | ```
199 |
200 | ```
201 | --skip-tests=true
202 | ```
203 |
204 | ```
205 | --curl generate curl commands to be executed from command line
206 | ```
207 |
208 | ```
209 | --override
210 | ```
211 |
212 | ```
213 | --delay={seconds}
214 | ```
215 |
216 | Upload node.js modules (by default the plugin will try to install npm in Apigee Edge)
217 | ```
218 | --upload-modules
219 | ```
220 |
221 | Node.js Deployment
222 | ====
223 | In order to compress node.js modules, it's required node directory to exist in the root folder. By default node_modules, public, and resources are generated as part of the build. Compress configuration in Gruntfile.js can be modified to include any other configuration.
224 |
225 | JavaCallout Policy Support
226 | ====
227 | This task comes disabled by default to prevent issues from OS environments (MacOS and Windows). To enable, remove comments from shell task in Gruntfile and customize as directions below.
228 |
229 | JavaCallouts are currently supported by leveraging [grunt-shell npm package](https://www.npmjs.org/package/grunt-shell). Therefore, compilation and packaging steps are dependent on your local installation of javac and jar tools. Source code directories must be located under java/src directory and any jar dependencies under java/lib directory. See Gruntfile.js shell task for more details.
230 |
231 | Note: Since javac requires to know where .java files are located, it is required to include java callout separated by spaces in shell javaCompile target.
232 |
233 | For instance:
234 | ```
235 | javac -sourcepath ./java/src/**/*.java -d ./target/java/bin -cp java/lib/expressions-1.0.0.jar:java/lib/message-flow-1.0.0.jar:jar:java/lib/message-flow-1.0.1.jar **java/src/com/example/SimpleJavaCallout.java**
236 | ```
237 |
238 | Search and Replace Functionality
239 | ======
240 |
241 | ####String
242 | Ability to search and replace strings from text files that match any pattern in Regex or string. See grunt/search-and-replace-files.js to setup per environment. This task leverages [grunt-string-replace module](https://www.npmjs.org/package/grunt-string-replace). See grunt/search-and-replace-files.js for an example.
243 |
244 | ####Include files from common Git submodule
245 | Ability to search and include content from files is also provided by string-replace task. See examples under grunt/search-and-replace-files.js that include fragments from common folder for fragments (multiple steps), policies, and JavaScript files. Note common folder leverages [Git Submodule](http://git-scm.com/book/en/Git-Tools-Submodules), which resides in a separate branch under the same repository. This allows reusing code across multiple APIs without adding more complexity.
246 |
247 | Continuous Integration with Jenkins
248 | ======
249 | [This repo provides a guide for setting up an instance of Jenkins with Grunt](https://github.com/dzuluagaapigee/apigee-ci-jenkins-git-maven-jmeter) to deploy and configure an API bundle.
250 |
251 | API Static Code Analysis
252 | ========
253 | This plugin is enabled to provide feedback about coding best practices for JavaScript.
254 |
255 | JSHint
256 | --------
257 | JSHInt provides a large set of configurable (options)[http://www.jshint.com/docs/options/] that can be enabled out-of-the-box.
258 | See jshint task in Gruntfile.js
259 |
260 | ESLint
261 | --------
262 | ESLint provides an pluggable framework to enable static code analysis. In contrast to JSHint, ESLint can be extended to write custom API specific rules. See conf/rules/if-curly-formatting.js rule and conf/eslint.json to manage alerts.
263 | See ESLint Gruntfile.js section
264 |
265 | Reusability of code with Maven Plugins and shell scripts/command line tools
266 | =====
267 | Grunt plugin can be extended to support plugins, shell script or any other command line tools. For instance Proxy Dependency Maven Plugin includes an example of a [pom.xml](https://github.com/apigeecs/apigee-deploy-grunt-plugin/tree/master/tools/proxy-dependency-maven-plugin).
268 |
269 | Contributing
270 | =====
271 | If you would like to contribute, simply fork the repository, push your changes to a branch and send a pull request:
272 |
273 | 1. Fork it
274 | 2. Create your feature branch (`git checkout -b my-new-feature`)
275 | 3. Commit your changes (`git commit -am 'Add some feature'`)
276 | 4. Push to the branch (`git push origin my-new-feature`)
277 | 5. Create new Pull Request
278 |
279 | Typo fixes, improvements to grammar or readability, it's all welcome.
280 |
281 | ## License
282 |
283 | Copyright (c) 2014 Diego Zuluaga (twitter: @dzuluaga)
284 | Licensed under the MIT license.
285 |
286 |
--------------------------------------------------------------------------------
/apiproxy/forecastweather-grunt-plugin-api.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | 1384727595303
5 | dzuluaga@apigee.com
6 | @@DESCRIPTION TO BE REPLACED BY GITHUB ID
7 | weather
8 | 1384727595303
9 | dzuluaga@apigee.com
10 |
11 | xmltojson-1
12 |
13 |
14 | default
15 |
16 |
17 |
18 |
19 | default
20 |
21 | false
22 |
23 |
--------------------------------------------------------------------------------
/apiproxy/policies/Assign-Message-Remove-Suffix.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | Assign Message Remove Suffix
4 |
5 |
6 |
7 | target.copy.pathsuffix
8 | false
9 |
10 | true
11 |
12 |
--------------------------------------------------------------------------------
/apiproxy/policies/JSON-to-XML.xml:
--------------------------------------------------------------------------------
1 | @@JSON-to-XML.xml
--------------------------------------------------------------------------------
/apiproxy/policies/Script-External-Variables.xml:
--------------------------------------------------------------------------------
1 | @@Script-External-Variables.xml
--------------------------------------------------------------------------------
/apiproxy/policies/SimpleJavaCallout.xml.bak:
--------------------------------------------------------------------------------
1 |
2 |
3 | com.example.SimpleJavaCallout
4 | java://javaCallouts.jar
5 |
--------------------------------------------------------------------------------
/apiproxy/policies/XMLtoJSON-Common.xml:
--------------------------------------------------------------------------------
1 | @@XMLtoJSON-Common.xml
--------------------------------------------------------------------------------
/apiproxy/proxies/default.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 | @@EXAMPLE-STEP-COMMON-XML-TO-JSON-GIT-SUBMODULE-FRAGMENT#1
10 |
11 | (proxy.pathsuffix MatchesPath "/apigee/**") and (request.verb = "GET")
12 |
13 |
14 |
15 |
16 |
17 | @@EXAMPLE-STEP-COMMON-XML-TO-JSON-GIT-SUBMODULE-FRAGMENT#2
18 |
19 | (proxy.pathsuffix MatchesPath "/forecastweather_node/**") and (request.verb = "GET")
20 |
21 |
22 |
23 |
24 |
25 | @@EXAMPLE-STEP-COMMON-XML-TO-JSON-GIT-SUBMODULE-FRAGMENT#3
26 |
27 | (proxy.pathsuffix MatchesPath "/images/**") and (request.verb = "GET")
28 |
29 |
30 |
31 |
32 |
33 |
34 |
38 |
39 | (proxy.pathsuffix MatchesPath "/javacallout") and (request.verb = "GET")
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 | /weathergrunt
48 | default
49 | secure
50 |
51 |
52 | (proxy.pathsuffix MatchesPath "/apigee/**") and (request.verb = "GET")
53 | default
54 |
55 |
56 |
57 | node
58 |
59 |
60 |
61 |
62 |
63 |
--------------------------------------------------------------------------------
/apiproxy/resources/jsc/js_external_vars.js:
--------------------------------------------------------------------------------
1 | // jshint ignore: start
2 | /* jshint ignore:start */
3 |
4 | @@js_external_vars.js
--------------------------------------------------------------------------------
/apiproxy/resources/jsc/search-and-replace-example.js:
--------------------------------------------------------------------------------
1 | function testFunction(){
2 | 'use strict';
3 | var test = "VALUE TO BE REPLACED #1";
4 | return test;
5 | }
6 | //remove comment to see jshint triggering errors
7 | //var a = "test";
8 | /*if(1 === 1) {
9 | if(2 === 2) {
10 | if(3 === 3) {
11 | if(4 === 4) {
12 |
13 | }
14 | }
15 | }
16 |
17 | }*/
18 |
19 | testFunction();
--------------------------------------------------------------------------------
/apiproxy/resources/jsc/search-and-replace-example2.js:
--------------------------------------------------------------------------------
1 | function testFunction2(){
2 | 'use strict';
3 | var test2 = "VALUE TO BE REPLACED #2";
4 | return test2;
5 | }
6 |
7 | testFunction2();
--------------------------------------------------------------------------------
/apiproxy/targets/default.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 | Assign-Message-Remove-Suffix
10 |
11 |
12 |
13 |
14 |
15 | http://weather.yahooapis.com/forecastrss
16 |
17 |
18 |
19 |
20 |
21 |
--------------------------------------------------------------------------------
/apiproxy/targets/node.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | Node Target
4 |
5 |
6 |
7 | node://app.js
8 |
9 |
--------------------------------------------------------------------------------
/config/kvm/testmyapi/passwords.json:
--------------------------------------------------------------------------------
1 | {
2 | "entry": [
3 | {
4 | "name": "dzuluaga+testoauth@apigee.com",
5 | "value": "b002625528157aeb315c91f3ae74cad9e5708af8:Q5ENLG2CoLQvyfSo4FQyRjQa4TEST"
6 | }
7 | ],
8 | "name": "passwords"
9 | }
--------------------------------------------------------------------------------
/config/kvm/testmyapi/passwords.json.encrypted:
--------------------------------------------------------------------------------
1 | 745e184792a532e9152810e931f0604edfbf164a91cdcd7a82905b34b753aec5d453d2e7b9cbfff61ba88f7223af23a05e21f34bde37b9c91c0820ae3cd59f60c67145dc54fd2aeaeb4cb7a36bad632bead85a61d1350393da2b31d756b537525e729d801c4fe49c0d51116ba9706e150c241c5921e9ec1a078ca02080460de4c1465c52d297505f5336c2709d9647327bec2fff77271d77943b94b3cf43c82ea8a82e58fc735b88241839d78cbeb6a3b2493b479c47e04e34506ed1678e324b
--------------------------------------------------------------------------------
/config/kvm/testmyapi/testmyapi-prod/passwords.json:
--------------------------------------------------------------------------------
1 | {
2 | "entry": [
3 | {
4 | "name": "dzuluaga+testoauth@apigee.com",
5 | "value": "b002625528157aeb315c91f3ae74cad9e5708af8:Q5ENLG2CoLQvyfSo4FQyRjQa4TEST"
6 | }
7 | ],
8 | "name": "passwords"
9 | }
--------------------------------------------------------------------------------
/config/kvm/testmyapi/testmyapi-prod/passwords.json.encrypted:
--------------------------------------------------------------------------------
1 | 745e184792a532e9152810e931f0604edfbf164a91cdcd7a82905b34b753aec5d453d2e7b9cbfff61ba88f7223af23a05e21f34bde37b9c91c0820ae3cd59f60c67145dc54fd2aeaeb4cb7a36bad632bead85a61d1350393da2b31d756b537525e729d801c4fe49c0d51116ba9706e150c241c5921e9ec1a078ca02080460de4c1465c52d297505f5336c2709d9647327bec2fff77271d77943b94b3cf43c82ea8a82e58fc735b88241839d78cbeb6a3b2493b479c47e04e34506ed1678e324b
--------------------------------------------------------------------------------
/config/kvm/testmyapi/testmyapi-prod/passwords2.json.encrypted:
--------------------------------------------------------------------------------
1 | 745e184792a532e9152810e931f0604edfbf164a91cdcd7a82905b34b753aec5d453d2e7b9cbfff61ba88f7223af23a05e21f34bde37b9c91c0820ae3cd59f60c67145dc54fd2aeaeb4cb7a36bad632bead85a61d1350393da2b31d756b537525e729d801c4fe49c0d51116ba9706e150c241c5921e9ec1a078ca02080460de4c1465c52d297505f5336c2709d9647327bec2fff77271d77943b94b3cf43c82ea8a82e58fc735b88241839d78cbeb6a3b2493b479c47e04e34506ed1678e324b
--------------------------------------------------------------------------------
/config/kvm/testmyapi/testmyapi-prod/targets.json:
--------------------------------------------------------------------------------
1 | {
2 | "entry": [
3 | {
4 | "name": "Key1",
5 | "value": "value_one-test"
6 | },
7 | {
8 | "name": "Key2",
9 | "value": "value_two-test"
10 | }
11 | ],
12 | "name": "targets"
13 | }
--------------------------------------------------------------------------------
/config/kvm/testmyapi/testmyapi-prod/targets.json.encrypted:
--------------------------------------------------------------------------------
1 | 745e184792a532e9152810e931f0604edfbf164a91cdcd7a82905b34b753aec58767290af189d2f7dba464f1f53792b60d678f2133d91bf4ac40764cbf34f2ee5af35f3b9aafff8b317aa6f756aed50bb45a460fde3c5fc05b3e4afe7d0c56a15f0814298536320b0943c68b18a153fa8883f6c242caa172405e03d5922eb04f347cb1d23e4d37233b8caca25eab935056df2017c54ee681df20c375b4536944a0e59b379b99b4f353a1405969a17667
--------------------------------------------------------------------------------
/config/kvm/testmyapi/testmyapi-test/passwords.json:
--------------------------------------------------------------------------------
1 | {
2 | "entry": [
3 | {
4 | "name": "dzuluaga+testoauth@apigee.com",
5 | "value": "b002625528157aeb315c91f3ae74cad9e5708af8:Q5ENLG2CoLQvyfSo4FQyRjQa4TEST"
6 | }
7 | ],
8 | "name": "passwords"
9 | }
--------------------------------------------------------------------------------
/config/kvm/testmyapi/testmyapi-test/passwords.json.encrypted:
--------------------------------------------------------------------------------
1 | 745e184792a532e9152810e931f0604edfbf164a91cdcd7a82905b34b753aec5d453d2e7b9cbfff61ba88f7223af23a05e21f34bde37b9c91c0820ae3cd59f60c67145dc54fd2aeaeb4cb7a36bad632bead85a61d1350393da2b31d756b537525e729d801c4fe49c0d51116ba9706e150c241c5921e9ec1a078ca02080460de4c1465c52d297505f5336c2709d9647327bec2fff77271d77943b94b3cf43c82ea8a82e58fc735b88241839d78cbeb6a3b2493b479c47e04e34506ed1678e324b
--------------------------------------------------------------------------------
/config/kvm/testmyapi/testmyapi-test/targets.json:
--------------------------------------------------------------------------------
1 | {
2 | "entry": [
3 | {
4 | "name": "Key1",
5 | "value": "value_one-test"
6 | },
7 | {
8 | "name": "Key2",
9 | "value": "value_two-test"
10 | }
11 | ],
12 | "name": "targets4"
13 | }
--------------------------------------------------------------------------------
/config/kvm/testmyapi/testmyapi-test/targets.json.encrypted:
--------------------------------------------------------------------------------
1 | 745e184792a532e9152810e931f0604edfbf164a91cdcd7a82905b34b753aec58767290af189d2f7dba464f1f53792b60d678f2133d91bf4ac40764cbf34f2ee5af35f3b9aafff8b317aa6f756aed50bb45a460fde3c5fc05b3e4afe7d0c56a15f0814298536320b0943c68b18a153fa8883f6c242caa172405e03d5922eb04f347cb1d23e4d37233b8caca25eab935056df2017c54ee681df20c375b4536944eb132568474852b5b3499b3e10c973fc
--------------------------------------------------------------------------------
/grunt/apigee-config.js:
--------------------------------------------------------------------------------
1 | exports.profiles = function(grunt){
2 | return {
3 | env : grunt.option('env'), // replace with environment
4 | 'test' : {
5 | apiproxy : 'forecastweather-grunt-plugin-api',
6 | org : 'testmyapi', // replace with organization
7 | env : 'test', // replace with environment
8 | url_mgmt : 'https://api.enterprise.apigee.com', // for cloud environments, leave as is
9 | username : grunt.option('username'), //|| process.env.ae_username, // pass credentials as arguments as grunt task --username=$ae_username --password=$ae_password
10 | password : grunt.option('password'), //|| process.env.ae_password, // use ae_username and ae_password are defined as environment variables and no arguments are passed
11 | revision : grunt.option('revision'), // provide revision to be undeployed by passing argument as --revision=X
12 | override : grunt.option('override') || true,
13 | delay : grunt.option('delay') || 10
14 | },
15 | 'prod' : {
16 | apiproxy : 'forecastweather-grunt-plugin-api',
17 | org : 'testmyapi', // replace with organization
18 | env : 'prod', // replace with environment
19 | url_mgmt : 'https://api.enterprise.apigee.com', // for cloud environments, leave as is
20 | username : grunt.option('username'), //|| process.env.ae_username, // pass credentials as arguments as grunt task --username=$ae_username --password=$ae_password
21 | password : grunt.option('password'), //|| process.env.ae_password, // use ae_username and ae_password are defined as environment variables and no arguments are passed
22 | revision : grunt.option('revision'), // provide revision to be undeployed by passing argument as --revision=X
23 | override : grunt.option('override') || true,
24 | delay : grunt.option('delay') || 10
25 | }
26 | }
27 | }
28 |
29 | exports.xmlconfig = function(env, grunt){
30 | config = { "test" : [
31 | {//sets description within API proxy for tracking purposes with this format 'git commit: 8974b5a by dzuluaga on Diegos-MacBook-Pro-2.local'
32 | //see grunt/tasks/saveGitRevision.js for further customization
33 | "options": {
34 | "xpath": "//APIProxy/Description",
35 | "value": "<%= grunt.option('gitRevision') %>"
36 | },
37 | "files": {
38 | "target/apiproxy/<%= apigee_profiles[grunt.option('env')].apiproxy %>.xml": "apiproxy/*.xml"
39 | }
40 | },
41 | {
42 | "options": {
43 | "xpath": "//TargetEndpoint/HTTPTargetConnection/URL",
44 | "value": "https://weather.yahooapis.com/forecastrss"
45 | },
46 | "files": {
47 | "target/apiproxy/targets/default.xml": "apiproxy/targets/default.xml"
48 | }
49 | },
50 | {
51 | "options": {
52 | "xpath": "//ProxyEndpoint/HTTPProxyConnection/BasePath",
53 | "value": "weathergrunt"
54 | },
55 | "files": {
56 | "target/apiproxy/proxies/default.xml": "apiproxy/proxies/default.xml"
57 | }
58 | }
59 | ],
60 | "prod" : [
61 | {//sets description within API proxy for tracking purposes with this format 'git commit: 8974b5a by dzuluaga on Diegos-MacBook-Pro-2.local'
62 | //see grunt/tasks/saveGitRevision.js for further customization
63 | "options": {
64 | "xpath": "//APIProxy/Description",
65 | "value": "<%= grunt.option('gitRevision') %>"
66 | },
67 | "files": {
68 | "target/apiproxy/<%= apigee_profiles[grunt.option('env')].apiproxy %>.xml": "apiproxy/*.xml"
69 | }
70 | },
71 | {
72 | "options": {
73 | "xpath": "//TargetEndpoint/HTTPTargetConnection/URL",
74 | "value": "https://weather.yahooapis.com/forecastrss"
75 | },
76 | "files": {
77 | "target/apiproxy/targets/default.xml": "apiproxy/targets/default.xml"
78 | }
79 | },
80 | {
81 | "options": {
82 | "xpath": "//ProxyEndpoint/HTTPProxyConnection/BasePath",
83 | "value": "weathergrunt"
84 | },
85 | "files": {
86 | "target/apiproxy/proxies/default.xml": "apiproxy/proxies/default.xml"
87 | }
88 | }
89 | ]}
90 | if(!config[env])grunt.fail.fatal('Environment '+ env +' does not exist under grunt/apigee-config.js')
91 | return config[env];
92 | }
--------------------------------------------------------------------------------
/grunt/conf/eslint.json:
--------------------------------------------------------------------------------
1 | {
2 | "rules": {
3 | "if-curly-formatting": 2,
4 | "no-undef": 0,
5 | "no-mixed-spaces-and-tabs" : 0,
6 | "quotes" : 0,
7 | "eol-last" : 0,
8 | "semi" : 0,
9 | "no-comma-dangle" : 0,
10 | "camelcase" : 0,
11 | "no-global-strict" : 0,
12 | "no-use-before-define" : 0
13 |
14 | }
15 | }
--------------------------------------------------------------------------------
/grunt/conf/rules/if-curly-formatting.js:
--------------------------------------------------------------------------------
1 | module.exports = function(context) {
2 | return {
3 | IfStatement: function(node) {
4 | var source = context.getSource(node.test, 0, 3);
5 | if (!source.match(/ {$/)) {
6 | context.report(node, "Found improperly formatted if-statement");
7 | }
8 | }
9 | };
10 | };
11 |
--------------------------------------------------------------------------------
/grunt/lib/helper-functions.js:
--------------------------------------------------------------------------------
1 | exports.generatecURL = function(options){
2 | //echo curl -H "Authorization:Basic $credentials" "$url/v1/organizations/$org/apis/$application/revisions" -X GET
3 | var optionsl = JSON.parse(JSON.stringify(options));
4 | var curl = require('curl-cmd');
5 | optionsl.auth = optionsl.auth.user + ":" + optionsl.auth.password
6 | optionsl.hostname = options.uri.replace('https://', '')
7 | optionsl.path = optionsl.hostname.substring(optionsl.hostname.indexOf('/'));
8 | optionsl.hostname = optionsl.hostname.replace(optionsl.path, '')
9 | console.log(curl.cmd(optionsl, {ssl: true, verbose: true}));
10 | }
11 |
12 | exports.setNodeResources = function(dir, options, files){
13 | var fs = require('fs');
14 | var task = {};
15 | if (fs.existsSync('./node')) {
16 | task.options = options;
17 | task.files = files
18 | }
19 | return task;
20 | }
21 |
22 | exports.prompts = function(grunt) {
23 | return {
24 | target: {
25 | options: {
26 | questions: [
27 | {
28 | config: 'username',
29 | type: 'input',
30 | message: 'Apigee Edge EMail',
31 | when: function(){
32 | return !grunt.option('username');
33 | }
34 | },
35 | {
36 | config: 'password', // arbitrary name or config for any other grunt task
37 | type: 'password', // list, checkbox, confirm, input, password
38 | message: 'Apigee Edge Password', // Question to ask the user, function needs to return a string,
39 | when: function(){
40 | return !grunt.option('password');
41 | }
42 | }
43 | ],
44 | then : function(results, done){
45 | if(results.username) {grunt.config("apigee_profiles." + grunt.option('env') + ".username", results.username);}
46 | if(results.password) {grunt.config("apigee_profiles." + grunt.option('env') + ".password", results.password);}
47 | done();
48 | return true;
49 | }
50 | }
51 | }
52 | }
53 | }
--------------------------------------------------------------------------------
/grunt/search-and-replace-files.js:
--------------------------------------------------------------------------------
1 | exports.searchAndReplaceFiles = function(env, grunt){
2 | var config = {
3 | test: {
4 | files: [{
5 | cwd: 'target/',
6 | src: ['**/*.js','**/*.xml','!node/node_modules/**/*.js'],
7 | dest: 'target/',
8 | expand: true,
9 | }],
10 | options: {
11 | replacements: [
12 | {
13 | pattern: 'VALUE TO BE REPLACED #1',
14 | replacement: '<%= grunt.template.today() %>_test'
15 | },
16 | {
17 | pattern: 'VALUE TO BE REPLACED #2',
18 | replacement: 'REPLACE VALUE #2_TEST'
19 | },
20 | {//fragment from common folder (Git submodule)
21 | pattern: '@@EXAMPLE-STEP-COMMON-XML-TO-JSON-GIT-SUBMODULE-FRAGMENT#1',
22 | replacement: "<%= grunt.file.read('common/apiproxy/proxies/xmltojson-js-steps-common-frag.xml') %>"
23 | },
24 | {//fragment from common folder (Git submodule)
25 | pattern: '@@EXAMPLE-STEP-COMMON-XML-TO-JSON-GIT-SUBMODULE-FRAGMENT#2',
26 | replacement: "<%= grunt.file.read('common/apiproxy/proxies/xmltojson-js-steps-common-frag.xml') %>"
27 | },
28 | {//fragment from common folder (Git submodule)
29 | pattern: '@@EXAMPLE-STEP-COMMON-XML-TO-JSON-GIT-SUBMODULE-FRAGMENT#3',
30 | replacement: "<%= grunt.file.read('common/apiproxy/proxies/xmltojson-js-steps-common-frag.xml') %>"
31 | },
32 | {
33 | pattern: '@@XMLtoJSON-Common.xml',
34 | replacement: "<%= grunt.file.read('common/apiproxy/policies/XMLtoJSON-Common.xml') %>"
35 | },
36 | {//fragment from common folder (Git submodule)
37 | pattern: '@@Script-External-Variables.xml',
38 | replacement: "<%= grunt.file.read('common/apiproxy/policies/Script-External-Variables.xml') %>"
39 | },
40 | {//fragment from common folder (Git submodule)
41 | pattern: '@@js_external_vars.js',
42 | replacement: "<%= grunt.file.read('common/apiproxy/resources/jsc/js_external_vars.js') %>"
43 | },
44 | {
45 | pattern: '@@JSON-to-XML.xml',
46 | replacement: "<%= grunt.file.read('common/apiproxy/policies/JSON-to-XML.xml') %>"
47 | },
48 | ]
49 | }
50 | },
51 | prod: {
52 | files: [{
53 | cwd: 'target/',
54 | src: ['**/*.js','**/*.xml','!node/node_modules/**/*.js'],
55 | dest: 'target/',
56 | expand: true,
57 | }],
58 | options: {
59 | replacements: [{
60 | pattern: 'VALUE TO BE REPLACED #1',
61 | replacement: '<%= grunt.template.today() %>_test'
62 | },
63 | {
64 | pattern: 'VALUE TO BE REPLACED #2',
65 | replacement: 'REPLACE VALUE #2_TEST'
66 | },
67 | {//fragment from common folder (Git submodule)
68 | pattern: '@@EXAMPLE-STEP-COMMON-XML-TO-JSON-GIT-SUBMODULE-FRAGMENT#1',
69 | replacement: "<%= grunt.file.read('common/apiproxy/proxies/xmltojson-js-steps-common-frag.xml') %>"
70 | },
71 | {//fragment from common folder (Git submodule)
72 | pattern: '@@EXAMPLE-STEP-COMMON-XML-TO-JSON-GIT-SUBMODULE-FRAGMENT#2',
73 | replacement: "<%= grunt.file.read('common/apiproxy/proxies/xmltojson-js-steps-common-frag.xml') %>"
74 | },
75 | {//fragment from common folder (Git submodule)
76 | pattern: '@@EXAMPLE-STEP-COMMON-XML-TO-JSON-GIT-SUBMODULE-FRAGMENT#3',
77 | replacement: "<%= grunt.file.read('common/apiproxy/proxies/xmltojson-js-steps-common-frag.xml') %>"
78 | },
79 | {
80 | pattern: '@@XMLtoJSON-Common.xml',
81 | replacement: "<%= grunt.file.read('common/apiproxy/policies/XMLtoJSON-Common.xml') %>"
82 | },
83 | {//fragment from common folder (Git submodule)
84 | pattern: '@@Script-External-Variables.xml',
85 | replacement: "<%= grunt.file.read('common/apiproxy/policies/Script-External-Variables.xml') %>"
86 | },
87 | {//fragment from common folder (Git submodule)
88 | pattern: '@@js_external_vars.js',
89 | replacement: "<%= grunt.file.read('common/apiproxy/resources/jsc/js_external_vars.js') %>"
90 | },
91 | {
92 | pattern: '@@JSON-to-XML.xml',
93 | replacement: "<%= grunt.file.read('common/apiproxy/policies/JSON-to-XML.xml') %>"
94 | },
95 | ]
96 | }
97 | },
98 | }
99 | if(!config[env])grunt.fail.fatal('Environment '+ env +' does not exist under grunt/search-and-replace-files.js')
100 | return(config[env])
101 | }
--------------------------------------------------------------------------------
/grunt/tasks/apigeeGruntPluginBanner.js:
--------------------------------------------------------------------------------
1 | /*jslint node: true */
2 | var FONTS = require('cfonts');
3 |
4 |
5 | module.exports = function(grunt) {
6 | 'use strict';
7 | grunt.registerTask("apigeeGruntPluginBanner", 'Display Apigee Grunt Plugin Banner', function(set){
8 | var fonts = new FONTS({
9 | 'text': 'Apigee Grunt Plugin', //text to be converted
10 | 'font': 'block', //define the font face
11 | 'colors': ['red','blue'], //define all colors
12 | 'background': 'black', //define the background color
13 | 'letterSpacing': 1, //define letter spacing
14 | 'space': true, //define if the output text should have empty lines on top and on the bottom
15 | 'maxLength': '12' //define how many character can be on one line
16 | });
17 | new FONTS({
18 | 'text': 'Welcome to Apigee Grunt Plugin!', //text to be converted
19 | 'font': 'console', //define the font face
20 | 'colors': ['red'], //define all colors
21 | 'background': 'blue', //define the background color
22 | 'letterSpacing': 10, //define letter spacing
23 | 'space': true, //define if the output text should have empty lines on top and on the bottom
24 | 'maxLength': '12' //define how many character can be on one line
25 | });
26 | });
27 | }
28 |
--------------------------------------------------------------------------------
/grunt/tasks/compressAlias.js:
--------------------------------------------------------------------------------
1 | /*jslint node: true */
2 |
3 | module.exports = function(grunt) {
4 | 'use strict';
5 | grunt.registerTask('compressAlias', 'compress alias task that conditionally runs compress task.', function() {
6 | grunt.log.debug('Node.js modules not include in API bundle.');
7 | var targetsFiltered = [];
8 | Object.keys(grunt.config('compress')).forEach(function (i){
9 | if(!grunt.option('upload-modules') && i == 'node-modules'){
10 | grunt.log.debug('skipped node-modules compress file');
11 | return;
12 | }else{
13 | targetsFiltered.push('compress:' + i);
14 | }
15 | })
16 | grunt.task.run(targetsFiltered || 'compress');
17 | });
18 | };
--------------------------------------------------------------------------------
/grunt/tasks/deleteApiRevision.js:
--------------------------------------------------------------------------------
1 | /*jslint node: true */
2 |
3 | var grunt_common = require('apigee-sdk-mgmt-api');
4 |
5 | module.exports = function(grunt) {
6 | 'use strict';
7 | grunt.registerTask('deleteApiRevision', 'Delete an API revision. e.g. grunt deleteApiRevision:{revision_id}', function(revision) {
8 | if(grunt.option.flags().indexOf('--keep-last-revision') === -1) { //delete revision when --keep-last-revision flag is not passed
9 | var deleteRevision = function(error, response, body){
10 | // if (!error && response.statusCode === 200) {
11 | // //var deletionResult = JSON.parse(body);
12 | // }
13 | grunt.log.debug(response.statusCode)
14 | grunt.log.debug(body);
15 | done();
16 | }
17 | var revisionl = revision || (grunt.option('revisions_undeployed') && grunt.option('revisions_undeployed').revision);
18 | if(!revisionl) {
19 | grunt.log.warn('invalid revision. e.g. grunt deleteApiRevision:{revision_id}');
20 | }else{
21 | var done = this.async();
22 | grunt_common.deleteApiRevision(grunt.config.get('apigee_profiles'), revisionl, deleteRevision, grunt.option.flags().indexOf('--curl') !== -1)
23 | }
24 | }
25 | else{
26 | grunt.log.ok('task skipped. Remove --keep-last-revision flag to delete undeployed revision.')
27 | }
28 | });
29 | };
30 |
--------------------------------------------------------------------------------
/grunt/tasks/deployApiRevision.js:
--------------------------------------------------------------------------------
1 | /*jslint node: true */
2 |
3 | var grunt_common = require('apigee-sdk-mgmt-api');
4 |
5 | module.exports = function(grunt) {
6 | 'use strict';
7 | grunt.registerTask('deployApiRevision', 'Deploy an API revision. deployApiRevision:{revision_id}', function(revision) {
8 | var deployedRevision = function(error, response, body) {
9 | /*eslint no-empty:0 */
10 | if (!error && response.statusCode === 200) {
11 | //var undeployResult = JSON.parse(body);
12 | }
13 | else{
14 | done(false)
15 | }
16 | grunt.log.debug(response.statusCode)
17 | grunt.log.debug(body);
18 | done(error);
19 | }
20 | //core logic
21 | if(!revision) {
22 | grunt.fail.fatal('invalid revision id. provide either argument as deployApiRevision:{revision_id}');
23 | }else{
24 | var done = this.async();
25 | grunt_common.deployApiRevision(grunt.config.get('apigee_profiles'), revision, deployedRevision, grunt.option.flags().indexOf('--curl') !== -1)
26 | }
27 | });
28 | };
29 |
--------------------------------------------------------------------------------
/grunt/tasks/deployApiRevisionAlias.js:
--------------------------------------------------------------------------------
1 | /*jslint node: true */
2 |
3 | module.exports = function(grunt) {
4 | 'use strict';
5 | grunt.registerTask('deployApiRevisionAlias', 'Deploy an API revision alias', function() {
6 | switch (grunt.cli.tasks[0]){
7 | case 'UPDATE_CURRENT_REVISION' :
8 | grunt.task.run('deployApiRevision:' + grunt.option('revisions_undeployed').name);
9 | break;
10 | case 'IMPORT_DEPLOY_BUMP_REVISION' :
11 | grunt.task.run('deployApiRevision:' + grunt.option('revision'));
12 | break;
13 | case 'DEPLOY_IMPORT_BUMP_SEAMLESS_REVISION' :
14 | grunt.task.run('deployApiRevision:' + grunt.option('revision'));
15 | break;
16 | default :
17 | grunt.task.run('deployApiRevision:' + grunt.option('revision'));
18 | break;
19 | }
20 | });
21 | };
22 |
--------------------------------------------------------------------------------
/grunt/tasks/executeTests.js:
--------------------------------------------------------------------------------
1 | /*jslint node: true */
2 |
3 | module.exports = function(grunt) {
4 | 'use strict';
5 | grunt.registerTask('executeTests', 'execute tests when flag --skip-tests is absent.', function() {
6 | /*eslint if-curly-formatting:0 */
7 | if(grunt.option.flags().indexOf('--skip-tests') === -1){
8 | grunt.task.run('mochaTest');
9 | }
10 | else{
11 | grunt.fail.warn('tests skipped. Remove --skip-tests to execute tests.');
12 | }
13 | });
14 | };
15 |
--------------------------------------------------------------------------------
/grunt/tasks/force.js:
--------------------------------------------------------------------------------
1 | /*jslint node: true */
2 |
3 | module.exports = function(grunt) {
4 | 'use strict';
5 | var previous_force_state = grunt.option("force");
6 | grunt.registerTask("force", 'Enable --force via its targets "on", "off", "restore"', function(set){
7 | if (set === "on") {
8 | grunt.option("force",true);
9 | }
10 | else if (set === "off") {
11 | grunt.option("force",false);
12 | }
13 | else if (set === "restore") {
14 | grunt.option("force",previous_force_state);
15 | }
16 | });
17 | }
18 |
--------------------------------------------------------------------------------
/grunt/tasks/getAllApiRevisions.js:
--------------------------------------------------------------------------------
1 | /*jslint node: true */
2 |
3 | var grunt_common = require('apigee-sdk-mgmt-api');
4 |
5 | module.exports = function(grunt) {
6 | 'use strict';
7 | grunt.registerTask('getAllApiRevisions', 'Retrieve all API revisions', function() {
8 | var apiRevisions = function(error, response, body) {
9 | grunt.log.writeln(response.statusCode)
10 | grunt.log.writeln(body);
11 | done();
12 | }
13 | var done = this.async();
14 | grunt_common.getAllApiRevisions(grunt.config.get('apigee_profiles'), apiRevisions, grunt.option.flags().indexOf('--curl') !== -1)
15 | });
16 | };
17 |
--------------------------------------------------------------------------------
/grunt/tasks/getDeployedApiRevisions.js:
--------------------------------------------------------------------------------
1 | /*jslint node: true */
2 |
3 | var grunt_common = require('apigee-sdk-mgmt-api');
4 |
5 | module.exports = function(grunt) {
6 | 'use strict';
7 | grunt.registerTask('getDeployedApiRevisions', 'Retrieve Last API revision deployed', function() {
8 | var apiRevisions = function(error, response, body) {
9 | if (!error && (response.statusCode === 200 || response.statusCode === 400)) {
10 | var apiDeployedrevisions = JSON.parse(body);
11 | grunt.option('revisions_deployed', apiDeployedrevisions);
12 | }
13 | grunt.log.debug(response.statusCode)
14 | grunt.log.debug(JSON.stringify(response.headers))
15 | grunt.log.debug(body);
16 | done();
17 | }
18 | var done = this.async();
19 | grunt_common.getDeployedApiRevisions(grunt.config.get('apigee_profiles'), apiRevisions, grunt.option.flags().indexOf('--curl') !== -1)
20 | });
21 | };
22 |
--------------------------------------------------------------------------------
/grunt/tasks/installNpmRevision.js:
--------------------------------------------------------------------------------
1 | /*jslint node: true */
2 |
3 | var grunt_common = require('apigee-sdk-mgmt-api');
4 |
5 | module.exports = function(grunt) {
6 | 'use strict';
7 | grunt.registerTask('installNpmRevision', 'install npm API revision. e.g. grunt installNpmRevision:{revision_id}', function(revision) {
8 | var done = this.async();
9 | if(grunt.option('upload-modules')){
10 | grunt.log.debug('skipped installNpmRevision due to upload-modules option');
11 | done();
12 | return false;
13 | }
14 | var installNpmRevision = function(error, response, body) {
15 | /*eslint no-empty:0 */
16 | if (!error && response.statusCode === 200) {
17 | //var undeployResult = JSON.parse(body);
18 | }
19 | else{
20 | done(false)
21 | }
22 | grunt.log.debug(response.statusCode)
23 | grunt.log.debug(body);
24 | done(error);
25 | }
26 |
27 | var revisionl = revision || grunt.option('revision');
28 | //core logic
29 | if(!revisionl) {
30 | grunt.fail.fatal('invalid revision id. provide either argument as installNpmRevision:{revision_id}');
31 | }else{
32 | grunt_common.npmInstallRevision(grunt.config.get('apigee_profiles'), revisionl, installNpmRevision, grunt.option.flags().indexOf('--curl') !== -1)
33 | }
34 | });
35 | };
36 |
--------------------------------------------------------------------------------
/grunt/tasks/installNpmRevisionAlias.js:
--------------------------------------------------------------------------------
1 | /*jslint node: true */
2 |
3 | module.exports = function(grunt) {
4 | 'use strict';
5 | grunt.registerTask('installNpmRevisionAlias', 'install npm API revision alias.', function() {
6 | //grunt.log.debug('Node.js modules not include in API bundle.');
7 | switch (grunt.cli.tasks[0]){
8 | case 'UPDATE_CURRENT_REVISION' :
9 | grunt.task.run('installNpmRevision:' + grunt.option('revisions_undeployed').name);
10 | break;
11 | case 'IMPORT_DEPLOY_BUMP_REVISION' :
12 | grunt.task.run('installNpmRevision:' + grunt.option('revision'));
13 | break;
14 | case 'DEPLOY_IMPORT_BUMP_SEAMLESS_REVISION' :
15 | grunt.task.run('installNpmRevision:' + grunt.option('revision'));
16 | break;
17 | default :
18 | grunt.task.run('installNpmRevision:' + grunt.option('revision'));
19 | break;
20 | }
21 | });
22 | };
23 |
--------------------------------------------------------------------------------
/grunt/tasks/saveGitRevision.js:
--------------------------------------------------------------------------------
1 | module.exports = function(grunt) {
2 | 'use strict';
3 | grunt.registerTask('saveGitRevision', function() {
4 | var git = require('gift');
5 | var repo = git(".")
6 | var done = this.async();
7 | var os = require("os");
8 | repo.current_commit( function(err, commit){
9 | var gitRevision = "";
10 | if(commit) {
11 | gitRevision = "git commit: " + commit.id.substring(0,7) + " by " + commit.author.name + " on " + os.hostname();
12 | grunt.option('gitRevision', gitRevision);
13 | }
14 | done();
15 | }
16 | )});
17 | };
--------------------------------------------------------------------------------
/grunt/tasks/undeployApiRevision.js:
--------------------------------------------------------------------------------
1 | /*jslint node: true */
2 |
3 | var grunt_common = require('apigee-sdk-mgmt-api');
4 |
5 | module.exports = function(grunt) {
6 | 'use strict';
7 | grunt.registerTask('undeployApiRevision', 'Undeploy an API revision. e.g. grunt undeployApiRevision:{revision_id}', function(revision) {
8 | var undeployedRevision = function(error, response, body) {
9 | /*eslint if-curly-formatting:0 */
10 | if (!error && response.statusCode === 200){
11 | var undeployResult = JSON.parse(body);
12 | grunt.option('revisions_undeployed', undeployResult)
13 | }
14 | grunt.log.debug(response.statusCode)
15 | grunt.log.debug(body);
16 | done();
17 | }
18 | var revisionl = revision || (grunt.option('revisions_deployed') && grunt.option('revisions_deployed').revision && grunt.option('revisions_deployed').revision[0].name);
19 | //revisions_deployed are only set when grunt is run in sequence, otherwise it'll be null
20 | if(!revisionl) {
21 | grunt.log.warn('Invalid revision id. e.g. grunt undeployApiRevision:{revision_id}');
22 | }else{
23 | var done = this.async();
24 | grunt_common.undeployApiRevision(grunt.config.get('apigee_profiles'), revisionl, undeployedRevision, grunt.option.flags().indexOf('--curl') !== -1); //send cURL switch to log curl commands
25 | }
26 | });
27 | };
28 |
--------------------------------------------------------------------------------
/grunt/tasks/updateApiRevision.js:
--------------------------------------------------------------------------------
1 | /*jslint node: true */
2 |
3 | var grunt_common = require('apigee-sdk-mgmt-api');
4 |
5 | module.exports = function(grunt) {
6 | 'use strict';
7 | grunt.registerTask('updateApiRevision', 'Update an API revision. e.g. grunt updateApiRevision:{revision_id}', function(revision) {
8 | var updateRevision = function(error, response, body){
9 | grunt.log.debug(response.statusCode)
10 | done();
11 | }
12 | var revisionl = revision || (grunt.option('revisions_undeployed') && grunt.option('revisions_undeployed').revision);
13 | if(!revisionl) {
14 | grunt.log.warn('invalid revision. e.g. grunt updateApiRevision:{revision_id}');
15 | }else{
16 | var done = this.async();
17 | grunt_common.updateApiRevision(grunt.config.get('apigee_profiles'), revisionl, updateRevision, grunt.option.flags().indexOf('--curl') !== -1)
18 | }
19 | });
20 | };
21 |
--------------------------------------------------------------------------------
/java/lib/expressions-1.0.0.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/apigeecs/apigee-deploy-grunt-plugin/8abc54f010d128a12f92b8ddc26e5b088f6370d0/java/lib/expressions-1.0.0.jar
--------------------------------------------------------------------------------
/java/lib/message-flow-1.0.0.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/apigeecs/apigee-deploy-grunt-plugin/8abc54f010d128a12f92b8ddc26e5b088f6370d0/java/lib/message-flow-1.0.0.jar
--------------------------------------------------------------------------------
/java/src/com/example/SimpleJavaCallout.java:
--------------------------------------------------------------------------------
1 | package com.example;
2 |
3 | import java.io.PrintWriter;
4 | import java.io.StringWriter;
5 | import com.apigee.flow.execution.ExecutionContext;
6 | import com.apigee.flow.execution.ExecutionResult;
7 | import com.apigee.flow.execution.spi.Execution;
8 | import com.apigee.flow.message.MessageContext;
9 |
10 | public class SimpleJavaCallout implements Execution{
11 | public ExecutionResult execute(MessageContext messageContext, ExecutionContext executionContext) {
12 | try
13 | {
14 | messageContext.setVariable("response.content", "Payload set by a Java Callout");
15 | return ExecutionResult.SUCCESS;
16 |
17 | } catch (Exception e) {
18 | StringWriter sw = new StringWriter();
19 | e.printStackTrace(new PrintWriter(sw));
20 | String exceptionAsString = sw.toString();
21 | messageContext.setVariable("ERROR_MESSAGE", exceptionAsString);
22 | return ExecutionResult.ABORT;
23 | }
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/node/.gitignore:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/apigeecs/apigee-deploy-grunt-plugin/8abc54f010d128a12f92b8ddc26e5b088f6370d0/node/.gitignore
--------------------------------------------------------------------------------
/node/app.js:
--------------------------------------------------------------------------------
1 | var express = require('express'),
2 | forecastweather_node = require('./resources/forecastweather_node'),
3 | app = express();
4 | //lessMiddleware = require('less-middleware'),
5 | path = require('path');
6 | app.use(express.static(path.join(__dirname, 'public')));
7 | app.get('/forecastweather_node/:woeid', forecastweather_node.get)
8 | app.listen(9000);
--------------------------------------------------------------------------------
/node/node_modules/path/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "author": {
3 | "name": "Joyent",
4 | "url": "http://www.joyent.com"
5 | },
6 | "name": "path",
7 | "description": "Node.JS path module",
8 | "keywords": [
9 | "ender",
10 | "path"
11 | ],
12 | "version": "0.4.9",
13 | "homepage": "http://nodejs.org/docs/v0.4.9/api/path.html",
14 | "repository": {
15 | "type": "git",
16 | "url": "git://github.com/coolaj86/nodejs-libs-4-browser.git"
17 | },
18 | "main": "./path.js",
19 | "directories": {
20 | "lib": "."
21 | },
22 | "engines": {
23 | "node": ">= 0.2.0",
24 | "ender": ">= 0.5.0"
25 | },
26 | "dependencies": {},
27 | "devDependencies": {},
28 | "_npmJsonOpts": {
29 | "file": "/Users/coolaj86/.npm/path/0.4.9/package/package.json",
30 | "wscript": false,
31 | "contributors": false,
32 | "serverjs": false
33 | },
34 | "_id": "path@0.4.9",
35 | "_engineSupported": true,
36 | "_npmVersion": "1.0.15",
37 | "_nodeVersion": "v0.4.8",
38 | "_defaultsLoaded": true,
39 | "dist": {
40 | "shasum": "380c68d01273e43f9368d7ad50fee5e3e8d477f0",
41 | "tarball": "http://registry.npmjs.org/path/-/path-0.4.9.tgz"
42 | },
43 | "scripts": {},
44 | "_shasum": "380c68d01273e43f9368d7ad50fee5e3e8d477f0",
45 | "_from": "path@^0.4.9",
46 | "_resolved": "https://registry.npmjs.org/path/-/path-0.4.9.tgz",
47 | "bugs": {
48 | "url": "https://github.com/coolaj86/nodejs-libs-4-browser/issues"
49 | },
50 | "readme": "ERROR: No README data found!"
51 | }
52 |
--------------------------------------------------------------------------------
/node/node_modules/path/path.js:
--------------------------------------------------------------------------------
1 | var process = process || {};
2 | (function () {
3 | "use strict";
4 |
5 | // Copyright Joyent, Inc. and other Node contributors.
6 | //
7 | // Permission is hereby granted, free of charge, to any person obtaining a
8 | // copy of this software and associated documentation files (the
9 | // "Software"), to deal in the Software without restriction, including
10 | // without limitation the rights to use, copy, modify, merge, publish,
11 | // distribute, sublicense, and/or sell copies of the Software, and to permit
12 | // persons to whom the Software is furnished to do so, subject to the
13 | // following conditions:
14 | //
15 | // The above copyright notice and this permission notice shall be included
16 | // in all copies or substantial portions of the Software.
17 | //
18 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
19 | // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
20 | // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
21 | // NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
22 | // DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
23 | // OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
24 | // USE OR OTHER DEALINGS IN THE SOFTWARE.
25 |
26 |
27 | var isWindows = process.platform === 'win32';
28 |
29 |
30 | // resolves . and .. elements in a path array with directory names there
31 | // must be no slashes, empty elements, or device names (c:\) in the array
32 | // (so also no leading and trailing slashes - it does not distinguish
33 | // relative and absolute paths)
34 | function normalizeArray(parts, allowAboveRoot) {
35 | // if the path tries to go above the root, `up` ends up > 0
36 | var up = 0;
37 | for (var i = parts.length; i >= 0; i--) {
38 | var last = parts[i];
39 | if (last == '.') {
40 | parts.splice(i, 1);
41 | } else if (last === '..') {
42 | parts.splice(i, 1);
43 | up++;
44 | } else if (up) {
45 | parts.splice(i, 1);
46 | up--;
47 | }
48 | }
49 |
50 | // if the path is allowed to go above the root, restore leading ..s
51 | if (allowAboveRoot) {
52 | for (; up--; up) {
53 | parts.unshift('..');
54 | }
55 | }
56 |
57 | return parts;
58 | }
59 |
60 |
61 | if (isWindows) {
62 |
63 | // Regex to split a filename into [*, dir, basename, ext]
64 | // windows version
65 | var splitPathRe = /^(.+(?:[\\\/](?!$)|:)|[\\\/])?((?:.+?)?(\.[^.]*)?)$/;
66 |
67 | // Regex to split a windows path into three parts: [*, device, slash,
68 | // tail] windows-only
69 | var splitDeviceRe =
70 | /^([a-zA-Z]:|[\\\/]{2}[^\\\/]+[\\\/][^\\\/]+)?([\\\/])?(.*?)$/;
71 |
72 | // path.resolve([from ...], to)
73 | // windows version
74 | exports.resolve = function() {
75 | var resolvedDevice = '',
76 | resolvedTail = '',
77 | resolvedAbsolute = false;
78 |
79 | for (var i = arguments.length; i >= -1; i--) {
80 | var path = (i >= 0)
81 | ? arguments[i]
82 | : process.cwd();
83 |
84 | // Skip empty and invalid entries
85 | if (typeof path !== 'string' || !path) {
86 | continue;
87 | }
88 |
89 | var result = splitDeviceRe.exec(path),
90 | device = result[1] || '',
91 | isUnc = device && device.charAt(1) !== ':',
92 | isAbsolute = !!result[2] || isUnc, // UNC paths are always absolute
93 | tail = result[3];
94 |
95 | if (device &&
96 | resolvedDevice &&
97 | device.toLowerCase() !== resolvedDevice.toLowerCase()) {
98 | // This path points to another device so it is not applicable
99 | continue;
100 | }
101 |
102 | if (!resolvedDevice) {
103 | resolvedDevice = device;
104 | }
105 | if (!resolvedAbsolute) {
106 | resolvedTail = tail + '\\' + resolvedTail;
107 | resolvedAbsolute = isAbsolute;
108 | }
109 |
110 | if (resolvedDevice && resolvedAbsolute) {
111 | break;
112 | }
113 | }
114 |
115 | if (!resolvedAbsolute && resolvedDevice) {
116 | // If we still don't have an absolute path,
117 | // prepend the current path for the device found.
118 |
119 | // TODO
120 | // Windows stores the current directories for 'other' drives
121 | // as hidden environment variables like =C:=c:\windows (literally)
122 | // var deviceCwd = os.getCwdForDrive(resolvedDevice);
123 | var deviceCwd = '';
124 |
125 | // If there is no cwd set for the drive, it is at root
126 | resolvedTail = deviceCwd + '\\' + resolvedTail;
127 | resolvedAbsolute = true;
128 | }
129 |
130 | // Replace slashes (in UNC share name) by backslashes
131 | resolvedDevice = resolvedDevice.replace(/\//g, '\\');
132 |
133 | // At this point the path should be resolved to a full absolute path,
134 | // but handle relative paths to be safe (might happen when process.cwd()
135 | // fails)
136 |
137 | // Normalize the tail path
138 |
139 | function f(p) {
140 | return !!p;
141 | }
142 |
143 | resolvedTail = normalizeArray(resolvedTail.split(/[\\\/]+/).filter(f),
144 | !resolvedAbsolute).join('\\');
145 |
146 | return (resolvedDevice + (resolvedAbsolute ? '\\' : '') + resolvedTail) ||
147 | '.';
148 | };
149 |
150 | // windows version
151 | exports.normalize = function(path) {
152 | var result = splitDeviceRe.exec(path),
153 | device = result[1] || '',
154 | isUnc = device && device.charAt(1) !== ':',
155 | isAbsolute = !!result[2] || isUnc, // UNC paths are always absolute
156 | tail = result[3],
157 | trailingSlash = /[\\\/]$/.test(tail);
158 |
159 | // Normalize the tail path
160 | tail = normalizeArray(tail.split(/[\\\/]+/).filter(function(p) {
161 | return !!p;
162 | }), !isAbsolute).join('\\');
163 |
164 | if (!tail && !isAbsolute) {
165 | tail = '.';
166 | }
167 | if (tail && trailingSlash) {
168 | tail += '\\';
169 | }
170 |
171 | return device + (isAbsolute ? '\\' : '') + tail;
172 | };
173 |
174 | // windows version
175 | exports.join = function() {
176 | function f(p) {
177 | return p && typeof p === 'string';
178 | }
179 |
180 | var paths = Array.prototype.slice.call(arguments, 0).filter(f);
181 | var joined = paths.join('\\');
182 |
183 | // Make sure that the joined path doesn't start with two slashes
184 | // - it will be mistaken for an unc path by normalize() -
185 | // unless the paths[0] also starts with two slashes
186 | if (/^[\\\/]{2}/.test(joined) && !/^[\\\/]{2}/.test(paths[0])) {
187 | joined = joined.slice(1);
188 | }
189 |
190 | return exports.normalize(joined);
191 | };
192 |
193 |
194 | } else /* posix */ {
195 |
196 | // Regex to split a filename into [*, dir, basename, ext]
197 | // posix version
198 | var splitPathRe = /^(.+\/(?!$)|\/)?((?:.+?)?(\.[^.]*)?)$/;
199 |
200 | // path.resolve([from ...], to)
201 | // posix version
202 | exports.resolve = function() {
203 | var resolvedPath = '',
204 | resolvedAbsolute = false;
205 |
206 | for (var i = arguments.length; i >= -1 && !resolvedAbsolute; i--) {
207 | var path = (i >= 0)
208 | ? arguments[i]
209 | : process.cwd();
210 |
211 | // Skip empty and invalid entries
212 | if (typeof path !== 'string' || !path) {
213 | continue;
214 | }
215 |
216 | resolvedPath = path + '/' + resolvedPath;
217 | resolvedAbsolute = path.charAt(0) === '/';
218 | }
219 |
220 | // At this point the path should be resolved to a full absolute path, but
221 | // handle relative paths to be safe (might happen when process.cwd() fails)
222 |
223 | // Normalize the path
224 | resolvedPath = normalizeArray(resolvedPath.split('/').filter(function(p) {
225 | return !!p;
226 | }), !resolvedAbsolute).join('/');
227 |
228 | return ((resolvedAbsolute ? '/' : '') + resolvedPath) || '.';
229 | };
230 |
231 | // path.normalize(path)
232 | // posix version
233 | exports.normalize = function(path) {
234 | var isAbsolute = path.charAt(0) === '/',
235 | trailingSlash = path.slice(-1) === '/';
236 |
237 | // Normalize the path
238 | path = normalizeArray(path.split('/').filter(function(p) {
239 | return !!p;
240 | }), !isAbsolute).join('/');
241 |
242 | if (!path && !isAbsolute) {
243 | path = '.';
244 | }
245 | if (path && trailingSlash) {
246 | path += '/';
247 | }
248 |
249 | return (isAbsolute ? '/' : '') + path;
250 | };
251 |
252 |
253 | // posix version
254 | exports.join = function() {
255 | var paths = Array.prototype.slice.call(arguments, 0);
256 | return exports.normalize(paths.filter(function(p, index) {
257 | return p && typeof p === 'string';
258 | }).join('/'));
259 | };
260 | }
261 |
262 |
263 | exports.dirname = function(path) {
264 | var dir = splitPathRe.exec(path)[1] || '';
265 | if (!dir) {
266 | // No dirname
267 | return '.';
268 | } else if (dir.length === 1 ||
269 | (isWindows && dir.length <= 3 && dir.charAt(1) === ':')) {
270 | // It is just a slash or a drive letter with a slash
271 | return dir;
272 | } else {
273 | // It is a full dirname, strip trailing slash
274 | return dir.substring(0, dir.length - 1);
275 | }
276 | };
277 |
278 |
279 | exports.basename = function(path, ext) {
280 | var f = splitPathRe.exec(path)[2] || '';
281 | // TODO: make this comparison case-insensitive on windows?
282 | if (ext && f.substr(-1 * ext.length) === ext) {
283 | f = f.substr(0, f.length - ext.length);
284 | }
285 | return f;
286 | };
287 |
288 |
289 | exports.extname = function(path) {
290 | return splitPathRe.exec(path)[3] || '';
291 | };
292 |
293 |
294 | exports.exists = function(path, callback) {
295 | process.binding('fs').stat(path, function(err, stats) {
296 | if (callback) callback(err ? false : true);
297 | });
298 | };
299 |
300 |
301 | exports.existsSync = function(path) {
302 | try {
303 | process.binding('fs').stat(path);
304 | return true;
305 | } catch (e) {
306 | return false;
307 | }
308 | };
309 |
310 | }());
311 |
--------------------------------------------------------------------------------
/node/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "express-test",
3 | "version": "1.0.0",
4 | "description": "",
5 | "main": "index.js",
6 | "scripts": {
7 | "test": "echo \"Error: no test specified\" && exit 1"
8 | },
9 | "author": "",
10 | "license": "ISC",
11 | "devDependencies": {
12 | "path": "^0.4.9"
13 | }
14 | }
15 |
--------------------------------------------------------------------------------
/node/public/images/tree.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/apigeecs/apigee-deploy-grunt-plugin/8abc54f010d128a12f92b8ddc26e5b088f6370d0/node/public/images/tree.jpg
--------------------------------------------------------------------------------
/node/public/tree.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/apigeecs/apigee-deploy-grunt-plugin/8abc54f010d128a12f92b8ddc26e5b088f6370d0/node/public/tree.jpg
--------------------------------------------------------------------------------
/node/resources/forecastweather_node.js:
--------------------------------------------------------------------------------
1 | exports.get = function(req, res){
2 | var woeid = req.params.woeid;
3 | //res.end('Hello, World!');
4 | var request = require('request');
5 |
6 | request('http://weather.yahooapis.com/forecastrss?w=' + woeid, function (error, response, body) {
7 | if (!error && response.statusCode == 200) {
8 | res.writeHead(200, {'Content-Type':'application/json;charset=utf-8'});
9 | res.end(JSON.stringify(response));
10 | }
11 | })
12 | }
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "apigee-deploy-grunt-plugin",
3 | "version": "0.0.4",
4 | "description": "Out of the box I include scaffolding apiproxy, Node.js, and Gruntfile to build your app.",
5 | "main": "index.js",
6 | "scripts": {
7 | "test": "grunt mochaTest -env=test"
8 | },
9 | "repository": {
10 | "type": "git",
11 | "url": "https://github.com/{org}/<%= apiname %>"
12 | },
13 | "keywords": [
14 | "apigee",
15 | "deploy",
16 | "lifecycle",
17 | "API"
18 | ],
19 | "author": "{YOUR_NAME_HERE}",
20 | "license": "ISC",
21 | "dependencies": {
22 | "apigee-sdk-mgmt-api": "^1.1.0",
23 | "async": "^0.9.0",
24 | "blanket": "^1.1.6",
25 | "chai": "^1.9.1",
26 | "chai-http": "^1.0.0",
27 | "curl-cmd": "0.0.0",
28 | "gift": "^0.4.3-1",
29 | "grunt": "^0.4.5",
30 | "grunt-available-tasks": "^0.5.0",
31 | "grunt-complexity": "^0.2.0",
32 | "grunt-contrib-clean": "^0.5.0",
33 | "grunt-contrib-compress": "^0.12.0",
34 | "grunt-contrib-concat": "^0.5.0",
35 | "grunt-contrib-copy": "^0.5.0",
36 | "grunt-contrib-jshint": "^0.10.0",
37 | "grunt-eslint": "^1.0.0",
38 | "grunt-mkdir": "^0.1.2",
39 | "grunt-mocha-test": "^0.11.0",
40 | "grunt-notify": "^0.3.1",
41 | "grunt-shell": "^1.1.1",
42 | "grunt-string-replace": "^1.0.0",
43 | "grunt-update-submodules": "^0.4.1",
44 | "grunt-apigee-kvm": "*",
45 | "grunt-xmlpoke": "^0.6.0",
46 | "jshint-stylish": "^0.4.0",
47 | "load-grunt-config": "^0.12.0",
48 | "load-grunt-tasks": "^0.6.0",
49 | "request": "^2.37.0",
50 | "time-grunt": "^1.0.0",
51 | "cfonts": "0.0.13",
52 | "grunt-prompt": "^1.3.0",
53 | "grunt-apigee-import-api-bundle": "^0.0.1"
54 | },
55 | "devDependencies": {}
56 | }
57 |
--------------------------------------------------------------------------------
/tests/diego-forecastweather-grunt-plugin-api-test-data.js:
--------------------------------------------------------------------------------
1 | /*jslint node: true */
2 |
3 | var common = {
4 | url : "https://testmyapi-test.apigee.net/weathergrunt/apigee/forecastrss",
5 | url_node : "https://testmyapi-test.apigee.net/weathergrunt/forecastweather_node"
6 | }
7 |
8 | exports.simpleWeatherArray = function(){
9 | "use strict";
10 | var weatherArray = [
11 | {
12 | "url" : common.url + "?w=2502265",
13 | "name" : "Sunnyvale",
14 | "responseCode" : 200
15 | },
16 | {
17 | "url" : common.url + "?w=766273",
18 | "name" : "Madrid",
19 | "responseCode" : 200
20 | },
21 | ];
22 | return weatherArray;
23 | }
24 |
25 | exports.simpleFormatArray = function(){
26 | "use strict";
27 | var weatherArray = [
28 | {
29 | "url" : common.url + "?w=2502265",
30 | "name" : "Sunnyvale",
31 | "contentType" : "text/xml;charset=UTF-8",
32 | "responseCode" : 200
33 | },
34 | {
35 | "url" : common.url + "?w=766273",
36 | "name" : "Madrid",
37 | "contentType" : "application/json;charset=UTF-8",
38 | "responseCode" : 200
39 | },
40 | ];
41 | return weatherArray;
42 | }
43 |
44 | exports.nodeArray = function(){
45 | "use strict";
46 | var weatherArray = [
47 | {
48 | "url" : common.url_node + "/368149",
49 | "name" : "Cali-Colombia",
50 | "contentAssertion" : "Weather for Cali",
51 | "responseCode" : 200
52 | },
53 | ];
54 | return weatherArray;
55 | }
--------------------------------------------------------------------------------
/tests/forecastweather-grunt-plugin-api-prod-data.js:
--------------------------------------------------------------------------------
1 | /*jslint node: true */
2 |
3 | var common = {
4 | url : "https://testmyapi-test.apigee.net/weathergrunt/apigee/forecastrss",
5 | url_node : "https://testmyapi-test.apigee.net/weathergrunt/forecastweather_node"
6 | }
7 |
8 | exports.simpleWeatherArray = function(){
9 | "use strict";
10 | var weatherArray = [
11 | {
12 | "url" : common.url + "?w=2502265",
13 | "name" : "Sunnyvale",
14 | "responseCode" : 200
15 | },
16 | {
17 | "url" : common.url + "?w=766273",
18 | "name" : "Madrid",
19 | "responseCode" : 200
20 | },
21 | ];
22 | return weatherArray;
23 | }
24 |
25 | exports.simpleFormatArray = function(){
26 | "use strict";
27 | var weatherArray = [
28 | {
29 | "url" : common.url + "?w=2502265",
30 | "name" : "Sunnyvale",
31 | "contentType" : "text/xml;charset=UTF-8",
32 | "responseCode" : 200
33 | },
34 | {
35 | "url" : common.url + "?w=766273",
36 | "name" : "Madrid",
37 | "contentType" : "application/json;charset=UTF-8",
38 | "responseCode" : 200
39 | },
40 | ];
41 | return weatherArray;
42 | }
43 |
44 | exports.nodeArray = function(){
45 | "use strict";
46 | var weatherArray = [
47 | {
48 | "url" : common.url_node + "/368149",
49 | "name" : "Cali-Colombia",
50 | "contentAssertion" : "Weather for Cali",
51 | "responseCode" : 200
52 | },
53 | ];
54 | return weatherArray;
55 | }
--------------------------------------------------------------------------------
/tests/forecastweather-grunt-plugin-api-test-data.js:
--------------------------------------------------------------------------------
1 | /*jslint node: true */
2 |
3 | var common = {
4 | url : "https://testmyapi-test.apigee.net/weathergrunt/apigee/forecastrss",
5 | url_node : "https://testmyapi-test.apigee.net/weathergrunt/forecastweather_node"
6 | }
7 |
8 | exports.simpleWeatherArray = function(){
9 | "use strict";
10 | var weatherArray = [
11 | {
12 | "url" : common.url + "?w=2502265",
13 | "name" : "Sunnyvale" ,
14 | "responseCode" : 200
15 | },
16 | {
17 | "url" : common.url + "?w=766273",
18 | "name" : "Madrid",
19 | "responseCode" : 200
20 | },
21 | ];
22 | return weatherArray;
23 | }
24 |
25 | exports.simpleFormatArray = function(){
26 | "use strict";
27 | var weatherArray = [
28 | {
29 | "url" : common.url + "?w=2502265",
30 | "name" : "Sunnyvale",
31 | "contentType" : "text/xml;charset=UTF-8",
32 | "responseCode" : 200
33 | },
34 | {
35 | "url" : common.url + "?w=766273",
36 | "name" : "Madrid",
37 | "contentType" : "application/json;charset=UTF-8",
38 | "responseCode" : 200
39 | },
40 | ];
41 | return weatherArray;
42 | }
43 |
44 | exports.nodeArray = function(){
45 | "use strict";
46 | var weatherArray = [
47 | {
48 | "url" : common.url_node + "/368149",
49 | "name" : "Cali-Colombia",
50 | "contentAssertion" : "Weather for Cali",
51 | "responseCode" : 200
52 | },
53 | ];
54 | return weatherArray;
55 | }
56 |
--------------------------------------------------------------------------------
/tests/forecastweather-grunt-plugin-api.js:
--------------------------------------------------------------------------------
1 | /*globals describe:true, it:true, expect:true, before:true, beforeEach:true, after:true, afterEach:true*/
2 | /*jslint node: true */
3 |
4 | var grunt = require('grunt');
5 | var testDataFilename = grunt.template.process("<%= apigee_profiles[grunt.option('env')].apiproxy + '-' + grunt.option('env') + '-data' %>");
6 | var async = require('async')
7 | var chai = require('chai')
8 | var assert = require('chai').assert
9 | var expect = require('chai').expect
10 | var request = require('request'), chaiHttp = require('chai-http');
11 | var weatherData = require('./' + testDataFilename);
12 |
13 | chai.use(chaiHttp);
14 |
15 | describe('ForecastWeather Public API Test',function() {
16 | "use strict";
17 | before(function () {
18 | // get OAuth 2.0 token
19 | // console.log('initialize');
20 | });
21 | beforeEach(function () {
22 | //console.log('initialize each test');
23 | });
24 |
25 | describe('Check weather in cities', function() {
26 | async.each(weatherData.simpleWeatherArray() , function(cityData, callback) {
27 | it('you should be able to get forecast weather for ' + cityData.name + ' from this API Proxy.', function(done) {
28 | var options = {
29 | url: cityData.url, //'https://testmyapi-test.apigee.net/weathergrunt/apigee/forecastrss?w=2502265',
30 | headers: {
31 | 'User-Agent': 'request'
32 | }
33 | }
34 | request(options, function (error, response, body) {
35 | expect(body).to.contain(cityData.name) //Sunnyvale, Madrid
36 | assert.equal(cityData.responseCode, response.statusCode)
37 | done()
38 | })
39 | })
40 | callback();
41 | });
42 | });
43 |
44 | describe('ForecastWeather Public API Test', function() {
45 | async.each(weatherData.simpleFormatArray(), function(cityData, callback){
46 | it('you should be able to get forecast weather for ' + cityData.name + ' from this API Proxy in ' + cityData.contentType, function(done) {
47 | var options = {
48 | url: cityData.url,//'https://testmyapi-test.apigee.net/weathergrunt/apigee/forecastrss?w=2502265',
49 | headers: {
50 | 'User-Agent': 'request',
51 | 'Accept' : cityData.contentType//'text/xml;charset=UTF-8'
52 | }
53 | }
54 | request(options, function (error, response, body) {
55 | expect(body).to.contain(cityData.name)
56 | assert.equal(cityData.responseCode, response.statusCode)
57 | expect(response).to.have.header('content-type', cityData.contentType);
58 | done()
59 | })
60 | })
61 | callback();
62 | });
63 |
64 | async.each(weatherData.nodeArray(),function(cityData, callback){
65 | it('you should be able to get forecast weather for ' + cityData.name + ' from this API Proxy via a Node.js Target', function(done) {
66 | var options = {
67 | url: cityData.url,
68 | headers: {
69 | 'User-Agent': 'request'
70 | }
71 | }
72 | request(options, function (error, response, body) {
73 | expect(body).to.contain(cityData.contentAssertion)
74 | assert.equal(cityData.responseCode, response.statusCode)
75 | done()
76 | })
77 | })
78 | callback();
79 | })
80 |
81 | it('you should be able to retrieve image with content-type header image/jpg', function(done) {
82 | chai.request('https://testmyapi-test.apigee.net/weathergrunt/images')
83 | .get('/tree.jpg')
84 | .set('test', '123')
85 | .end(function (err, res) {
86 | expect(res).to.have.status(200);
87 | expect(res).to.have.header('content-type','image/jpeg');
88 | done();
89 | });
90 | })
91 |
92 | it('you should be able use oauth', function(done) {
93 | done()
94 | })
95 | //Disabled by default (JavaCallout Policy)
96 | /* describe('you should be able to make a call to resource which executes a JavaCallout', function() {
97 | it('with a response "Payload set by a Java Callout"', function(done) {
98 | chai.request('https://testmyapi-test.apigee.net/weathergrunt')
99 | .get('/javacallout')
100 | .res(function (res) {
101 | //expect(res.content).to.contain('Weather for Cali')
102 | expect(res.text).to.contain('Payload set by a Java Callout')
103 | done();
104 | });
105 | })
106 | })*/
107 |
108 | });
109 | after(function () {
110 | // teardown test
111 | //console.log('destroy');
112 | });
113 | afterEach(function () {
114 | //console.log('finalize each test');
115 | });
116 | });
117 |
118 | //pending test
119 | describe('Array - pending test', function(){
120 | "use strict";
121 | describe('#indexOf()', function(){
122 | it('should return -1 when the value is not present')
123 | })
124 | })
125 |
--------------------------------------------------------------------------------
/tools/CommonProxy/apiproxy/policies/Script-External-Variables.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | Script-External-Variables
4 |
5 |
6 | jsc://js_external_vars.js
7 |
--------------------------------------------------------------------------------
/tools/CommonProxy/apiproxy/policies/xmltojson-1.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | XMLtoJSON-1
5 |
6 |
7 | yahoo
8 | response
9 | response
10 |
11 |
--------------------------------------------------------------------------------
/tools/CommonProxy/apiproxy/proxies/common-js-vars.flowfrag:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Script-External-Variables
5 |
--------------------------------------------------------------------------------
/tools/CommonProxy/apiproxy/proxies/xmltojson.flowfrag:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | xmltojson-1
5 |
--------------------------------------------------------------------------------
/tools/CommonProxy/apiproxy/resources/jsc/js_external_vars.js:
--------------------------------------------------------------------------------
1 | var client_start_time = context.getVariable('client.received.start.timestamp');
2 | var target_start_time = context.getVariable('target.sent.start.timestamp');
3 | var client_end_time = context.getVariable('system.timestamp');
4 | var target_end_time = context.getVariable('target.received.end.timestamp');
5 |
6 | context.setVariable("total_request_time",(client_end_time-client_start_time)+'');
7 | context.setVariable("total_target_time", (target_end_time-target_start_time)+'');
8 |
9 | response.headers['total_request_time'] =(client_end_time-client_start_time)+'';
10 | response.headers['total_target_time'] = (target_end_time-target_start_time)+'';
--------------------------------------------------------------------------------
/tools/forecastweather-jmeter-example/README.md:
--------------------------------------------------------------------------------
1 | README.md
2 | ====
3 |
4 | Switching to JMeter framework to run tests is as easy as following these steps:
5 |
6 | #### **Step 1:**
7 | Copy pom.xml file to root folder (where Gruntfile.js file resides)
8 | #### **Step 2:**
9 | Copy tests jmx and data files to tests root folder
10 | #### **Step 3:**
11 | Enable shell task to run run_jmeter_tests in Gruntfile.js
12 |
13 | That's it! You can now run JMeter tests from Grunt through Maven. ```grunt shell:run_jmeter_tests```.
--------------------------------------------------------------------------------
/tools/forecastweather-jmeter-example/pom.xml:
--------------------------------------------------------------------------------
1 |
16 |
18 | 4.0.0
19 | apigee
20 | forecastweatherapi-grunt
21 | 1.0
22 | forecastweatherapi-grunt
23 | pom
24 |
25 |
26 | test
27 |
28 |
29 |
30 | com.lazerycode.jmeter
31 | jmeter-maven-plugin
32 | 1.8.1
33 |
34 |
35 | jmeter-tests
36 | test
37 |
38 | jmeter
39 |
40 |
41 | ${skipTests}
42 | true
43 | false
44 |
45 | weather_test.csv
46 | 5
47 | 5
48 | 2
49 |
50 |
51 |
52 |
53 |
54 | tests
55 | false
56 |
57 |
58 |
59 |
60 |
61 |
62 | prod
63 |
64 |
65 |
66 | com.lazerycode.jmeter
67 | jmeter-maven-plugin
68 | 1.8.1
69 |
70 |
71 | jmeter-tests
72 | test
73 |
74 | jmeter
75 |
76 |
77 | ${skipTests}
78 | true
79 | false
80 |
81 | weather_prod.csv
82 | 5
83 | 5
84 | 2
85 |
86 |
87 |
88 |
89 |
90 | tests
91 | false
92 |
93 |
94 |
95 |
96 |
97 |
98 |
99 |
100 |
--------------------------------------------------------------------------------
/tools/forecastweather-jmeter-example/tests/weather.jmx:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | false
7 | false
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 | continue
16 |
17 | false
18 | ${__P(loopCount,1)}
19 |
20 | ${__P(threadNum,10)}
21 | ${__P(rampUpPeriodSecs,3)}
22 | 1384727829000
23 | 1384727829000
24 | false
25 |
26 |
27 |
28 |
29 |
30 | ,
31 |
32 | ${__P(testData,weather_dev.csv)}
33 | false
34 | true
35 | shareMode.all
36 | true
37 |
38 |
39 |
40 |
41 | "${execute}" == "Y"
42 | false
43 |
44 |
45 |
46 |
47 |
48 |
49 | false
50 | ${woeid}
51 | =
52 | true
53 | w
54 |
55 |
56 | false
57 | ${units}
58 | =
59 | true
60 | u
61 |
62 |
63 |
64 | ${servername}
65 |
66 |
67 |
68 |
69 |
70 | ${path}
71 | GET
72 | true
73 | false
74 | true
75 | false
76 | HttpClient4
77 | false
78 |
79 |
80 |
81 |
82 |
83 | ${assertheader}
84 |
85 | Assertion.response_headers
86 | true
87 | 2
88 | dddd
89 |
90 |
91 |
92 | false
93 | city
94 | "city": "(.+?)"
95 | $1$
96 | NOT_FOUND
97 |
98 |
99 |
100 |
101 |
102 | ${assertcontent}
103 |
104 | Assertion.response_data
105 | false
106 | 2
107 |
108 |
109 |
110 |
111 | ${assertcontentnegative}
112 |
113 | Assertion.response_data
114 | false
115 | 6
116 |
117 |
118 |
119 |
120 | false
121 |
122 | saveConfig
123 |
124 |
125 | true
126 | true
127 | true
128 |
129 | true
130 | false
131 | true
132 | true
133 | true
134 | true
135 | true
136 | false
137 | true
138 | true
139 | false
140 | false
141 | false
142 | false
143 | true
144 | 0
145 | true
146 | true
147 | true
148 | true
149 | true
150 | true
151 |
152 |
153 | ../target/jmeter/results/weather.jtl
154 |
155 |
156 |
157 |
158 |
159 |
160 |
--------------------------------------------------------------------------------
/tools/forecastweather-jmeter-example/tests/weather_prod.csv:
--------------------------------------------------------------------------------
1 | testcaseid,userstory,testcasedescription,servername,path,woeid,units,execute,assertheader,assertcontent,env,assertcontentnegative
2 | WEATHER-1-1,WEATHER-1,valid location (woeid),testmyapi-prod.apigee.net,/weather/forecastrss,2502265,c,Y,HTTP/1.1 200 OK,city,DEV,NON-EXISTENT-WORD
3 | WEATHER-1-2,WEATHER-1,valid location (woeid),testmyapi-prod.apigee.net,/weather/forecastrss,56465629,c,Y,HTTP/1.1 200 OK,city,DEV,NON-EXISTENT-WORD
4 | WEATHER-1-3,WEATHER-1,weather at maine,testmyapi-prod.apigee.net,/weather/forecastrss,2524575,c,Y,HTTP/1.1 200 OK,city,DEV,NON-EXISTENT-WORD
5 | WEATHER-1-4,WEATHER-1,invalid location (woed),testmyapi-prod.apigee.net,/weather/forecastrss,00000000,c,Y,HTTP/1.1 200 OK,,DEV,city,NON-EXISTENT-WORD
6 | WEATHER-1-5,WEATHER-1,invalid location (woed) test that channel word does not exist,testmyapi-prod.apigee.net,/weather/forecastrss,00000000,c,N,HTTP/1.1 200 OK,,DEV,channel
--------------------------------------------------------------------------------
/tools/forecastweather-jmeter-example/tests/weather_test.csv:
--------------------------------------------------------------------------------
1 | testcaseid,userstory,testcasedescription,servername,path,woeid,units,execute,assertheader,assertcontent,env,assertcontentnegative
2 | WEATHER-1-1,WEATHER-1,valid location (woeid),testmyapi-test.apigee.net,/weather/forecastrss,2502265,c,Y,HTTP/1.1 200 OK,city,DEV,NON-EXISTENT-WORD
3 | WEATHER-1-2,WEATHER-1,valid location (woeid),testmyapi-test.apigee.net,/weather/forecastrss,56465629,c,Y,HTTP/1.1 200 OK,city,DEV,NON-EXISTENT-WORD
4 | WEATHER-1-3,WEATHER-1,weather at maine,testmyapi-test.apigee.net,/weather/forecastrss,2524575,c,Y,HTTP/1.1 200 OK,city,DEV,NON-EXISTENT-WORD
5 | WEATHER-1-4,WEATHER-1,invalid location (woed),testmyapi-test.apigee.net,/weather/forecastrss,00000000,c,Y,HTTP/1.1 200 OK,,DEV,city,NON-EXISTENT-WORD
6 | WEATHER-1-5,WEATHER-1,invalid location (woed) test that channel word does not exist,testmyapi-test.apigee.net,/weather/forecastrss,00000000,c,N,HTTP/1.1 200 OK,,DEV,channel
7 |
--------------------------------------------------------------------------------
/tools/proxy-dependency-maven-plugin/CommonProxy/apiproxy/policies/Script-External-Variables.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | Script-External-Variables
4 |
5 |
6 | jsc://js_external_vars.js
7 |
--------------------------------------------------------------------------------
/tools/proxy-dependency-maven-plugin/CommonProxy/apiproxy/policies/xmltojson-1.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | XMLtoJSON-1
5 |
6 |
7 | yahoo
8 | response
9 | response
10 |
11 |
--------------------------------------------------------------------------------
/tools/proxy-dependency-maven-plugin/CommonProxy/apiproxy/proxies/common-js-vars.flowfrag:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Script-External-Variables
5 |
--------------------------------------------------------------------------------
/tools/proxy-dependency-maven-plugin/CommonProxy/apiproxy/proxies/xmltojson.flowfrag:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | xmltojson-1
5 |
--------------------------------------------------------------------------------
/tools/proxy-dependency-maven-plugin/CommonProxy/apiproxy/resources/jsc/js_external_vars.js:
--------------------------------------------------------------------------------
1 | var client_start_time = context.getVariable('client.received.start.timestamp');
2 | var target_start_time = context.getVariable('target.sent.start.timestamp');
3 | var client_end_time = context.getVariable('system.timestamp');
4 | var target_end_time = context.getVariable('target.received.end.timestamp');
5 |
6 | context.setVariable("total_request_time",(client_end_time-client_start_time)+'');
7 | context.setVariable("total_target_time", (target_end_time-target_start_time)+'');
8 |
9 | response.headers['total_request_time'] =(client_end_time-client_start_time)+'';
10 | response.headers['total_target_time'] = (target_end_time-target_start_time)+'';
--------------------------------------------------------------------------------
/tools/proxy-dependency-maven-plugin/Gruntfile.js:
--------------------------------------------------------------------------------
1 | /*jslint node: true */
2 |
3 | module.exports = function(grunt) {
4 | var apigee_conf = require('./apigee-config.js')
5 | require('load-grunt-tasks')(grunt);
6 | // Project configuration.
7 | grunt.initConfig({
8 | pkg: grunt.file.readJSON('package.json'),
9 | apigee_profiles : apigee_conf.profiles(grunt),//{
10 | clean: ["target"],
11 | mkdir: {
12 | all: {
13 | options: {
14 | create: ['target']
15 | },
16 | },
17 | },
18 | copy: {
19 | main: {
20 | src: 'apiproxy/**',
21 | dest: 'target/',
22 | },
23 | },
24 | // make a zipfile
25 | compress: {
26 | main: {
27 | options: {
28 | mode : 'zip',
29 | archive: function(){
30 | var ap = grunt.config.get("apigee_profiles")
31 | return 'target/' + ap[ap.env].apiproxy + ".zip"
32 | }
33 | },
34 | files: [
35 | {expand: true, cwd: 'target/apiproxy/', src: ['**'], dest: 'apiproxy/' }, // makes all src relative to cwd
36 | ]
37 | }
38 | },
39 | // task for configuration management: search and replace elements within XML files
40 | xmlpoke: apigee_conf.config(apigee_conf.profiles(grunt).env),
41 | // Configure a mochaTest task
42 | mochaTest: {
43 | test: {
44 | options: {
45 | reporter: 'spec',
46 | timeout : 5000
47 | },
48 | src: ['tests/**.js']
49 | }
50 | },
51 | jshint: {
52 | options: { //see options reference http://www.jshint.com/docs/options/
53 | curly: true,
54 | eqeqeq: true,
55 | eqnull: true,
56 | browser: true,
57 | asi : true,
58 | debug : true,
59 | undef : true,
60 | unused : true,
61 | maxcomplexity : 5,
62 | reporter: require('jshint-stylish')
63 | },
64 | all: ['Gruntfile.js', 'apiproxy/**/*.js', 'tests/**/*.js', 'tasks/*.js']
65 | },
66 | eslint: { // task
67 | options: {
68 | config: 'conf/eslint.json', // custom config
69 | rulesdir: ['conf/rules'] // custom rules
70 | },
71 | target: ['Gruntfile.js', 'apiproxy/**/*.js', 'tests/**/*.js', 'tasks/*.js'] // array of files
72 | },
73 | shell: { // Task
74 | callMaven: { // Target
75 | command: 'mvn install -Ptest -Dusername=$ae_username -Dpassword=$ae_password'
76 | }
77 | }
78 | })
79 |
80 | grunt.registerTask('buildApiBundle', 'Build zip without importing it to Edge', ['jshint', 'eslint', 'clean', 'mkdir','copy', 'shell:callMaven','xmlpoke','compress']);
81 |
82 | // Default task(s).
83 | //delete and then import revision keeping same id
84 | grunt.registerTask('default', [ 'buildApiBundle',/*'force:on',*/ 'getDeployedApiRevisions', 'undeployApiRevision',
85 | 'deleteApiRevision', /*'force:restore',*/ 'importApiBundle', 'deployApiRevision', 'executeTests']);
86 |
87 | grunt.loadTasks('tasks');
88 | if(grunt.option.flags().indexOf('--help') === -1 && !apigee_conf.profiles(grunt).env) {
89 | grunt.fail.fatal('Invalid environment flag --env={env}. Provide environment as argument, see apigee_profiles in Grunfile.js.')
90 | }
91 |
92 | };
--------------------------------------------------------------------------------
/tools/proxy-dependency-maven-plugin/README.md:
--------------------------------------------------------------------------------
1 | ## Support for Maven Plugins
2 | Grunt Plugin can be enabled to support Maven Plugins. For instance Proxy Dependency Plugin can be incorporated by following these steps:
3 |
4 | #### Step 1: Include pom.xml under Gruntfile.js file
5 | #### Step 2: Include CommonProxy folder where fragments are extracted from
6 | #### Step 3: Incorporate shell task into Gruntfile.js. This task execute a shell task that calls a Maven target. Then after that all other tasks will continue to be executed by Grunt
7 | See example included
8 | ```
9 | shell: { // Task
10 | callMaven: { // Target
11 | command: 'mvn install -Ptest -Dusername=$ae_username -Dpassword=$ae_password'
12 | }
13 | }
14 | ```
15 | #### Step 4: Execute this shell task after copy target. Note that this task will replace target folder.
16 |
17 | ```
18 | grunt.registerTask('buildApiBundle', 'Build zip without importing it to Edge', ['jshint', 'eslint', 'clean', 'mkdir','copy', 'shell:callMaven','xmlpoke','compress']);
19 |
20 | ```
21 |
22 | #### Step 5: This plugin requires that apiproxy folder is under another folder to work properly. So, for instance, proxySrcDir will point to apiproxyroot, then apiproxy will exist be under it.
23 | ```
24 | ./apiproxyroot
25 | ```
26 |
--------------------------------------------------------------------------------
/tools/proxy-dependency-maven-plugin/apiproxy/forecastweather-grunt-plugin-api.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | 1384727595303
5 | dzuluaga@apigee.com
6 | @@DESCRIPTION TO BE REPLACED BY GITHUB ID
7 | weather
8 | 1384727595303
9 | dzuluaga@apigee.com
10 |
11 | xmltojson-1
12 |
13 |
14 | default
15 |
16 |
17 |
18 |
19 | default
20 |
21 | false
22 |
23 |
--------------------------------------------------------------------------------
/tools/proxy-dependency-maven-plugin/apiproxy/policies/Assign-Message-Remove-Suffix.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | Assign Message Remove Suffix
4 |
5 |
6 |
7 | target.copy.pathsuffix
8 | false
9 |
10 | true
11 |
12 |
--------------------------------------------------------------------------------
/tools/proxy-dependency-maven-plugin/apiproxy/policies/JSON-to-XML.xml:
--------------------------------------------------------------------------------
1 | @@JSON-to-XML.xml
--------------------------------------------------------------------------------
/tools/proxy-dependency-maven-plugin/apiproxy/policies/Script-External-Variables.xml:
--------------------------------------------------------------------------------
1 | @@Script-External-Variables.xml
--------------------------------------------------------------------------------
/tools/proxy-dependency-maven-plugin/apiproxy/policies/SimpleJavaCallout.xml.bak:
--------------------------------------------------------------------------------
1 |
2 |
3 | com.example.SimpleJavaCallout
4 | java://javaCallouts.jar
5 |
--------------------------------------------------------------------------------
/tools/proxy-dependency-maven-plugin/apiproxy/policies/XMLtoJSON-Common.xml:
--------------------------------------------------------------------------------
1 | @@XMLtoJSON-Common.xml
--------------------------------------------------------------------------------
/tools/proxy-dependency-maven-plugin/apiproxy/proxies/default.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 | @@EXAMPLE-STEP-COMMON-XML-TO-JSON-GIT-SUBMODULE-FRAGMENT#1
10 |
11 | (proxy.pathsuffix MatchesPath "/apigee/**") and (request.verb = "GET")
12 |
13 |
14 |
15 |
16 |
17 | @@EXAMPLE-STEP-COMMON-XML-TO-JSON-GIT-SUBMODULE-FRAGMENT#2
18 |
19 | (proxy.pathsuffix MatchesPath "/forecastweather_node/**") and (request.verb = "GET")
20 |
21 |
22 |
23 |
24 |
25 | @@EXAMPLE-STEP-COMMON-XML-TO-JSON-GIT-SUBMODULE-FRAGMENT#3
26 |
27 | (proxy.pathsuffix MatchesPath "/images/**") and (request.verb = "GET")
28 |
29 |
30 |
31 |
32 |
33 |
34 |
38 |
39 | (proxy.pathsuffix MatchesPath "/javacallout") and (request.verb = "GET")
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 | /weathergrunt
48 | default
49 | secure
50 |
51 |
52 | (proxy.pathsuffix MatchesPath "/apigee/**") and (request.verb = "GET")
53 | default
54 |
55 |
56 |
57 | node
58 |
59 |
60 |
61 |
62 |
63 |
--------------------------------------------------------------------------------
/tools/proxy-dependency-maven-plugin/apiproxy/resources/jsc/js_external_vars.js:
--------------------------------------------------------------------------------
1 | // jshint ignore: start
2 | /* jshint ignore:start */
3 |
4 | @@js_external_vars.js
--------------------------------------------------------------------------------
/tools/proxy-dependency-maven-plugin/apiproxy/resources/jsc/search-and-replace-example.js:
--------------------------------------------------------------------------------
1 | function testFunction(){
2 | 'use strict';
3 | var test = "VALUE TO BE REPLACED #1";
4 | return test;
5 | }
6 | //remove comment to see jshint triggering errors
7 | //var a = "test";
8 | /*if(1 === 1) {
9 | if(2 === 2) {
10 | if(3 === 3) {
11 | if(4 === 4) {
12 |
13 | }
14 | }
15 | }
16 |
17 | }*/
18 |
19 | testFunction();
--------------------------------------------------------------------------------
/tools/proxy-dependency-maven-plugin/apiproxy/resources/jsc/search-and-replace-example2.js:
--------------------------------------------------------------------------------
1 | function testFunction2(){
2 | 'use strict';
3 | var test2 = "VALUE TO BE REPLACED #2";
4 | return test2;
5 | }
6 |
7 | testFunction2();
--------------------------------------------------------------------------------
/tools/proxy-dependency-maven-plugin/apiproxy/targets/default.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 | Assign-Message-Remove-Suffix
10 |
11 |
12 |
13 |
14 |
15 | http://weather.yahooapis.com/forecastrss
16 |
17 |
18 |
19 |
20 |
21 |
--------------------------------------------------------------------------------
/tools/proxy-dependency-maven-plugin/apiproxy/targets/node.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | Node Target
4 |
5 |
6 |
7 | node://app.js
8 |
9 |
--------------------------------------------------------------------------------
/tools/proxy-dependency-maven-plugin/pom.xml:
--------------------------------------------------------------------------------
1 |
18 |
20 |
26 |
27 | 4.0.0
28 | apigee
29 | apigee-deploy-grunt-plugin-maven
30 | 1.0
31 | apigee-deploy-grunt-plugin-maven
32 | pom
33 |
34 |
35 |
36 | test
37 |
38 | testmyapi
39 | validate,update
40 | test
41 | test
42 | https://api.enterprise.apigee.com
43 | v1
44 | ${org}
45 | ${username}
46 | ${password}
47 | ${options}
48 |
49 |
50 |
51 |
52 |
53 |
54 | io.apigee.build-tools.enterprise4g
55 | proxy-dependency-maven-plugin
56 | 2.0.0
57 |
58 |
59 | prepare-package
60 |
61 | resolve
62 |
63 |
64 | ./apiproxyroot
65 |
66 | ../CommonProxy
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 | prod
77 |
78 | testmyapi
79 | validate,update
80 | test
81 | prod
82 | https://api.enterprise.apigee.com
83 | v1
84 | ${org}
85 | ${username}
86 | ${password}
87 | ${options}
88 |
89 |
90 |
91 |
92 |
93 |
94 | io.apigee.build-tools.enterprise4g
95 | proxy-dependency-maven-plugin
96 | 2.0.0
97 |
98 |
99 | prepare-package
100 |
101 | resolve
102 |
103 |
104 | ./apiproxyroot
105 |
106 | ../CommonProxy
107 |
108 |
109 |
110 |
111 |
112 |
113 |
114 |
115 |
116 |
117 |
--------------------------------------------------------------------------------