Skip to content

Commit 793f15d

Browse files
authored
Add ports field to FluentBitSpec (anvil-verifier#435)
Signed-off-by: Wenjie Ma <[email protected]>
1 parent eab1405 commit 793f15d

File tree

10 files changed

+148
-20
lines changed

10 files changed

+148
-20
lines changed

deploy/fluent/crd.yaml

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1560,6 +1560,32 @@ spec:
15601560
type: string
15611561
default: {}
15621562
type: object
1563+
ports:
1564+
items:
1565+
description: ContainerPort represents a network port in a single container.
1566+
properties:
1567+
containerPort:
1568+
description: "Number of port to expose on the pod's IP address. This must be a valid port number, 0 < x < 65536."
1569+
format: int32
1570+
type: integer
1571+
hostIP:
1572+
description: What host IP to bind the external port to.
1573+
type: string
1574+
hostPort:
1575+
description: "Number of port to expose on the host. If specified, this must be a valid port number, 0 < x < 65536. If HostNetwork is specified, this must match ContainerPort. Most containers do not need this."
1576+
format: int32
1577+
type: integer
1578+
name:
1579+
description: "If specified, this must be an IANA_SVC_NAME and unique within the pod. Each named port in a pod must have a unique name. Name for the port that can be referred to by services."
1580+
type: string
1581+
protocol:
1582+
description: "Protocol for port. Must be UDP, TCP, or SCTP. Defaults to \"TCP\".\n\n"
1583+
type: string
1584+
required:
1585+
- containerPort
1586+
type: object
1587+
nullable: true
1588+
type: array
15631589
positionDB:
15641590
description: Represents a host path mapped into a pod. Host path volumes do not support ownership management or SELinux relabeling.
15651591
nullable: true

e2e/src/fluent_e2e.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,12 @@ pub fn fluent_bit() -> String {
3535
image: kubesphere/fluent-bit:v2.1.7
3636
tolerations:
3737
- operator: Exists
38+
ports:
39+
- name: forward
40+
containerPort: 24224
41+
protocol: TCP
42+
- containerPort: 8443
43+
name: https
3844
"
3945
.to_string()
4046
}

src/controller_examples/fluent_controller/fluentbit/exec/resource/daemon_set.rs

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -249,7 +249,11 @@ fn make_fluentbit_pod_spec(fb: &FluentBit) -> (pod_spec: PodSpec)
249249
volume_mounts
250250
});
251251
fb_container.set_ports({
252-
let mut ports = Vec::new();
252+
let mut ports = if fb.spec().ports().is_some() {
253+
fb.spec().ports().unwrap()
254+
} else {
255+
Vec::new()
256+
};
253257
let metrics_port = if fb.spec().metrics_port().is_some() { fb.spec().metrics_port().unwrap() } else { 2020 };
254258
ports.push(ContainerPort::new_with(new_strlit("metrics").to_string(), metrics_port));
255259
proof {
@@ -340,7 +344,7 @@ fn make_fluentbit_pod_spec(fb: &FluentBit) -> (pod_spec: PodSpec)
340344
volume
341345
});
342346
}
343-
347+
344348
proof {
345349
assert_seqs_equal!(
346350
volumes@.map_values(|vol: Volume| vol@),
@@ -389,5 +393,4 @@ fn make_env(fb: &FluentBit) -> (env_vars: Vec<EnvVar>)
389393
env_vars
390394
}
391395

392-
393396
}

src/controller_examples/fluent_controller/fluentbit/exec/resource/service.rs

