-
Notifications
You must be signed in to change notification settings - Fork 9
/
resourceprovider.go
116 lines (95 loc) · 3.49 KB
/
resourceprovider.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
// Copyright 2022 Namespace Labs Inc; All rights reserved.
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
package parsing
import (
"context"
"fmt"
"namespacelabs.dev/foundation/framework/rpcerrors/multierr"
"namespacelabs.dev/foundation/internal/fnerrors"
"namespacelabs.dev/foundation/schema"
"namespacelabs.dev/foundation/std/pkggraph"
)
func transformResourceProvider(ctx context.Context, pl EarlyPackageLoader, pkg *pkggraph.Package, provider *schema.ResourceProvider) (*pkggraph.ResourceProvider, error) {
if provider.InitializedWith == nil && provider.PrepareWith == nil && !isRuntimeResource(provider.ProvidesClass) {
return nil, fnerrors.NewWithLocation(pkg.Location, "resource provider requires either initializedWith or prepareWith")
}
if provider.InitializedWith != nil {
if _, _, err := pkggraph.LoadBinary(ctx, pl, provider.InitializedWith.BinaryRef); err != nil {
return nil, err
}
}
if provider.PrepareWith != nil {
if _, _, err := pkggraph.LoadBinary(ctx, pl, provider.PrepareWith.BinaryRef); err != nil {
return nil, err
}
}
var errs []error
if _, err := pkggraph.LookupResourceClass(ctx, pl, pkg, provider.ProvidesClass); err != nil {
errs = append(errs, err)
}
rp := pkggraph.ResourceProvider{Spec: provider}
provider.PackageName = pkg.Location.PackageName.String()
if provider.IntentType != nil {
parseOpts, err := MakeProtoParseOpts(ctx, pl, pkg.Location.Module.Workspace)
if err != nil {
errs = append(errs, err)
} else {
intentType, err := loadUserType(ctx, pl, parseOpts, pkg.Location, provider.IntentType)
if err != nil {
errs = append(errs, err)
} else {
rp.IntentType = &intentType
}
}
}
for _, input := range provider.ResourceInput {
if rp.LookupExpected(input.Name) != nil {
errs = append(errs, fnerrors.BadInputError("resource input %q defined more than once", input.Name.Canonical()))
continue
}
class, err := pkggraph.LookupResourceClass(ctx, pl, pkg, input.Class)
if err != nil {
errs = append(errs, err)
} else {
x := pkggraph.ExpectedResourceInstance{
Name: input.Name,
Class: *class,
}
if input.DefaultResource != nil {
if input.DefaultResource.PackageName != pkg.PackageName().String() {
if err := pl.Ensure(ctx, schema.PackageName(input.DefaultResource.PackageName)); err != nil {
return nil, err
}
}
x.DefaultResource = input.DefaultResource
}
rp.ResourceInputs = append(rp.ResourceInputs, x)
}
}
rp.ProviderID = fmt.Sprintf("{%s; class=%s}", provider.PackageName, provider.ProvidesClass.Canonical())
if instances, err := LoadResources(ctx, pl, pkg, rp.ProviderID, provider.ResourcePack); err != nil {
errs = append(errs, err)
} else {
for _, instance := range instances {
if rp.LookupExpected(instance.ResourceRef) != nil {
errs = append(errs, fnerrors.BadInputError("%q is both a resource input and a static input", instance.ResourceRef.Name))
} else {
rp.Resources = append(rp.Resources, instance)
}
}
}
// Make sure that all referenced classes and providers are loaded.
for _, pkg := range provider.AvailableClasses {
err := pl.Ensure(ctx, pkg.AsPackageName())
errs = append(errs, err)
}
for _, pkg := range provider.AvailablePackages {
err := pl.Ensure(ctx, schema.PackageName(pkg))
errs = append(errs, err)
}
if err := multierr.New(errs...); err != nil {
return nil, fnerrors.AttachLocation(pkg.Location, err)
}
return &rp, nil
}