eaglelandsonce commited on
Commit
82a4ea3
·
verified ·
1 Parent(s): aef66ba

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +17 -67
app.py CHANGED
@@ -71,24 +71,21 @@ def resolve_template_expressions(template):
71
 
72
  # Function to estimate the cost of resources
73
  def estimate_cost(resources):
74
- # This is a simplified cost estimation. In a real scenario, you'd need to
75
- # integrate with Azure's pricing API or use a more comprehensive pricing model.
76
  cost_estimates = {
77
- "Microsoft.Storage/storageAccounts": 10, # $10 per month
78
- "Microsoft.Compute/virtualMachines": 50, # $50 per month
79
- "Microsoft.Web/sites": 30, # $30 per month
80
- "Microsoft.Sql/servers": 40, # $40 per month
81
- # Add more resource types and their estimated costs
82
  }
83
-
84
  total_cost = 0
85
  for resource in resources:
86
  resource_type = resource.get('type')
87
  if resource_type in cost_estimates:
88
  total_cost += cost_estimates[resource_type]
89
  else:
90
- total_cost += 5 # Default cost for unknown resource types
91
-
92
  return total_cost
93
 
94
  # Function to create a dependency graph of resources
@@ -108,8 +105,6 @@ def plot_dependency_graph(G):
108
  pos = nx.spring_layout(G)
109
  nx.draw(G, pos, with_labels=True, node_color='lightblue',
110
  node_size=3000, font_size=8, font_weight='bold')
111
- edge_labels = nx.get_edge_attributes(G, 'weight')
112
- nx.draw_networkx_edge_labels(G, pos, edge_labels=edge_labels)
113
  plt.title("Resource Dependency Graph")
114
  return plt
115
 
@@ -117,41 +112,29 @@ def plot_dependency_graph(G):
117
  def lint_template(template):
118
  lint_results = []
119
 
120
- # Check 1: Ensure all resources have tags
121
  for resource in template.get('resources', []):
122
  if 'tags' not in resource:
123
  lint_results.append(f"Warning: Resource '{resource.get('name')}' does not have any tags.")
124
-
125
- # Check 2: Ensure parameters have descriptions
126
  for param_name, param_value in template.get('parameters', {}).items():
127
  if 'metadata' not in param_value or 'description' not in param_value['metadata']:
128
  lint_results.append(f"Warning: Parameter '{param_name}' does not have a description.")
129
-
130
- # Check 3: Warn about hardcoded values in resource properties
131
- for resource in template.get('resources', []):
132
- for prop, value in resource.get('properties', {}).items():
133
- if isinstance(value, (str, int, float)) and not isinstance(value, bool):
134
- lint_results.append(f"Info: Consider using a parameter for the hardcoded value in resource '{resource.get('name')}', property '{prop}'.")
135
-
136
  return lint_results
137
 
138
  # Function to generate a system diagram
139
  def generate_system_diagram(resources):
140
- # Create a new Graphviz graph
141
  dot = graphviz.Digraph()
142
- dot.attr(rankdir='TB') # Top to bottom layout
143
 
144
- # Create nodes for each resource
145
  for i, resource in enumerate(resources):
146
  resource_type = resource['type'].split('/')[-1]
147
  node_id = f"R{i}"
148
  dot.node(node_id, f"{resource_type}\n{resource['name']}")
149
 
150
- # Create connections based on dependencies
151
  for resource in resources:
152
  if 'dependsOn' in resource:
153
  for dependency in resource['dependsOn']:
154
- # Find the node id for the dependency
155
  dep_id = next((f"R{j}" for j, r in enumerate(resources) if r['name'] == dependency), None)
156
  if dep_id:
157
  dot.edge(dep_id, f"R{resources.index(resource)}")
@@ -163,12 +146,10 @@ def simulate_deployment(arm_template):
163
  try:
164
  template = json.loads(arm_template)
165
 
166
- # Validate template
167
  is_valid, validation_message = validate_template(template)
168
  if not is_valid:
169
  return [], [], [], [], 0, None, [], None, validation_message
170
 
171
- # Resolve expressions
172
  resolved_template = resolve_template_expressions(template)
173
 
174
  resources_to_create = []
@@ -205,16 +186,12 @@ def simulate_deployment(arm_template):
205
  if resource_name not in [r.get('name') for r in resolved_template.get('resources', [])]:
206
  resources_to_delete.append(resource_name)
207
 
208
- # Estimate cost
209
  estimated_cost = estimate_cost(resource_details)
210
 
211
- # Create dependency graph
212
  dependency_graph = create_dependency_graph(resolved_template.get('resources', []))
213
 
214
- # Lint template
215
  lint_results = lint_template(template)
