Spaces:
Sleeping
Sleeping
Update app.py
Browse files
app.py
CHANGED
@@ -5,6 +5,7 @@ import re
|
|
5 |
import networkx as nx
|
6 |
import matplotlib.pyplot as plt
|
7 |
import io
|
|
|
8 |
|
9 |
# Mock existing resources (customizable)
|
10 |
existing_resources = {
|
@@ -45,6 +46,7 @@ arm_schema = {
|
|
45 |
"required": ["$schema", "contentVersion", "resources"]
|
46 |
}
|
47 |
|
|
|
48 |
def validate_template(template):
|
49 |
try:
|
50 |
validate(instance=template, schema=arm_schema)
|
@@ -52,6 +54,7 @@ def validate_template(template):
|
|
52 |
except ValidationError as e:
|
53 |
return False, f"Template validation error: {e.message}"
|
54 |
|
|
|
55 |
def resolve_template_expressions(template):
|
56 |
def resolve_expression(match):
|
57 |
expr = match.group(1)
|
@@ -66,6 +69,7 @@ def resolve_template_expressions(template):
|
|
66 |
resolved_str = re.sub(r'\[(\w+\.\w+)\]', resolve_expression, template_str)
|
67 |
return json.loads(resolved_str)
|
68 |
|
|
|
69 |
def estimate_cost(resources):
|
70 |
# This is a simplified cost estimation. In a real scenario, you'd need to
|
71 |
# integrate with Azure's pricing API or use a more comprehensive pricing model.
|
@@ -87,6 +91,7 @@ def estimate_cost(resources):
|
|
87 |
|
88 |
return total_cost
|
89 |
|
|
|
90 |
def create_dependency_graph(resources):
|
91 |
G = nx.DiGraph()
|
92 |
for resource in resources:
|
@@ -97,6 +102,7 @@ def create_dependency_graph(resources):
|
|
97 |
G.add_edge(dep, resource_name)
|
98 |
return G
|
99 |
|
|
|
100 |
def plot_dependency_graph(G):
|
101 |
plt.figure(figsize=(12, 8))
|
102 |
pos = nx.spring_layout(G)
|
@@ -107,6 +113,7 @@ def plot_dependency_graph(G):
|
|
107 |
plt.title("Resource Dependency Graph")
|
108 |
return plt
|
109 |
|
|
|
110 |
def lint_template(template):
|
111 |
lint_results = []
|
112 |
|
@@ -128,26 +135,30 @@ def lint_template(template):
|
|
128 |
|
129 |
return lint_results
|
130 |
|
|
|
131 |
def generate_system_diagram(resources):
|
132 |
-
|
133 |
-
|
134 |
-
|
|
|
135 |
# Create nodes for each resource
|
136 |
for i, resource in enumerate(resources):
|
137 |
resource_type = resource['type'].split('/')[-1]
|
138 |
node_id = f"R{i}"
|
139 |
-
|
140 |
-
|
141 |
-
|
142 |
# Create connections based on dependencies
|
143 |
for resource in resources:
|
144 |
if 'dependsOn' in resource:
|
145 |
for dependency in resource['dependsOn']:
|
146 |
-
|
147 |
-
|
148 |
-
|
149 |
-
|
|
|
|
|
150 |
|
|
|
151 |
def simulate_deployment(arm_template):
|
152 |
try:
|
153 |
template = json.loads(arm_template)
|
@@ -155,7 +166,7 @@ def simulate_deployment(arm_template):
|
|
155 |
# Validate template
|
156 |
is_valid, validation_message = validate_template(template)
|
157 |
if not is_valid:
|
158 |
-
return [], [], [], [], 0, None, [],
|
159 |
|
160 |
# Resolve expressions
|
161 |
resolved_template = resolve_template_expressions(template)
|
@@ -208,7 +219,7 @@ def simulate_deployment(arm_template):
|
|
208 |
|
209 |
return resources_to_create, resources_to_update, resources_to_delete, resource_details, estimated_cost, dependency_graph, lint_results, system_diagram, "Simulation completed successfully."
|
210 |
except json.JSONDecodeError:
|
211 |
-
return [], [], [], [], 0, None, [],
|
212 |
|
213 |
# Streamlit UI
|
214 |
st.title("Comprehensive ARM Template Simulator")
|
@@ -284,7 +295,7 @@ if st.button("Simulate Template"):
|
|
284 |
|
285 |
st.write("### System Diagram:")
|
286 |
if system_diagram:
|
287 |
-
st.
|
288 |
else:
|
289 |
st.write("Unable to generate system diagram.")
|
290 |
|
|
|
5 |
import networkx as nx
|
6 |
import matplotlib.pyplot as plt
|
7 |
import io
|
8 |
+
import graphviz
|
9 |
|
10 |
# Mock existing resources (customizable)
|
11 |
existing_resources = {
|
|
|
46 |
"required": ["$schema", "contentVersion", "resources"]
|
47 |
}
|
48 |
|
49 |
+
# Function to validate the ARM template against the schema
|
50 |
def validate_template(template):
|
51 |
try:
|
52 |
validate(instance=template, schema=arm_schema)
|
|
|
54 |
except ValidationError as e:
|
55 |
return False, f"Template validation error: {e.message}"
|
56 |
|
57 |
+
# Function to resolve template expressions (like parameters and variables)
|
58 |
def resolve_template_expressions(template):
|
59 |
def resolve_expression(match):
|
60 |
expr = match.group(1)
|
|
|
69 |
resolved_str = re.sub(r'\[(\w+\.\w+)\]', resolve_expression, template_str)
|
70 |
return json.loads(resolved_str)
|
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.
|
|
|
91 |
|
92 |
return total_cost
|
93 |
|
94 |
+
# Function to create a dependency graph of resources
|
95 |
def create_dependency_graph(resources):
|
96 |
G = nx.DiGraph()
|
97 |
for resource in resources:
|
|
|
102 |
G.add_edge(dep, resource_name)
|
103 |
return G
|
104 |
|
105 |
+
# Function to plot the dependency graph
|
106 |
def plot_dependency_graph(G):
|
107 |
plt.figure(figsize=(12, 8))
|
108 |
pos = nx.spring_layout(G)
|
|
|
113 |
plt.title("Resource Dependency Graph")
|
114 |
return plt
|
115 |
|
116 |
+
# Function to lint the ARM template
|
117 |
def lint_template(template):
|
118 |
lint_results = []
|
119 |
|
|
|
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)}")
|
158 |
+
|
159 |
+
return dot
|
160 |
|
161 |
+
# Main function to simulate the deployment
|
162 |
def simulate_deployment(arm_template):
|
163 |
try:
|
164 |
template = json.loads(arm_template)
|
|
|
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)
|
|
|
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."
|
221 |
except json.JSONDecodeError:
|
222 |
+
return [], [], [], [], 0, None, [], None, "Invalid JSON format. Please check your ARM template."
|
223 |
|
224 |
# Streamlit UI
|
225 |
st.title("Comprehensive ARM Template Simulator")
|
|
|
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 |
|