Skip to content

Commit fe07c66

Browse files
committed
Add some tests, refactor queries to be faster/more useable
1 parent 6e36154 commit fe07c66

12 files changed

+1748
-381
lines changed

test/cmd/aro-hcp-tests/custom-link-tools/artifacts/custom-link-tools.tmpl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,7 @@
7272
{{range $index, $element := .Elements}}
7373
<tr class="status-{{$element.Status}}">
7474
<td>{{$element.TestName}}</td>
75-
<td>tbd</td>
75+
<td>{{$element.Status}}</td>
7676
<td>{{$element.ResourceGroupName}}</td>
7777
<td>
7878
{{range $element.Links}}
Lines changed: 8 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,27 +1,18 @@
1-
// Recommended is to first get the cluster ID from the service logs, then hard code it in the below query.
2-
// Alternative query to get the cluster ID
1+
let _startTime = datetime("{{.StartTime}}");
2+
let _endTime = datetime("{{.EndTime}}");
3+
let _resource_group = '{{.ResourceGroupName}}';
34
database('ServiceLogs').table('containerLogs')
4-
| where log has '{{.ResourceGroupName}}'
5+
| where timestamp between (_startTime .. _endTime)
6+
| where log has _resource_group
57
| extend cid=extract(@"cid='([a-v0-9]{32})'", 1, tostring(log))
68
| where strlen( cid) > 0
79
| distinct cid
810

911
// Copy the cid from the above query to the below query to get the hosted control plane logs
1012
let cid = 'paste value here';
13+
let _startTime = datetime("{{.StartTime}}");
14+
let _endTime = datetime("{{.EndTime}}");
1115
database('HostedControlPlaneLogs').table('containerLogs')
16+
| where timestamp between (_startTime .. _endTime)
1217
| where namespace_name has cid
1318
| project timestamp, log
14-
15-
16-
// Alternative query to get the cluster ID, slower, but only one query.
17-
set notruncation;
18-
database('ServiceLogs').table('containerLogs')
19-
| where log has '{{.ResourceGroupName}}'
20-
| extend cid=extract(@"cid='([a-v0-9]{32})'", 1, tostring(log))
21-
| where strlen( cid) > 0
22-
| distinct cid
23-
| join kind=inner (
24-
database('HostedControlPlaneLogs').table('containerLogs')
25-
| extend cid=extract(@"([a-v0-9]{32})", 1, tostring(namespace_name))
26-
)
27-
on $left.cid == $right.cid
Lines changed: 37 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,37 @@
1-
// Get the service logs for the given resource group
2-
database('ServiceLogs').table('containerLogs')
3-
| where log has '{{.ResourceGroupName}}'
4-
5-
6-
// Get Frontend logs for the given resource group
7-
database('ServiceLogs').table('frontendLogs')
8-
| where log has '{{.ResourceGroupName}}'
9-
10-
11-
// Get Backend logs for the given resource group
12-
database('ServiceLogs').table('backendLogs')
13-
| where log has '{{.ResourceGroupName}}'
14-
15-
16-
// Get ClustersService logs for the given resource group
17-
database('ServiceLogs').table('clustersServiceLogs')
18-
| where log has '{{.ResourceGroupName}}'
1+
let _startTime = datetime("{{.StartTime}}");
2+
let _endTime = datetime("{{.EndTime}}");
3+
let _resource_group = '{{.ResourceGroupName}}';
4+
let cluster_resource_id = (database('ServiceLogs').table('frontendLogs')
5+
| where timestamp between (_startTime .. _endTime)
6+
| where resource_group == _resource_group
7+
| where msg has 'creating resource'
8+
| extend resource_id=extract(@"creating resource ([A-Za-z0-9\-\.\/]+)", 1, tostring(log))
9+
| distinct tostring(resource_id)
10+
| limit 1);
11+
union
12+
(
13+
database('ServiceLogs').table('backendLogs')
14+
| where timestamp between (_startTime .. _endTime)
15+
| where resource_id in (cluster_resource_id)
16+
| project timestamp, container_name, msg
17+
),
18+
(
19+
database('ServiceLogs').table('frontendLogs')
20+
| where timestamp between (_startTime .. _endTime)
21+
| where resource_group == _resource_group
22+
| project timestamp, container_name, msg
23+
),
24+
( // for now, we can parse
25+
database('ServiceLogs').table('containerLogs')
26+
| where timestamp between (_startTime .. _endTime)
27+
| where namespace_name == 'clusters-service'
28+
| extend resource_id=extract(@"resource_id='([^\']+)'", 1, tostring(log))
29+
| where resource_id in (cluster_resource_id)
30+
| project timestamp, container_name, log
31+
),
32+
( // in the future, we query
33+
database('ServiceLogs').table('clustersServiceLogs')
34+
| where timestamp between (_startTime .. _endTime)
35+
| where resource_id in (cluster_resource_id)
36+
| project timestamp, container_name, msg
37+
)
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
// Copyright 2025 Microsoft Corporation
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// http://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
15+
package customlinktools
16+
17+
import (
18+
"path/filepath"
19+
"testing"
20+
21+
"github.com/go-logr/logr"
22+
"github.com/go-logr/logr/testr"
23+
24+
"github.com/Azure/ARO-HCP/test/util/testutil"
25+
)
26+
27+
func TestGeneratedHTML(t *testing.T) {
28+
ctx := logr.NewContext(t.Context(), testr.New(t))
29+
tmpdir := t.TempDir()
30+
opts := Options{
31+
completedOptions: &completedOptions{
32+
TimingInputDir: "../testdata/output",
33+
OutputDir: tmpdir,
34+
},
35+
}
36+
err := opts.Run(ctx)
37+
if err != nil {
38+
t.Fatalf("failed to run custom link tools: %v", err)
39+
}
40+
testutil.CompareFileWithFixture(t, filepath.Join(tmpdir, "custom-link-tools.html"))
41+
}

