diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index b78a8de..e8befcd 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -21,7 +21,7 @@ jobs: - name: Checkout repository uses: actions/checkout@v3 - name: Install toolchain - uses: dtolnay/rust-toolchain@v1 + uses: dtolnay/rust-toolchain@nightly with: toolchain: stable - name: Cache Dependencies @@ -37,7 +37,7 @@ jobs: - name: Checkout repository uses: actions/checkout@v3 - name: Install toolchain - uses: dtolnay/rust-toolchain@stable + uses: dtolnay/rust-toolchain@nightly with: toolchain: stable components: rustfmt diff --git a/src/manifest.rs b/src/manifest.rs index 6462d3a..aa95b1c 100644 --- a/src/manifest.rs +++ b/src/manifest.rs @@ -5,7 +5,7 @@ use crate::prelude::*; use std::fs; use std::path::PathBuf; use yaml_rust::yaml::Hash; -use yaml_rust::{Yaml, YamlLoader}; +use yaml_rust::{Yaml, YamlEmitter, YamlLoader}; #[derive(Debug, Clone)] pub struct Manifest { @@ -31,7 +31,7 @@ impl Manifest { return Err(anyhow!("Path is a directory {}", path.as_path().display())); } - let raw = fs::read_to_string(path.as_path())?; + let mut raw = fs::read_to_string(path.as_path())?; let mut docs = YamlLoader::load_from_str(&raw)?; if docs.is_empty() { @@ -55,7 +55,33 @@ impl Manifest { metadata.remove(&Yaml::String(String::from("managedFields"))); ycopy.remove(&Yaml::String(String::from("metadata"))); ycopy.insert(Yaml::String(String::from("metadata")), Yaml::Hash(metadata)); + + // we want to make sure that the display of the raw file is in a familiar format + // to accomplish that, we want the metadata field to appear first, then spec, then status + let spec = ycopy[&Yaml::String(String::from("spec"))] + .as_hash() + .unwrap_or(&Hash::new()) + .clone(); + ycopy.remove(&Yaml::String(String::from("spec"))); + ycopy.insert(Yaml::String(String::from("spec")), Yaml::Hash(spec)); + let status = ycopy[&Yaml::String(String::from("status"))] + .as_hash() + .unwrap_or(&Hash::new()) + .clone(); + ycopy.remove(&Yaml::String(String::from("status"))); + ycopy.insert(Yaml::String(String::from("status")), Yaml::Hash(status)); + yaml = Yaml::Hash(ycopy); + let mut out_str = String::new(); + let mut emitter = YamlEmitter::new(&mut out_str); + // if we have an error creating the string, default to using the original + raw = match emitter.dump(&yaml) { + Ok(()) => { + out_str.push('\n'); + out_str + } + Err(_) => raw, + }; } Ok(Manifest { name, raw, yaml }) } @@ -137,8 +163,7 @@ mod tests { #[test] fn test_manifest_as_raw() { - let expected = include_str!( - "../testdata/must-gather-valid/sample-openshift-release/cluster-scoped-resources/core/nodes/ip-10-0-0-1.control.plane.yaml"); + let expected = include_str!("../testdata/ip-10-0-0-1.control.plane.no-managed-fields.yaml"); let manifest = Manifest::from(PathBuf::from( "testdata/must-gather-valid/sample-openshift-release/cluster-scoped-resources/core/nodes/ip-10-0-0-1.control.plane.yaml" )).unwrap(); diff --git a/testdata/ip-10-0-0-1.control.plane.no-managed-fields.yaml b/testdata/ip-10-0-0-1.control.plane.no-managed-fields.yaml new file mode 100755 index 0000000..3af0c70 --- /dev/null +++ b/testdata/ip-10-0-0-1.control.plane.no-managed-fields.yaml @@ -0,0 +1,101 @@ +--- +apiVersion: v1 +kind: Node +metadata: + annotations: + machine.openshift.io/machine: openshift-machine-api/control-plane1 + machineconfiguration.openshift.io/controlPlaneTopology: HighlyAvailable + machineconfiguration.openshift.io/currentConfig: rendered-master-0 + machineconfiguration.openshift.io/desiredConfig: rendered-master-0 + machineconfiguration.openshift.io/reason: "" + machineconfiguration.openshift.io/state: Done + nfd.node.kubernetes.io/master.version: "1.16" + volumes.kubernetes.io/controller-managed-attach-detach: "true" + creationTimestamp: "2022-01-01T00:00:00Z" + labels: + beta.kubernetes.io/arch: amd64 + beta.kubernetes.io/instance-type: xlarge + beta.kubernetes.io/os: linux + failure-domain.beta.kubernetes.io/region: region-1 + failure-domain.beta.kubernetes.io/zone: zone-1 + kubernetes.io/arch: amd64 + kubernetes.io/hostname: ip-10-0-0-1.control.plane + kubernetes.io/os: linux + node-role.kubernetes.io/master: "" + node.kubernetes.io/instance-type: xlarge + node.openshift.io/os_id: rhcos + topology.kubernetes.io/region: region-1 + topology.kubernetes.io/zone: zone-1 + name: ip-10-0-0-1.control.plane + resourceVersion: "89485" + uid: 00000000-0000-0000-0000-000000000000 +spec: + providerID: "fake://ip-10-0-0-1.control.plane" + taints: + - effect: NoSchedule + key: node-role.kubernetes.io/master +status: + addresses: + - address: 10.0.0.1 + type: InternalIP + - address: ip-10-0-0-1.control.plane + type: Hostname + - address: ip-10-0-0-1.control.plane + type: InternalDNS + allocatable: + cpu: 3500m + ephemeral-storage: "115470533646" + hugepages-1Gi: "0" + hugepages-2Mi: "0" + memory: 14955324Ki + pods: "250" + capacity: + cpu: "4" + ephemeral-storage: 125293548Ki + hugepages-1Gi: "0" + hugepages-2Mi: "0" + memory: 16106300Ki + pods: "250" + conditions: + - lastHeartbeatTime: "2022-01-01T00:00:00Z" + lastTransitionTime: "2022-01-01T00:00:00Z" + message: kubelet has sufficient memory available + reason: KubeletHasSufficientMemory + status: "False" + type: MemoryPressure + - lastHeartbeatTime: "2022-01-01T00:00:00Z" + lastTransitionTime: "2022-01-01T00:00:00Z" + message: kubelet has no disk pressure + reason: KubeletHasNoDiskPressure + status: "False" + type: DiskPressure + - lastHeartbeatTime: "2022-01-01T00:00:00Z" + lastTransitionTime: "2022-01-01T00:00:00Z" + message: kubelet has sufficient PID available + reason: KubeletHasSufficientPID + status: "False" + type: PIDPressure + - lastHeartbeatTime: "2022-01-01T00:00:00Z" + lastTransitionTime: "2022-01-01T00:00:00Z" + message: kubelet is posting ready status + reason: KubeletReady + status: "True" + type: Ready + daemonEndpoints: + kubeletEndpoint: + Port: 10250 + images: + - names: + - quay.io/openshift-release-dev/ocp-v4.0-art-dev + sizeBytes: 1139449201 + nodeInfo: + architecture: amd64 + bootID: 00000000-0000-0000-0000-000000000000 + containerRuntimeVersion: "cri-o://1.24.alpha.fake" + kernelVersion: 5.fake + kubeProxyVersion: v1.24 + kubeletVersion: v1.24 + machineID: 493810f75ca55b6099ceec0c9373f2fe + operatingSystem: linux + osImage: Linux + systemUUID: 00000000-0000-0000-0000-000000000000 diff --git a/testdata/must-gather-valid/sample-openshift-release/cluster-scoped-resources/core/nodes/ip-10-0-0-1.control.plane.yaml b/testdata/must-gather-valid/sample-openshift-release/cluster-scoped-resources/core/nodes/ip-10-0-0-1.control.plane.yaml index eabd026..52aa03d 100755 --- a/testdata/must-gather-valid/sample-openshift-release/cluster-scoped-resources/core/nodes/ip-10-0-0-1.control.plane.yaml +++ b/testdata/must-gather-valid/sample-openshift-release/cluster-scoped-resources/core/nodes/ip-10-0-0-1.control.plane.yaml @@ -143,7 +143,7 @@ status: kernelVersion: 5.fake kubeProxyVersion: v1.24 kubeletVersion: v1.24 - machineID: 00000000000000000000000000000000 + machineID: 493810f75ca55b6099ceec0c9373f2fe operatingSystem: linux osImage: Linux systemUUID: 00000000-0000-0000-0000-000000000000