Skip to content

Commit 3f77e4a

Browse files
author
Patrick J. McNerthney
committed
Disable using Secrets packages by default
1 parent ed0eb4c commit 3f77e4a

File tree

11 files changed

+107
-57
lines changed

11 files changed

+107
-57
lines changed

README.md

Lines changed: 19 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -38,9 +38,9 @@ spec:
3838
3939
In addtion to an inline script, the python implementation can be specified
4040
as the complete path to a python class. Python packages can be deployed using
41-
ConfigMaps or Secrets enabling the use of your IDE of choice for writting
42-
the code. See [ConfigMap and Secret Packages](#configmap-and-secret-packages)
43-
and [Filing System Packages](#filing-system-packages).
41+
ConfigMaps, enabling using your IDE of choice for writting the code. See
42+
[ConfigMap Packages](#configmap-packages) and
43+
[Filing System Packages](#filing-system-packages).
4444
4545
## Examples
4646
@@ -57,7 +57,7 @@ kind: Function
5757
metadata:
5858
name: function-pythonic
5959
spec:
60-
package: ghcr.io/fortra/function-pythonic:v0.0.3
60+
package: ghcr.io/fortra/function-pythonic:v0.0.7
6161
```
6262
6363
## Composed Resource Dependencies
@@ -301,12 +301,12 @@ spec:
301301
self.status.composite = 'Hello, World!'
302302
```
303303

304-
## ConfigMap and Secret Packages
304+
## ConfigMap Packages
305305

306-
ConfigMap and Secret based python packages are enable using the `--packages`
307-
and `--packages-namespace` command line options. ConfigMaps and Secrets
308-
with the label `function-pythonic.package` will be incorporated in the python
309-
path at the location configured in the label value. For example, the following
306+
ConfigMap based python packages are enable using the `--packages` and
307+
`--packages-namespace` command line options. ConfigMaps with the label
308+
`function-pythonic.package` will be incorporated in the python path at
309+
the location configured in the label value. For example, the following
310310
ConfigMap will enable python to use `import example.pythonic.features`
311311
```yaml
312312
apiVersion: v1
@@ -338,7 +338,7 @@ Then, in your Composition:
338338
...
339339
```
340340
The entire function-pythonic Composite class can be coded in the ConfigMap and
341-
the only the complete path is needed in the step configuration.
341+
only the complete Composite class path is needed in the step configuration.
342342
```yaml
343343
apiVersion: v1
344344
kind: ConfigMap
@@ -374,7 +374,7 @@ kind: Function
374374
metadata:
375375
name: function-pythonic
376376
spec:
377-
package: ghcr.io/fortra/function-pythonic:v0.0.6
377+
package: ghcr.io/fortra/function-pythonic:v0.0.7
378378
runtimeConfigRef:
379379
name: function-pythonic
380380
---
@@ -413,7 +413,6 @@ rules:
413413
- ''
414414
resources:
415415
- configmaps
416-
- secrets
417416
verbs:
418417
- list
419418
- watch
@@ -432,10 +431,14 @@ subjects:
432431
namespace: crossplane-system
433432
name: function-pythonic
434433
```
435-
When enabled, labeled ConfigMaps and Secrets are obtained cluster wide,
436-
requiring the above ClusterRole permissions. The `--packages-name` command
437-
line option will restrict to only using the supplied namespaces. Per namespace
438-
RBAC permissions are then required.
434+
When enabled, labeled ConfigMaps are obtained cluster wide, requiring the above
435+
ClusterRole permissions. The `--packages-namespace` command line option will restrict
436+
to only using the supplied namespace. This option can be invoked multiple times.
437+
The above RBAC permission can then be per namespace RBAC Role permissions.
438+
439+
Secrets can also be used in an identical manner as ConfigMaps by enabling the
440+
`--packages-secrets` command line option. Secrets permissions need to be
441+
added to the above RBAC configuration.
439442

440443
## Filing System Packages
441444

crossplane/pythonic/__init__.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,13 @@
11
import base64
22

33
from .composite import BaseComposite
4-
from .protobuf import Map, List, Unknown, Yaml, Json
4+
from .protobuf import append, Map, List, Unknown, Yaml, Json
55
B64Encode = lambda s: base64.b64encode(s.encode('utf-8')).decode('utf-8')
66
B64Decode = lambda s: base64.b64decode(s.encode('utf-8')).decode('utf-8')
77

88
__all__ = [
99
'BaseComposite',
10+
'append',
1011
'Map',
1112
'List',
1213
'Unknown',

crossplane/pythonic/function.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
from .. import pythonic
1616

1717
builtins.BaseComposite = pythonic.BaseComposite
18+
builtins.append = pythonic.append
1819
builtins.Map = pythonic.Map
1920
builtins.List = pythonic.List
2021
builtins.Unknown = pythonic.Unknown

crossplane/pythonic/main.py

Lines changed: 24 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -13,10 +13,9 @@
1313
import crossplane.function.logging
1414
import crossplane.function.proto.v1.run_function_pb2_grpc as grpcv1
1515
import grpc
16-
import kopf
1716
import pip._internal.cli.main
1817

19-
from . import function, packages
18+
from . import function
2019

2120

2221
def main():
@@ -35,6 +34,12 @@ async def main(self):
3534
action='store_true',
3635
help='Emit debug logs.',
3736
)
37+
parser.add_argument(
38+
'--log-name-width',
39+
type=int,
40+
default=40,
41+
help='Width of the logger name in the log output, default 40',
42+
)
3843
parser.add_argument(
3944
'--address',
4045
default='0.0.0.0:9443',
@@ -53,7 +58,12 @@ async def main(self):
5358
parser.add_argument(
5459
'--packages',
5560
action='store_true',
56-
help='Discover python packages from function-pythonic ConfigMaps and Secrets.'
61+
help='Discover python packages from function-pythonic ConfigMaps.'
62+
)
63+
parser.add_argument(
64+
'--packages-secrets',
65+
action='store_true',
66+
help='Also Discover python packages from function-pythonic Secrets.'
5767
)
5868
parser.add_argument(
5969
'--packages-namespace',
@@ -122,21 +132,15 @@ async def main(self):
122132
await grpc_server.start()
123133

124134
if args.packages:
125-
packages_dir = pathlib.Path(args.packages_dir).expanduser().resolve()
126-
sys.path.insert(0, str(packages_dir))
127-
packages.setup(packages_dir, grpc_runner)
128-
@kopf.on.startup()
129-
async def startup(settings, **_):
130-
settings.scanning.disabled = True
131-
@kopf.on.cleanup()
132-
async def cleanup(logger=None, **_):
133-
await grpc_server.stop(5)
135+
from . import packages
134136
async with asyncio.TaskGroup() as tasks:
135137
tasks.create_task(grpc_server.wait_for_termination())
136-
tasks.create_task(kopf.operator(
137-
standalone=True,
138-
clusterwide=not args.packages_namespace,
139-
namespaces=args.packages_namespace,
138+
tasks.create_task(packages.operator(
139+
args.packages_secrets,
140+
args.packages_namespace,
141+
args.packages_dir,
142+
grpc_server,
143+
grpc_runner,
140144
))
141145
else:
142146
def stop():
@@ -147,14 +151,12 @@ def stop():
147151
await grpc_server.wait_for_termination()
148152

149153
def configure_logging(self, args):
150-
formatter = Formatter(30)
154+
formatter = Formatter(args.log_name_width)
151155
handler = logging.StreamHandler()
152156
handler.setFormatter(formatter)
153157
logger = logging.getLogger()
154158
logger.addHandler(handler)
155159
logger.setLevel(logging.DEBUG if args.debug else logging.INFO)
156-
if args.debug:
157-
logging.getLogger('kopf.objects').setLevel(logging.INFO)
158160

159161

160162
class Formatter(logging.Formatter):
@@ -172,12 +174,11 @@ def format(self, record):
172174
if extra > 0:
173175
names = record.sname.split('.')
174176
for ix, name in enumerate(names):
175-
if len(name) <= extra:
176-
names[ix] = name[:1]
177-
extra -= len(name) - 1
178-
else:
177+
if len(name) > extra:
179178
names[ix] = name[extra:]
180179
break
180+
names[ix] = name[:1]
181+
extra -= len(name) - 1
181182
record.sname = '.'.join(names)
182183
return super(Formatter, self).format(record)
183184

crossplane/pythonic/packages.py

Lines changed: 35 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,25 +1,51 @@
11

22
import base64
33
import importlib
4+
import logging
45
import pathlib
56
import sys
67

78
import kopf
89

910

11+
PACKAGE_LABEL = {'function-pythonic.package': kopf.PRESENT}
1012
PACKAGES_DIR = None
13+
GRPC_SERVER = None
1114
GRPC_RUNNER = None
1215

13-
def setup(packages_dir, packages_runner):
14-
global PACKAGES_DIR, GRPC_RUNNER
16+
17+
def operator(packages_secrets, packages_namespace, packages_dir, grpc_server, grpc_runner):
18+
logging.getLogger('kopf.objects').setLevel(logging.INFO)
19+
global PACKAGES_DIR, GRPC_SERVER, GRPC_RUNNER
1520
PACKAGES_DIR = packages_dir
16-
GRPC_RUNNER = packages_runner
21+
GRPC_SERVER = grpc_server
22+
GRPC_RUNNER = grpc_runner
23+
PACKAGES_DIR = pathlib.Path(packages_dir).expanduser().resolve()
24+
sys.path.insert(0, str(PACKAGES_DIR))
25+
if packages_secrets:
26+
kopf.on.create('', 'v1', 'secrets', labels=PACKAGE_LABEL)(create)
27+
kopf.on.resume('', 'v1', 'secrets', labels=PACKAGE_LABEL)(create)
28+
kopf.on.update('', 'v1', 'secrets', labels=PACKAGE_LABEL)(update)
29+
kopf.on.delete('', 'v1', 'secrets', labels=PACKAGE_LABEL)(delete)
30+
return kopf.operator(
31+
standalone=True,
32+
clusterwide=not packages_namespace,
33+
namespaces=packages_namespace,
34+
)
35+
36+
37+
@kopf.on.startup()
38+
async def startup(settings, **_):
39+
settings.scanning.disabled = True
40+
41+
42+
@kopf.on.cleanup()
43+
async def cleanup(**_):
44+
await GRPC_SERVER.stop(5)
1745

1846

19-
@kopf.on.create('', 'v1', 'configmaps', labels={'function-pythonic.package': kopf.PRESENT})
20-
@kopf.on.resume('', 'v1', 'configmaps', labels={'function-pythonic.package': kopf.PRESENT})
21-
@kopf.on.create('', 'v1', 'secrets', labels={'function-pythonic.package': kopf.PRESENT})
22-
@kopf.on.resume('', 'v1', 'secrets', labels={'function-pythonic.package': kopf.PRESENT})
47+
@kopf.on.create('', 'v1', 'configmaps', labels=PACKAGE_LABEL)
48+
@kopf.on.resume('', 'v1', 'configmaps', labels=PACKAGE_LABEL)
2349
async def create(body, logger, **_):
2450
package_dir, package = get_package_dir(body)
2551
if package_dir:
@@ -40,8 +66,7 @@ async def create(body, logger, **_):
4066
logger.info(f"Created file: {'/'.join(package + [name])}")
4167

4268

43-
@kopf.on.update('', 'v1', 'configmaps', labels={'function-pythonic.package': kopf.PRESENT})
44-
@kopf.on.update('', 'v1', 'secrets', labels={'function-pythonic.package': kopf.PRESENT})
69+
@kopf.on.update('', 'v1', 'configmaps', labels=PACKAGE_LABEL)
4570
async def update(body, old, logger, **_):
4671
old_package_dir, old_package = get_package_dir(old)
4772
if old_package_dir:
@@ -91,8 +116,7 @@ async def update(body, old, logger, **_):
91116
old_package.pop()
92117

93118

94-
@kopf.on.delete('', 'v1', 'configmaps', labels={'function-pythonic.package': kopf.PRESENT})
95-
@kopf.on.delete('', 'v1', 'secrets', labels={'function-pythonic.package': kopf.PRESENT})
119+
@kopf.on.delete('', 'v1', 'configmaps', labels=PACKAGE_LABEL)
96120
async def delete(old, logger, **_):
97121
package_dir, package = get_package_dir(old)
98122
if package_dir:

crossplane/pythonic/protobuf.py

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,11 @@
1818
import datetime
1919
import google.protobuf.struct_pb2
2020
import json
21+
import sys
2122
import yaml
2223

24+
append = sys.maxsize
25+
2326

2427
def Map(**kwargs):
2528
return Values(None, None, None, Values.Type.MAP)(**kwargs)
@@ -442,6 +445,10 @@ def __setitem__(self, key, message):
442445
raise ValueError(f"{self._readOnly} is read only")
443446
if self._messages is None:
444447
self._messages = self._parent._create_child(self._key)
448+
if key == append:
449+
key = len(self._messages)
450+
elif key < 0:
451+
key = len(self._messages) + key
445452
while key >= len(self._messages):
446453
self._messages.add()
447454
if isinstance(message, Message):
@@ -738,6 +745,10 @@ def __setitem__(self, key, value):
738745
else:
739746
self.__dict__['_values'] = self._parent._create_child(self._key, self._type)
740747
values = self._values.values
748+
if key == append:
749+
key = len(values)
750+
elif key < 0:
751+
key = len(values) + key
741752
while key >= len(values):
742753
values.add()
743754
else:

examples/eks-cluster/functions.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,4 +5,4 @@ metadata:
55
annotations:
66
render.crossplane.io/runtime: Development
77
spec:
8-
package: ghcr.io/fortra/function-pythonic:v0.0.5
8+
package: ghcr.io/fortra/function-pythonic:v0.0.7

examples/helm-copy-secret/functions.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,4 +5,4 @@ metadata:
55
annotations:
66
render.crossplane.io/runtime: Development
77
spec:
8-
package: ghcr.io/fortra/function-pythonic:v0.0.6
8+
package: ghcr.io/fortra/function-pythonic:v0.0.7

pyproject.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ packages = ["crossplane"]
3838
[tool.hatch.envs.default.scripts]
3939
production = "python -m crossplane.pythonic.main --insecure"
4040
development = "python -m crossplane.pythonic.main --insecure --debug"
41-
packages = "python -m crossplane.pythonic.main --insecure --debug --packages"
41+
packages = "python -m crossplane.pythonic.main --insecure --debug --packages --packages-secrets"
4242

4343
[tool.hatch.envs.lint]
4444
type = "virtual"

scripts/setup-local.sh

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -188,16 +188,16 @@ spec:
188188
name: function-pythonic
189189
EOF
190190

191-
# package: ghcr.io/fortra/function-pythonic:v0.0.6
192-
# package: ghcr.io/iciclespider/function-pythonic:v0.0.0-20250816062312-0422a3a5c727
191+
# package: ghcr.io/fortra/function-pythonic:v0.0.0-20250819201108-49cfb066579f
192+
# package: ghcr.io/fortra/function-pythonic:v0.0.7
193193

194194
kubectl apply -f - <<EOF
195195
apiVersion: pkg.crossplane.io/v1
196196
kind: Function
197197
metadata:
198198
name: function-pythonic
199199
spec:
200-
package: ghcr.io/fortra/function-pythonic:v0.0.6
200+
package: ghcr.io/fortra/function-pythonic:v0.0.7
201201
runtimeConfigRef:
202202
apiVersion: pkg.crossplane.io/v1beta1
203203
kind: DeploymentRuntimeConfig

0 commit comments

Comments
 (0)