berryworld 1.0.0.196646__py3-none-any.whl → 1.0.0.196834__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.
berryworld/__init__.py CHANGED
@@ -1,5 +1,5 @@
1
1
  from .xml_parser import XMLparser
2
- from .handy_mix import HandyMix, URLResolver
2
+ from .handy_mix import HandyMix
3
3
  from .transportation_solver import TransportationAlgorithm
4
4
  from .allocation_solver import AllocationSolver
5
5
  from .pickle_management import PickleManagement
@@ -53,19 +53,24 @@ class EnvVariables:
53
53
 
54
54
  return config
55
55
 
56
- def fetch_secrets_by_tag(self, config):
57
- """ Fetch secrets from Azure Key Vault based on tags
56
+ def get_secret_client(self, config):
57
+ """ Create a Key Vault client
58
58
  :param config: Dictionary containing Azure Key Vault configuration
59
59
  """
60
60
  tenant_id = config["AZURE-TENANT-ID"]
61
61
  client_id = config["AZURE-CLIENT-ID"]
62
62
  client_secret = config["AZURE-CLIENT-SECRET"]
63
63
  vault_url = f"https://{config['AZURE-KEY-VAULT-NAME']}.vault.azure.net/"
64
- project_tags = config["AZURE-KEY-VAULT-PROJECT-TAGS"]
65
-
66
64
  credential = ClientSecretCredential(tenant_id, client_id, client_secret)
67
- client = SecretClient(vault_url=vault_url, credential=credential)
68
65
 
66
+ return SecretClient(vault_url=vault_url, credential=credential)
67
+
68
+ def fetch_secrets_by_tag(self, config):
69
+ """ Fetch enabled secrets from Azure Key Vault based on tags
70
+ :param config: Dictionary containing Azure Key Vault configuration
71
+ """
72
+ client = self.get_secret_client(config)
73
+ project_tags = config.get("AZURE-KEY-VAULT-PROJECT-TAGS", [])
69
74
  secrets = {}
70
75
  for prop in client.list_properties_of_secrets():
71
76
  if not prop.enabled:
@@ -78,33 +83,120 @@ class EnvVariables:
78
83
  secrets[key] = secret.value
79
84
  return secrets
80
85
 
81
- def generate_akv_env_file(self, config_path=None, env_path=None):
86
+ def fetch_all_secrets(self, config):
87
+ """ Fetch all enabled secrets from the Key Vault
88
+ :param config: Dictionary containing Azure Key Vault configuration
89
+ """
90
+ client = self.get_secret_client(config)
91
+ secrets = {}
92
+ for prop in client.list_properties_of_secrets():
93
+ if prop.enabled:
94
+ secret = client.get_secret(prop.name)
95
+ secrets[secret.name] = {
96
+ "value": secret.value,
97
+ "tags": prop.tags or {}
98
+ }
99
+ return secrets
100
+
101
+ def create_or_update_akv_secret(self, config, name=None, value=None, tags=None, tag_name=None, tag_value=None,
102
+ disable_old=True, secrets_dict=None):
103
+ """ Create or update a secret / all secrets in Key Vault :
104
+ :param config: Dictionary containing Azure Key Vault configuration
105
+ :param name: Name of the secret to be created / updated
106
+ :param value: Value of the secret to be created / updated
107
+ :param tags: Dictionary containing Azure Key Vault configuration
108
+ :param tag_name: Tag name of the secret to be created / updated
109
+ :param tag_value: Tag value of the secret to be created / updated
110
+ :param disable_old: Flag if previous version should be disabled
111
+ :param secrets_dict: Dictionary of all the secrets from AKV
112
+ """
113
+ client = self.get_secret_client(config)
114
+
115
+ # If secrets_dict is provided, loop through it
116
+ if secrets_dict is not None:
117
+ for s_name, s_data in secrets_dict.items():
118
+ self.create_or_update_akv_secret(
119
+ config,
120
+ name=s_name,
121
+ value=s_data["value"],
122
+ tags=s_data.get("tags"),
123
+ disable_old=disable_old
124
+ )
125
+ return
126
+
127
+ if (name is None and value is None) and secrets_dict is None:
128
+ raise ValueError("Must provide either secrets_dict or both name and value")
129
+
130
+ # Check the latest version of the secret
131
+ latest_secret = None
132
+ latest_tags = {}
133
+ try:
134
+ latest_secret = client.get_secret(name)
135
+ latest_tags = latest_secret.properties.tags or {}
136
+ except Exception:
137
+ pass
138
+
139
+ updated_tags = {**latest_tags}
140
+ if tags is not None:
141
+ updated_tags.update(tags)
142
+ elif tag_name is not None and tag_value is not None:
143
+ updated_tags[tag_name] = tag_value
144
+
145
+ # Check if anything changed in the value or tag
146
+ value_changed = latest_secret is None or latest_secret.value != value
147
+ tags_changed = updated_tags != latest_tags
148
+
149
+ if not value_changed and not tags_changed:
150
+ print(f"Secret {name} already up to date. Skipping.")
151
+ return
152
+
153
+ # Create new version
154
+ new_secret = client.set_secret(name, value, tags=updated_tags)
155
+ new_version = new_secret.properties.version
156
+ print(f"Secret {name} updated. New version: {new_version}.")
157
+
158
+ # Disable previous versions
159
+ if disable_old:
160
+ for secret_prop in client.list_properties_of_secret_versions(name):
161
+ if secret_prop.version != new_version and secret_prop.enabled:
162
+ client.update_secret_properties(secret_prop.name, secret_prop.version, enabled=False)
163
+
164
+ def generate_akv_env_file(self, config_path=None, env_path=None, fetch_all=False):
82
165
  """ Generate the environment variables file from Azure Key Vault secrets