Lines changed: 69 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -131,17 +131,25 @@ pub fn make_service(fb: &FluentBit) -> (service: Service)
131131
service.set_spec({
132132
let mut service_spec = ServiceSpec::default();
133133
service_spec.set_ports({
134-
let mut ports = Vec::new();
135-
ports.push({
136-
let mut port = ServicePort::default();
137-
port.set_name(new_strlit("metrics").to_string());
138-
if fb.spec().metrics_port().is_some() {
139-
port.set_port(fb.spec().metrics_port().unwrap());
134+
let mut ports = if fb.spec().ports().is_some() {
135+
make_new_ports(fb.spec().ports().unwrap())
140136
} else {
141-
port.set_port(2020);
142-
}
143-
port
144-
});
137+
Vec::new()
138+
};
139+
let mut port = ServicePort::default();
140+
port.set_name(new_strlit("metrics").to_string());
141+
if fb.spec().metrics_port().is_some() {
142+
port.set_port(fb.spec().metrics_port().unwrap());
143+
} else {
144+
port.set_port(2020);
145+
}
146+
proof {
147+
assert_seqs_equal!(
148+
ports@.map_values(|port: ServicePort| port@).push(port@),
149+
model_resource::make_service(fb@).spec.get_Some_0().ports.get_Some_0()
150+
);
151+
}
152+
ports.push(port);
145153
proof {
146154
assert_seqs_equal!(
147155
ports@.map_values(|port: ServicePort| port@),
@@ -156,4 +164,55 @@ pub fn make_service(fb: &FluentBit) -> (service: Service)
156164
service
157165
}
158166

167+
fn make_new_ports(ports: Vec<ContainerPort>) -> (service_ports: Vec<ServicePort>)
168+
ensures service_ports@.map_values(|p: ServicePort| p@) == ports@.map_values(|p: ContainerPort| model_resource::make_service_port(p@)),
169+
{
170+
let mut service_ports = Vec::new();
171+
let mut i = 0;
172+
proof {
173+
assert_seqs_equal!(
174+
service_ports@.map_values(|p: ServicePort| p@),
175+
Seq::new(i as nat, |k: int| model_resource::make_service_port(ports[k]@))
176+
);
177+
}
178+
while i < ports.len()
179+
invariant
180+
i <= ports@.len(),
181+
service_ports@.map_values(|p: ServicePort| p@) == Seq::new(i as nat, |k: int| model_resource::make_service_port(ports[k]@)),
182+
ensures
183+
service_ports@.map_values(|p: ServicePort| p@) == Seq::new(ports@.len(), |k: int| model_resource::make_service_port(ports[k]@)),
184+
{
185+
let port = &ports[i];
186+
let mut service_port = ServicePort::default();
187+
service_port.set_port(port.container_port());
188+
if port.name().is_some() {
189+
service_port.set_name(port.name().unwrap());
190+
}
191+
if port.protocol().is_some() {
192+
service_port.set_protocol(port.protocol().unwrap());
193+
}
194+
service_ports.push(service_port);
195+
proof {
196+
assert(service_port@ == model_resource::make_service_port(port@));
197+
assert_seqs_equal!(
198+
service_ports@.map_values(|p: ServicePort| p@),
199+
Seq::new(i as nat, |k: int| model_resource::make_service_port(ports[k]@)).push(service_port@)
200+
);
201+
assert_seqs_equal!(
202+
Seq::new(i as nat, |k: int| model_resource::make_service_port(ports[k]@)).push(service_port@),
203+
Seq::new((i + 1) as nat, |k: int| model_resource::make_service_port(ports[k]@))
204+
);
205+
}
206+
i = i + 1;
207+
}
208+
proof {
209+
assert_seqs_equal!(
210+
ports@.map_values(|p: ContainerPort| model_resource::make_service_port(p@)),
211+
Seq::new(ports@.len(), |k: int| model_resource::make_service_port(ports[k]@))
212+
);
213+
}
214+
215+
service_ports
216+
}
217+
159218
}

src/controller_examples/fluent_controller/fluentbit/model/resource/daemon_set.rs

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -238,14 +238,19 @@ pub open spec fn make_fluentbit_pod_spec(fb: FluentBitView) -> PodSpecView {
238238
}
239239
}
240240
}),
241-
ports: Some(seq![
242-
ContainerPortView::default()
241+
ports: {
242+
let metrics_port = ContainerPortView::default()
243243
.set_name(new_strlit("metrics")@)
244244
.set_container_port({
245245
let port = if fb.spec.metrics_port.is_Some() { fb.spec.metrics_port.get_Some_0() } else { 2020 };
246246
port
247-
}),
248-
]),
247+
});
248+
if fb.spec.ports.is_Some() {
249+
Some(fb.spec.ports.get_Some_0().push(metrics_port))
250+
} else {
251+
Some(seq![metrics_port])
252+
}
253+
},
249254
resources: fb.spec.resources,
250255
args: if fb.spec.args.is_Some() {
251256
fb.spec.args

src/controller_examples/fluent_controller/fluentbit/model/resource/service.rs

Lines changed: 17 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -101,22 +101,36 @@ pub open spec fn make_service(fb: FluentBitView) -> ServiceView {
101101
..ObjectMetaView::default()
102102
},
103103
spec: Some(ServiceSpecView {
104-
ports: Some(seq![
105-
ServicePortView {
104+
ports: {
105+
let metrics_port = ServicePortView {
106106
name: Some(new_strlit("metrics")@),
107107
port: if fb.spec.metrics_port.is_Some() {
108108
fb.spec.metrics_port.get_Some_0()
109109
} else {
110110
2020
111111
},
112112
..ServicePortView::default()
113+
};
114+
if fb.spec.ports.is_Some() {
115+
Some(fb.spec.ports.get_Some_0().map_values(|p: ContainerPortView| make_service_port(p)).push(metrics_port))
116+
} else {
117+
Some(seq![metrics_port])
113118
}
114-
]),
119+
},
115120
selector: Some(make_base_labels(fb)),
116121
..ServiceSpecView::default()
117122
}),
118123
..ServiceView::default()
119124
}
120125
}
121126

