kong-deck-tools 0.1.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2025 Michael Tan
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,144 @@
1
+ Metadata-Version: 2.4
2
+ Name: kong-deck-tools
3
+ Version: 0.1.0
4
+ Summary: Kong API Gateway configuration tools for certificate management and cross-environment comparison
5
+ Author: Michael Tan
6
+ License: MIT
7
+ Project-URL: Homepage, https://github.com/michaeltan/kong-deck-tools
8
+ Project-URL: Repository, https://github.com/michaeltan/kong-deck-tools
9
+ Keywords: kong,api-gateway,deck,configuration,certificates
10
+ Classifier: Development Status :: 4 - Beta
11
+ Classifier: Environment :: Console
12
+ Classifier: Intended Audience :: Developers
13
+ Classifier: Intended Audience :: System Administrators
14
+ Classifier: License :: OSI Approved :: MIT License
15
+ Classifier: Operating System :: OS Independent
16
+ Classifier: Programming Language :: Python :: 3
17
+ Classifier: Programming Language :: Python :: 3.8
18
+ Classifier: Programming Language :: Python :: 3.9
19
+ Classifier: Programming Language :: Python :: 3.10
20
+ Classifier: Programming Language :: Python :: 3.11
21
+ Classifier: Programming Language :: Python :: 3.12
22
+ Classifier: Topic :: System :: Systems Administration
23
+ Classifier: Topic :: Utilities
24
+ Requires-Python: >=3.8
25
+ Description-Content-Type: text/markdown
26
+ License-File: LICENSE
27
+ Requires-Dist: ruamel.yaml>=0.18.0
28
+ Dynamic: license-file
29
+
30
+ # kong-deck-tools
31
+
32
+ Kong API Gateway configuration tools for certificate management and cross-environment comparison.
33
+
34
+ ## Overview
35
+
36
+ This package provides CLI tools for managing Kong API Gateway configurations:
37
+
38
+ 1. **Extract certificates** from Kong configurations into separate files, allowing templates to be safely committed to git while keeping sensitive certificate data separate
39
+ 2. **Enforce consistent key ordering** across all configurations, making it easy to compare configurations across different environments (local, staging, production)
40
+
41
+ ## Installation
42
+
43
+ ```bash
44
+ pip install kong-deck-tools
45
+ ```
46
+
47
+ ## Usage
48
+
49
+ ### kong-templatize
50
+
51
+ Splits a Kong configuration into a template and a certificate values file:
52
+
53
+ ```bash
54
+ kong-templatize config.yaml
55
+ ```
56
+
57
+ **Input:** `config.yaml` (full Kong configuration with certificates)
58
+
59
+ **Output:**
60
+ - `config.tmpl.yaml` - Template with Helm-style placeholders for certificates
61
+ - `config.certs.values.yaml` - Extracted certificate values (name, cert, key)
62
+
63
+ The script also prettifies the template by reordering YAML keys for consistency and readability.
64
+
65
+ ### kong-hydrate
66
+
67
+ Reconstructs a full Kong configuration from template and values:
68
+
69
+ ```bash
70
+ kong-hydrate config.tmpl.yaml
71
+ ```
72
+
73
+ **Input:** `config.tmpl.yaml` (template file; values file `config.certs.values.yaml` is derived automatically)
74
+
75
+ **Output:** `config.rendered.yaml` (complete Kong configuration)
76
+
77
+ ## Workflow with Kong deck
78
+
79
+ ```bash
80
+ # 1. Export current Kong configuration
81
+ deck gateway dump -o config.yaml
82
+
83
+ # 2. Extract certificates and create template
84
+ kong-templatize config.yaml
85
+
86
+ # 3. Commit template to git (certificates stay separate)
87
+ git add config.tmpl.yaml
88
+ git commit -m "Update Kong configuration"
89
+
90
+ # 4. Before deploying, hydrate the template with certificates
91
+ kong-hydrate config.tmpl.yaml
92
+
93
+ # 5. Compare with current Kong state
94
+ deck gateway diff config.rendered.yaml
95
+
96
+ # 6. Apply changes
97
+ deck gateway sync config.rendered.yaml
98
+ ```
99
+
100
+ ## Key Ordering
101
+
102
+ The `kong-templatize` command enforces consistent key ordering to make configs:
103
+ - **Human-readable**: Important fields (name, enabled) appear first
104
+ - **Diff-friendly**: Consistent ordering reduces noise in git diffs
105
+ - **Hierarchical**: Configuration objects (routes, plugins) appear after their properties
106
+
107
+ Key ordering by entity type:
108
+ - **Plugins**: name -> enabled -> config -> protocols -> tags
109
+ - **Services**: name -> enabled -> host -> port -> protocol -> timeouts -> tags -> plugins -> routes
110
+ - **Routes**: name -> hosts -> paths -> protocols -> strip_path -> preserve_host -> ... -> plugins
111
+ - **Upstreams**: name -> algorithm -> slots -> hash_* -> tags -> healthchecks -> targets
112
+ - **Consumers**: username -> custom_id -> tags
113
+
114
+ ## Requirements
115
+
116
+ - Python 3.8+
117
+ - Kong deck CLI (for dumping/syncing configurations)
118
+
119
+ ## Development
120
+
121
+ ### Install in development mode
122
+
123
+ ```bash
124
+ git clone https://github.com/michaeltan/kong-deck-tools.git
125
+ cd kong-deck-tools
126
+ pip install -e .
127
+ ```
128
+
129
+ ### Publishing to PyPI
130
+
131
+ ```bash
132
+ # Install uv (if not already installed)
133
+ brew install uv
134
+
135
+ # Build the package
136
+ uv build
137
+
138
+ # Upload to PyPI
139
+ uv publish
140
+ ```
141
+
142
+ ## License
143
+
144
+ MIT
@@ -0,0 +1,115 @@
1
+ # kong-deck-tools
2
+
3
+ Kong API Gateway configuration tools for certificate management and cross-environment comparison.
4
+
5
+ ## Overview
6
+
7
+ This package provides CLI tools for managing Kong API Gateway configurations:
8
+
9
+ 1. **Extract certificates** from Kong configurations into separate files, allowing templates to be safely committed to git while keeping sensitive certificate data separate
10
+ 2. **Enforce consistent key ordering** across all configurations, making it easy to compare configurations across different environments (local, staging, production)
11
+
12
+ ## Installation
13
+
14
+ ```bash
15
+ pip install kong-deck-tools
16
+ ```
17
+
18
+ ## Usage
19
+
20
+ ### kong-templatize
21
+
22
+ Splits a Kong configuration into a template and a certificate values file:
23
+
24
+ ```bash
25
+ kong-templatize config.yaml
26
+ ```
27
+
28
+ **Input:** `config.yaml` (full Kong configuration with certificates)
29
+
30
+ **Output:**
31
+ - `config.tmpl.yaml` - Template with Helm-style placeholders for certificates
32
+ - `config.certs.values.yaml` - Extracted certificate values (name, cert, key)
33
+
34
+ The script also prettifies the template by reordering YAML keys for consistency and readability.
35
+
36
+ ### kong-hydrate
37
+
38
+ Reconstructs a full Kong configuration from template and values:
39
+
40
+ ```bash
41
+ kong-hydrate config.tmpl.yaml
42
+ ```
43
+
44
+ **Input:** `config.tmpl.yaml` (template file; values file `config.certs.values.yaml` is derived automatically)
45
+
46
+ **Output:** `config.rendered.yaml` (complete Kong configuration)
47
+
48
+ ## Workflow with Kong deck
49
+
50
+ ```bash
51
+ # 1. Export current Kong configuration
52
+ deck gateway dump -o config.yaml
53
+
54
+ # 2. Extract certificates and create template
55
+ kong-templatize config.yaml
56
+
57
+ # 3. Commit template to git (certificates stay separate)
58
+ git add config.tmpl.yaml
59
+ git commit -m "Update Kong configuration"
60
+
61
+ # 4. Before deploying, hydrate the template with certificates
62
+ kong-hydrate config.tmpl.yaml
63
+
64
+ # 5. Compare with current Kong state
65
+ deck gateway diff config.rendered.yaml
66
+
67
+ # 6. Apply changes
68
+ deck gateway sync config.rendered.yaml
69
+ ```
70
+
71
+ ## Key Ordering
72
+
73
+ The `kong-templatize` command enforces consistent key ordering to make configs:
74
+ - **Human-readable**: Important fields (name, enabled) appear first
75
+ - **Diff-friendly**: Consistent ordering reduces noise in git diffs
76
+ - **Hierarchical**: Configuration objects (routes, plugins) appear after their properties
77
+
78
+ Key ordering by entity type:
79
+ - **Plugins**: name -> enabled -> config -> protocols -> tags
80
+ - **Services**: name -> enabled -> host -> port -> protocol -> timeouts -> tags -> plugins -> routes
81
+ - **Routes**: name -> hosts -> paths -> protocols -> strip_path -> preserve_host -> ... -> plugins
82
+ - **Upstreams**: name -> algorithm -> slots -> hash_* -> tags -> healthchecks -> targets
83
+ - **Consumers**: username -> custom_id -> tags
84
+
85
+ ## Requirements
86
+
87
+ - Python 3.8+
88
+ - Kong deck CLI (for dumping/syncing configurations)
89
+
90
+ ## Development
91
+
92
+ ### Install in development mode
93
+
94
+ ```bash
95
+ git clone https://github.com/michaeltan/kong-deck-tools.git
96
+ cd kong-deck-tools
97
+ pip install -e .
98
+ ```
99
+
100
+ ### Publishing to PyPI
101
+
102
+ ```bash
103
+ # Install uv (if not already installed)
104
+ brew install uv
105
+
106
+ # Build the package
107
+ uv build
108
+
109
+ # Upload to PyPI
110
+ uv publish
111
+ ```
112
+
113
+ ## License
114
+
115
+ MIT
@@ -0,0 +1,45 @@
1
+ [build-system]
2
+ requires = ["setuptools>=61.0", "wheel"]
3
+ build-backend = "setuptools.build_meta"
4
+
5
+ [project]
6
+ name = "kong-deck-tools"
7
+ version = "0.1.0"
8
+ description = "Kong API Gateway configuration tools for certificate management and cross-environment comparison"
9
+ readme = "README.md"
10
+ license = {text = "MIT"}
11
+ requires-python = ">=3.8"
12
+ authors = [
13
+ {name = "Michael Tan"}
14
+ ]
15
+ keywords = ["kong", "api-gateway", "deck", "configuration", "certificates"]
16
+ classifiers = [
17
+ "Development Status :: 4 - Beta",
18
+ "Environment :: Console",
19
+ "Intended Audience :: Developers",
20
+ "Intended Audience :: System Administrators",
21
+ "License :: OSI Approved :: MIT License",
22
+ "Operating System :: OS Independent",
23
+ "Programming Language :: Python :: 3",
24
+ "Programming Language :: Python :: 3.8",
25
+ "Programming Language :: Python :: 3.9",
26
+ "Programming Language :: Python :: 3.10",
27
+ "Programming Language :: Python :: 3.11",
28
+ "Programming Language :: Python :: 3.12",
29
+ "Topic :: System :: Systems Administration",
30
+ "Topic :: Utilities",
31
+ ]
32
+ dependencies = [
33
+ "ruamel.yaml>=0.18.0",
34
+ ]
35
+
36
+ [project.urls]
37
+ Homepage = "https://github.com/michaeltan/kong-deck-tools"
38
+ Repository = "https://github.com/michaeltan/kong-deck-tools"
39
+
40
+ [project.scripts]
41
+ kong-templatize = "kong_deck_tools.templatize:main"
42
+ kong-hydrate = "kong_deck_tools.hydrate:main"
43
+
44
+ [tool.setuptools.packages.find]
45
+ where = ["src"]
@@ -0,0 +1,4 @@
1
+ [egg_info]
2
+ tag_build =
3
+ tag_date = 0
4
+
@@ -0,0 +1,8 @@
1
+ """
2
+ kong-deck-tools: Kong API Gateway configuration management tools.
3
+
4
+ Tools for managing Kong configurations by extracting certificates into separate
5
+ files and enforcing consistent key ordering for easy cross-environment comparison.
6
+ """
7
+
8
+ __version__ = "0.1.0"
@@ -0,0 +1,135 @@
1
+ #!/usr/bin/env python3
2
+ """
3
+ hydrate.py
4
+ Renders a Kong template file by substituting certificate values from values file.
5
+ This reverses the templatize operation.
6
+
7
+ Usage: kong-hydrate <template_file>
8
+ Example: kong-hydrate config.tmpl.yaml
9
+
10
+ Uses ruamel.yaml for format preservation to ensure lossless round-trips.
11
+ """
12
+
13
+ import re
14
+ import sys
15
+ from io import StringIO
16
+ from pathlib import Path
17
+ from ruamel.yaml import YAML
18
+
19
+
20
+ def load_certificate_values(file_path):
21
+ """Load certificate values from values file."""
22
+ with open(file_path, 'r') as f:
23
+ content = f.read()
24
+
25
+ # Split by 'name:' but keep the delimiter
26
+ parts = re.split(r'(?=^name: )', content, flags=re.MULTILINE)
27
+
28
+ yaml = YAML()
29
+ yaml.preserve_quotes = True
30
+
31
+ certs = []
32
+ for part in parts:
33
+ part = part.strip()
34
+ if part:
35
+ try:
36
+ cert_doc = yaml.load(StringIO(part))
37
+ if cert_doc and 'name' in cert_doc:
38
+ certs.append(cert_doc)
39
+ except Exception:
40
+ pass
41
+
42
+ return certs
43
+
44
+
45
+ def load_yaml(file_path):
46
+ """Load a single YAML document with format preservation."""
47
+ yaml = YAML()
48
+ yaml.preserve_quotes = True
49
+ yaml.default_flow_style = False
50
+
51
+ with open(file_path, 'r') as f:
52
+ return yaml.load(f)
53
+
54
+
55
+ def main():
56
+ if len(sys.argv) < 2:
57
+ print("Usage: kong-hydrate <template_file>")
58
+ print("Example: kong-hydrate config.tmpl.yaml")
59
+ sys.exit(1)
60
+
61
+ template_file = sys.argv[1]
62
+
63
+ # Validate input file exists
64
+ if not Path(template_file).exists():
65
+ print(f"Error: Template file '{template_file}' not found")
66
+ sys.exit(1)
67
+
68
+ # Derive basename by stripping .tmpl.yaml or .tmpl.yml extension
69
+ basename = template_file
70
+ for ext in ['.tmpl.yaml', '.tmpl.yml']:
71
+ if basename.endswith(ext):
72
+ basename = basename[:-len(ext)]
73
+ break
74
+
75
+ values_file = f"{basename}.certs.values.yaml"
76
+ output_file = f"{basename}.rendered.yaml"
77
+
78
+ if not Path(values_file).exists():
79
+ print(f"Error: Values file '{values_file}' not found")
80
+ sys.exit(1)
81
+
82
+ print("Rendering Kong configuration...")
83
+ print(f" Template: {template_file}")
84
+ print(f" Values: {values_file}")
85
+ print("")
86
+
87
+ # Load template
88
+ template = load_yaml(template_file)
89
+
90
+ # Load certificate values
91
+ cert_values = load_certificate_values(values_file)
92
+
93
+ # Create a mapping of SNI name to certificate data
94
+ cert_map = {}
95
+ for cert_doc in cert_values:
96
+ if cert_doc and 'name' in cert_doc:
97
+ cert_map[cert_doc['name']] = {
98
+ 'cert': cert_doc.get('cert', ''),
99
+ 'key': cert_doc.get('key', '')
100
+ }
101
+
102
+ # Substitute certificates in template
103
+ if 'certificates' in template:
104
+ for cert in template['certificates']:
105
+ if 'snis' in cert and len(cert['snis']) > 0:
106
+ sni_name = cert['snis'][0]['name']
107
+ if sni_name in cert_map:
108
+ print(f" Substituting certificate for: {sni_name}")
109
+ cert_value = cert_map[sni_name]['cert']
110
+ key_value = cert_map[sni_name]['key']
111
+
112
+ # Ensure keys end with newline to match Kong's format
113
+ if not key_value.endswith('\n'):
114
+ key_value = key_value + '\n'
115
+
116
+ cert['cert'] = cert_value
117
+ cert['key'] = key_value
118
+
119
+ # Write rendered output with format preservation
120
+ yaml = YAML()
121
+ yaml.preserve_quotes = True
122
+ yaml.default_flow_style = False
123
+ yaml.width = 4096 # Prevent line wrapping
124
+
125
+ with open(output_file, 'w') as f:
126
+ yaml.dump(template, f)
127
+
128
+ print("")
129
+ print("Configuration rendered successfully!")
130
+ print(f" Output: {output_file}")
131
+ print("")
132
+
133
+
134
+ if __name__ == '__main__':
135
+ main()
@@ -0,0 +1,236 @@
1
+ #!/usr/bin/env python3
2
+ """
3
+ templatize.py
4
+ Splits Kong configuration into template and values files, then prettifies.
5
+ This creates diff-friendly, Helm-ready configuration files.
6
+
7
+ Usage: kong-templatize <config_file>
8
+ Example: kong-templatize config.yaml
9
+ """
10
+
11
+ import sys
12
+ from pathlib import Path
13
+ from ruamel.yaml import YAML
14
+ from ruamel.yaml.comments import CommentedMap
15
+
16
+
17
+ # Key ordering definitions for each entity type
18
+ PLUGIN_KEY_ORDER = ['name', 'enabled', 'config', 'protocols', 'tags']
19
+ SERVICE_KEY_ORDER = ['name', 'enabled', 'host', 'port', 'protocol',
20
+ 'connect_timeout', 'read_timeout', 'write_timeout',
21
+ 'retries', 'tags']
22
+ SERVICE_TRAILING_KEYS = ['plugins', 'routes']
23
+ ROUTE_KEY_ORDER = ['name', 'hosts', 'paths', 'protocols', 'strip_path',
24
+ 'preserve_host', 'https_redirect_status_code', 'path_handling',
25
+ 'regex_priority', 'request_buffering', 'response_buffering', 'tags']
26
+ ROUTE_TRAILING_KEYS = ['plugins']
27
+ UPSTREAM_KEY_ORDER = ['name', 'algorithm', 'slots', 'hash_on', 'hash_fallback',
28
+ 'hash_on_cookie_path', 'use_srv_name', 'tags']
29
+ UPSTREAM_TRAILING_KEYS = ['healthchecks', 'targets']
30
+ TARGET_KEY_ORDER = ['target', 'weight', 'tags']
31
+ CONSUMER_KEY_ORDER = ['username', 'custom_id', 'tags']
32
+
33
+
34
+ def reorder_keys(obj, key_order, trailing_keys=None):
35
+ """Reorder keys in a CommentedMap according to specified order."""
36
+ if not isinstance(obj, dict):
37
+ return obj
38
+
39
+ trailing_keys = trailing_keys or []
40
+ ordered = CommentedMap()
41
+
42
+ # First, add keys in specified order
43
+ for key in key_order:
44
+ if key in obj:
45
+ ordered[key] = obj[key]
46
+
47
+ # Then add remaining keys (except trailing ones)
48
+ all_specified = set(key_order) | set(trailing_keys)
49
+ for key in obj:
50
+ if key not in all_specified:
51
+ ordered[key] = obj[key]
52
+
53
+ # Finally add trailing keys
54
+ for key in trailing_keys:
55
+ if key in obj:
56
+ ordered[key] = obj[key]
57
+
58
+ return ordered
59
+
60
+
61
+ def reorder_plugins(plugins):
62
+ """Reorder keys in plugin configurations."""
63
+ if not plugins:
64
+ return plugins
65
+ return [reorder_keys(p, PLUGIN_KEY_ORDER) for p in plugins]
66
+
67
+
68
+ def reorder_routes(routes):
69
+ """Reorder keys in route configurations."""
70
+ if not routes:
71
+ return routes
72
+ result = []
73
+ for route in routes:
74
+ ordered = reorder_keys(route, ROUTE_KEY_ORDER, ROUTE_TRAILING_KEYS)
75
+ if 'plugins' in ordered:
76
+ ordered['plugins'] = reorder_plugins(ordered['plugins'])
77
+ result.append(ordered)
78
+ return result
79
+
80
+
81
+ def reorder_services(services):
82
+ """Reorder keys in service configurations."""
83
+ if not services:
84
+ return services
85
+ result = []
86
+ for service in services:
87
+ ordered = reorder_keys(service, SERVICE_KEY_ORDER, SERVICE_TRAILING_KEYS)
88
+ if 'plugins' in ordered:
89
+ ordered['plugins'] = reorder_plugins(ordered['plugins'])
90
+ if 'routes' in ordered:
91
+ ordered['routes'] = reorder_routes(ordered['routes'])
92
+ result.append(ordered)
93
+ return result
94
+
95
+
96
+ def reorder_targets(targets):
97
+ """Reorder keys in target configurations."""
98
+ if not targets:
99
+ return targets
100
+ return [reorder_keys(t, TARGET_KEY_ORDER) for t in targets]
101
+
102
+
103
+ def reorder_upstreams(upstreams):
104
+ """Reorder keys in upstream configurations."""
105
+ if not upstreams:
106
+ return upstreams
107
+ result = []
108
+ for upstream in upstreams:
109
+ ordered = reorder_keys(upstream, UPSTREAM_KEY_ORDER, UPSTREAM_TRAILING_KEYS)
110
+ if 'targets' in ordered:
111
+ ordered['targets'] = reorder_targets(ordered['targets'])
112
+ result.append(ordered)
113
+ return result
114
+
115
+
116
+ def reorder_consumers(consumers):
117
+ """Reorder keys in consumer configurations."""
118
+ if not consumers:
119
+ return consumers
120
+ return [reorder_keys(c, CONSUMER_KEY_ORDER) for c in consumers]
121
+
122
+
123
+ def prettify_config(config):
124
+ """Prettify the entire configuration by reordering keys."""
125
+ if 'plugins' in config:
126
+ config['plugins'] = reorder_plugins(config['plugins'])
127
+ if 'services' in config:
128
+ config['services'] = reorder_services(config['services'])
129
+ if 'upstreams' in config:
130
+ config['upstreams'] = reorder_upstreams(config['upstreams'])
131
+ if 'consumers' in config:
132
+ config['consumers'] = reorder_consumers(config['consumers'])
133
+ return config
134
+
135
+
136
+ def extract_certificates(config):
137
+ """Extract certificates from config into a list of certificate values."""
138
+ certs = []
139
+ if 'certificates' in config and config['certificates']:
140
+ for cert in config['certificates']:
141
+ if 'snis' in cert and cert['snis']:
142
+ cert_entry = CommentedMap()
143
+ cert_entry['name'] = cert['snis'][0]['name']
144
+ cert_entry['cert'] = cert.get('cert', '')
145
+ cert_entry['key'] = cert.get('key', '')
146
+ certs.append(cert_entry)
147
+ return certs
148
+
149
+
150
+ def create_template(config):
151
+ """Create template by replacing certificate values with Helm placeholders."""
152
+ if 'certificates' in config and config['certificates']:
153
+ for cert in config['certificates']:
154
+ cert['cert'] = "{{ .Values.certificates[.snis[0].name].cert }}"
155
+ cert['key'] = "{{ .Values.certificates[.snis[0].name].key }}"
156
+ return config
157
+
158
+
159
+ def main():
160
+ if len(sys.argv) < 2:
161
+ print("Usage: kong-templatize <config_file>")
162
+ print("Example: kong-templatize config.yaml")
163
+ sys.exit(1)
164
+
165
+ input_file = sys.argv[1]
166
+
167
+ # Validate input file exists
168
+ input_path = Path(input_file)
169
+ if not input_path.exists():
170
+ print(f"Error: Input file '{input_file}' not found")
171
+ sys.exit(1)
172
+
173
+ # Extract basename (remove .yaml or .yml extension)
174
+ basename = input_file
175
+ for ext in ['.yaml', '.yml']:
176
+ if basename.endswith(ext):
177
+ basename = basename[:-len(ext)]
178
+ break
179
+
180
+ # Define output files
181
+ template_file = f"{basename}.tmpl.yaml"
182
+ values_file = f"{basename}.certs.values.yaml"
183
+
184
+ print(f"Processing Kong configuration: {input_file}")
185
+ print("")
186
+
187
+ # Initialize YAML parser
188
+ yaml = YAML()
189
+ yaml.preserve_quotes = True
190
+ yaml.default_flow_style = False
191
+ yaml.width = 4096 # Prevent line wrapping
192
+
193
+ # Load input configuration
194
+ with open(input_file, 'r') as f:
195
+ config = yaml.load(f)
196
+
197
+ # Step 1: Extract certificates to values file
198
+ print("Extracting certificates to values file...")
199
+ certs = extract_certificates(config)
200
+
201
+ if certs:
202
+ with open(values_file, 'w') as f:
203
+ for cert in certs:
204
+ yaml.dump(cert, f)
205
+ print(f" Certificates extracted to: {values_file}")
206
+ else:
207
+ print(" No certificates found or extraction failed")
208
+ # Create empty values file
209
+ with open(values_file, 'w') as f:
210
+ pass
211
+
212
+ # Step 2: Create template with Helm placeholders
213
+ print("Creating template with Helm placeholders...")
214
+ template = create_template(config)
215
+ print(f" Template created: {template_file}")
216
+ print("")
217
+
218
+ # Step 3: Prettify the template file with key reordering
219
+ print("Prettifying template structure...")
220
+ template = prettify_config(template)
221
+
222
+ # Write template file
223
+ with open(template_file, 'w') as f:
224
+ yaml.dump(template, f)
225
+
226
+ print("")
227
+ print("Kong configuration processed successfully!")
228
+ print("")
229
+ print("Files created:")
230
+ print(f" Template: {template_file}")
231
+ print(f" Values: {values_file}")
232
+ print("")
233
+
234
+
235
+ if __name__ == '__main__':
236
+ main()
@@ -0,0 +1,144 @@
1
+ Metadata-Version: 2.4
2
+ Name: kong-deck-tools
3
+ Version: 0.1.0
4
+ Summary: Kong API Gateway configuration tools for certificate management and cross-environment comparison
5
+ Author: Michael Tan
6
+ License: MIT
7
+ Project-URL: Homepage, https://github.com/michaeltan/kong-deck-tools
8
+ Project-URL: Repository, https://github.com/michaeltan/kong-deck-tools
9
+ Keywords: kong,api-gateway,deck,configuration,certificates
10
+ Classifier: Development Status :: 4 - Beta
11
+ Classifier: Environment :: Console
12
+ Classifier: Intended Audience :: Developers
13
+ Classifier: Intended Audience :: System Administrators
14
+ Classifier: License :: OSI Approved :: MIT License
15
+ Classifier: Operating System :: OS Independent
16
+ Classifier: Programming Language :: Python :: 3
17
+ Classifier: Programming Language :: Python :: 3.8
18
+ Classifier: Programming Language :: Python :: 3.9
19
+ Classifier: Programming Language :: Python :: 3.10
20
+ Classifier: Programming Language :: Python :: 3.11
21
+ Classifier: Programming Language :: Python :: 3.12
22
+ Classifier: Topic :: System :: Systems Administration
23
+ Classifier: Topic :: Utilities
24
+ Requires-Python: >=3.8
25
+ Description-Content-Type: text/markdown
26
+ License-File: LICENSE
27
+ Requires-Dist: ruamel.yaml>=0.18.0
28
+ Dynamic: license-file
29
+
30
+ # kong-deck-tools
31
+
32
+ Kong API Gateway configuration tools for certificate management and cross-environment comparison.
33
+
34
+ ## Overview
35
+
36
+ This package provides CLI tools for managing Kong API Gateway configurations:
37
+
38
+ 1. **Extract certificates** from Kong configurations into separate files, allowing templates to be safely committed to git while keeping sensitive certificate data separate
39
+ 2. **Enforce consistent key ordering** across all configurations, making it easy to compare configurations across different environments (local, staging, production)
40
+
41
+ ## Installation
42
+
43
+ ```bash
44
+ pip install kong-deck-tools
45
+ ```
46
+
47
+ ## Usage
48
+
49
+ ### kong-templatize
50
+
51
+ Splits a Kong configuration into a template and a certificate values file:
52
+
53
+ ```bash
54
+ kong-templatize config.yaml
55
+ ```
56
+
57
+ **Input:** `config.yaml` (full Kong configuration with certificates)
58
+
59
+ **Output:**
60
+ - `config.tmpl.yaml` - Template with Helm-style placeholders for certificates
61
+ - `config.certs.values.yaml` - Extracted certificate values (name, cert, key)
62
+
63
+ The script also prettifies the template by reordering YAML keys for consistency and readability.
64
+
65
+ ### kong-hydrate
66
+
67
+ Reconstructs a full Kong configuration from template and values:
68
+
69
+ ```bash
70
+ kong-hydrate config.tmpl.yaml
71
+ ```
72
+
73
+ **Input:** `config.tmpl.yaml` (template file; values file `config.certs.values.yaml` is derived automatically)
74
+
75
+ **Output:** `config.rendered.yaml` (complete Kong configuration)
76
+
77
+ ## Workflow with Kong deck
78
+
79
+ ```bash
80
+ # 1. Export current Kong configuration
81
+ deck gateway dump -o config.yaml
82
+
83
+ # 2. Extract certificates and create template
84
+ kong-templatize config.yaml
85
+
86
+ # 3. Commit template to git (certificates stay separate)
87
+ git add config.tmpl.yaml
88
+ git commit -m "Update Kong configuration"
89
+
90
+ # 4. Before deploying, hydrate the template with certificates
91
+ kong-hydrate config.tmpl.yaml
92
+
93
+ # 5. Compare with current Kong state
94
+ deck gateway diff config.rendered.yaml
95
+
96
+ # 6. Apply changes
97
+ deck gateway sync config.rendered.yaml
98
+ ```
99
+
100
+ ## Key Ordering
101
+
102
+ The `kong-templatize` command enforces consistent key ordering to make configs:
103
+ - **Human-readable**: Important fields (name, enabled) appear first
104
+ - **Diff-friendly**: Consistent ordering reduces noise in git diffs
105
+ - **Hierarchical**: Configuration objects (routes, plugins) appear after their properties
106
+
107
+ Key ordering by entity type:
108
+ - **Plugins**: name -> enabled -> config -> protocols -> tags
109
+ - **Services**: name -> enabled -> host -> port -> protocol -> timeouts -> tags -> plugins -> routes
110
+ - **Routes**: name -> hosts -> paths -> protocols -> strip_path -> preserve_host -> ... -> plugins
111
+ - **Upstreams**: name -> algorithm -> slots -> hash_* -> tags -> healthchecks -> targets
112
+ - **Consumers**: username -> custom_id -> tags
113
+
114
+ ## Requirements
115
+
116
+ - Python 3.8+
117
+ - Kong deck CLI (for dumping/syncing configurations)
118
+
119
+ ## Development
120
+
121
+ ### Install in development mode
122
+
123
+ ```bash
124
+ git clone https://github.com/michaeltan/kong-deck-tools.git
125
+ cd kong-deck-tools
126
+ pip install -e .
127
+ ```
128
+
129
+ ### Publishing to PyPI
130
+
131
+ ```bash
132
+ # Install uv (if not already installed)
133
+ brew install uv
134
+
135
+ # Build the package
136
+ uv build
137
+
138
+ # Upload to PyPI
139
+ uv publish
140
+ ```
141
+
142
+ ## License
143
+
144
+ MIT
@@ -0,0 +1,12 @@
1
+ LICENSE
2
+ README.md
3
+ pyproject.toml
4
+ src/kong_deck_tools/__init__.py
5
+ src/kong_deck_tools/hydrate.py
6
+ src/kong_deck_tools/templatize.py
7
+ src/kong_deck_tools.egg-info/PKG-INFO
8
+ src/kong_deck_tools.egg-info/SOURCES.txt
9
+ src/kong_deck_tools.egg-info/dependency_links.txt
10
+ src/kong_deck_tools.egg-info/entry_points.txt
11
+ src/kong_deck_tools.egg-info/requires.txt
12
+ src/kong_deck_tools.egg-info/top_level.txt
@@ -0,0 +1,3 @@
1
+ [console_scripts]
2
+ kong-hydrate = kong_deck_tools.hydrate:main
3
+ kong-templatize = kong_deck_tools.templatize:main
@@ -0,0 +1 @@
1
+ ruamel.yaml>=0.18.0
@@ -0,0 +1 @@
1
+ kong_deck_tools