83
166
  :param config_path: Path to the Terraform configuration file (optional)
84
167
  :param env_path: Path to the destination .env file (optional)
168
+ :param fetch_all: Flag if all the secrets should be fetched
85
169
  """
86
170
  config = self.extract_akv_config_from_tf(config_path)
87
- secrets = self.fetch_secrets_by_tag(config)
88
-
89
- # Create .env file for UnitTest
90
- with open(env_path, "w") as f:
91
- for key, value in secrets.items():
92
- f.write(f"{key}={value}\n")
93
-
94
- # Create .env file for container apps
95
- if os.name != "nt" and self.env is not None:
96
- # Linux/Mac: generate terraform .tfvars file
97
- tfvars_path = f"./environments/{self.env}/secrets.auto.tfvars.json"
98
- os.makedirs(os.path.dirname(tfvars_path), exist_ok=True)
99
- with open(tfvars_path, "w") as f:
100
- json.dump({"keyvault_secrets": secrets}, f, indent=2)
101
-
102
- def generate_env_tf(self, config_path='./environments/prod/step01.tf', env_path='.env'):
171
+ if fetch_all:
172
+ secrets = self.fetch_all_secrets(config)
173
+ else:
174
+ secrets = self.fetch_secrets_by_tag(config)
175
+
176
+ if fetch_all:
177
+ return secrets
178
+
179
+ if not fetch_all:
180
+ # Create .env file for UnitTest
181
+ with open(env_path, "w") as f:
182
+ for key, value in secrets.items():
183
+ f.write(f"{key}={value}\n")
184
+
185
+ # Create .env file for container apps
186
+ if os.name != "nt" and self.env is not None:
187
+ # Linux/Mac: generate terraform .tfvars file
188
+ tfvars_path = f"./environments/{self.env}/secrets.auto.tfvars.json"
189
+ os.makedirs(os.path.dirname(tfvars_path), exist_ok=True)
190
+ with open(tfvars_path, "w") as f:
191
+ json.dump({"keyvault_secrets": secrets}, f, indent=2)
192
+
193
+ def generate_env_tf(self, config_path='./environments/prod/step01.tf', env_path='.env', fetch_all=False):
103
194
  """ Main function to parse arguments and generate AKV environment variables file.
104
195
  :param config_path: Path to the Terraform configuration file
105
196
  :param env_path: Path to the destination .env file