216
 
217
- # Generate system diagram
218
  system_diagram = generate_system_diagram(resource_details)
219
 
220
  return resources_to_create, resources_to_update, resources_to_delete, resource_details, estimated_cost, dependency_graph, lint_results, system_diagram, "Simulation completed successfully."
@@ -225,64 +202,44 @@ def simulate_deployment(arm_template):
225
  st.title("Comprehensive ARM Template Simulator")
226
  st.subheader("Upload your ARM template or paste it below to simulate its deployment.")
227
 
228
- # File uploader
229
  uploaded_file = st.file_uploader("Choose an ARM template file", type=["json"])
230
 
231
- # Input box for ARM template
232
  template_input = st.text_area("Or paste ARM Template JSON here:", height=300)
233
 
234
- # Function to read file contents
235
  def read_file_contents(file):
236
  return file.getvalue().decode("utf-8")
237
 
238
- # Button to simulate the evaluation
239
  if st.button("Simulate Template"):
240
- # Check if a file was uploaded
241
  if uploaded_file is not None:
242
- # Read the contents of the uploaded file
243
  file_contents = read_file_contents(uploaded_file)
244
- # Use the file contents for simulation
245
  template_to_simulate = file_contents
246
  elif template_input:
247
- # Use the pasted input for simulation
248
  template_to_simulate = template_input
249
  else:
250
  st.error("Please either upload a file or paste an ARM template to simulate.")
251
  st.stop()
252
 
253
- # Proceed with simulation
254
  resources_to_create, resources_to_update, resources_to_delete, resource_details, estimated_cost, dependency_graph, lint_results, system_diagram, message = simulate_deployment(template_to_simulate)
255
-
256
  st.subheader("Simulation Results:")
257
  st.write(message)
258
 
259
  if resources_to_create or resources_to_update or resources_to_delete:
260
  st.write("### Resources to be Created:")
261
- if resources_to_create:
262
- st.write(resources_to_create)
263
- else:
264
- st.write("No new resources will be created.")
265
 
266
  st.write("### Resources to be Updated:")
267
- if resources_to_update:
268
- st.write(resources_to_update)
269
- else:
270
- st.write("No resources will be updated.")
271
 
272
  st.write("### Resources to be Deleted:")
273
- if resources_to_delete:
274
- st.write(resources_to_delete)
275
- else:
276
- st.write("No resources will be deleted.")
277
 
278
  st.write("### Detailed Resource Information:")
279
  for resource in resource_details:
280
  st.write(f"**Name:** {resource['name']}")
281
  st.write(f"**Type:** {resource['type']}")
282
  st.write(f"**Location:** {resource['location']}")
283
- st.write("**Properties:**")
284
  st.json(resource['properties'])
285
- st.write("---")
286
 
287
  st.write(f"### Estimated Monthly Cost: ${estimated_cost}")
288
 
@@ -290,20 +247,13 @@ if st.button("Simulate Template"):
290
  if dependency_graph:
291
  fig = plot_dependency_graph(dependency_graph)
292
  st.pyplot(fig)
293
- else:
294
- st.write("No dependencies found between resources.")
295
 
296
  st.write("### System Diagram:")
297
  if system_diagram:
298
  st.graphviz_chart(system_diagram)
299
- else:
300
- st.write("Unable to generate system diagram.")
301
 
302
  st.write("### Template Lint Results:")
303
- if lint_results:
304
- for result in lint_results:
305
- st.write(result)
306
- else:
307
- st.write("No linting issues found.")
308
  else:
309
- st.write("No changes detected in the simulation.")
 
71
 
72
  # Function to estimate the cost of resources
73
  def estimate_cost(resources):
 
 
74
  cost_estimates = {
75
+ "Microsoft.Storage/storageAccounts": 10,
76
+ "Microsoft.Compute/virtualMachines": 50,
77
+ "Microsoft.Web/sites": 30,
78
+ "Microsoft.Sql/servers": 40,
 
79
  }
80
+
81
  total_cost = 0
82
  for resource in resources:
83
  resource_type = resource.get('type')
84
  if resource_type in cost_estimates:
85
  total_cost += cost_estimates[resource_type]
86
  else:
87
+ total_cost += 5
88
+
89
  return total_cost
90
 
91
  # Function to create a dependency graph of resources
 
105
  pos = nx.spring_layout(G)
106
  nx.draw(G, pos, with_labels=True, node_color='lightblue',
107
  node_size=3000, font_size=8, font_weight='bold')
 
 
108
  plt.title("Resource Dependency Graph")
109
  return plt
110
 
 
112
  def lint_template(template):
113
  lint_results = []
114
 
 
115
  for resource in template.get('resources', []):