127+
pub open spec fn make_service_port(port: ContainerPortView) -> ServicePortView {
128+
ServicePortView {
129+
port: port.container_port,
130+
name: if port.name.is_Some() { port.name } else { ServicePortView::default().name },
131+
protocol: if port.protocol.is_Some() { port.protocol } else { ServicePortView::default().protocol },
132+
..ServicePortView::default()
133+
}
134+
}
135+
122136
}

src/controller_examples/fluent_controller/fluentbit/proof/helper_invariants/proof.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -175,6 +175,7 @@ pub proof fn lemma_eventually_always_every_resource_update_request_implies_at_af
175175
leads_to_always_tla_forall_subresource(spec, true_pred(), |sub_resource: SubResource| lift_state(every_resource_update_request_implies_at_after_update_resource_step(sub_resource, fb)));
176176
}
177177

178+
#[verifier(spinoff_prover)]
178179
pub proof fn make_fluentbit_pod_spec_determined_by_spec_and_name(fb1: FluentBitView, fb2: FluentBitView)
179180
requires
180181
fb1.metadata.name.get_Some_0() == fb2.metadata.name.get_Some_0(),

src/controller_examples/fluent_controller/fluentbit/trusted/exec_types.rs

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -448,6 +448,18 @@ impl FluentBitSpec {
448448
None => None,
449449
}
450450
}
451+
452+
#[verifier(external_body)]
453+
pub fn ports(&self) -> (ports: Option<Vec<ContainerPort>>)
454+
ensures
455+
self@.ports.is_Some() == ports.is_Some(),
456+
ports.is_Some() ==> ports.get_Some_0()@.map_values(|c: ContainerPort| c@) == self@.ports.get_Some_0(),
457+
{
458+
match &self.inner.ports {
459+
Some(ports) => Some(ports.clone().into_iter().map(|c: deps_hack::k8s_openapi::api::core::v1::ContainerPort| ContainerPort::from_kube(c)).collect()),
460+
None => None,
461+
}
462+
}
451463
}
452464

453465
}

src/controller_examples/fluent_controller/fluentbit/trusted/spec_types.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -171,6 +171,7 @@ pub struct FluentBitSpecView {
171171
pub liveness_probe: Option<ProbeView>,
172172
pub readiness_probe: Option<ProbeView>,
173173
pub init_containers: Option<Seq<ContainerView>>,
174+
pub ports: Option<Seq<ContainerPortView>>,
174175
}
175176

176177
}

src/deps_hack/src/lib.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -251,6 +251,7 @@ pub struct FluentBitSpec {
251251
pub readiness_probe: Option<k8s_openapi::api::core::v1::Probe>,
252252
#[serde(rename = "initContainers")]
253253
pub init_containers: Option<Vec<k8s_openapi::api::core::v1::Container>>,
254+
pub ports: Option<Vec<k8s_openapi::api::core::v1::ContainerPort>>,
254255
}
255256

256257
#[derive(

0 commit comments

Comments
 (0)