197
+ :param fetch_all: Flag if all the secrets should be fetched
106
198
  """
107
- self.generate_akv_env_file(config_path=config_path, env_path=env_path)
199
+ self.generate_akv_env_file(config_path=config_path, env_path=env_path, fetch_all=fetch_all)
108
200
 
109
201
  @staticmethod
110
202
  def generate_env_file(yaml_path='./environments/prd1/step01.yaml', env_path='./.env'):
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: berryworld
3
- Version: 1.0.0.196646
3
+ Version: 1.0.0.196834
4
4
  Summary: Handy classes to improve ETL processes
5
5
  Home-page: https://www.berryworld.com
6
6
  Author: BerryWorld ltd
@@ -1,4 +1,4 @@
1
- berryworld/__init__.py,sha256=x0BONOWraAH1SG_BRHWpZNarRMUqoRHKkdASKMtAdhc,1140
1
+ berryworld/__init__.py,sha256=y8vZZSv7up3H-uYHEGPDW_ucf-ynzIsoRY6jJvIPsrE,1127
2
2
  berryworld/aks_logs.py,sha256=Gb2_cokiZbEX01Yoptd0MxpDociaug-GrXdwliyxFBo,2293
3
3
  berryworld/allocation_solver.py,sha256=asFtaCAze6-eHUGWXA0kAp67UBS-Upj1KKdrVLj_ttQ,8513
4
4
  berryworld/app_logs.py,sha256=MKzKPYd3JuPfOQNAapIgaeZeFHw1z_w2mbn9I6QCADE,4180
@@ -8,7 +8,7 @@ berryworld/credentials.py,sha256=oyBvdf0q6KrofONGWIhLDTcIIon0pkA0vGOyI_dt8AE,664
8
8
  berryworld/devops.py,sha256=7mRbyZPGzk5ox-6J2etv3NxCcfP4cprG0_Xelh7prn8,9776
9
9
  berryworld/email_con.py,sha256=CVyEDVnc_iVeRTwJgIU31ToFgyix7L2yn4Ih9Wu7I5s,15806
10
10
  berryworld/email_logging.py,sha256=LeSrTExhQhar49gJR2wGC1dS0lqsNpFl9pS3eYWqnuo,4936
11
- berryworld/generate_env.py,sha256=kJuBb0OOYjoa2gyAnZHgn3gpoEZ8rPbMhnKcTYfENUk,11875
11
+ berryworld/generate_env.py,sha256=LrqUH8AjCI6P0uU6BMBRYC9cnmyKkYcpXF1KKIzxkZ8,15900
12
12
  berryworld/handy_mix.py,sha256=SqJ3UjIjmIOgjbp-_1eyKQJ3OJLN7OfpDQIASvjNZ_Q,9672
13
13
  berryworld/logging.py,sha256=tOxzaFALQm3aVVEc3I7t8MU6PwgUI9VSnzNCH9yRryo,1013
14
14
  berryworld/logic_apps.py,sha256=a0uU4tNO3v2w7grdBv-OOx4hUf7VBIerJpwZ9U-29dQ,14591
@@ -26,12 +26,12 @@ berryworld/verify_keys.py,sha256=X7VUHqYDklWPDO0bGVHIOXeLq5Qi4fZRZbHYw5x7UnA,435
26
26
  berryworld/vivantio.py,sha256=QfZo0UKqkzVRg_LyiwivNd3aEup4TH57x4KxLZkCJwc,10627
27
27
  berryworld/vivantio_logging.py,sha256=ciy7gA4u3FrgUIpEBnMgocbNPp6jcu9TPoy-kLcrTZU,5736
28
28
  berryworld/xml_parser.py,sha256=HWD71NaTN3DaIOGT6Wzxs4CEsroFhGQwe9iPLIL80Co,957
29
- berryworld-1.0.0.196646.dist-info/licenses/LICENSE,sha256=vtkVCJM6E2af2gnsi2XxKPr4WY-uIbvzVLXieFND0UU,1074
29
+ berryworld-1.0.0.196834.dist-info/licenses/LICENSE,sha256=vtkVCJM6E2af2gnsi2XxKPr4WY-uIbvzVLXieFND0UU,1074
30
30
  tests/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
31
31
  tests/test_allocation_config.py,sha256=e12l6fE9U57eSPS35g6ekJ_hol7-RHg89JV60_m1BlE,4633
32
32
  tests/test_handy_mix_config.py,sha256=Un56mz9KJmdn4K4OwzHAHLSRzDU1Xv2nFrONNuzOG04,2594
33
33
  tests/test_xml_parser.py,sha256=3QTlhFEd6KbK6nRFKZnc35tad6wqukTbe4QrFi8mr_8,859
34
- berryworld-1.0.0.196646.dist-info/METADATA,sha256=vhie3997slP6IMtdOSo1W4-5A07_aiytRm0NJSq1Ihs,1445
35
- berryworld-1.0.0.196646.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
36
- berryworld-1.0.0.196646.dist-info/top_level.txt,sha256=GIZ5qy-P5oxfEH755vA1IMFeTVdX3-40JxMe6nOe5I8,17
37
- berryworld-1.0.0.196646.dist-info/RECORD,,
34
+ berryworld-1.0.0.196834.dist-info/METADATA,sha256=7XEbbDOOj1CWZf4zWjjk5nnG5dTpD57LHa9zVMeUrQc,1445
35
+ berryworld-1.0.0.196834.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
36
+ berryworld-1.0.0.196834.dist-info/top_level.txt,sha256=GIZ5qy-P5oxfEH755vA1IMFeTVdX3-40JxMe6nOe5I8,17
37
+ berryworld-1.0.0.196834.dist-info/RECORD,,