1 | # apigeelint
|
2 |
|
3 | [![Codacy Badge](https://api.codacy.com/project/badge/Grade/260964318a4e4e689cbd6d059472765e)](https://www.codacy.com/app/davidwallen/bundle-linter?utm_source=github.com&utm_medium=referral&utm_content=apigeecs/bundle-linter&utm_campaign=Badge_Grade)
|
4 |
|
5 | Static code analysis for Apigee proxy and sharedflow bundles to encourage API developers to use best practices and avoid anti-patterns.
|
6 |
|
7 | This utility is intended to capture the best practices knowledge from across Apigee including our Global Support Center team, Customer Success, Engineering, and our product team in a tool that will help developers create more scalable, performant, and stable API bundles using the Apigee DSL.
|
8 |
|
9 | ## Status
|
10 |
|
11 | At this point we are focused on plugin execution and modelling the various lintable assets including Bundles, Proxies, SharedFlows, Targets, Flows, Steps, and Policies.
|
12 |
|
13 | Plugins that test these abstractions are being developed concurrently.
|
14 |
|
15 | Reporters (the means to report out results), Ingesters (bundle loaders) are to be developed with Filesystem being the only supported means of loading a bundle and all reporting now going to console.
|
16 |
|
17 | ## Installation
|
18 |
|
19 | Install using npm
|
20 |
|
21 | ```
|
22 | npm install -g apigeelint
|
23 | ```
|
24 |
|
25 | ## Usage
|
26 |
|
27 | Help
|
28 | ```
|
29 | apigeelint -h
|
30 | Usage: apigeelint [options]
|
31 |
|
32 | Options:
|
33 | -V, --version output the version number
|
34 | -s, --path <path> Path of the proxies
|
35 | -f, --formatter [value] Specify formatters (default json.js)
|
36 | -w, --write [value] file path to write results
|
37 | -d, --destPath [value] Provide the host and path to upload linter results
|
38 | -e, --excluded [value] The comma separated list of tests to be excluded
|
39 | --maxWarnings [value] Number of warnings to trigger nonzero exit code - default: -1
|
40 | -u, --user [value] Apigee user account
|
41 | -p, --password [value] Apigee password
|
42 | -o, --organization [value] Apigee organization
|
43 | -x, --externalPluginsDirectory [value] Relative or full path to an external plugins directory
|
44 | -h, --help output usage information
|
45 | ```
|
46 | Example:
|
47 | ```
|
48 | apigeelint -s sampleProxy/ -f table.js
|
49 | ```
|
50 |
|
51 | Where `-s` points to the apiProxy source directory and `-f` is the output formatter desired.
|
52 |
|
53 | Possible formats are "json.js" (the default), "stylish.js", "compact.js", "codeframe.js", "html.js", "table.js", "unix.js", "visualstudio.js", "checkstyle.js", "jslint-xml.js", "junit.js" and "tap.js".
|
54 |
|
55 | Example Using External Plugins:
|
56 | ```
|
57 | apigeelint -x ./externalPlugins -e PO007 -s test/fixtures/resources/sampleProxy/24Solver/apiproxy -f table.js
|
58 | ```
|
59 | Where `-x` points to the directory containing externally developed plugins and `-e` excludes the builtin plugin from executing.
|
60 | This example uses the "externalPlugins" directory with a plugin for alternate policy naming conventions and effectively overrides the built in naming conventions plugin. The output will include the external plugin identifier `EX-PO007`.
|
61 |
|
62 |
|
63 | ## Does this tool just lint or does it also check style?
|
64 |
|
65 | This tool does both traditional linting (looking for problematic patterns) and style checking (enforcement of conventions). You can use it for both.
|
66 |
|
67 | ## Tests
|
68 |
|
69 | The `test` directory includes scripts to exercise a subset of rules. Overall linting can be tested with:
|
70 |
|
71 | ```
|
72 | apigeelint -s ./test/sampleProxy/24Solver/apiproxy/
|
73 | ```
|
74 |
|
75 | This sample includes many bad practices and as such generates a bit of noise.
|
76 |
|
77 | ## Contributing
|
78 |
|
79 | In lieu of a formal style guide, take care to maintain the existing coding style.
|
80 | Add unit tests for any new or changed functionality. Lint and test your code.
|
81 |
|
82 | ## Rules
|
83 |
|
84 | The list of rules is a work in progress and expected to increase over time. As product features change, rules will change as well. Linting and reporting will fall into one of the following broad categories:
|
85 |
|
86 | | Linter | Status | Code | Name | Description |
|
87 | | ------ | ------ | ---- | ---- | ----------- |
|
88 | | Bundle | | | | |
|
89 | | |:white_check_mark:| BN001 | Bundle folder structure correctness. This plugin ignores some files, like .DS\_store and any file ending in ~. | Bundles have a clear structure. |
|
90 | | |:white_check_mark:| BN002 | Extraneous files. | Ensure each folder contains appropriate resources in the bundle. |
|
91 | | |:white_check_mark:| BN003 | Cache Coherence | A bundle that includes cache reads should include cache writes with the same keys. |
|
92 | | |:white_medium_square:| BN004 | Unused variables. | Within a bundle variables created should be used in conditions, resource callouts, or policies. |
|
93 | | |:white_check_mark:| BN005 | Unattached policies. | Unattached policies are dead code and should be removed from production bundles. |
|
94 | | |:white_check_mark:| BN006 | Bundle size - policies. | Large bundles are a symptom of poor design. A high number of policies is predictive of an oversized bundle. |
|
95 | | |:white_check_mark:| BN007 | Bundle size - resource callouts. | Large bundles are a symptom of poor design. A high number of resource callouts is indicative of underutilizing out of the box Apigee policies. |
|
96 | | |:white_medium_square:| BN008 | IgnoreUnresolvedVariables and FaultRules | Use of IgnoreUnresolvedVariables without the use of FaultRules may lead to unexpected errors. |
|
97 | | |:white_check_mark:| BN009 | Statistics Collector - duplicate policies | Warn on duplicate policies when no conditions are present or conditions are duplicates. |
|
98 | | Proxy Definition | | | | |
|
99 | | |:white_medium_square:| PD001 | RouteRules to Targets | RouteRules should map to defined Targets |
|
100 | | |:white_check_mark:| PD002 | Unreachable Route Rules - defaults | Only one RouteRule should be present without a condition |
|
101 | | |:white_check_mark:| PD003 | Unreachable Route Rules | RouteRule without a condition should be last. |
|
102 | | |:white_check_mark:| PD004 | ProxyEndpoint name | ProxyEndpoint name should match basename of filename. |
|
103 | | Target Definition | | | | |
|
104 | | |:white_check_mark:| TD001 | Mgmt Server as Target | Discourage calls to the Management Server from a Proxy via target. |
|
105 | | |:white_check_mark:| TD002 | Use Target Servers | Encourage the use of target servers |
|
106 | | |:white_check_mark:| TD003 | TargetEndpoint name | TargetEndpoint name should match basename of filename. |
|
107 | | Flow | | | | |
|
108 | | |:white_check_mark:| FL001 | Unconditional Flows | Only one unconditional flow will get executed. Error if more than one was detected. |
|
109 | | Step | | | | |
|
110 | | |:white_check_mark:| ST001 | Empty Step | Empty steps clutter the bundle. |
|
111 | | |:white_check_mark:| ST002 | Step Structure | each Step should have at most one Name element, one Condition element, no others. |
|
112 | | Policy | | | | |
|
113 | | |:white_check_mark:| PO001 | JSON Threat Protection | A check for a body element must be performed before policy execution. |
|
114 | | |:white_check_mark:| PO002 | XML Threat Protection | A check for a body element must be performed before policy execution. |
|
115 | | |:white_check_mark:| PO003 | Extract Variables with JSONPayload | A check for a body element must be performed before policy execution. |
|
116 | | |:white_check_mark:| PO004 | Extract Variables with XMLPayload | A check for a body element must be performed before policy execution. |
|
117 | | |:white_check_mark:| PO005 | Extract Variables with FormParam | A check for a body element must be performed before policy execution. |
|
118 | | |:white_check_mark:| PO006 | Policy Name & filename agreement | Policy name attribute should coincide with the policy filename. |
|
119 | | |:white_check_mark:| PO007 | Policy Naming Conventions - type indication | It is recommended that the policy name use a prefix that indicates the policy type. |
|
120 | | |:white_check_mark:| PO008 | Policy DisplayName & DisplayName agreement | Check that the policy filename matches the display name of the policy. |
|
121 | | |:white_medium_square:| PO009 | Service Callout Target - Mgmt Server | Targeting management server may result in higher than expected latency use with caution. |
|
122 | | |:white_medium_square:| PO010 | Service Callout Target - Target Server | Encourage use of target servers. |
|
123 | | |:white_medium_square:| PO011 | Service Callout Target - Dynamic URLs | Error on dynamic URLs in target server URL tag. |
|
124 | | |:white_medium_square:| PO012 | Service Callout Target - Script Target Node | JSHint, ESLint. |
|
125 | | |:white_check_mark:| PO013 | Resource Call Out - Javascript | JSHint, ESLint. |
|
126 | | |:white_medium_square:| PO014 | Resource Call Out - Java | PMD, Checkstyle. |
|
127 | | |:white_medium_square:| PO015 | Resource Call Out - Python | Pylint. |
|
128 | | |:white_medium_square:| PO016 | Statistics Collector - duplicate variables | Warn on duplicate variables. |
|
129 | | |:white_medium_square:| PO017 | Misconfigured - FaultRules/Fault Rule in Policy | FaultRules are configured in ProxyEndpoints and TargetEndpoints. |
|
130 | | |:white_check_mark:| PO018 | Regex Lookahead/Lookbehind are Expensive - Threat Protection Policy | Regular expressions that include lookahead or lookbehind perform slowly on large payloads and are typically not required.|
|
131 | | |:white_check_mark:| PO019 | Reserved words as variables - ServiceCallout Request | Using "request" as the name of a Request may cause unexpected side effects.|
|
132 | | |:white_check_mark:| PO020 | Reserved words as variables - ServiceCallout Response | Using "response" as the name of a Response may cause unexpected side effects.|
|
133 | | |:white_medium_square:| PO021 | Statistics Collector - reserved variables | Warn on insertion of duplicate variables. |
|
134 | | |:white_check_mark:| PO022 | Nondistributed Quota | When using nondistributed quota the number of allowed calls is influenced by the number of Message Processors (MPs) deployed. This may lead to higher than expected transactions for a given quota as MPs now autoscale. |
|
135 | | |:white_check_mark:| PO023 | Quota Policy Reuse | When the same Quota policy is used more than once you must ensure that the conditions of execution are mutually exclusive or that you intend for a call to count more than once per message processed. |
|
136 | | |:white_check_mark:| PO024 | Cache Error Responses | By default the ResponseCache policy will cache non 200 responses. Either create a condition or use policy configuration options to exclude non 200 responses. |
|
137 | | |:white_check_mark:| PO025 | EsLint Errors | Runs EsLint on all policy resources. |
|
138 | | |:white_check_mark:| PO026 | AssignVariable Usage | With AssignMessage/AssignVariable, check various usage issues. Example: The Name element must be present. The Ref element, if any, should not be surrounded in curlies. And so on. |
|
139 | | |:white_check_mark:| PO027 | HMAC Usage | With HMAC, check that the SecretKey is present and that a ref= attribute refers to a private variable. |
|
140 | | FaultRules | | | | |
|
141 | | |:white_check_mark:| FR001 | No Condition on FaultRule | It's not a best practice to have a FaultRule without an outer condition, which automatically makes the FaultRule true. |
|
142 | | |:white_check_mark:| FR002 | DefaultFaultRule Structure | DefaultFaultRule should have only supported child elements, at most one AlwaysEnforce element, and at most one Condition element. |
|
143 | | Conditional | | | | |
|
144 | | |:white_check_mark:| CC001 | Literals in Conditionals | Warn on literals in any conditional statement. |
|
145 | | |:white_medium_square:| CC002 | Null Blank Checks | Blank checks should also check for null conditions. (to be reviewed) |
|
146 | | |:white_check_mark:| CC003 | Long condition statement | Conditions should not be long. |
|
147 | | |:white_check_mark:| CC004 | Overly complex condition | Condition complexity should be limited to fix number of variables and conjunctions. |
|
148 | | |:white_check_mark:| CC006 | Detect logical absurdities | Conditions should not have internal logic conflicts - warn when these are detected. |
|
149 |
|
150 | From an implementation perspective the focus is on plugin support and flexibility over performance. Compute is cheap.
|
151 |
|
152 |
|
153 | ## Disclaimer
|
154 | This is not an officially supported Google product.
|