eaglelandsonce commited on
Commit
8bcd745
·
verified ·
1 Parent(s): 00bce7b

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +96 -6
app.py CHANGED
@@ -2,6 +2,8 @@ import streamlit as st
2
  import json
3
  from jsonschema import validate, ValidationError
4
  import re
 
 
5
 
6
  # Mock existing resources (customizable)
7
  existing_resources = {
@@ -32,7 +34,8 @@ arm_schema = {
32
  "type": {"type": "string"},
33
  "name": {"type": "string"},
34
  "location": {"type": "string"},
35
- "properties": {"type": "object"}
 
36
  }
37
  }
38
  },
@@ -62,6 +65,68 @@ def resolve_template_expressions(template):
62
  resolved_str = re.sub(r'\[(\w+\.\w+)\]', resolve_expression, template_str)
63
  return json.loads(resolved_str)
64
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
65
  def simulate_deployment(arm_template):
66
  try:
67
  template = json.loads(arm_template)
@@ -69,7 +134,7 @@ def simulate_deployment(arm_template):
69
  # Validate template
70
  is_valid, validation_message = validate_template(template)
71
  if not is_valid:
72
- return [], [], [], [], validation_message
73
 
74
  # Resolve expressions
75
  resolved_template = resolve_template_expressions(template)
@@ -107,12 +172,21 @@ def simulate_deployment(arm_template):
107
  if resource_name not in [r.get('name') for r in resolved_template.get('resources', [])]:
108
  resources_to_delete.append(resource_name)
109
 
110
- return resources_to_create, resources_to_update, resources_to_delete, resource_details, "Simulation completed successfully."
 
 
 
 
 
 
 
 
 
111
  except json.JSONDecodeError:
112
- return [], [], [], [], "Invalid JSON format. Please check your ARM template."
113
 
114
  # Streamlit UI
115
- st.title("Enhanced ARM Template Simulator")
116
  st.subheader("Paste your ARM template below to simulate its deployment.")
117
 
118
  # Input box for ARM template
@@ -121,7 +195,7 @@ template_input = st.text_area("Paste ARM Template JSON here:", height=300)
121
  # Button to simulate the evaluation
122
  if st.button("Simulate Template"):
123
  if template_input:
124
- resources_to_create, resources_to_update, resources_to_delete, resource_details, message = simulate_deployment(template_input)
125
 
126
  st.subheader("Simulation Results:")
127
  st.write(message)
@@ -153,6 +227,22 @@ if st.button("Simulate Template"):
153
  st.write("**Properties:**")
154
  st.json(resource['properties'])
155
  st.write("---")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
156
  else:
157
  st.write("No changes detected in the simulation.")
158
  else:
 
2
  import json
3
  from jsonschema import validate, ValidationError
4
  import re
5
+ import networkx as nx
6
+ import matplotlib.pyplot as plt
7
 
8
  # Mock existing resources (customizable)
9
  existing_resources = {
 
34
  "type": {"type": "string"},
35
  "name": {"type": "string"},
36
  "location": {"type": "string"},
37
+ "properties": {"type": "object"},
38
+ "dependsOn": {"type": "array", "items": {"type": "string"}}
39
  }
40
  }
41
  },
 
65
  resolved_str = re.sub(r'\[(\w+\.\w+)\]', resolve_expression, template_str)
66
  return json.loads(resolved_str)
67
 
