Skip to content

Commit 85590f0

Browse files
committed
feat(tables): add yc_quotamanager_* tables
commit_hash:71c1e194b01afe0957bbacae413836ef928b9da3
1 parent 463ec94 commit 85590f0

File tree

16 files changed

+281
-21
lines changed

16 files changed

+281
-21
lines changed

.mapping.json

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -96,6 +96,8 @@
9696
"docs/tables/yc_organizationmanager_organizations.md":"security/cloudquery/cq-source-yc/docs/tables/yc_organizationmanager_organizations.md",
9797
"docs/tables/yc_organizationmanager_oslogin_settings.md":"security/cloudquery/cq-source-yc/docs/tables/yc_organizationmanager_oslogin_settings.md",
9898
"docs/tables/yc_organizationmanager_users.md":"security/cloudquery/cq-source-yc/docs/tables/yc_organizationmanager_users.md",
99+
"docs/tables/yc_quotamanager_quota_limits.md":"security/cloudquery/cq-source-yc/docs/tables/yc_quotamanager_quota_limits.md",
100+
"docs/tables/yc_quotamanager_quota_services.md":"security/cloudquery/cq-source-yc/docs/tables/yc_quotamanager_quota_services.md",
99101
"docs/tables/yc_resourcemanager_clouds.md":"security/cloudquery/cq-source-yc/docs/tables/yc_resourcemanager_clouds.md",
100102
"docs/tables/yc_resourcemanager_folders.md":"security/cloudquery/cq-source-yc/docs/tables/yc_resourcemanager_folders.md",
101103
"docs/tables/yc_serverless_apigateway_gateways.md":"security/cloudquery/cq-source-yc/docs/tables/yc_serverless_apigateway_gateways.md",
@@ -193,6 +195,8 @@
193195
"resources/organizationmanager/organizations.go":"security/cloudquery/cq-source-yc/resources/organizationmanager/organizations.go",
194196
"resources/organizationmanager/oslogin_settings.go":"security/cloudquery/cq-source-yc/resources/organizationmanager/oslogin_settings.go",
195197
"resources/organizationmanager/users.go":"security/cloudquery/cq-source-yc/resources/organizationmanager/users.go",
198+
"resources/quotamanager/limits.go":"security/cloudquery/cq-source-yc/resources/quotamanager/limits.go",
199+
"resources/quotamanager/services.go":"security/cloudquery/cq-source-yc/resources/quotamanager/services.go",
196200
"resources/resourcemanager/clouds.go":"security/cloudquery/cq-source-yc/resources/resourcemanager/clouds.go",
197201
"resources/resourcemanager/folders.go":"security/cloudquery/cq-source-yc/resources/resourcemanager/folders.go",
198202
"resources/serverless/api_gateways.go":"security/cloudquery/cq-source-yc/resources/serverless/api_gateways.go",

client/client.go

