crossplane-function-pythonic 0.0.10__py3-none-any.whl → 0.1.0__py3-none-any.whl
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.
- crossplane/pythonic/__init__.py +1 -4
- crossplane/pythonic/composite.py +68 -18
- crossplane/pythonic/function.py +176 -88
- crossplane/pythonic/main.py +6 -1
- crossplane/pythonic/packages.py +61 -70
- crossplane/pythonic/protobuf.py +701 -354
- {crossplane_function_pythonic-0.0.10.dist-info → crossplane_function_pythonic-0.1.0.dist-info}/METADATA +24 -2
- crossplane_function_pythonic-0.1.0.dist-info/RECORD +11 -0
- crossplane_function_pythonic-0.0.10.dist-info/RECORD +0 -11
- {crossplane_function_pythonic-0.0.10.dist-info → crossplane_function_pythonic-0.1.0.dist-info}/WHEEL +0 -0
- {crossplane_function_pythonic-0.0.10.dist-info → crossplane_function_pythonic-0.1.0.dist-info}/entry_points.txt +0 -0
- {crossplane_function_pythonic-0.0.10.dist-info → crossplane_function_pythonic-0.1.0.dist-info}/licenses/LICENSE +0 -0
crossplane/pythonic/packages.py
CHANGED
@@ -1,6 +1,5 @@
|
|
1
1
|
|
2
2
|
import base64
|
3
|
-
import importlib
|
4
3
|
import logging
|
5
4
|
import pathlib
|
6
5
|
import sys
|
@@ -10,8 +9,8 @@ import kopf
|
|
10
9
|
|
11
10
|
GRPC_SERVER = None
|
12
11
|
GRPC_RUNNER = None
|
13
|
-
PACKAGE_LABEL = {'function-pythonic.package': kopf.PRESENT}
|
14
12
|
PACKAGES_DIR = None
|
13
|
+
PACKAGE_LABEL = {'function-pythonic.package': kopf.PRESENT}
|
15
14
|
|
16
15
|
|
17
16
|
def operator(grpc_server, grpc_runner, packages_secrets, packages_namespaces, packages_dir):
|
@@ -46,95 +45,43 @@ async def cleanup(**_):
|
|
46
45
|
@kopf.on.create('', 'v1', 'configmaps', labels=PACKAGE_LABEL)
|
47
46
|
@kopf.on.resume('', 'v1', 'configmaps', labels=PACKAGE_LABEL)
|
48
47
|
async def create(body, logger, **_):
|
49
|
-
package_dir
|
48
|
+
package_dir = get_package_dir(body, logger)
|
50
49
|
if package_dir:
|
51
|
-
package_dir.mkdir(parents=True, exist_ok=True)
|
52
50
|
secret = body['kind'] == 'Secret'
|
53
|
-
invalidate = False
|
54
51
|
for name, text in body.get('data', {}).items():
|
55
|
-
|
56
|
-
if secret:
|
57
|
-
package_file.write_bytes(base64.b64decode(text.encode('utf-8')))
|
58
|
-
else:
|
59
|
-
package_file.write_text(text)
|
60
|
-
if package_file.suffixes == ['.py']:
|
61
|
-
module = '.'.join(package + [package_file.stem])
|
62
|
-
GRPC_RUNNER.invalidate_module(module)
|
63
|
-
logger.info(f"Created module: {module}")
|
64
|
-
else:
|
65
|
-
logger.info(f"Created file: {'/'.join(package + [name])}")
|
52
|
+
package_file_write(package_dir, name, secret, text, 'Created', logger)
|
66
53
|
|
67
54
|
|
68
55
|
@kopf.on.update('', 'v1', 'configmaps', labels=PACKAGE_LABEL)
|
69
56
|
async def update(body, old, logger, **_):
|
70
|
-
old_package_dir
|
57
|
+
old_package_dir = get_package_dir(old)
|
71
58
|
if old_package_dir:
|
72
59
|
old_data = old.get('data', {})
|
73
60
|
else:
|
74
61
|
old_data = {}
|
75
62
|
old_names = set(old_data.keys())
|
76
|
-
package_dir
|
63
|
+
package_dir = get_package_dir(body, logger)
|
77
64
|
if package_dir:
|
78
|
-
package_dir.mkdir(parents=True, exist_ok=True)
|
79
65
|
secret = body['kind'] == 'Secret'
|
80
66
|
for name, text in body.get('data', {}).items():
|
81
|
-
package_file = package_dir / name
|
82
67
|
if package_dir == old_package_dir and text == old_data.get(name, None):
|
83
68
|
action = 'Unchanged'
|
84
69
|
else:
|
85
|
-
if secret:
|
86
|
-
package_file.write_bytes(base64.b64decode(text.encode('utf-8')))
|
87
|
-
else:
|
88
|
-
package_file.write_text(text)
|
89
70
|
action = 'Updated' if package_dir == old_package_dir and name in old_names else 'Created'
|
90
|
-
|
91
|
-
module = '.'.join(package + [package_file.stem])
|
92
|
-
if action != 'Unchanged':
|
93
|
-
GRPC_RUNNER.invalidate_module(module)
|
94
|
-
logger.info(f"{action} module: {module}")
|
95
|
-
else:
|
96
|
-
logger.info(f"{action} file: {'/'.join(package + [name])}")
|
71
|
+
package_file_write(package_dir, name, secret, text, action, logger)
|
97
72
|
if package_dir == old_package_dir:
|
98
73
|
old_names.discard(name)
|
99
74
|
if old_package_dir:
|
100
75
|
for name in old_names:
|
101
|
-
|
102
|
-
package_file.unlink(missing_ok=True)
|
103
|
-
if package_file.suffixes == ['.py']:
|
104
|
-
module = '.'.join(old_package + [package_file.stem])
|
105
|
-
GRPC_RUNNER.invalidate_module(module)
|
106
|
-
logger.info(f"Removed module: {module}")
|
107
|
-
else:
|
108
|
-
logger.info(f"Removed file: {'/'.join(old_package + [name])}")
|
109
|
-
while old_package and old_package_dir.is_dir() and not list(old_package_dir.iterdir()):
|
110
|
-
old_package_dir.rmdir()
|
111
|
-
module = '.'.join(old_package)
|
112
|
-
GRPC_RUNNER.invalidate_module(module)
|
113
|
-
logger.info(f"Removed package: {module}")
|
114
|
-
old_package_dir = old_package_dir.parent
|
115
|
-
old_package.pop()
|
76
|
+
package_file_unlink(old_package_dir, name, 'Removed', logger)
|
116
77
|
|
117
78
|
|
118
79
|
@kopf.on.delete('', 'v1', 'configmaps', labels=PACKAGE_LABEL)
|
119
80
|
async def delete(old, logger, **_):
|
120
|
-
package_dir
|
81
|
+
package_dir = get_package_dir(old)
|
121
82
|
if package_dir:
|
122
83
|
for name in old.get('data', {}).keys():
|
123
|
-
|
124
|
-
package_file.unlink(missing_ok=True)
|
125
|
-
if package_file.suffixes == ['.py']:
|
126
|
-
module = '.'.join(package + [package_file.stem])
|
127
|
-
GRPC_RUNNER.invalidate_module(module)
|
128
|
-
logger.info(f"Deleted module: {module}")
|
129
|
-
else:
|
130
|
-
logger.info(f"Deleted file: {'/'.join(package + [name])}")
|
131
|
-
while package and package_dir.is_dir() and not list(package_dir.iterdir()):
|
132
|
-
package_dir.rmdir()
|
133
|
-
module = '.'.join(package)
|
134
|
-
GRPC_RUNNER.invalidate_module(module)
|
135
|
-
logger.info(f"Deleted package: {module}")
|
136
|
-
package_dir = package_dir.parent
|
137
|
-
package.pop()
|
84
|
+
package_file_unlink(package_dir, name, 'Deleted', logger)
|
138
85
|
|
139
86
|
|
140
87
|
def get_package_dir(body, logger=None):
|
@@ -142,16 +89,60 @@ def get_package_dir(body, logger=None):
|
|
142
89
|
if package is None:
|
143
90
|
if logger:
|
144
91
|
logger.error('function-pythonic.package label is missing')
|
145
|
-
return None
|
92
|
+
return None
|
146
93
|
package_dir = PACKAGES_DIR
|
147
|
-
if package
|
148
|
-
|
149
|
-
else:
|
150
|
-
package = package.split('.')
|
151
|
-
for segment in package:
|
94
|
+
if package:
|
95
|
+
for segment in package.split('.'):
|
152
96
|
if not segment.isidentifier():
|
153
97
|
if logger:
|
154
98
|
logger.error('Package has invalid package name: %s', package)
|
155
|
-
return None
|
99
|
+
return None
|
156
100
|
package_dir = package_dir / segment
|
157
|
-
return package_dir
|
101
|
+
return package_dir
|
102
|
+
|
103
|
+
|
104
|
+
def package_file_write(package_dir, name, secret, text, action, logger):
|
105
|
+
package_file = package_dir / name
|
106
|
+
if action != 'Unchanged':
|
107
|
+
package_file.parent.mkdir(parents=True, exist_ok=True)
|
108
|
+
if secret:
|
109
|
+
package_file.write_bytes(base64.b64decode(text.encode('utf-8')))
|
110
|
+
else:
|
111
|
+
package_file.write_text(text)
|
112
|
+
module, name = package_file_name(package_file)
|
113
|
+
if module:
|
114
|
+
if action != 'Unchanged':
|
115
|
+
GRPC_RUNNER.invalidate_module(name)
|
116
|
+
logger.info(f"{action} module: {name}")
|
117
|
+
else:
|
118
|
+
logger.info(f"{action} file: {name}")
|
119
|
+
|
120
|
+
|
121
|
+
def package_file_unlink(package_dir, name, action, logger):
|
122
|
+
package_file = package_dir / name
|
123
|
+
package_file.unlink(missing_ok=True)
|
124
|
+
module, name = package_file_name(package_file)
|
125
|
+
if module:
|
126
|
+
GRPC_RUNNER.invalidate_module(name)
|
127
|
+
logger.info(f"{action} module: {name}")
|
128
|
+
else:
|
129
|
+
logger.info(f"{action} file: {name}")
|
130
|
+
package_dir = package_file.parent
|
131
|
+
while (
|
132
|
+
package_dir.is_relative_to(PACKAGES_DIR)
|
133
|
+
and package_dir.is_dir()
|
134
|
+
and not list(package_dir.iterdir())
|
135
|
+
):
|
136
|
+
package_dir.rmdir()
|
137
|
+
module = str(package_dir.relative_to(PACKAGES_DIR)).replace('/', '.')
|
138
|
+
if module != '.':
|
139
|
+
GRPC_RUNNER.invalidate_module(module)
|
140
|
+
logger.info(f"{action} package: {module}")
|
141
|
+
package_dir = package_dir.parent
|
142
|
+
|
143
|
+
|
144
|
+
def package_file_name(package_file):
|
145
|
+
name = str(package_file.relative_to(PACKAGES_DIR))
|
146
|
+
if name.endswith('.py'):
|
147
|
+
return True, name[:-3].replace('/', '.')
|
148
|
+
return False, name
|