68
+ def estimate_cost(resources):
69
+ # This is a simplified cost estimation. In a real scenario, you'd need to
70
+ # integrate with Azure's pricing API or use a more comprehensive pricing model.
71
+ cost_estimates = {
72
+ "Microsoft.Storage/storageAccounts": 10, # $10 per month
73
+ "Microsoft.Compute/virtualMachines": 50, # $50 per month
74
+ "Microsoft.Web/sites": 30, # $30 per month
75
+ "Microsoft.Sql/servers": 40, # $40 per month
76
+ # Add more resource types and their estimated costs
77
+ }
78
+
79
+ total_cost = 0
80
+ for resource in resources:
81
+ resource_type = resource.get('type')
82
+ if resource_type in cost_estimates:
83
+ total_cost += cost_estimates[resource_type]
84
+ else:
85
+ total_cost += 5 # Default cost for unknown resource types
86
+
87
+ return total_cost
88
+
89
+ def create_dependency_graph(resources):
90
+ G = nx.DiGraph()
91
+ for resource in resources:
92
+ resource_name = resource.get('name')
93
+ G.add_node(resource_name)
94
+ dependencies = resource.get('dependsOn', [])
95
+ for dep in dependencies:
96
+ G.add_edge(dep, resource_name)
97
+ return G
98
+
99
+ def plot_dependency_graph(G):
100
+ plt.figure(figsize=(12, 8))
101
+ pos = nx.spring_layout(G)
102
+ nx.draw(G, pos, with_labels=True, node_color='lightblue',
103
+ node_size=3000, font_size=8, font_weight='bold')
104
+ edge_labels = nx.get_edge_attributes(G, 'weight')
105
+ nx.draw_networkx_edge_labels(G, pos, edge_labels=edge_labels)
106
+ plt.title("Resource Dependency Graph")
107
+ return plt
108
+
109
+ def lint_template(template):
110
+ lint_results = []
111
+
112
+ # Check 1: Ensure all resources have tags
113
+ for resource in template.get('resources', []):
114
+ if 'tags' not in resource:
115
+ lint_results.append(f"Warning: Resource '{resource.get('name')}' does not have any tags.")
116
+
117
+ # Check 2: Ensure parameters have descriptions
118
+ for param_name, param_value in template.get('parameters', {}).items():
119
+ if 'metadata' not in param_value or 'description' not in param_value['metadata']:
120
+ lint_results.append(f"Warning: Parameter '{param_name}' does not have a description.")
121
+
122
+ # Check 3: Warn about hardcoded values in resource properties
123
+ for resource in template.get('resources', []):
124
+ for prop, value in resource.get('properties', {}).items():
125
+ if isinstance(value, (str, int, float)) and not isinstance(value, bool):
126
+ lint_results.append(f"Info: Consider using a parameter for the hardcoded value in resource '{resource.get('name')}', property '{prop}'.")
127
+
128
+ return lint_results
129
+
130
  def simulate_deployment(arm_template):
131
  try:
132
  template = json.loads(arm_template)
 
134
  # Validate template
135
  is_valid, validation_message = validate_template(template)
136
  if not is_valid:
137
+ return [], [], [], [], 0, [], validation_message
138
 
139
  # Resolve expressions
140
  resolved_template = resolve_template_expressions(template)
 
172
  if resource_name not in [r.get('name') for r in resolved_template.get('resources', [])]:
173
  resources_to_delete.append(resource_name)
174
 
175
+ # Estimate cost
176
+ estimated_cost = estimate_cost(resource_details)
177
+
178
+ # Create dependency graph
179
+ dependency_graph = create_dependency_graph(resolved_template.get('resources', []))
180
+
181
+ # Lint template
182
+ lint_results = lint_template(template)
183
+
184
+ return resources_to_create, resources_to_update, resources_to_delete, resource_details, estimated_cost, dependency_graph, lint_results, "Simulation completed successfully."
185
  except json.JSONDecodeError:
186
+ return [], [], [], [], 0, None, [], "Invalid JSON format. Please check your ARM template."
187
 
188
  # Streamlit UI
189
+ st.title("Comprehensive ARM Template Simulator")
190
  st.subheader("Paste your ARM template below to simulate its deployment.")
191
 
192
  # Input box for ARM template
 
195
  # Button to simulate the evaluation
196
  if st.button("Simulate Template"):
197
  if template_input:
198
+ resources_to_create, resources_to_update, resources_to_delete, resource_details, estimated_cost, dependency_graph, lint_results, message = simulate_deployment(template_input)
199
 
200
  st.subheader("Simulation Results:")
201
  st.write(message)
 
227
  st.write("**Properties:**")
228
  st.json(resource['properties'])
229
  st.write("---")
230
+
231
+ st.write(f"### Estimated Monthly Cost: ${estimated_cost}")
232
+
233
+ st.write("### Resource Dependency Graph:")
234
+ if dependency_graph:
235
+ fig = plot_dependency_graph(dependency_graph)
236
+ st.pyplot(fig)
237
+ else:
238
+ st.write("No dependencies found between resources.")
239
+
240
+ st.write("### Template Lint Results:")
241
+ if lint_results:
242
+ for result in lint_results:
243
+ st.write(result)
244
+ else:
245
+ st.write("No linting issues found.")
246
  else:
247
  st.write("No changes detected in the simulation.")
248
  else: