diff --git a/omnibus/config/software/cacerts.rb b/omnibus/config/software/cacerts.rb index 56fb5732c2ed..3805ab1503f2 100644 --- a/omnibus/config/software/cacerts.rb +++ b/omnibus/config/software/cacerts.rb @@ -25,13 +25,11 @@ # doing this. name "cacerts" -# We have a synthetic monitor on the latest cacerts file to warn us when the latest -# cacerts bundle changes. -# This allows us to always use up-to-date cacerts, without breaking all builds -# when they change. -default_version "latest" -source url: "https://curl.se/ca/cacert.pem", - sha256: "f66dff1bdf8f96060b8177976f8b7d9254bc89bc4db933d769f7384d28480bc9", +# Pinned to a dated curl release: the moving cacert.pem breaks every build when +# curl publishes a new bundle, and this fork has no monitor for it. +default_version "2026-09-25" +source url: "https://curl.se/ca/cacert-#{version}.pem", + sha256: "a41b5d356aea97a529fe27e0f7316d2f9d946d75927476cf9cf1b90637d00505", target_filename: "cacert.pem" relative_path "cacerts-#{version}" diff --git a/pkg/collector/corechecks/cluster/topologycollectors/persistent_volume_collector.go b/pkg/collector/corechecks/cluster/topologycollectors/persistent_volume_collector.go index 2ecd44c8620a..f1f779c47512 100644 --- a/pkg/collector/corechecks/cluster/topologycollectors/persistent_volume_collector.go +++ b/pkg/collector/corechecks/cluster/topologycollectors/persistent_volume_collector.go @@ -51,6 +51,10 @@ func (pvc *PersistentVolumeCollector) CollectorFunction() error { // Produce a map t nodeByPersistentVolume := make(map[string]string) for _, va := range volumeAttachments { + // Inline-spec attachments (CSI migration) have no PersistentVolume to relate to. + if va.Spec.Source.PersistentVolumeName == nil { + continue + } nodeByPersistentVolume[*va.Spec.Source.PersistentVolumeName] = va.Spec.NodeName } @@ -83,6 +87,9 @@ func (pvc *PersistentVolumeCollector) CollectorFunction() error { } for _, va := range volumeAttachments { + if va.Spec.Source.PersistentVolumeName == nil { + continue + } persistentVolumeExternalID := pvc.buildPersistentVolumeExternalID(*va.Spec.Source.PersistentVolumeName) nodeExternalID := pvc.buildNodeExternalID(va.Spec.NodeName) pvc.SubmitRelation(pvc.nodeToPersistentVolumeStackStateRelation(nodeExternalID, persistentVolumeExternalID)) diff --git a/pkg/collector/corechecks/cluster/topologycollectors/persistent_volume_inline_attachment_test.go b/pkg/collector/corechecks/cluster/topologycollectors/persistent_volume_inline_attachment_test.go new file mode 100644 index 000000000000..525c842141ee --- /dev/null +++ b/pkg/collector/corechecks/cluster/topologycollectors/persistent_volume_inline_attachment_test.go @@ -0,0 +1,87 @@ +//go:build kubeapiserver + +package topologycollectors + +import ( + "fmt" + "testing" + + "github.com/StackVista/stackstate-receiver-go-client/pkg/model/topology" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + coreV1 "k8s.io/api/core/v1" + storageV1 "k8s.io/api/storage/v1" + v1 "k8s.io/apimachinery/pkg/apis/meta/v1" +) + +func TestPersistentVolumeCollectorSkipsInlineVolumeAttachments(t *testing.T) { + componentChannel := make(chan *topology.Component) + relationChannel := make(chan *topology.Relation) + + ebs := coreV1.AWSElasticBlockStoreVolumeSource{VolumeID: "id-of-the-aws-block-store"} + inline := storageV1.VolumeAttachment{ + ObjectMeta: v1.ObjectMeta{Name: "csi-inline"}, + Spec: storageV1.VolumeAttachmentSpec{ + Attacher: "ebs.csi.aws.com", + NodeName: "test-node-2", + Source: storageV1.VolumeAttachmentSource{ + InlineVolumeSpec: &coreV1.PersistentVolumeSpec{ + PersistentVolumeSource: coreV1.PersistentVolumeSource{ + CSI: &coreV1.CSIPersistentVolumeSource{Driver: "ebs.csi.aws.com", VolumeHandle: "vol-inline"}, + }, + }, + }, + }, + } + client := &MockPersistentVolumeAPICollectorClient{ + getPersistentVolumes: func() ([]coreV1.PersistentVolume, error) { + pv := NewTestPV("aws-elastic-block-store-volume") + pv.Spec.PersistentVolumeSource = coreV1.PersistentVolumeSource{AWSElasticBlockStore: &ebs} + return []coreV1.PersistentVolume{pv}, nil + }, + getPersistentVolumeClaims: func() ([]coreV1.PersistentVolumeClaim, error) { + return []coreV1.PersistentVolumeClaim{}, nil + }, + getVolumeAttachments: func() ([]storageV1.VolumeAttachment, error) { + return []storageV1.VolumeAttachment{inline, NewTestVolumeAttachment("aws-elastic-block-store-volume")}, nil + }, + } + common := NewTestCommonClusterCollector(client, componentChannel, relationChannel) + common.SetUseRelationCache(false) + collector := NewPersistentVolumeCollector(common, true) + + done := make(chan error, 1) + go func() { + defer func() { + if r := recover(); r != nil { + done <- fmt.Errorf("collector panicked: %v", r) + } + }() + done <- collector.CollectorFunction() + }() + + var persistentVolume *topology.Component + var nodeRelations []*topology.Relation + for { + select { + case component := <-componentChannel: + if component.Type.Name == "persistent-volume" { + persistentVolume = component + } + case relation := <-relationChannel: + if relation.SourceID == "urn:kubernetes:/test-cluster-name:node/test-node-1" || + relation.SourceID == "urn:kubernetes:/test-cluster-name:node/test-node-2" { + nodeRelations = append(nodeRelations, relation) + } + case err := <-done: + require.NoError(t, err) + require.NotNil(t, persistentVolume) + tags, ok := persistentVolume.Data["tags"].(map[string]string) + require.True(t, ok) + assert.Equal(t, "test-node-1", tags["persistent-volume-node"]) + require.Len(t, nodeRelations, 1, "only the attachment naming a PersistentVolume relates a node to it") + assert.Equal(t, "urn:kubernetes:/test-cluster-name:persistent-volume/aws-elastic-block-store-volume", nodeRelations[0].TargetID) + return + } + } +}