Skip to content

Commit 353e4b9

Browse files
craig[bot]williamchoe3shghasemiyuzefovich
committed
154467: roachprod: azure GetVMSpecs() implementation r=DarrylWong a=williamchoe3 Informs #146202 Implementation for previously unimplemented interface method `GetVMSpecs()` for Azure. This will allow for cluster information to be fetched in roachtest via `FetchVMSpecs` Also changed `azureIDPattern` to match the optional type name pairs that may exist in a fully qualified azure resource id. See comments for more details. Previously, if these optional type name pairs existed, they were just a part of the `resourceName` field. Currently, I didn't see any of these child resource ids being parsed, but if we were to ever parse those in the future the previous implementation wouldn't make sense. * Note: Although the regex selects child resource type and names in the last matching group, they are not saved to AzureId struct because they are not being used For Azure, `client.Get(...)` allows you to pass in an optional `expander` parameter which seems to provide additional information for `"instanceView"` and runs an optionally passed in user script (passed in on vm creation) when `"userData"` is passed in. * `"userData"` doesn't seem relevant for us "retrieves the UserData property as part of the VM model view that was provided by the user during the VM Create/Update operation" https://learn.microsoft.com/en-us/rest/api/compute/virtual-machines/get?view=rest-compute-2025-04-01&tabs=HTTP * "The `instanceView` of an Azure Virtual Machine (VM) provides a snapshot of the runtime properties and status of the VM" https://learn.microsoft.com/en-us/rest/api/compute/virtual-machines/instance-view?view=rest-compute-2025-04-01&tabs=HTTP Seems nice, but there's no diff in the json returned by `"instanceView"` and the default when `expander` is not set (referred to `model view` in some places on thier docs) ```go InstanceViewTypesInstanceView InstanceViewTypes = "instanceView" InstanceViewTypesUserData InstanceViewTypes = "userData" ``` IBM PR: #155368 156547: sql: add ColumnGeneratedAsIdentity as a new schema change element r=shghasemi a=shghasemi Previously, GeneratedAsIdentity was part of the Column element. Creating a new schema change element will allow the declarative schema changer to add/remove/update such columns without dropping the Column element. Epic: [CRDB-31283](https://cockroachlabs.atlassian.net/browse/CRDB-31283) Part of: #142918 Release note: None 156953: kvclient/kvcoord: remove stale TODO in Step r=yuzefovich a=yuzefovich We currently have a TODO in Step to add an assertion that stepping is only done on the RootTxn which references a now-closed issue. I did a little bit archeology, and in bd255e5 we consciously removed the assertion like this since stepping on a LeafTxn should be no-op, should just work, and is actually needed behavior for internal executors when they run on remote nodes as part of DistSQL plan. (In connExecutor we currently unconditionally Step the txn on the main query path.) Thus I don't think we want to implement the TODO and should just remove it. Epic: None Release note: None 156987: sql: remove now-stale growstack for internal executor r=yuzefovich a=yuzefovich As of 4a5c503, we now grow stack unconditionally for all async tasks. Some time ago we added an ability to growstack in the async task of the internal executor when used in the LDR, and now that has become redundant, so we remove this special case. Epic: None Release note: None Co-authored-by: William Choe <[email protected]> Co-authored-by: Shadi Ghasemitaheri <[email protected]> Co-authored-by: Yahor Yuzefovich <[email protected]>
5 parents 77b21df + 67e3bed + dbb0574 + de735d7 + b9ddf79 commit 353e4b9

File tree

59 files changed

+685
-148
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

59 files changed

+685
-148
lines changed

pkg/cmd/roachtest/tests/roachtest.go

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,18 @@ func registerRoachtest(r registry.Registry) {
8181
monitorFatalTestGlobal(ctx, t, c)
8282
},
8383
})
84+
85+
// Manual test for verifying framework behavior in a test success scenario
86+
r.Add(registry.TestSpec{
87+
Name: "roachtest/manual/success",
88+
Owner: registry.OwnerTestEng,
89+
Cluster: r.MakeClusterSpec(3),
90+
CompatibleClouds: registry.AllClouds,
91+
Suites: registry.ManualOnly,
92+
Run: func(ctx context.Context, t test.Test, c cluster.Cluster) {
93+
t.L().Printf("hello")
94+
},
95+
})
8496
}
8597

8698
// monitorFatalTest will always fail with a node logging a fatal error in a

