Skip to content

Commit fcec53b

Browse files
aaronferntakoverflowgagan16kgardener-github-actions[bot]github-actions[bot]
authored
[rel-v0.17] Cherry pick PRs for v0.17.1 release (#211)
* Add arm64 arch to oci-platforms (#203) * Fetch GNA secret when running IT locally (#206) * ci(build): add unit test job (#208) * Orphan Safety Controller missing VM's due to large resource query (#207) * Upgrade github.com/gardener/machine-controller-manager (#210) from v0.60.0 to v0.60.1 Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> --------- Co-authored-by: Prashant Tak <prashant.tak@sap.com> Co-authored-by: Gagan <gagan.surathkal@gmail.com> Co-authored-by: gardener-github-actions[bot] <207909872+gardener-github-actions[bot]@users.noreply.github.com> Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
1 parent d4d301b commit fcec53b

File tree

7 files changed

+449
-24
lines changed

7 files changed

+449
-24
lines changed

.ci/local_integration_test

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ declare TARGET_CLUSTER
1414
declare CONTROL_CLUSTER
1515
declare GARDEN_CORE_NAMESPACE
1616
declare CONTROL_KUBECONFIG
17-
DEFAULT_MCM_REPO_PATH=$(realpath "$(pwd)/../machine-controller-manager")
17+
declare GNA_SECRET_NAME
1818
DEFAULT_MCM_REPO_PATH=$(realpath "$(pwd)/../machine-controller-manager")
1919

2020

@@ -237,6 +237,13 @@ fi
237237

238238
set -o allexport
239239
source .env
240+
printf "\e[33mFetching the gardener-node-agent secret name. (If gardener-node-agent authorizer webhook is enabled, then this value is compulsory. Link to PR:https://github.com/gardener/gardener/pull/10535. The value can be found in machineClass.providerSpec.tags/labels. \e[0m\n"
241+
GNA_SECRET_NAME=$(kubectl --kubeconfig=$CONTROL_KUBECONFIG get mcc -n $CONTROL_CLUSTER_NAMESPACE -o jsonpath='{.items[0].providerSpec.tags.worker\.gardener\.cloud_gardener-node-agent-secret-name}')
242+
if [ -z "GNA_SECRET_NAME" ]
243+
then
244+
printf "\e[31m GNA Secret name is empty\e[0m\n"
245+
fi
246+
export GNA_SECRET_NAME=$GNA_SECRET_NAME
240247
set +o allexport
241248

242249
CREDENTIALS_SECRET_NAME=shoot-operator-az-team

.github/workflows/build.yaml

Lines changed: 31 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@ jobs:
5151
target: ${{ matrix.args.target }}
5252
oci-registry: ${{ needs.prepare.outputs.oci-registry }}
5353
oci-repository: ${{ matrix.args.oci-repository }}
54-
oci-platforms: linux/amd64
54+
oci-platforms: linux/amd64,linux/arm64
5555
ocm-labels: ${{ toJSON(matrix.args.ocm-labels) }}
5656
extra-tags: latest
5757

@@ -63,3 +63,33 @@ jobs:
6363
linter: gosec
6464
run: .ci/check
6565
go-version: '1.23.3'
66+
67+
test:
68+
runs-on: ubuntu-latest
69+
permissions:
70+
contents: read
71+
steps:
72+
- uses: gardener/cc-utils/.github/actions/trusted-checkout@master
73+
- uses: actions/setup-go@v5
74+
with:
75+
go-version: '1.23.3'
76+
- name: run-tests
77+
run: |
78+
set -euo pipefail
79+
mkdir /tmp/blobs.d
80+
PATHINWS=src SKIP_INTEGRATION_TESTS=true .ci/test |& tee /tmp/blobs.d/test-log.txt
81+
tar czf /tmp/blobs.d/test-log.tar.gz -C /tmp/blobs.d test-log.txt
82+
- name: add-unittest-results-to-component-descriptor
83+
uses: gardener/cc-utils/.github/actions/export-ocm-fragments@master
84+
with:
85+
blobs-directory: /tmp/blobs.d
86+
ocm-resources: |
87+
- name: test-results
88+
relation: local
89+
access:
90+
type: localBlob
91+
localReference: test-log.tar.gz
92+
labels:
93+
- name: gardener.cloud/purposes
94+
value:
95+
- test

.ocm/base-component.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
componentReferences:
22
- componentName: github.com/gardener/machine-controller-manager
33
name: machine-controller-manager
4-
version: v0.60.0
4+
version: v0.60.1
55
main-source:
66
labels:
77
- name: cloud.gardener.cnudie/dso/scanning-hints/source_analysis/v1
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
ocm:
2+
component_name: github.com/gardener/machine-controller-manager
3+
component_version: v0.60.1
4+
release_notes:
5+
- audience: operator
6+
author:
7+
hostname: github.com
8+
type: githubUser
9+
username: takoverflow
10+
category: bugfix
11+
contents: Added a safeguard to delay deletion of machines that are undergoing a
12+
`Create` Request to prevent orphaning of VMs.
13+
mimetype: text/markdown
14+
reference: '[#1045](https://github.com/gardener/machine-controller-manager/pull/1045)'
15+
type: standard
Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
// SPDX-FileCopyrightText: 2024 SAP SE or an SAP affiliate company and Gardener contributors
2+
//
3+
// SPDX-License-Identifier: Apache-2.0
4+
5+
package helpers
6+
7+
import (
8+
"context"
9+
10+
"github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/resourcegraph/armresourcegraph"
11+
)
12+
13+
// FakeResourceGraphClient is a fake implementation of ResourceGraphClient for testing.
14+
type FakeResourceGraphClient struct {
15+
// Responses is a list of responses to return in sequence for each call to Resources
16+
Responses []armresourcegraph.ClientResourcesResponse
17+
// Errors is a list of errors to return in sequence for each call to Resources
18+
Errors []error
19+
// CallCount tracks how many times Resources has been called
20+
CallCount int
21+
// RecordedRequests stores all query requests made to the client
22+
RecordedRequests []armresourcegraph.QueryRequest
23+
}
24+
25+
// NewFakeResourceGraphClient creates a new FakeResourceGraphClient for testing.
26+
func NewFakeResourceGraphClient() *FakeResourceGraphClient {
27+
return &FakeResourceGraphClient{
28+
Responses: []armresourcegraph.ClientResourcesResponse{},
29+
Errors: []error{},
30+
RecordedRequests: []armresourcegraph.QueryRequest{},
31+
}
32+
}
33+
34+
// Resources implements the ResourceGraphClient interface.
35+
// Returns the next response/error in the sequence based on CallCount.
36+
func (f *FakeResourceGraphClient) Resources(_ context.Context, query armresourcegraph.QueryRequest, _ *armresourcegraph.ClientResourcesOptions) (armresourcegraph.ClientResourcesResponse, error) {
37+
f.RecordedRequests = append(f.RecordedRequests, query)
38+
index := f.CallCount
39+
f.CallCount++
40+
41+
if index < len(f.Errors) && f.Errors[index] != nil {
42+
return armresourcegraph.ClientResourcesResponse{}, f.Errors[index]
43+
}
44+
45+
if index < len(f.Responses) {
46+
return f.Responses[index], nil
47+
}
48+
49+
return armresourcegraph.ClientResourcesResponse{}, nil
50+
}
51+
52+
// AddResponse adds a response to be returned by the fake client.
53+
func (f *FakeResourceGraphClient) AddResponse(response armresourcegraph.ClientResourcesResponse) *FakeResourceGraphClient {
54+
f.Responses = append(f.Responses, response)
55+
return f
56+
}
57+
58+
// AddError adds an error to be returned by the fake client.
59+
func (f *FakeResourceGraphClient) AddError(err error) *FakeResourceGraphClient {
60+
f.Errors = append(f.Errors, err)
61+
return f
62+
}

pkg/azure/access/helpers/resourcegraph.go

Lines changed: 54 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -12,49 +12,82 @@ import (
1212
"github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/resourcegraph/armresourcegraph"
1313
"github.com/gardener/machine-controller-manager-provider-azure/pkg/azure/access/errors"
1414
"github.com/gardener/machine-controller-manager-provider-azure/pkg/azure/instrument"
15-
"k8s.io/utils/pointer"
15+
"k8s.io/klog/v2"
16+
"k8s.io/utils/ptr"
1617
)
1718

1819
const (
1920
resourceGraphQueryServiceLabel = "resource_graph_query"
2021
)
2122

23+
// ResourceGraphClient is an interface for Azure Resource Graph client operations.
24+
// This allows for easier testing by enabling mock implementations.
25+
type ResourceGraphClient interface {
26+
Resources(ctx context.Context, query armresourcegraph.QueryRequest, options *armresourcegraph.ClientResourcesOptions) (armresourcegraph.ClientResourcesResponse, error)
27+
}
28+
29+
// Azure client implements interface
30+
var _ ResourceGraphClient = (*armresourcegraph.Client)(nil)
31+
2232
// MapperFn maps a row of result (represented as map[string]interface{}) to any type T.
2333
type MapperFn[T any] func(map[string]interface{}) *T
2434

2535
// QueryAndMap fires a resource graph KUSTO query constructing it from queryTemplate and templateArgs.
2636
// The result of the query are then mapped using a mapperFn and the result or an error is returned.
2737
// NOTE: All calls to this Azure API are instrumented as prometheus metric.
28-
func QueryAndMap[T any](ctx context.Context, client *armresourcegraph.Client, subscriptionID string, mapperFn MapperFn[T], queryTemplate string, templateArgs ...any) (results []T, err error) {
38+
func QueryAndMap[T any](ctx context.Context, client ResourceGraphClient, subscriptionID string, mapperFn MapperFn[T], queryTemplate string, templateArgs ...any) (results []T, err error) {
2939
defer instrument.AZAPIMetricRecorderFn(resourceGraphQueryServiceLabel, &err)()
3040

3141
query := fmt.Sprintf(queryTemplate, templateArgs...)
32-
resources, err := client.Resources(ctx,
33-
armresourcegraph.QueryRequest{
42+
var skipToken *string
43+
pageCount := 0
44+
45+
// Continue fetching results while there is a skipToken
46+
for {
47+
queryRequest := armresourcegraph.QueryRequest{
3448
Query: to.Ptr(query),
3549
Options: nil,
3650
Subscriptions: []*string{to.Ptr(subscriptionID)},
37-
}, nil)
51+
}
3852

39-
if err != nil {
40-
errors.LogAzAPIError(err, "ResourceGraphQuery failure to execute Query: %s", query)
41-
return nil, err
42-
}
53+
// Set skipToken in options if present for subsequent pages
54+
if skipToken != nil {
55+
queryRequest.Options = &armresourcegraph.QueryRequestOptions{
56+
SkipToken: skipToken,
57+
}
58+
}
4359

44-
if resources.TotalRecords == pointer.Int64(0) {
45-
return results, nil
46-
}
60+
resources, err := client.Resources(ctx, queryRequest, nil)
61+
if err != nil {
62+
errors.LogAzAPIError(err, "ResourceGraphQuery failure to execute Query: %s, with skipToken: %s", query, ptr.Deref(skipToken, "<nil>"))
63+
return nil, err
64+
}
65+
pageCount++
4766

48-
// resourceResponse.Data is a []interface{}
49-
if objSlice, ok := resources.Data.([]interface{}); ok {
50-
for _, obj := range objSlice {
51-
// Each obj in resourceResponse.Data is a map[string]Interface{}
52-
rowElements := obj.(map[string]interface{})
53-
result := mapperFn(rowElements)
54-
if result != nil {
55-
results = append(results, *result)
67+
if ptr.Deref(resources.TotalRecords, 0) == 0 {
68+
klog.Infof("Query completed: fetched %d pages, no results retrieved", pageCount)
69+
return results, nil
70+
}
71+
72+
// resourceResponse.Data is a []interface{}
73+
if objSlice, ok := resources.Data.([]interface{}); ok {
74+
for _, obj := range objSlice {
75+
// Each obj in resourceResponse.Data is a map[string]Interface{}
76+
rowElements := obj.(map[string]interface{})
77+
result := mapperFn(rowElements)
78+
if result != nil {
79+
results = append(results, *result)
80+
}
5681
}
5782
}
83+
// Check if there are more pages to fetch and set skipToken for next iteration
84+
if resources.SkipToken == nil || *resources.SkipToken == "" {
85+
break
86+
}
87+
klog.Infof("Fetching next page (page %d) with skipToken: %s", pageCount+1, *resources.SkipToken)
88+
skipToken = resources.SkipToken
5889
}
59-
return
90+
91+
klog.Infof("Query completed: fetched %d pages, total results: %d", pageCount, len(results))
92+
return results, nil
6093
}

0 commit comments

Comments
 (0)