116
  if 'tags' not in resource:
117
  lint_results.append(f"Warning: Resource '{resource.get('name')}' does not have any tags.")
118
+
 
119
  for param_name, param_value in template.get('parameters', {}).items():
120
  if 'metadata' not in param_value or 'description' not in param_value['metadata']:
121
  lint_results.append(f"Warning: Parameter '{param_name}' does not have a description.")
122
+
 
 
 
 
 
 
123
  return lint_results
124
 
125
  # Function to generate a system diagram
126
  def generate_system_diagram(resources):
 
127
  dot = graphviz.Digraph()
128
+ dot.attr(rankdir='TB')
129
 
 
130
  for i, resource in enumerate(resources):
131
  resource_type = resource['type'].split('/')[-1]
132
  node_id = f"R{i}"
133
  dot.node(node_id, f"{resource_type}\n{resource['name']}")
134
 
 
135
  for resource in resources:
136
  if 'dependsOn' in resource:
137
  for dependency in resource['dependsOn']:
 
138
  dep_id = next((f"R{j}" for j, r in enumerate(resources) if r['name'] == dependency), None)
139
  if dep_id:
140
  dot.edge(dep_id, f"R{resources.index(resource)}")
 
146
  try:
147
  template = json.loads(arm_template)
148
 
 
149
  is_valid, validation_message = validate_template(template)
150
  if not is_valid:
151
  return [], [], [], [], 0, None, [], None, validation_message
152
 
 
153
  resolved_template = resolve_template_expressions(template)
154
 
155
  resources_to_create = []
 
186
  if resource_name not in [r.get('name') for r in resolved_template.get('resources', [])]:
187
  resources_to_delete.append(resource_name)
188
 
 
189
  estimated_cost = estimate_cost(resource_details)
190
 
 
191
  dependency_graph = create_dependency_graph(resolved_template.get('resources', []))
192
 
 
193
  lint_results = lint_template(template)
194
 
 
195
  system_diagram = generate_system_diagram(resource_details)
196
 
197
  return resources_to_create, resources_to_update, resources_to_delete, resource_details, estimated_cost, dependency_graph, lint_results, system_diagram, "Simulation completed successfully."
 
202
  st.title("Comprehensive ARM Template Simulator")
203
  st.subheader("Upload your ARM template or paste it below to simulate its deployment.")
204
 
 
205
  uploaded_file = st.file_uploader("Choose an ARM template file", type=["json"])
206
 
 
207
  template_input = st.text_area("Or paste ARM Template JSON here:", height=300)
208
 
 
209
  def read_file_contents(file):
210
  return file.getvalue().decode("utf-8")
211
 
 
212
  if st.button("Simulate Template"):
 
213
  if uploaded_file is not None:
 
214
  file_contents = read_file_contents(uploaded_file)
 
215
  template_to_simulate = file_contents
216
  elif template_input:
 
217
  template_to_simulate = template_input
218
  else:
219
  st.error("Please either upload a file or paste an ARM template to simulate.")
220
  st.stop()
221
 
 
222
  resources_to_create, resources_to_update, resources_to_delete, resource_details, estimated_cost, dependency_graph, lint_results, system_diagram, message = simulate_deployment(template_to_simulate)
223
+
224
  st.subheader("Simulation Results:")
225
  st.write(message)
226
 
227
  if resources_to_create or resources_to_update or resources_to_delete:
228
  st.write("### Resources to be Created:")
229
+ st.write(resources_to_create or "No new resources will be created.")
 
 
 
230
 
231
  st.write("### Resources to be Updated:")
232
+ st.write(resources_to_update or "No resources will be updated.")
 
 
 
233
 
234
  st.write("### Resources to be Deleted:")
235
+ st.write(resources_to_delete or "No resources will be deleted.")
 
 
 
236
 
237
  st.write("### Detailed Resource Information:")
238
  for resource in resource_details:
239
  st.write(f"**Name:** {resource['name']}")
240
  st.write(f"**Type:** {resource['type']}")
241
  st.write(f"**Location:** {resource['location']}")
 
242
  st.json(resource['properties'])
 
243
 
244
  st.write(f"### Estimated Monthly Cost: ${estimated_cost}")
245
 
 
247
  if dependency_graph:
248
  fig = plot_dependency_graph(dependency_graph)
249
  st.pyplot(fig)
 
 
250
 
251
  st.write("### System Diagram:")
252
  if system_diagram:
253
  st.graphviz_chart(system_diagram)
 
 
254
 
255
  st.write("### Template Lint Results:")
256
+ for result in lint_results:
257
+ st.write(result)
 
 
 
258
  else:
259
+ st.write("No changes detected in the simulation.")