pkg/crosscluster/logical/lww_row_processor.go

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -407,10 +407,6 @@ var (
407407
// Use generic query plans since our queries are extremely simple and
408408
// won't benefit from custom plans.
409409
PlanCacheMode: &forceGenericPlan,
410-
// We've observed in the CPU profiles that the default goroutine stack
411-
// of the connExecutor goroutine is insufficient for evaluation of the
412-
// ingestion queries, so we grow the stack right away to 32KiB.
413-
GrowStackSize: true,
414410
// We don't get any benefits from generating plan gists for internal
415411
// queries, so we disable them.
416412
DisablePlanGists: true,

pkg/kv/kvclient/kvcoord/txn_coord_sender.go

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1525,11 +1525,6 @@ func (tc *TxnCoordSender) TestingCloneTxn() *roachpb.Transaction {
15251525

15261526
// Step is part of the TxnSender interface.
15271527
func (tc *TxnCoordSender) Step(ctx context.Context, allowReadTimestampStep bool) error {
1528-
// TODO(nvanbenschoten): it should be possible to make this assertion, but
1529-
// the API is currently misused by the connExecutor. See #86162.
1530-
// if tc.typ != kv.RootTxn {
1531-
// return errors.AssertionFailedf("cannot step in non-root txn")
1532-
// }
15331528
tc.mu.Lock()
15341529
defer tc.mu.Unlock()
15351530
if allowReadTimestampStep && tc.shouldStepReadTimestampLocked() {

pkg/roachprod/vm/azure/BUILD.bazel

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,10 @@ go_library(
4141

4242
go_test(
4343
name = "azure_test",
44-
srcs = ["utils_test.go"],
44+
srcs = [
45+
"ids_test.go",
46+
"utils_test.go",
47+
],
4548
data = glob(["testdata/**"]),
4649
embed = [":azure"],
4750
deps = [

pkg/roachprod/vm/azure/azure.go

Lines changed: 40 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -210,10 +210,49 @@ func (p *Provider) GetLiveMigrationVMs(
210210
return liveMigrationVMs, nil
211211
}
212212

213+
// GetVMSpecs implements the vm.GetVMSpecs interface method which returns a
214+
// map from VM.Name to a map of VM attributes
213215
func (p *Provider) GetVMSpecs(
214216
l *logger.Logger, vms vm.List,
215217
) (map[string]map[string]interface{}, error) {
216-
return nil, nil
218+
ctx, cancel := context.WithTimeout(context.Background(), p.OperationTimeout)
219+
defer cancel()
220+
sub, err := p.getSubscription(ctx)
221+
if err != nil {
222+
return nil, err
223+
}
224+
client := compute.NewVirtualMachinesClient(sub)
225+
if client.Authorizer, err = p.getAuthorizer(); err != nil {
226+
return nil, err
227+
}
228+
229+
// Extract the spec of all VMs and create a map from VM name to spec.
230+
vmSpecs := make(map[string]map[string]interface{})
231+
for _, vmInstance := range vms {
232+
if vmInstance.ProviderID == "" {
233+
return nil, errors.Errorf("provider id not found for vm: %s", vmInstance.Name)
234+
}
235+
azureVmId, err := parseAzureID(vmInstance.ProviderID)
236+
if err != nil {
237+
return nil, err
238+
}
239+
l.Printf("Getting VM Specs for VM: %s", vmInstance.Name)
240+
azureVm, err := client.Get(ctx, azureVmId.resourceGroup, azureVmId.resourceName, "")
241+
if err != nil {
242+
return nil, errors.Wrapf(err, "failed to get vm information for vm %s", vmInstance.Name)
243+
}
244+
// Marshaling & unmarshalling struct to match interface method return type
245+
rawJSON, err := azureVm.MarshalJSON()
246+
if err != nil {
247+
return nil, errors.Wrapf(err, "failed to marshal vm information for vm %s", vmInstance.Name)
248+
}
249+
var vmSpec map[string]interface{}
250+
if err := json.Unmarshal(rawJSON, &vmSpec); err != nil {
251+
return nil, errors.Wrapf(err, "failed to parse raw json")
252+
}
253+
vmSpecs[vmInstance.Name] = vmSpec
254+
}
255+
return vmSpecs, nil
217256
}
218257

219258
func (p *Provider) CreateVolumeSnapshot(

pkg/roachprod/vm/azure/ids.go

Lines changed: 32 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -20,9 +20,35 @@ import (
2020
// https://github.com/Azure/azure-sdk-for-go/issues/3080
2121
// is solved.
2222

23+
// azureIDPattern matches
24+
// /subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/{namespace}/{type}/{name}[/childType/childName ...]
25+
// If child resource type name pair(s) are not present, the last matching
26+
// group will be empty. Otherwise, the last matching group will contain all
27+
// additional pairs.
28+
//
29+
// Currently, we are not using any Azure Resource IDs that contain child
30+
// resource type name pairs, so we do not save them as a field in azureID. If
31+
// we need to use them in the future we can add a field to azureID and set
32+
// that field in parseAzureID.
33+
// Note: the number of child resource pairs is ambiguous and currently the
34+
// entire remainder of the string gets matched to the last group if a trailing
35+
// '/' is present after resourceName.
2336
var azureIDPattern = regexp.MustCompile(
24-
"/subscriptions/(.+)/resourceGroups/(.+)/providers/(.+?)/(.+?)/(.+)")
37+
`/subscriptions/([^/]+)/resourceGroups/([^/]+)/providers/([^/]+)/([^/]+)/([^/]+)(?:/(.*))?`)
2538

39+
// azureID defines a fully qualified Azure Resource ID which must contain a
40+
// subscription ID, a resourceGroup name, a provider namespace, and at least
41+
// one type and name pair. The first type name pair describes the resourceType
42+
// and resourceName. For examples, reference unit tests.
43+
//
44+
// Additional type name pairs are optional, and if they exist, this Resource ID
45+
// is describing a child resource or sometimes referred to as a subresource.
46+
// This struct does not contain a field for child resources. If a
47+
// child resource ID needs to be parsed, this struct must be extended.
48+
//
49+
// Template:
50+
//
51+
// /subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/{namespace}/{type}/{name}[/childType/childName ...]
2652
type azureID struct {
2753
provider string
2854
resourceGroup string
@@ -31,14 +57,17 @@ type azureID struct {
3157
subscription string
3258
}
3359

60+
// String does not account for child resources since they are not saved after
61+
// being parsed
3462
func (id azureID) String() string {
35-
return fmt.Sprintf("/subscriptions/%s/resourceGroups/%s/providers/%s/%s/%s",
63+
s := fmt.Sprintf("/subscriptions/%s/resourceGroups/%s/providers/%s/%s/%s",
3664
id.subscription, id.resourceGroup, id.provider, id.resourceType, id.resourceName)
65+
return s
3766
}
3867

3968
func parseAzureID(id string) (azureID, error) {
4069
parts := azureIDPattern.FindStringSubmatch(id)
41-
if len(parts) == 0 {
70+
if len(parts) != 7 {
4271
return azureID{}, errors.Errorf("could not parse Azure ID %q", id)
4372
}
4473
ret := azureID{

pkg/roachprod/vm/azure/ids_test.go

Lines changed: 103 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,103 @@
1+
// Copyright 2025 The Cockroach Authors.
2+
//
3+
// Use of this software is governed by the CockroachDB Software License
4+
// included in the /LICENSE file.
5+
6+
package azure
7+
8+
import "testing"
9+
10+
func TestParseAzureID(t *testing.T) {
11+
tests := []struct {
12+
name string
13+
input string
14+
expectedString string
15+
expectErr bool
16+
expected azureID
17+
}{
18+
{
19+
name: "Valid VM",
20+
input: "/subscriptions/1234-abcd/resourceGroups/my-rg/providers/Microsoft.Compute/virtualMachines/n01",
21+
expectedString: "/subscriptions/1234-abcd/resourceGroups/my-rg/providers/Microsoft.Compute/virtualMachines/n01",
22+
expected: azureID{
23+
subscription: "1234-abcd",
24+
resourceGroup: "my-rg",
25+
provider: "Microsoft.Compute",
26+
resourceType: "virtualMachines",
27+
resourceName: "n01",
28+
},
29+
},
30+
{
31+
name: "Valid NIC",
32+
input: "/subscriptions/1234-abcd/resourceGroups/test-rg/providers/Microsoft.Network/networkInterfaces/test-nic01",
33+
expectedString: "/subscriptions/1234-abcd/resourceGroups/test-rg/providers/Microsoft.Network/networkInterfaces/test-nic01",
34+
expected: azureID{
35+
subscription: "1234-abcd",
36+
resourceGroup: "test-rg",
37+
provider: "Microsoft.Network",
38+
resourceType: "networkInterfaces",
39+
resourceName: "test-nic01",
40+
},
41+
},
42+
{
43+
// Since child resources are not implemented, all we are checking here is
44+
// that the resourceName gets selected out properly
45+
name: "Valid with child resource",
46+
input: "/subscriptions/1111/resourceGroups/rg1/providers/Microsoft.Network/loadBalancers/lb01/frontendIPConfigurations/ipconfig1",
47+
expectedString: "/subscriptions/1111/resourceGroups/rg1/providers/Microsoft.Network/loadBalancers/lb01",
48+
expected: azureID{
49+
subscription: "1111",
50+
resourceGroup: "rg1",
51+
provider: "Microsoft.Network",
52+
resourceType: "loadBalancers",
53+
resourceName: "lb01",
54+
},
55+
},
56+
{
57+
name: "Invalid - missing fields",
58+
input: "/subscriptions/abcd/resourceGroups//providers/Microsoft.Compute/virtualMachines/vm1",
59+
expectErr: true,
60+
},
61+
{
62+
name: "Invalid - not an Azure ID",
63+
input: "/this/is/not/an/azure/id",
64+
expectErr: true,
65+
},
66+
}
67+
68+
for _, tt := range tests {
69+
t.Run(tt.name, func(t *testing.T) {
70+
actual, err := parseAzureID(tt.input)
71+
if tt.expectErr {
72+
if err == nil {
73+
t.Errorf("expected error but got none")
74+
}
75+
return
76+
}
77+
if err != nil {
78+
t.Errorf("unexpected error: %v", err)
79+
return
80+
}
81+
// Compare fields
82+
if actual.subscription != tt.expected.subscription {
83+
t.Errorf("subscription: actual %q, expected %q", actual.subscription, tt.expected.subscription)
84+
}
85+
if actual.resourceGroup != tt.expected.resourceGroup {
86+
t.Errorf("resourceGroup: actual %q, expected %q", actual.resourceGroup, tt.expected.resourceGroup)
87+
}
88+
if actual.provider != tt.expected.provider {
89+
t.Errorf("provider: actual %q, expected %q", actual.provider, tt.expected.provider)
90+
}
91+
if actual.resourceType != tt.expected.resourceType {
92+
t.Errorf("resourceType: actual %q, expected %q", actual.resourceType, tt.expected.resourceType)
93+
}
94+
if actual.resourceName != tt.expected.resourceName {
95+
t.Errorf("resourceName: actual %q, expected %q", actual.resourceName, tt.expected.resourceName)
96+
}
97+
// Ensure String() reconstructs the same input
98+
if actual.String() != tt.expectedString {
99+
t.Errorf("String(): actual %q, expected %q", actual.String(), tt.expectedString)
100+
}
101+
})
102+
}
103+
}

pkg/sql/BUILD.bazel

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -575,7 +575,6 @@ go_library(
575575
"//pkg/util/errorutil",
576576
"//pkg/util/errorutil/unimplemented",
577577
"//pkg/util/fsm",
578-
"//pkg/util/growstack",
579578
"//pkg/util/grpcutil",
580579
"//pkg/util/grunning",
581580
"//pkg/util/hlc",

pkg/sql/internal.go

Lines changed: 1 addition & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,6 @@ import (
3939
"github.com/cockroachdb/cockroach/pkg/sql/sqltelemetry"
4040
"github.com/cockroachdb/cockroach/pkg/sql/types"
4141
"github.com/cockroachdb/cockroach/pkg/util/fsm"
42-
"github.com/cockroachdb/cockroach/pkg/util/growstack"
4342
"github.com/cockroachdb/cockroach/pkg/util/log"
4443
"github.com/cockroachdb/cockroach/pkg/util/mon"
4544
"github.com/cockroachdb/cockroach/pkg/util/retry"
@@ -223,7 +222,6 @@ func (ie *InternalExecutor) runWithEx(
223222
syncCallback func([]*streamingCommandResult),
224223
errCallback func(error),
225224
attributeToUser bool,
226-
growStackSize bool,
227225
) error {
228226
ex, err := ie.initConnEx(ctx, txn, w, mode, sd, stmtBuf, syncCallback, attributeToUser)
229227
if err != nil {
@@ -251,11 +249,6 @@ func (ie *InternalExecutor) runWithEx(
251249
go func() {
252250
defer hdl.Activate(ctx).Release(ctx)
253251
defer cleanup(ctx)
254-
// TODO(yuzefovich): benchmark whether we should be growing the
255-
// stack size unconditionally.
256-
if growStackSize {
257-
growstack.Grow()
258-
}
259252
if err := ex.run(
260253
ctx,
261254
ie.mon,
@@ -1196,7 +1189,6 @@ func (ie *InternalExecutor) execInternal(
11961189
txn.SetBufferedWritesEnabled(false)
11971190
}
11981191
attributeToUser := sessionDataOverride.AttributeToUser && attributeToUserEnabled.Get(&ie.s.cfg.Settings.SV)
1199-
growStackSize := sessionDataOverride.GrowStackSize
12001192
if !rw.async() && (txn != nil && txn.Type() == kv.RootTxn) {
12011193
// If the "outer" query uses the RootTxn and the sync result channel is
12021194
// requested, then we must disable both DistSQL and Streamer to ensure
@@ -1308,7 +1300,7 @@ func (ie *InternalExecutor) execInternal(
13081300
errCallback := func(err error) {
13091301
_ = rw.addResult(ctx, ieIteratorResult{err: err})
13101302
}
1311-
err = ie.runWithEx(ctx, opName, txn, rw, mode, sd, stmtBuf, &wg, syncCallback, errCallback, attributeToUser, growStackSize)
1303+
err = ie.runWithEx(ctx, opName, txn, rw, mode, sd, stmtBuf, &wg, syncCallback, errCallback, attributeToUser)
13121304
if err != nil {
13131305
return nil, err
13141306
}

pkg/sql/schemachanger/scbuild/internal/scbuildstmt/alter_table_add_column.go

Lines changed: 28 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -116,11 +116,10 @@ func alterTableAddColumn(
116116
spec := addColumnSpec{
117117
tbl: tbl,
118118
col: &scpb.Column{
119-
TableID: tbl.TableID,
120-
ColumnID: desc.ID,
121-
IsHidden: desc.Hidden,
122-
IsInaccessible: desc.Inaccessible,
123-
GeneratedAsIdentityType: desc.GeneratedAsIdentityType,
119+
TableID: tbl.TableID,
120+
ColumnID: desc.ID,
121+
IsHidden: desc.Hidden,
122+
IsInaccessible: desc.Inaccessible,
124123
},
125124
unique: d.Unique.IsUnique,
126125
notNull: !desc.Nullable,
@@ -139,9 +138,6 @@ func alterTableAddColumn(
139138
if pgAttNum := desc.GetPGAttributeNum(); pgAttNum != catid.PGAttributeNum(desc.ID) {
140139
spec.col.PgAttributeNum = pgAttNum
141140
}
142-
if ptr := desc.GeneratedAsIdentitySequenceOption; ptr != nil {
143-
spec.col.GeneratedAsIdentitySequenceOption = *ptr
144-
}
145141
spec.name = &scpb.ColumnName{
146142
TableID: tbl.TableID,
147143
ColumnID: spec.col.ColumnID,
@@ -290,6 +286,26 @@ func alterTableAddColumn(
290286
}
291287
b.IncrementSchemaChangeAddColumnQualificationCounter("on_update")
292288
}
289+
if d.GeneratedIdentity.IsGeneratedAsIdentity {
290+
generatedAsIdentityType := desc.GeneratedAsIdentityType
291+
seqOptions := ""
292+
if ptr := desc.GeneratedAsIdentitySequenceOption; ptr != nil {
293+
seqOptions = *ptr
294+
}
295+
// Versions from 26.1 GeneratedAsIdentity will have a separate element for
296+
// GeneratedAsIdentity. Older versios store it in the column element.
297+
if spec.colType.ElementCreationMetadata.In_26_1OrLater {
298+
spec.generatedAsID = &scpb.ColumnGeneratedAsIdentity{
299+
TableID: tbl.TableID,
300+
ColumnID: spec.col.ColumnID,
301+
Type: generatedAsIdentityType,
302+
SequenceOption: seqOptions,
303+
}
304+
} else {
305+
spec.col.GeneratedAsIdentityType = generatedAsIdentityType
306+
spec.col.GeneratedAsIdentitySequenceOption = seqOptions
307+
}
308+
}
293309
// Add secondary indexes for this column.
294310
backing := addColumn(b, spec, t)
295311
if idx != nil {
@@ -458,6 +474,7 @@ type addColumnSpec struct {
458474
compute *scpb.ColumnComputeExpression
459475
transientCompute *scpb.ColumnComputeExpression
460476
comment *scpb.ColumnComment
477+
generatedAsID *scpb.ColumnGeneratedAsIdentity
461478
unique bool
462479
notNull bool
463480
}
@@ -494,6 +511,9 @@ func addColumn(b BuildCtx, spec addColumnSpec, n tree.NodeFormatter) (backing *s
494511
if spec.comment != nil {
495512
b.Add(spec.comment)
496513
}
514+
if spec.generatedAsID != nil {
515+
b.Add(spec.generatedAsID)
516+
}
497517
// Don't need to modify primary indexes for virtual columns.
498518
if spec.colType.IsVirtual {
499519
return getLatestPrimaryIndex(b, spec.tbl.TableID)

0 commit comments

Comments
 (0)