pulumi/pkg/codegen/schema/loader.go
Pat Gavlin d07c3698e5
[codegen/{hcl2,schema}] Abstract package loading. (#4975)
Instead of requiring a plugin host for package loading in the HCL2
binder, define a much narrower interface that exposes the ability to
fetch the schema for a package at a specific version. This interface is
defined in the schema package, which also exposes a caching loader that
is backed by provider plugins.

These changes also add some convenience methods to `*schema.Package` for
fast access to particular resources and functions.

Related to #1635.
2020-07-07 14:45:18 -07:00

80 lines
1.4 KiB
Go

package schema
import (
"sync"
"github.com/blang/semver"
jsoniter "github.com/json-iterator/go"
"github.com/pulumi/pulumi/sdk/v2/go/common/resource/plugin"
"github.com/pulumi/pulumi/sdk/v2/go/common/tokens"
)
type Loader interface {
LoadPackage(pkg string, version *semver.Version) (*Package, error)
}
type pluginLoader struct {
m sync.RWMutex
host plugin.Host
entries map[string]*Package
}
func NewPluginLoader(host plugin.Host) Loader {
return &pluginLoader{
host: host,
entries: map[string]*Package{},
}
}
func (l *pluginLoader) getPackage(key string) (*Package, bool) {
l.m.RLock()
defer l.m.RUnlock()
p, ok := l.entries[key]
return p, ok
}
func (l *pluginLoader) LoadPackage(pkg string, version *semver.Version) (*Package, error) {
key := pkg + "@"
if version != nil {
key += version.String()
}
if p, ok := l.getPackage(key); ok {
return p, nil
}
provider, err := l.host.Provider(tokens.Package(pkg), version)
if err != nil {
return nil, err
}
schemaFormatVersion := 0
schemaBytes, err := provider.GetSchema(schemaFormatVersion)
if err != nil {
return nil, err
}
var spec PackageSpec
if err := jsoniter.Unmarshal(schemaBytes, &spec); err != nil {
return nil, err
}
p, err := ImportSpec(spec, nil)
if err != nil {
return nil, err
}
l.m.Lock()
defer l.m.Unlock()
if p, ok := l.entries[pkg]; ok {
return p, nil
}
l.entries[pkg] = p
return p, nil
}