Skip to content

Commit de09874

Browse files
Lionel-Wilsonactions-user
authored andcommitted
feat: create Elastic SAN volume snapshot adapter (#4209)
<img width="2934" height="1992" alt="image" src="https://github.com/user-attachments/assets/b29c553f-4169-478a-8f1a-04f4b5caf8b1" /> <!-- CURSOR_SUMMARY --> --- > [!NOTE] > **Medium Risk** > Introduces a new Azure resource adapter and changes GET query parsing for Azure to accept full resource IDs, which could affect query behavior for Azure adapters if path-key mappings are missing or incorrect. > > **Overview** > Adds a new Azure adapter for Elastic SAN volume snapshots, including an Azure SDK client wrapper, lookups/linking to parent Elastic SAN/volume group (and source volume when available), Terraform mappings, and unit tests/mocks. > > Extends the core `standardAdapterCore.Get` path parsing to accept full Azure resource IDs (e.g. from Terraform mappings) by extracting query parts based on per-type path key definitions, returning explicit query errors when unsupported. > > Also updates dependencies (`armelasticsan`), registers the new adapter in `azure/manual/adapters.go`, adds ElasticSAN item types/resources + resourceID path-key mapping, tightens k8s `Endpoints` staticcheck suppressions, and makes multiple tests safer by returning after `t.Fatal`/`t.Fatalf` to avoid nil dereferences. > > <sup>Written by [Cursor Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit c7e10ad43d6ec2031feae80015364980a25527af. This will update automatically on new commits. Configure [here](https://cursor.com/dashboard?tab=bugbot).</sup> <!-- /CURSOR_SUMMARY --> GitOrigin-RevId: 97899d2e8b23eae053e5a6612affd3df5d872e73
1 parent 0aedf74 commit de09874

19 files changed

Lines changed: 658 additions & 8 deletions

aws-source/adapters/ecs-task_test.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -124,6 +124,7 @@ func TestTaskGetInputMapper(t *testing.T) {
124124

125125
if input == nil {
126126
t.Fatal("input is nil")
127+
return
127128
}
128129

129130
if *input.Cluster != "test-ECSCluster-Bt4SqcM3CURk" {

cmd/auth_client_test.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -208,6 +208,7 @@ func TestNewRetryableHTTPClientRespectsProxy(t *testing.T) {
208208

209209
if httpTransport == nil {
210210
t.Fatal("Could not get http.Transport")
211+
return
211212
}
212213

213214
// Verify proxy function is set to ProxyFromEnvironment

cmd/explore_test.go

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,7 @@ func TestUnifiedGCPConfigs(t *testing.T) {
6060

6161
if foundConfig == nil {
6262
t.Fatalf("Could not find config for project %s in result", originalConfig.ProjectID)
63+
return
6364
}
6465

6566
if !reflect.DeepEqual(foundConfig.Regions, originalConfig.Regions) {
@@ -115,9 +116,11 @@ func TestUnifiedGCPConfigs(t *testing.T) {
115116

116117
if unifiedConfig == nil {
117118
t.Fatal("Could not find unified-project config in result")
119+
return
118120
}
119121
if differentConfig == nil {
120122
t.Fatal("Could not find different-project config in result")
123+
return
121124
}
122125

123126
// Verify unified config has all regions
@@ -315,9 +318,11 @@ func TestUnifiedAzureConfigs(t *testing.T) {
315318

316319
if unifiedConfig == nil {
317320
t.Fatal("Could not find config for subscription 00000000-0000-0000-0000-000000000001 in result")
321+
return
318322
}
319323
if differentConfig == nil {
320324
t.Fatal("Could not find config for subscription 00000000-0000-0000-0000-000000000002 in result")
325+
return
321326
}
322327

323328
// Verify the first config was kept (tenant-first, client-first)

go.mod

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@ require (
5050
github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/compute/armcompute/v7 v7.3.0
5151
github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/cosmos/armcosmos/v3 v3.4.0
5252
github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/dns/armdns v1.2.0
53+
github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/elasticsan/armelasticsan v1.2.0
5354
github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/keyvault/armkeyvault/v2 v2.0.1
5455
github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/msi/armmsi v1.3.0
5556
github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/network/armnetwork/v9 v9.0.0

go.sum

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -124,6 +124,8 @@ github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/cosmos/armcosmos/v3 v3.4.0
124124
github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/cosmos/armcosmos/v3 v3.4.0/go.mod h1:Bb7kqorvA2acMCNFac+2ldoQWi7QrcMdH+9Gg9C7fSM=
125125
github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/dns/armdns v1.2.0 h1:lpOxwrQ919lCZoNCd69rVt8u1eLZuMORrGXqy8sNf3c=
126126
github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/dns/armdns v1.2.0/go.mod h1:fSvRkb8d26z9dbL40Uf/OO6Vo9iExtZK3D0ulRV+8M0=
127+
github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/elasticsan/armelasticsan v1.2.0 h1:8xYBtaMs3Msy1bFYTVrVFBh05JUGNMMP/v3z3x5hoIw=
128+
github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/elasticsan/armelasticsan v1.2.0/go.mod h1:bXxc3uCnIUCh68pl4njcH45qUgRuR0kZfR6v06k18/A=
127129
github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/internal/v3 v3.1.1 h1:1kpY4qe+BGAH2ykv4baVSqyx+AY5VjXeJ15SldlU6hs=
128130
github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/internal/v3 v3.1.1/go.mod h1:nT6cWpWdUt+g81yuKmjeYPUtI73Ak3yQIT4PVVsCEEQ=
129131
github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/keyvault/armkeyvault/v2 v2.0.1 h1:nFZ7AvJqTpWobmnZlprsK6GucrByFsXWB+DwkhRxM9I=

go/discovery/adapter_test.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -708,6 +708,7 @@ func TestNewQueryResultStream(t *testing.T) {
708708
// Test Initialization
709709
if stream == nil {
710710
t.Fatal("Expected stream to be initialized, got nil")
711+
return
711712
}
712713
if stream.itemHandler == nil || stream.errHandler == nil {
713714
t.Fatal("Expected handlers to be set")

k8s-source/adapters/endpoints.go

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@
77
// and acceptable. When the SDK eventually drops support for v1.Endpoints we
88
// will need to split out version-specific builds of the k8s-source.
99

10-
//nolint:staticcheck // See note at top of file
1110
package adapters
1211

1312
import (
@@ -18,7 +17,7 @@ import (
1817
"k8s.io/client-go/kubernetes"
1918
)
2019

21-
func EndpointsExtractor(resource *v1.Endpoints, scope string) ([]*sdp.LinkedItemQuery, error) {
20+
func EndpointsExtractor(resource *v1.Endpoints, scope string) ([]*sdp.LinkedItemQuery, error) { //nolint:staticcheck,nolintlint // SA1019: v1.Endpoints deprecated; see note at top of file
2221
queries := make([]*sdp.LinkedItemQuery, 0)
2322

2423
sd, err := ParseScope(scope, true)
@@ -72,15 +71,15 @@ func EndpointsExtractor(resource *v1.Endpoints, scope string) ([]*sdp.LinkedItem
7271
}
7372

7473
func newEndpointsAdapter(cs *kubernetes.Clientset, cluster string, namespaces []string, cache sdpcache.Cache) discovery.ListableAdapter {
75-
return &KubeTypeAdapter[*v1.Endpoints, *v1.EndpointsList]{
74+
return &KubeTypeAdapter[*v1.Endpoints, *v1.EndpointsList]{ //nolint:staticcheck,nolintlint // SA1019: v1.Endpoints deprecated; see note at top of file
7675
ClusterName: cluster,
7776
Namespaces: namespaces,
7877
TypeName: "Endpoints",
79-
NamespacedInterfaceBuilder: func(namespace string) ItemInterface[*v1.Endpoints, *v1.EndpointsList] {
78+
NamespacedInterfaceBuilder: func(namespace string) ItemInterface[*v1.Endpoints, *v1.EndpointsList] { //nolint:staticcheck,nolintlint // SA1019
8079
return cs.CoreV1().Endpoints(namespace)
8180
},
82-
ListExtractor: func(list *v1.EndpointsList) ([]*v1.Endpoints, error) {
83-
extracted := make([]*v1.Endpoints, len(list.Items))
81+
ListExtractor: func(list *v1.EndpointsList) ([]*v1.Endpoints, error) { //nolint:staticcheck,nolintlint // SA1019
82+
extracted := make([]*v1.Endpoints, len(list.Items)) //nolint:staticcheck,nolintlint // SA1019
8483

8584
for i := range list.Items {
8685
extracted[i] = &list.Items[i]
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
package clients
2+
3+
import (
4+
"context"
5+
6+
"github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/elasticsan/armelasticsan"
7+
)
8+
9+
//go:generate mockgen -destination=../shared/mocks/mock_elastic_san_volume_snapshot_client.go -package=mocks -source=elastic-san-volume-snapshot-client.go
10+
11+
// ElasticSanVolumeSnapshotPager is a type alias for the generic Pager interface with volume snapshot list response type.
12+
type ElasticSanVolumeSnapshotPager = Pager[armelasticsan.VolumeSnapshotsClientListByVolumeGroupResponse]
13+
14+
// ElasticSanVolumeSnapshotClient is an interface for interacting with Azure Elastic SAN volume snapshots.
15+
type ElasticSanVolumeSnapshotClient interface {
16+
Get(ctx context.Context, resourceGroupName string, elasticSanName string, volumeGroupName string, snapshotName string, options *armelasticsan.VolumeSnapshotsClientGetOptions) (armelasticsan.VolumeSnapshotsClientGetResponse, error)
17+
ListByVolumeGroup(ctx context.Context, resourceGroupName string, elasticSanName string, volumeGroupName string, options *armelasticsan.VolumeSnapshotsClientListByVolumeGroupOptions) ElasticSanVolumeSnapshotPager
18+
}
19+
20+
type elasticSanVolumeSnapshotClient struct {
21+
client *armelasticsan.VolumeSnapshotsClient
22+
}
23+
24+
func (c *elasticSanVolumeSnapshotClient) Get(ctx context.Context, resourceGroupName string, elasticSanName string, volumeGroupName string, snapshotName string, options *armelasticsan.VolumeSnapshotsClientGetOptions) (armelasticsan.VolumeSnapshotsClientGetResponse, error) {
25+
return c.client.Get(ctx, resourceGroupName, elasticSanName, volumeGroupName, snapshotName, options)
26+
}
27+
28+
func (c *elasticSanVolumeSnapshotClient) ListByVolumeGroup(ctx context.Context, resourceGroupName string, elasticSanName string, volumeGroupName string, options *armelasticsan.VolumeSnapshotsClientListByVolumeGroupOptions) ElasticSanVolumeSnapshotPager {
29+
return c.client.NewListByVolumeGroupPager(resourceGroupName, elasticSanName, volumeGroupName, options)
30+
}
31+
32+
// NewElasticSanVolumeSnapshotClient creates a new ElasticSanVolumeSnapshotClient from the Azure SDK client.
33+
func NewElasticSanVolumeSnapshotClient(client *armelasticsan.VolumeSnapshotsClient) ElasticSanVolumeSnapshotClient {
34+
return &elasticSanVolumeSnapshotClient{client: client}
35+
}

sources/azure/manual/adapters.go

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ import (
1515
"github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/msi/armmsi"
1616
"github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/network/armnetwork/v9"
1717
"github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/postgresql/armpostgresqlflexibleservers/v5"
18+
"github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/elasticsan/armelasticsan"
1819
"github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/resources/armresources/v2"
1920
"github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/sql/armsql/v2"
2021
"github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/storage/armstorage/v3"
@@ -412,6 +413,11 @@ func Adapters(ctx context.Context, subscriptionID string, regions []string, cred
412413
return nil, fmt.Errorf("failed to create snapshots client: %w", err)
413414
}
414415

416+
elasticSanVolumeSnapshotsClient, err := armelasticsan.NewVolumeSnapshotsClient(subscriptionID, cred, nil)
417+
if err != nil {
418+
return nil, fmt.Errorf("failed to create elastic san volume snapshots client: %w", err)
419+
}
420+
415421
sharedGalleryImagesClient, err := armcompute.NewSharedGalleryImagesClient(subscriptionID, cred, nil)
416422
if err != nil {
417423
return nil, fmt.Errorf("failed to create shared gallery images client: %w", err)
@@ -692,6 +698,10 @@ func Adapters(ctx context.Context, subscriptionID string, regions []string, cred
692698
clients.NewSnapshotsClient(snapshotsClient),
693699
resourceGroupScopes,
694700
), cache),
701+
sources.WrapperToAdapter(NewElasticSanVolumeSnapshot(
702+
clients.NewElasticSanVolumeSnapshotClient(elasticSanVolumeSnapshotsClient),
703+
resourceGroupScopes,
704+
), cache),
695705
)
696706
}
697707

@@ -780,6 +790,7 @@ func Adapters(ctx context.Context, subscriptionID string, regions []string, cred
780790
sources.WrapperToAdapter(NewComputeGallery(nil, placeholderResourceGroupScopes), noOpCache),
781791
sources.WrapperToAdapter(NewComputeGalleryImage(nil, placeholderResourceGroupScopes), noOpCache),
782792
sources.WrapperToAdapter(NewComputeSnapshot(nil, placeholderResourceGroupScopes), noOpCache),
793+
sources.WrapperToAdapter(NewElasticSanVolumeSnapshot(nil, placeholderResourceGroupScopes), noOpCache),
783794
sources.WrapperToAdapter(NewComputeSharedGalleryImage(nil, subscriptionID), noOpCache),
784795
sources.WrapperToAdapter(NewNetworkPrivateEndpoint(nil, placeholderResourceGroupScopes), noOpCache),
785796
)

0 commit comments

Comments
 (0)