test/cmd/aro-hcp-tests/custom-link-tools/options.go

Lines changed: 31 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,6 @@ import (
3535

3636
"github.com/Azure/ARO-HCP/internal/utils"
3737
"github.com/Azure/ARO-HCP/test/util/timing"
38-
"github.com/Azure/ARO-HCP/tooling/templatize/pkg/pipeline"
3938
)
4039

4140
//go:embed artifacts/*.tmpl
@@ -78,7 +77,6 @@ type ValidatedOptions struct {
7877

7978
// completedOptions is a private wrapper that enforces a call of Complete() before config generation can be invoked.
8079
type completedOptions struct {
81-
Steps []pipeline.NodeInfo
8280
TimingInputDir string
8381
OutputDir string
8482
}
@@ -124,9 +122,17 @@ type LinkDetails struct {
124122

125123
type QueryInfo struct {
126124
ResourceGroupName string
125+
StartTime string
126+
EndTime string
127127
Database string
128128
}
129129

130+
type TimingInfo struct {
131+
StartTime string
132+
EndTime string
133+
ResourceGroupNames []string
134+
}
135+
130136
func createQueryURL(templatePath string, info QueryInfo) string {
131137
currURL := url.URL{
132138
Scheme: "https",
@@ -178,20 +184,8 @@ func encodeKustoQuery(query string) string {
178184
}
179185

180186
func (o *ValidatedOptions) Complete(logger logr.Logger) (*Options, error) {
181-
// we consume steps.yaml (output of templatize and stored for us by the visualization) to determine the cluster name
182-
stepsYamlBytes, err := os.ReadFile(path.Join(o.TimingInputDir, "steps.yaml"))
183-
if err != nil {
184-
return nil, utils.TrackError(err)
185-
}
186-
187-
var steps []pipeline.NodeInfo
188-
if err := yaml.Unmarshal(stepsYamlBytes, &steps); err != nil {
189-
return nil, fmt.Errorf("failed to unmarshal timing input file: %w", err)
190-
}
191-
192187
return &Options{
193188
completedOptions: &completedOptions{
194-
Steps: steps,
195189
OutputDir: o.OutputDir,
196190
TimingInputDir: o.TimingInputDir,
197191
},
@@ -201,27 +195,32 @@ func (o *ValidatedOptions) Complete(logger logr.Logger) (*Options, error) {
201195
func (o Options) Run(ctx context.Context) error {
202196
allTestRows := []TestRow{}
203197

204-
deploymentResourceGroups, err := gatherResourceGroups(o.TimingInputDir)
198+
timingInfo, err := gatherTimingInfo(o.TimingInputDir)
205199
if err != nil {
206200
return utils.TrackError(err)
207201
}
208202

209-
for testName, rgs := range deploymentResourceGroups {
210-
for _, rg := range rgs {
203+
for testName, timing := range timingInfo {
204+
for _, rg := range timing.ResourceGroupNames {
211205
allTestRows = append(allTestRows, TestRow{
212206
TestName: testName,
213207
ResourceGroupName: rg,
214208
Links: []LinkDetails{
215209
createLinkForTest("Hosted Control Plane Logs", "hosted-controlplane.kql.tmpl", QueryInfo{
216210
ResourceGroupName: rg,
217211
Database: "HostedControlPlaneLogs",
212+
StartTime: timing.StartTime,
213+
EndTime: timing.EndTime,
218214
}),
219215
createLinkForTest("Service Logs", "service-logs.kql.tmpl", QueryInfo{
220216
ResourceGroupName: rg,
221217
Database: "ServiceLogs",
218+
StartTime: timing.StartTime,
219+
EndTime: timing.EndTime,
222220
}),
223221
},
224222
Database: "HostedControlPlaneLogs",
223+
Status: "tbd",
225224
})
226225
}
227226
}
@@ -259,7 +258,7 @@ func (o Options) Run(ctx context.Context) error {
259258
return nil
260259
}
261260

262-
func gatherResourceGroups(timingInputDir string) (map[string][]string, error) {
261+
func gatherTimingInfo(timingInputDir string) (map[string]TimingInfo, error) {
263262
timingDir, err := os.Stat(path.Join(timingInputDir, "test-timing/"))
264263
if err != nil {
265264
return nil, err
@@ -269,7 +268,7 @@ func gatherResourceGroups(timingInputDir string) (map[string][]string, error) {
269268
}
270269

271270
var allTimingFiles []string
272-
filepath.Walk(path.Join(timingInputDir, "test-timing/"), func(path string, info os.FileInfo, err error) error {
271+
err = filepath.Walk(path.Join(timingInputDir, "test-timing/"), func(path string, info os.FileInfo, err error) error {
273272
if err != nil {
274273
return err
275274
}
@@ -278,8 +277,11 @@ func gatherResourceGroups(timingInputDir string) (map[string][]string, error) {
278277
}
279278
return nil
280279
})
280+
if err != nil {
281+
return nil, err
282+
}
281283

282-
var allResourceGroups map[string][]string = make(map[string][]string)
284+
var allTimingInfo = make(map[string]TimingInfo)
283285

284286
for _, timingFile := range allTimingFiles {
285287
timingFileBytes, err := os.ReadFile(timingFile)
@@ -293,18 +295,24 @@ func gatherResourceGroups(timingInputDir string) (map[string][]string, error) {
293295
}
294296
deployment := strings.Join(timing.Identifier, " ")
295297

296-
var rgNames map[string]bool = make(map[string]bool)
298+
var rgNames = make(map[string]bool)
297299
for resourceGroup := range timing.Deployments {
298300
rgNames[resourceGroup] = true
299301
}
300302

303+
rgNameList := make([]string, 0)
301304
for rgName := range rgNames {
302305
if rgName == "" {
303306
continue
304307
}
305-
allResourceGroups[deployment] = append(allResourceGroups[deployment], rgName)
308+
rgNameList = append(rgNameList, rgName)
309+
}
310+
allTimingInfo[deployment] = TimingInfo{
311+
StartTime: timing.StartedAt,
312+
EndTime: timing.FinishedAt,
313+
ResourceGroupNames: rgNameList,
306314
}
307315
}
308316

309-
return allResourceGroups, nil
317+
return allTimingInfo, nil
310318
}

0 commit comments

Comments
 (0)