-
Notifications
You must be signed in to change notification settings - Fork 165
/
resources_list.go
195 lines (167 loc) · 5.95 KB
/
resources_list.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
package adminactions
// Copyright (c) Microsoft Corporation.
// Licensed under the Apache License 2.0.
import (
"context"
"io"
mgmtcompute "github.com/Azure/azure-sdk-for-go/services/compute/mgmt/2020-06-01/compute"
mgmtfeatures "github.com/Azure/azure-sdk-for-go/services/resources/mgmt/2019-07-01/features"
"github.com/Azure/go-autorest/autorest/azure"
"github.com/Azure/ARO-RP/pkg/api"
apisubnet "github.com/Azure/ARO-RP/pkg/api/util/subnet"
"github.com/Azure/ARO-RP/pkg/util/arm"
"github.com/Azure/ARO-RP/pkg/util/azureclient"
"github.com/Azure/ARO-RP/pkg/util/stringutils"
)
var commaAsByteArray = []byte(",")
func (a *azureActions) GroupResourceList(ctx context.Context) ([]mgmtfeatures.GenericResourceExpanded, error) {
clusterRGName := stringutils.LastTokenByte(a.oc.Properties.ClusterProfile.ResourceGroupID, '/')
return a.resources.ListByResourceGroup(ctx, clusterRGName, "", "", nil)
}
func (a *azureActions) ResourcesList(ctx context.Context, resources []mgmtfeatures.GenericResourceExpanded, writer io.WriteCloser) error {
defer writer.Close()
clusterRGName := stringutils.LastTokenByte(a.oc.Properties.ClusterProfile.ResourceGroupID, '/')
writer.Write([]byte("["))
// +4 because we expect +2 subnet and +1 vnets and optional +1 diskEncryptionSet
armResources := make([]arm.Resource, 0, 4)
armResources, err := a.appendAzureNetworkResources(ctx, armResources)
if err != nil {
a.log.Warnf("error when getting network resources: %s", err)
}
armResources, err = a.appendAzureDiskEncryptionSetResources(ctx, armResources)
if err != nil {
a.log.Warnf("error when getting DiskEncryptionSet resources: %s", err)
}
hasWritten := false
for _, resource := range armResources {
if hasWritten {
writer.Write(commaAsByteArray)
}
a.writeObject(writer, resource)
hasWritten = true
}
for _, res := range resources {
apiVersion := azureclient.APIVersion(*res.Type)
if apiVersion == "" {
// If custom resource types, or any we don't have listed in pkg/util/azureclient/apiversions.go,
// are returned, then skip over them instead of returning an error, otherwise it results in an
// HTTP 500 and prevents the known resource types from being returned.
a.log.Warnf("API version not found for type %q", *res.Type)
continue
}
if hasWritten {
writer.Write(commaAsByteArray)
}
hasWritten = true
switch *res.Type {
case "Microsoft.Compute/virtualMachines":
vm, err := a.virtualMachines.Get(ctx, clusterRGName, *res.Name, mgmtcompute.InstanceView)
if err != nil {
a.log.Warn(err) // can happen when the ARM cache is lagging
a.writeObject(writer, arm.Resource{
Resource: res,
})
continue
}
a.writeObject(writer, arm.Resource{
Resource: vm,
})
default:
gr, err := a.resources.GetByID(ctx, *res.ID, apiVersion)
if err != nil {
a.log.Warn(err) // can happen when the ARM cache is lagging
a.writeObject(writer, arm.Resource{
Resource: res,
})
continue
}
a.writeObject(writer, arm.Resource{
Resource: gr,
})
}
}
_, err = writer.Write([]byte("]"))
return err
}
func (a *azureActions) writeObject(writer io.Writer, resource arm.Resource) {
bytes, err := resource.MarshalJSON()
if err != nil {
a.log.Warn(err) // very unlikely , only a handful of cases trigger an error
// here. and since we get the object from a database , it probably will never happen
return
}
_, err = writer.Write(bytes)
if err != nil {
a.log.Warn(err) // can happen if the the connection is closed for example
}
}
func (a *azureActions) appendAzureNetworkResources(ctx context.Context, armResources []arm.Resource) ([]arm.Resource, error) {
vNetID, _, err := apisubnet.Split(a.oc.Properties.MasterProfile.SubnetID)
if err != nil {
return nil, err
}
r, err := azure.ParseResourceID(vNetID)
if err != nil {
return armResources, err
}
vnet, err := a.virtualNetworks.Get(ctx, r.ResourceGroup, r.ResourceName, "")
if err != nil {
return armResources, err
}
armResources = append(armResources, arm.Resource{
Resource: vnet,
})
if vnet.Subnets != nil {
for _, snet := range *vnet.Subnets {
//we already have the VNet resource, filtering subnets instead of fetching them individually with a SubnetClient
interestingSubnet := (*snet.ID == a.oc.Properties.MasterProfile.SubnetID)
workerProfiles, _ := api.GetEnrichedWorkerProfiles(a.oc.Properties)
for _, wProfile := range workerProfiles {
interestingSubnet = interestingSubnet || (*snet.ID == wProfile.SubnetID)
}
if !interestingSubnet {
continue
}
//by this time the snet subnet is used in a Master or Worker profile
if snet.RouteTable != nil {
r, err := azure.ParseResourceID(*snet.RouteTable.ID)
if err != nil {
a.log.Warnf("skipping route table '%s' due to ID parse error: %s", *snet.RouteTable.ID, err)
continue
}
rt, err := a.routeTables.Get(ctx, r.ResourceGroup, r.ResourceName, "")
if err != nil {
a.log.Warnf("skipping route table '%s' due to Get error: %s", *snet.RouteTable.ID, err)
continue
}
armResources = append(armResources, arm.Resource{
Resource: rt,
})
}
}
}
return armResources, nil
}
func (a *azureActions) appendAzureDiskEncryptionSetResources(ctx context.Context, armResources []arm.Resource) ([]arm.Resource, error) {
// possible for there to be no DiskEncryptionSet, if so, ignore
if a.oc.Properties.MasterProfile.DiskEncryptionSetID == "" {
return armResources, nil
}
r, err := azure.ParseResourceID(a.oc.Properties.MasterProfile.DiskEncryptionSetID)
if err != nil {
return armResources, err
}
diskEncryptionSets, err := a.diskEncryptionSets.Get(ctx, r.ResourceGroup, r.ResourceName)
if err != nil {
return armResources, err
}
armResources = append(armResources, arm.Resource{
Resource: diskEncryptionSets,
})
return armResources, nil
}
func (a *azureActions) WriteToStream(ctx context.Context, writer io.WriteCloser) error {
resources, err := a.GroupResourceList(ctx)
go a.ResourcesList(ctx, resources, writer)
return err
}