Lines changed: 12 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -25,10 +25,11 @@ const (
2525
type Client struct {
2626
hierarchy *ResourceHierarchy
2727

28-
OrganizationId string
29-
CloudId string
30-
FolderId string
31-
MultiplexedResourceId string
28+
OrganizationId string
29+
CloudId string
30+
FolderId string
31+
MultiplexedResourceId string
32+
MultiplexedResourceType ResourceType
3233

3334
Backend state.Client
3435
Logger zerolog.Logger
@@ -59,20 +60,23 @@ func (c *Client) WithOrganization(id string) *Client {
5960
newC := *c
6061
newC.Logger = c.Logger.With().Str("organization", id).Logger()
6162
newC.OrganizationId = id
63+
newC.MultiplexedResourceType = ResourceTypeOrganization
6264
return &newC
6365
}
6466

6567
func (c *Client) WithCloud(id string) *Client {
6668
newC := *c
6769
newC.Logger = c.Logger.With().Str("cloud", id).Logger()
6870
newC.CloudId = id
71+
newC.MultiplexedResourceType = ResourceTypeCloud
6972
return &newC
7073
}
7174

7275
func (c *Client) WithFolder(id string) *Client {
7376
newC := *c
7477
newC.Logger = c.Logger.With().Str("folder", id).Logger()
7578
newC.FolderId = id
79+
newC.MultiplexedResourceType = ResourceTypeFolder
7680
return &newC
7781
}
7882

@@ -96,8 +100,7 @@ func New(ctx context.Context, logger zerolog.Logger, spec *Spec) (*Client, error
96100
streamInterceptors := []grpc.StreamClientInterceptor{}
97101

98102
var dialOpts = []grpc.DialOption{
99-
grpc.WithChainUnaryInterceptor(unaryInterceptors...),
100-
grpc.WithChainStreamInterceptor(streamInterceptors...),
103+
grpc.WithUserAgent(DefaultUserAgent),
101104
}
102105

103106
if spec.MaxRetries > 0 {
@@ -117,14 +120,14 @@ func New(ctx context.Context, logger zerolog.Logger, spec *Spec) (*Client, error
117120
streamInterceptors = append(streamInterceptors, logging.StreamClientInterceptor(grpczerolog.InterceptorLogger(logger)))
118121
}
119122

123+
dialOpts = append(dialOpts, grpc.WithChainUnaryInterceptor(unaryInterceptors...), grpc.WithChainStreamInterceptor(streamInterceptors...))
124+
120125
sdk, err := ycsdk.Build(ctx,
121126
ycsdk.Config{
122127
Credentials: credentials,
123128
Endpoint: spec.Endpoint,
124129
},
125-
grpc.WithUserAgent(DefaultUserAgent),
126-
grpc.WithChainUnaryInterceptor(unaryInterceptors...),
127-
grpc.WithChainStreamInterceptor(streamInterceptors...),
130+
dialOpts...,
128131
)
129132
if err != nil {
130133
return nil, fmt.Errorf("initialize Yandex Cloud SDK: %w", err)

client/multiplexer.go

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,3 +43,13 @@ func PrependEmptyMultiplex(multiplexer schema.Multiplexer) schema.Multiplexer {
4343
return append([]schema.ClientMeta{client}, multiplexer(meta)...)
4444
}
4545
}
46+
47+
func CombineMultiplex(multiplexers ...schema.Multiplexer) schema.Multiplexer {
48+
return func(meta schema.ClientMeta) []schema.ClientMeta {
49+
clients := []schema.ClientMeta{}
50+
for _, m := range multiplexers {
51+
clients = append(clients, m(meta)...)
52+
}
53+
return clients
54+
}
55+
}

client/resolvers.go

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ import (
1010
"google.golang.org/protobuf/reflect/protoreflect"
1111
"google.golang.org/protobuf/runtime/protoimpl"
1212
"google.golang.org/protobuf/types/known/timestamppb"
13+
"google.golang.org/protobuf/types/known/wrapperspb"
1314
)
1415

1516
func ResolveProtoEnum(path string) schema.ColumnResolver {
@@ -40,6 +41,20 @@ func ResolveProtoTimestamp(path string) schema.ColumnResolver {
4041
}
4142
}
4243

44+
func ResolveDouble(path string) schema.ColumnResolver {
45+
return func(ctx context.Context, meta schema.ClientMeta, resource *schema.Resource, c schema.Column) error {
46+
data := funk.Get(resource.Item, path)
47+
if data == nil {
48+
return nil
49+
}
50+
double, ok := data.(*wrapperspb.DoubleValue)
51+
if !ok {
52+
return fmt.Errorf("unexpected type, wanted \"*wrapperspb.DoubleValue\", have \"%T\"", data)
53+
}
54+
return resource.Set(c.Name, double.GetValue())
55+
}
56+
}
57+
4358
var ParentIdColumn schema.Column = schema.Column{
4459
Name: "id",
4560
Type: arrow.BinaryTypes.String,

client/resourcehierarchy.go

Lines changed: 33 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import (
88

99
"github.com/rs/zerolog"
1010
"github.com/yandex-cloud/cq-source-yc/internal/util"
11+
"github.com/yandex-cloud/go-genproto/yandex/cloud/billing/v1"
1112
"github.com/yandex-cloud/go-genproto/yandex/cloud/endpoint"
1213
"github.com/yandex-cloud/go-genproto/yandex/cloud/organizationmanager/v1"
1314
"github.com/yandex-cloud/go-genproto/yandex/cloud/resourcemanager/v1"
@@ -18,7 +19,8 @@ import (
1819
)
1920

2021
// Self-made name for struct holding info about resource model hierarchy.
21-
// Each field could be nil.
22+
// Each field could be empty.
23+
// https://yandex.cloud/en/docs/resource-manager/concepts/resources-hierarchy
2224
type ResourceHierarchyItem struct {
2325
Organization string
2426
Cloud string
@@ -84,11 +86,36 @@ func (h *ResourceHierarchy) FolderRows() []ResourceHierarchyItem {
8486
})
8587
}
8688

89+
type Service string
90+
91+
const (
92+
ServiceResourceManager Service = "resource-manager"
93+
ServiceOrganizationManager Service = "organization-manager"
94+
)
95+
96+
type ResourceType string
97+
8798
const (
88-
serviceResourceManager = "resource-manager"
89-
serviceOrganizationManager = "organization-manager"
99+
ResourceTypeOrganization ResourceType = "organization-manager.organization"
100+
ResourceTypeCloud ResourceType = "resource-manager.cloud"
101+
ResourceTypeFolder ResourceType = "resource-manager.folder"
102+
ResourceTypeBillingAccount ResourceType = "billing.account"
90103
)
91104

105+
// TODO: codegen
106+
func ResourceTypeFromProto(p any) (ResourceType, bool) {
107+
switch p.(type) {
108+
case organizationmanager.Organization:
109+
return ResourceTypeOrganization, true
110+
case resourcemanager.Cloud:
111+
return ResourceTypeCloud, true
112+
case billing.BillingAccount:
113+
return ResourceTypeBillingAccount, true
114+
default:
115+
return ResourceType(""), false
116+
}
117+
}
118+
92119
// discover the hierarchy using Breadth-first search
93120
func bfs(ctx context.Context, sdk *ycsdk.SDK, logger zerolog.Logger, init []ResourceHierarchyItem, organizations []string, clouds []string, folders []string, opts ...grpc.CallOption) ([]ResourceHierarchyItem, error) {
94121
// call ApiEndpoint.List to fill internal endpoint list in ycsdk.SDK
@@ -123,7 +150,7 @@ func bfs(ctx context.Context, sdk *ycsdk.SDK, logger zerolog.Logger, init []Reso
123150
if item.Folder != "" {
124151
// just append to items
125152
continue
126-
} else if item.Cloud != "" && services[serviceResourceManager] {
153+
} else if item.Cloud != "" && services[string(ServiceResourceManager)] {
127154
// discover folders
128155
it := sdk.ResourceManager().Folder().FolderIterator(ctx, &resourcemanager.ListFoldersRequest{CloudId: item.Cloud}, opts...)
129156
for it.Next() {
@@ -144,7 +171,7 @@ func bfs(ctx context.Context, sdk *ycsdk.SDK, logger zerolog.Logger, init []Reso
144171
}
145172
return nil, err
146173
}
147-
} else if item.Organization != "" && services[serviceResourceManager] {
174+
} else if item.Organization != "" && services[string(ServiceResourceManager)] {
148175
// discover clouds
149176
it := sdk.ResourceManager().Cloud().CloudIterator(ctx, &resourcemanager.ListCloudsRequest{OrganizationId: item.Organization}, opts...)
150177
for it.Next() {
@@ -165,7 +192,7 @@ func bfs(ctx context.Context, sdk *ycsdk.SDK, logger zerolog.Logger, init []Reso
165192
}
166193
return nil, err
167194
}
168-
} else if services[serviceOrganizationManager] {
195+
} else if services[string(ServiceOrganizationManager)] {
169196
// discover organizations
170197
it := sdk.OrganizationManager().Organization().OrganizationIterator(ctx, &organizationmanager.ListOrganizationsRequest{}, opts...)
171198
for it.Next() {

client/transformers.go

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,13 +9,17 @@ import (
99
cqtypes "github.com/cloudquery/plugin-sdk/v4/types"
1010
"google.golang.org/protobuf/reflect/protoreflect"
1111
"google.golang.org/protobuf/types/known/timestamppb"
12+
"google.golang.org/protobuf/types/known/wrapperspb"
1213
)
1314

1415
func typeTransformer(field reflect.StructField) (arrow.DataType, error) {
1516
switch reflect.New(field.Type).Elem().Interface().(type) {
1617
case *timestamppb.Timestamp,
1718
timestamppb.Timestamp:
1819
return arrow.FixedWidthTypes.Timestamp_us, nil
20+
case *wrapperspb.DoubleValue,
21+
wrapperspb.DoubleValue:
22+
return arrow.PrimitiveTypes.Float64, nil
1923
case protoreflect.Enum:
2024
return arrow.BinaryTypes.String, nil
2125
case nil:
@@ -30,6 +34,9 @@ func resolverTransformer(field reflect.StructField, path string) schema.ColumnRe
3034
case *timestamppb.Timestamp,
3135
timestamppb.Timestamp:
3236
return ResolveProtoTimestamp(path)
37+
case *wrapperspb.DoubleValue,
38+
wrapperspb.DoubleValue:
39+
return ResolveDouble(path)
3340
case protoreflect.Enum:
3441
return ResolveProtoEnum(path)
3542
default:

docs/tables/README.md

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,8 @@
7171
- [yc_organizationmanager_organizations](yc_organizationmanager_organizations.md)
7272
- [yc_organizationmanager_oslogin_settings](yc_organizationmanager_oslogin_settings.md)
7373
- [yc_organizationmanager_users](yc_organizationmanager_users.md)
74+
- [yc_quotamanager_quota_services](yc_quotamanager_quota_services.md)
75+
- [yc_quotamanager_quota_limits](yc_quotamanager_quota_limits.md)
7476
- [yc_resourcemanager_clouds](yc_resourcemanager_clouds.md)
7577
- [yc_resourcemanager_folders](yc_resourcemanager_folders.md)
7678
- [yc_serverless_apigateway_gateways](yc_serverless_apigateway_gateways.md)
@@ -88,4 +90,4 @@
8890
- [yc_vpc_security_groups](yc_vpc_security_groups.md)
8991
- [yc_vpc_subnets](yc_vpc_subnets.md)
9092
- [yc_ydb_databases](yc_ydb_databases.md)
91-
- [yc_access_bindings_ydb_databases](yc_access_bindings_ydb_databases.md)
93+
- [yc_access_bindings_ydb_databases](yc_access_bindings_ydb_databases.md)

docs/tables/yc_cdn_resources.md

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,4 +25,6 @@ The primary key for this table is **id**.
2525
|origin_group_name|`utf8`|
2626
|origin_protocol|`utf8`|
2727
|ssl_certificate|`json`|
28-
|labels|`json`|
28+
|labels|`json`|
29+
|provider_type|`utf8`|
30+
|provider_cname|`utf8`|
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
# Table: yc_quotamanager_quota_limits
2+
3+
This table shows data for YC Quota Manager Quota Limits.
4+
5+
https://yandex.cloud/ru/docs/quota-manager/api-ref/grpc/QuotaLimit/list#yandex.cloud.quotamanager.v1.QuotaLimit
6+
7+
The composite primary key for this table is (**resource_id**, **quota_id**).
8+
9+
## Relations
10+
11+
This table depends on [yc_quotamanager_quota_services](yc_quotamanager_quota_services.md).
12+
13+
## Columns
14+
15+
| Name | Type |
16+
| ------------- | ------------- |
17+
|_cq_id|`uuid`|
18+
|_cq_parent_id|`uuid`|
19+
|resource_id (PK)|`utf8`|
20+
|resource_type|`utf8`|
21+
|quota_id (PK)|`utf8`|
22+
|limit|`json`|
23+
|usage|`json`|
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
# Table: yc_quotamanager_quota_services
2+
3+
This table shows data for YC Quota Manager Quota Services.
4+
5+
https://yandex.cloud/ru/docs/quota-manager/api-ref/grpc/QuotaLimit/listServices#yandex.cloud.quotamanager.v1.Service
6+
7+
The composite primary key for this table is (**id**, **resource_type**).
8+
9+
## Relations
10+
11+
The following tables depend on yc_quotamanager_quota_services:
12+
- [yc_quotamanager_quota_limits](yc_quotamanager_quota_limits.md)
13+
14+
## Columns
15+
16+
| Name | Type |
17+
| ------------- | ------------- |
18+
|_cq_id|`uuid`|
19+
|_cq_parent_id|`uuid`|
20+
|id (PK)|`utf8`|
21+
|name|`utf8`|
22+
|resource_type (PK)|`utf8`|

0 commit comments

Comments
 (0)