Support remote components in Python (#5375)

This commit is contained in:
Justin Van Patten 2020-09-30 21:09:20 +00:00 committed by GitHub
parent 38172999e7
commit 9bcf02e7ed
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
19 changed files with 334 additions and 103 deletions

View file

@ -3,7 +3,8 @@ CHANGELOG
## HEAD (Unreleased) ## HEAD (Unreleased)
_(None)_ - Add internal scaffolding for using cross-language components from Python.
[#5375](https://github.com/pulumi/pulumi/pull/5375)
## 2.11.0 (2020-09-30) ## 2.11.0 (2020-09-30)
@ -18,7 +19,6 @@ _(None)_
(fixes [#5446](https://github.com/pulumi/pulumi/issues/5446)) (fixes [#5446](https://github.com/pulumi/pulumi/issues/5446))
[#5465](https://github.com/pulumi/pulumi/pull/5465) [#5465](https://github.com/pulumi/pulumi/pull/5465)
## 2.10.2 (2020-09-21) ## 2.10.2 (2020-09-21)
- [sdk/go] Add missing Version field to invokeOptions - [sdk/go] Add missing Version field to invokeOptions
@ -26,7 +26,7 @@ _(None)_
- Add `pulumi console` command which opens the currently selected stack in the Pulumi console. - Add `pulumi console` command which opens the currently selected stack in the Pulumi console.
[#5368](https://github.com/pulumi/pulumi/pull/5368) [#5368](https://github.com/pulumi/pulumi/pull/5368)
- Python SDK: Cast numbers intended to be integers to `int`. - Python SDK: Cast numbers intended to be integers to `int`.
[#5419](https://github.com/pulumi/pulumi/pull/5419) [#5419](https://github.com/pulumi/pulumi/pull/5419)

View file

@ -1570,6 +1570,36 @@ func (pt *ProgramTester) copyTestToTemporaryDirectory() (string, string, error)
return "", "", errors.Wrapf(err, "Failed to prepare %v", projdir) return "", "", errors.Wrapf(err, "Failed to prepare %v", projdir)
} }
// TODO[pulumi/pulumi#5455]: Dynamic providers fail to load when used from multi-lang components.
// Until that's been fixed, this environment variable can be set by a test, which results in
// a package.json being emitted in the project directory and `yarn install && yarn link @pulumi/pulumi`
// being run.
// When the underlying issue has been fixed, the use of this environment variable should be removed.
var yarnLinkPulumi bool
for _, env := range pt.opts.Env {
if env == "PULUMI_TEST_YARN_LINK_PULUMI=true" {
yarnLinkPulumi = true
break
}
}
if yarnLinkPulumi {
const packageJSON = `{
"name": "test",
"peerDependencies": {
"@pulumi/pulumi": "latest"
}
}`
if err := ioutil.WriteFile(filepath.Join(projdir, "package.json"), []byte(packageJSON), 0600); err != nil {
return "", "", err
}
if err = pt.runYarnCommand("yarn-install", []string{"install"}, projdir); err != nil {
return "", "", err
}
if err := pt.runYarnCommand("yarn-link", []string{"link", "@pulumi/pulumi"}, projdir); err != nil {
return "", "", err
}
}
fprintf(stdout, "projdir: %v\n", projdir) fprintf(stdout, "projdir: %v\n", projdir)
return tmpdir, projdir, nil return tmpdir, projdir, nil
} }

View file

@ -1252,7 +1252,7 @@ proto.pulumirpc.RegisterResourceRequest.toObject = function(includeInstance, msg
customtimeouts: (f = msg.getCustomtimeouts()) && proto.pulumirpc.RegisterResourceRequest.CustomTimeouts.toObject(includeInstance, f), customtimeouts: (f = msg.getCustomtimeouts()) && proto.pulumirpc.RegisterResourceRequest.CustomTimeouts.toObject(includeInstance, f),
deletebeforereplacedefined: jspb.Message.getBooleanFieldWithDefault(msg, 18, false), deletebeforereplacedefined: jspb.Message.getBooleanFieldWithDefault(msg, 18, false),
supportspartialvalues: jspb.Message.getBooleanFieldWithDefault(msg, 19, false), supportspartialvalues: jspb.Message.getBooleanFieldWithDefault(msg, 19, false),
remote: jspb.Message.getBooleanFieldWithDefault(msg, 21, false) remote: jspb.Message.getBooleanFieldWithDefault(msg, 20, false)
}; };
if (includeInstance) { if (includeInstance) {
@ -1369,7 +1369,7 @@ proto.pulumirpc.RegisterResourceRequest.deserializeBinaryFromReader = function(m
var value = /** @type {boolean} */ (reader.readBool()); var value = /** @type {boolean} */ (reader.readBool());
msg.setSupportspartialvalues(value); msg.setSupportspartialvalues(value);
break; break;
case 21: case 20:
var value = /** @type {boolean} */ (reader.readBool()); var value = /** @type {boolean} */ (reader.readBool());
msg.setRemote(value); msg.setRemote(value);
break; break;
@ -1537,7 +1537,7 @@ proto.pulumirpc.RegisterResourceRequest.serializeBinaryToWriter = function(messa
f = message.getRemote(); f = message.getRemote();
if (f) { if (f) {
writer.writeBool( writer.writeBool(
21, 20,
f f
); );
} }
@ -2351,11 +2351,11 @@ proto.pulumirpc.RegisterResourceRequest.prototype.setSupportspartialvalues = fun
/** /**
* optional bool remote = 21; * optional bool remote = 20;
* @return {boolean} * @return {boolean}
*/ */
proto.pulumirpc.RegisterResourceRequest.prototype.getRemote = function() { proto.pulumirpc.RegisterResourceRequest.prototype.getRemote = function() {
return /** @type {boolean} */ (jspb.Message.getBooleanFieldWithDefault(this, 21, false)); return /** @type {boolean} */ (jspb.Message.getBooleanFieldWithDefault(this, 20, false));
}; };
@ -2364,7 +2364,7 @@ proto.pulumirpc.RegisterResourceRequest.prototype.getRemote = function() {
* @return {!proto.pulumirpc.RegisterResourceRequest} returns this * @return {!proto.pulumirpc.RegisterResourceRequest} returns this
*/ */
proto.pulumirpc.RegisterResourceRequest.prototype.setRemote = function(value) { proto.pulumirpc.RegisterResourceRequest.prototype.setRemote = function(value) {
return jspb.Message.setProto3BooleanField(this, 21, value); return jspb.Message.setProto3BooleanField(this, 20, value);
}; };

View file

@ -295,7 +295,7 @@ type RegisterResourceRequest struct {
CustomTimeouts *RegisterResourceRequest_CustomTimeouts `protobuf:"bytes,17,opt,name=customTimeouts,proto3" json:"customTimeouts,omitempty"` CustomTimeouts *RegisterResourceRequest_CustomTimeouts `protobuf:"bytes,17,opt,name=customTimeouts,proto3" json:"customTimeouts,omitempty"`
DeleteBeforeReplaceDefined bool `protobuf:"varint,18,opt,name=deleteBeforeReplaceDefined,proto3" json:"deleteBeforeReplaceDefined,omitempty"` DeleteBeforeReplaceDefined bool `protobuf:"varint,18,opt,name=deleteBeforeReplaceDefined,proto3" json:"deleteBeforeReplaceDefined,omitempty"`
SupportsPartialValues bool `protobuf:"varint,19,opt,name=supportsPartialValues,proto3" json:"supportsPartialValues,omitempty"` SupportsPartialValues bool `protobuf:"varint,19,opt,name=supportsPartialValues,proto3" json:"supportsPartialValues,omitempty"`
Remote bool `protobuf:"varint,21,opt,name=remote,proto3" json:"remote,omitempty"` Remote bool `protobuf:"varint,20,opt,name=remote,proto3" json:"remote,omitempty"`
XXX_NoUnkeyedLiteral struct{} `json:"-"` XXX_NoUnkeyedLiteral struct{} `json:"-"`
XXX_unrecognized []byte `json:"-"` XXX_unrecognized []byte `json:"-"`
XXX_sizecache int32 `json:"-"` XXX_sizecache int32 `json:"-"`
@ -761,63 +761,63 @@ func init() { proto.RegisterFile("resource.proto", fileDescriptor_d1b72f771c35e3
var fileDescriptor_d1b72f771c35e3b8 = []byte{ var fileDescriptor_d1b72f771c35e3b8 = []byte{
// 927 bytes of a gzipped FileDescriptorProto // 927 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xa4, 0x56, 0x5f, 0x73, 0xdb, 0x44, 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xa4, 0x56, 0x5f, 0x73, 0xdb, 0x44,
0x10, 0x8f, 0xed, 0x54, 0xb1, 0x37, 0xa9, 0x13, 0x2e, 0xa9, 0x73, 0x15, 0x4c, 0x08, 0x82, 0x07, 0x10, 0x8f, 0xed, 0x54, 0xb1, 0x37, 0xa9, 0x13, 0x2e, 0xc1, 0xb9, 0x0a, 0x26, 0x04, 0xc1, 0x83,
0xc3, 0x83, 0xd3, 0x06, 0x66, 0x1a, 0x18, 0xfe, 0xcc, 0xd0, 0x16, 0xa6, 0x0f, 0x85, 0xa2, 0x30, 0xe1, 0xc1, 0x69, 0x03, 0x33, 0x0d, 0x0c, 0x7f, 0x66, 0x68, 0x0b, 0xd3, 0x87, 0x42, 0x51, 0x18,
0x0c, 0x30, 0x03, 0x33, 0x17, 0x69, 0xe3, 0x8a, 0xc8, 0xba, 0xeb, 0xdd, 0x29, 0x33, 0x7e, 0x83, 0x06, 0x98, 0x81, 0x99, 0x8b, 0xb4, 0x71, 0x45, 0x64, 0xdd, 0xf5, 0xee, 0x94, 0x19, 0xbf, 0xc1,
0x47, 0xbe, 0x16, 0x9f, 0x86, 0x67, 0x3e, 0x01, 0x73, 0x77, 0x92, 0xb1, 0x2c, 0x39, 0xb1, 0xcb, 0x23, 0x5f, 0x8b, 0x4f, 0xc3, 0x33, 0x9f, 0x80, 0xb9, 0x3b, 0xc9, 0x58, 0x96, 0x9c, 0xd8, 0xed,
0xdb, 0xed, 0xee, 0xdd, 0x4a, 0xfb, 0xfb, 0xfd, 0x76, 0xef, 0xa0, 0x2f, 0x51, 0xf1, 0x5c, 0x46, 0xdb, 0xed, 0xee, 0xdd, 0x4a, 0xfb, 0xfb, 0xfd, 0x76, 0xef, 0xa0, 0x2f, 0x51, 0xf1, 0x5c, 0x46,
0x38, 0x12, 0x92, 0x6b, 0x4e, 0x7a, 0x22, 0x4f, 0xf3, 0x49, 0x22, 0x45, 0xe4, 0xbf, 0x39, 0xe6, 0x38, 0x12, 0x92, 0x6b, 0x4e, 0x7a, 0x22, 0x4f, 0xf3, 0x49, 0x22, 0x45, 0xe4, 0xbf, 0x35, 0xe6,
0x7c, 0x9c, 0xe2, 0x89, 0x0d, 0x5c, 0xe4, 0x97, 0x27, 0x38, 0x11, 0x7a, 0xea, 0xf6, 0xf9, 0x6f, 0x7c, 0x9c, 0xe2, 0x89, 0x0d, 0x5c, 0xe4, 0x97, 0x27, 0x38, 0x11, 0x7a, 0xea, 0xf6, 0xf9, 0x6f,
0x2d, 0x06, 0x95, 0x96, 0x79, 0xa4, 0x8b, 0x68, 0x5f, 0x48, 0x7e, 0x9d, 0xc4, 0x28, 0x9d, 0x1d, 0x2f, 0x06, 0x95, 0x96, 0x79, 0xa4, 0x8b, 0x68, 0x5f, 0x48, 0x7e, 0x9d, 0xc4, 0x28, 0x9d, 0x1d,
0x0c, 0x61, 0x70, 0x9e, 0x0b, 0xc1, 0xa5, 0x56, 0x5f, 0x21, 0xd3, 0xb9, 0xc4, 0x10, 0x5f, 0xe5, 0x0c, 0x61, 0x70, 0x9e, 0x0b, 0xc1, 0xa5, 0x56, 0x5f, 0x23, 0xd3, 0xb9, 0xc4, 0x10, 0x5f, 0xe6,
0xa8, 0x34, 0xe9, 0x43, 0x3b, 0x89, 0x69, 0xeb, 0xb8, 0x35, 0xec, 0x85, 0xed, 0x24, 0x0e, 0x3e, 0xa8, 0x34, 0xe9, 0x43, 0x3b, 0x89, 0x69, 0xeb, 0xb8, 0x35, 0xec, 0x85, 0xed, 0x24, 0x0e, 0x3e,
0x86, 0xc3, 0xda, 0x4e, 0x25, 0x78, 0xa6, 0x90, 0x1c, 0x01, 0xbc, 0x64, 0xaa, 0x88, 0xda, 0x23, 0x81, 0xc3, 0xda, 0x4e, 0x25, 0x78, 0xa6, 0x90, 0x1c, 0x01, 0xbc, 0x60, 0xaa, 0x88, 0xda, 0x23,
0xdd, 0x70, 0xce, 0x13, 0xfc, 0xd3, 0x86, 0xfd, 0x10, 0x59, 0x1c, 0x16, 0x15, 0x2d, 0xf9, 0x04, 0xdd, 0x70, 0xce, 0x13, 0xfc, 0xdb, 0x86, 0xfd, 0x10, 0x59, 0x1c, 0x16, 0x15, 0x2d, 0xf9, 0x04,
0x21, 0xb0, 0xa9, 0xa7, 0x02, 0x69, 0xdb, 0x7a, 0xec, 0xda, 0xf8, 0x32, 0x36, 0x41, 0xda, 0x71, 0x21, 0xb0, 0xa9, 0xa7, 0x02, 0x69, 0xdb, 0x7a, 0xec, 0xda, 0xf8, 0x32, 0x36, 0x41, 0xda, 0x71,
0x3e, 0xb3, 0x26, 0x03, 0xf0, 0x04, 0x93, 0x98, 0x69, 0xba, 0x69, 0xbd, 0x85, 0x45, 0x1e, 0x01, 0x3e, 0xb3, 0x26, 0x03, 0xf0, 0x04, 0x93, 0x98, 0x69, 0xba, 0x69, 0xbd, 0x85, 0x45, 0x1e, 0x02,
0x08, 0xc9, 0x05, 0x4a, 0x9d, 0xa0, 0xa2, 0x77, 0x8e, 0x5b, 0xc3, 0xed, 0xd3, 0xc3, 0x91, 0xc3, 0x08, 0xc9, 0x05, 0x4a, 0x9d, 0xa0, 0xa2, 0x77, 0x8e, 0x5b, 0xc3, 0xed, 0xd3, 0xc3, 0x91, 0xc3,
0x63, 0x54, 0xe2, 0x31, 0x3a, 0xb7, 0x78, 0x84, 0x73, 0x5b, 0x49, 0x00, 0x3b, 0x31, 0x0a, 0xcc, 0x63, 0x54, 0xe2, 0x31, 0x3a, 0xb7, 0x78, 0x84, 0x73, 0x5b, 0x49, 0x00, 0x3b, 0x31, 0x0a, 0xcc,
0x62, 0xcc, 0x22, 0x73, 0xd4, 0x3b, 0xee, 0x0c, 0x7b, 0x61, 0xc5, 0x47, 0x7c, 0xe8, 0x96, 0xd8, 0x62, 0xcc, 0x22, 0x73, 0xd4, 0x3b, 0xee, 0x0c, 0x7b, 0x61, 0xc5, 0x47, 0x7c, 0xe8, 0x96, 0xd8,
0xd1, 0x2d, 0xfb, 0xd9, 0x99, 0x4d, 0x28, 0x6c, 0x5d, 0xa3, 0x54, 0x09, 0xcf, 0x68, 0xd7, 0x86, 0xd1, 0x2d, 0xfb, 0xd9, 0x99, 0x4d, 0x28, 0x6c, 0x5d, 0xa3, 0x54, 0x09, 0xcf, 0x68, 0xd7, 0x86,
0x4a, 0x93, 0xbc, 0x07, 0x77, 0x59, 0x14, 0xa1, 0xd0, 0xe7, 0x18, 0x49, 0xd4, 0x8a, 0xf6, 0x2c, 0x4a, 0x93, 0xbc, 0x0f, 0x77, 0x59, 0x14, 0xa1, 0xd0, 0xe7, 0x18, 0x49, 0xd4, 0x8a, 0xf6, 0x2c,
0x3a, 0x55, 0x27, 0x39, 0x83, 0x43, 0x16, 0xc7, 0x89, 0x4e, 0x78, 0xc6, 0x52, 0xe7, 0xfc, 0x36, 0x3a, 0x55, 0x27, 0x39, 0x83, 0x43, 0x16, 0xc7, 0x89, 0x4e, 0x78, 0xc6, 0x52, 0xe7, 0xfc, 0x2e,
0xd7, 0x22, 0xd7, 0x8a, 0x82, 0xfd, 0x95, 0x65, 0x61, 0xf3, 0x65, 0x96, 0x26, 0x4c, 0xa1, 0xa2, 0xd7, 0x22, 0xd7, 0x8a, 0x82, 0xfd, 0x95, 0x65, 0x61, 0xf3, 0x65, 0x96, 0x26, 0x4c, 0xa1, 0xa2,
0xdb, 0x76, 0x67, 0x69, 0x06, 0x0c, 0x0e, 0xaa, 0x98, 0x17, 0x64, 0xed, 0x41, 0x27, 0x97, 0x59, 0xdb, 0x76, 0x67, 0x69, 0x06, 0x0c, 0x0e, 0xaa, 0x98, 0x17, 0x64, 0xed, 0x41, 0x27, 0x97, 0x59,
0x81, 0xba, 0x59, 0x2e, 0xc0, 0xd6, 0x5e, 0x19, 0xb6, 0xe0, 0xef, 0x2e, 0x1c, 0x86, 0x38, 0x4e, 0x81, 0xba, 0x59, 0x2e, 0xc0, 0xd6, 0x5e, 0x19, 0xb6, 0xe0, 0x9f, 0x2e, 0x1c, 0x86, 0x38, 0x4e,
0x94, 0x46, 0xb9, 0xc8, 0x6d, 0xc9, 0x65, 0xab, 0x81, 0xcb, 0x76, 0x23, 0x97, 0x9d, 0x0a, 0x97, 0x94, 0x46, 0xb9, 0xc8, 0x6d, 0xc9, 0x65, 0xab, 0x81, 0xcb, 0x76, 0x23, 0x97, 0x9d, 0x0a, 0x97,
0x03, 0xf0, 0xa2, 0x5c, 0x69, 0x3e, 0xb1, 0x1c, 0x77, 0xc3, 0xc2, 0x22, 0x27, 0xe0, 0xf1, 0x8b, 0x03, 0xf0, 0xa2, 0x5c, 0x69, 0x3e, 0xb1, 0x1c, 0x77, 0xc3, 0xc2, 0x22, 0x27, 0xe0, 0xf1, 0x8b,
0xdf, 0x30, 0xd2, 0xb7, 0xf1, 0x5b, 0x6c, 0x33, 0x08, 0x99, 0x90, 0x39, 0xe1, 0xd9, 0x4c, 0xa5, 0xdf, 0x31, 0xd2, 0xb7, 0xf1, 0x5b, 0x6c, 0x33, 0x08, 0x99, 0x90, 0x39, 0xe1, 0xd9, 0x4c, 0xa5,
0x59, 0x63, 0x7d, 0xeb, 0x16, 0xd6, 0xbb, 0x0b, 0xac, 0x0b, 0x38, 0x28, 0xc0, 0x98, 0x3e, 0x99, 0x59, 0x63, 0x7d, 0xeb, 0x16, 0xd6, 0xbb, 0x0b, 0xac, 0x0b, 0x38, 0x28, 0xc0, 0x98, 0x3e, 0x9e,
0xcf, 0xd3, 0x3b, 0xee, 0x0c, 0xb7, 0x4f, 0x3f, 0x1d, 0xcd, 0x1a, 0x76, 0xb4, 0x04, 0xa4, 0xd1, 0xcf, 0xd3, 0x3b, 0xee, 0x0c, 0xb7, 0x4f, 0x3f, 0x1b, 0xcd, 0x1a, 0x76, 0xb4, 0x04, 0xa4, 0xd1,
0x8b, 0x86, 0xe3, 0x4f, 0x33, 0x2d, 0xa7, 0x61, 0x63, 0x66, 0xf2, 0x00, 0xf6, 0x63, 0x4c, 0x51, 0xf3, 0x86, 0xe3, 0x4f, 0x32, 0x2d, 0xa7, 0x61, 0x63, 0x66, 0x72, 0x1f, 0xf6, 0x63, 0x4c, 0x51,
0xe3, 0x97, 0x78, 0xc9, 0x4d, 0x03, 0x8a, 0x94, 0x45, 0x48, 0xc1, 0xd6, 0xd5, 0x14, 0x9a, 0x57, 0xe3, 0x57, 0x78, 0xc9, 0x4d, 0x03, 0x8a, 0x94, 0x45, 0x48, 0xc1, 0xd6, 0xd5, 0x14, 0x9a, 0x57,
0xe6, 0x76, 0x4d, 0x99, 0xc9, 0x38, 0xe3, 0x12, 0x1f, 0xbf, 0x64, 0xd9, 0x18, 0x15, 0xdd, 0xb1, 0xe6, 0x76, 0x4d, 0x99, 0xc9, 0x38, 0xe3, 0x12, 0x1f, 0xbd, 0x60, 0xd9, 0x18, 0x15, 0xdd, 0xb1,
0xe5, 0x57, 0x9d, 0x75, 0xfd, 0xde, 0x5d, 0x53, 0xbf, 0xfd, 0x95, 0xf5, 0xbb, 0x5b, 0xd1, 0xaf, 0xe5, 0x57, 0x9d, 0x75, 0xfd, 0xde, 0x5d, 0x53, 0xbf, 0xfd, 0x95, 0xf5, 0xbb, 0x5b, 0xd1, 0xaf,
0x41, 0x3e, 0x99, 0x98, 0xf1, 0xf1, 0x2c, 0xa6, 0x7b, 0x0e, 0xf9, 0xd2, 0x26, 0x3f, 0x41, 0xdf, 0x41, 0x3e, 0x99, 0x98, 0xf1, 0xf1, 0x34, 0xa6, 0x7b, 0x0e, 0xf9, 0xd2, 0x26, 0x3f, 0x43, 0xdf,
0xc9, 0xe1, 0xfb, 0x64, 0x82, 0xdc, 0x7c, 0xe6, 0x0d, 0x2b, 0x86, 0x87, 0x2b, 0x60, 0xfe, 0xb8, 0xc9, 0xe1, 0x87, 0x64, 0x82, 0xdc, 0x7c, 0xe6, 0x0d, 0x2b, 0x86, 0x07, 0x2b, 0x60, 0xfe, 0xa8,
0x72, 0x30, 0x5c, 0x48, 0x44, 0x3e, 0x07, 0xbf, 0x01, 0xc7, 0x27, 0x78, 0x99, 0x64, 0x18, 0x53, 0x72, 0x30, 0x5c, 0x48, 0x44, 0xbe, 0x00, 0xbf, 0x01, 0xc7, 0xc7, 0x78, 0x99, 0x64, 0x18, 0x53,
0x62, 0xab, 0xbf, 0x61, 0x07, 0xf9, 0x08, 0xee, 0xa9, 0x62, 0x4c, 0xbe, 0x60, 0x52, 0x27, 0x2c, 0x62, 0xab, 0xbf, 0x61, 0x07, 0xf9, 0x18, 0xde, 0x54, 0xc5, 0x98, 0x7c, 0xce, 0xa4, 0x4e, 0x58,
0xfd, 0x81, 0xa5, 0x39, 0x2a, 0xba, 0x6f, 0x8f, 0x36, 0x07, 0x8d, 0xda, 0x25, 0x4e, 0xb8, 0x46, 0xfa, 0x23, 0x4b, 0x73, 0x54, 0x74, 0xdf, 0x1e, 0x6d, 0x0e, 0x1a, 0xb5, 0x4b, 0x9c, 0x70, 0x8d,
0x7a, 0xcf, 0xa9, 0xdd, 0x59, 0xfe, 0x07, 0x70, 0xd0, 0xa4, 0x11, 0xd3, 0x49, 0xb9, 0xcc, 0x14, 0xf4, 0xc0, 0xa9, 0xdd, 0x59, 0xfe, 0x87, 0x70, 0xd0, 0xa4, 0x11, 0xd3, 0x49, 0xb9, 0xcc, 0x14,
0x6d, 0x59, 0xcc, 0xec, 0xda, 0xff, 0x11, 0xfa, 0xd5, 0xda, 0x6c, 0x0f, 0x49, 0x64, 0xba, 0xec, 0x6d, 0x59, 0xcc, 0xec, 0xda, 0xff, 0x09, 0xfa, 0xd5, 0xda, 0x6c, 0x0f, 0x49, 0x64, 0xba, 0xec,
0xc2, 0xc2, 0x32, 0xfe, 0x5c, 0xc4, 0xc6, 0xef, 0x3a, 0xb1, 0xb0, 0x8c, 0xdf, 0x55, 0x56, 0xf6, 0xc2, 0xc2, 0x32, 0xfe, 0x5c, 0xc4, 0xc6, 0xef, 0x3a, 0xb1, 0xb0, 0x8c, 0xdf, 0x55, 0x56, 0xf6,
0xa2, 0xb3, 0xfc, 0xdf, 0x5b, 0x70, 0x7f, 0xa9, 0x54, 0xcd, 0x40, 0xb9, 0xc2, 0x69, 0x39, 0x50, 0xa2, 0xb3, 0xfc, 0x3f, 0x5a, 0x70, 0x6f, 0xa9, 0x54, 0xcd, 0x40, 0xb9, 0xc2, 0x69, 0x39, 0x50,
0xae, 0x70, 0x4a, 0x9e, 0xc3, 0x9d, 0x6b, 0x53, 0x57, 0x31, 0x4b, 0x1e, 0xbd, 0x66, 0x27, 0x84, 0xae, 0x70, 0x4a, 0x9e, 0xc1, 0x9d, 0x6b, 0x53, 0x57, 0x31, 0x4b, 0x1e, 0xbe, 0x62, 0x27, 0x84,
0x2e, 0xcb, 0x27, 0xed, 0xb3, 0x56, 0xf0, 0x57, 0x07, 0x68, 0xfd, 0xec, 0xd2, 0x91, 0xe6, 0x6e, 0x2e, 0xcb, 0xa7, 0xed, 0xb3, 0x56, 0xf0, 0x77, 0x07, 0x68, 0xfd, 0xec, 0xd2, 0x91, 0xe6, 0x6e,
0x96, 0xf6, 0xec, 0x66, 0xf9, 0x6f, 0x6a, 0x74, 0x56, 0x9b, 0x1a, 0x03, 0xf0, 0x94, 0x66, 0x17, 0x96, 0xf6, 0xec, 0x66, 0xf9, 0x7f, 0x6a, 0x74, 0x56, 0x9b, 0x1a, 0x03, 0xf0, 0x94, 0x66, 0x17,
0x29, 0x96, 0xe3, 0xc7, 0x59, 0x46, 0xaf, 0x6e, 0x65, 0xee, 0x17, 0xab, 0xd7, 0xc2, 0x24, 0xaf, 0x29, 0x96, 0xe3, 0xc7, 0x59, 0x46, 0xaf, 0x6e, 0x65, 0xee, 0x17, 0xab, 0xd7, 0xc2, 0x24, 0x2f,
0x96, 0x4c, 0x03, 0xcf, 0x4e, 0x83, 0xcf, 0x6e, 0xc4, 0xc0, 0xd5, 0xb1, 0xee, 0x38, 0x58, 0x4b, 0x97, 0x4c, 0x03, 0xcf, 0x4e, 0x83, 0xcf, 0x6f, 0xc4, 0xc0, 0xd5, 0xb1, 0xee, 0x38, 0x58, 0x4b,
0x1d, 0x7f, 0xac, 0xc9, 0xe1, 0x37, 0x55, 0x0e, 0xcf, 0x5e, 0xf7, 0xff, 0xe7, 0x49, 0x44, 0x38, 0x1d, 0x7f, 0xae, 0xc9, 0xe1, 0xb7, 0x55, 0x0e, 0xcf, 0x5e, 0xf5, 0xff, 0xe7, 0x49, 0x44, 0x38,
0x5a, 0x3c, 0x5b, 0xcc, 0x81, 0xf2, 0xd6, 0xa8, 0x33, 0xf9, 0x10, 0xb6, 0x78, 0x31, 0x4a, 0x6e, 0x5a, 0x3c, 0x5b, 0xcc, 0x81, 0xf2, 0xd6, 0xa8, 0x33, 0xf9, 0x00, 0xb6, 0x78, 0x31, 0x4a, 0x6e,
0xb9, 0x99, 0xca, 0x7d, 0xa7, 0x7f, 0x6e, 0xc2, 0x6e, 0x99, 0xff, 0x39, 0xcf, 0x12, 0xcd, 0x25, 0xb9, 0x99, 0xca, 0x7d, 0xa7, 0x7f, 0x6d, 0xc2, 0x6e, 0x99, 0xff, 0x19, 0xcf, 0x12, 0xcd, 0x25,
0xf9, 0x19, 0x76, 0x17, 0x5e, 0x2f, 0xe4, 0x9d, 0xb9, 0x92, 0x9a, 0xdf, 0x40, 0x7e, 0x70, 0xd3, 0xf9, 0x05, 0x76, 0x17, 0x5e, 0x2f, 0xe4, 0xdd, 0xb9, 0x92, 0x9a, 0xdf, 0x40, 0x7e, 0x70, 0xd3,
0x16, 0x57, 0x74, 0xb0, 0x41, 0xbe, 0x00, 0xef, 0x59, 0x76, 0xcd, 0xaf, 0x90, 0xd0, 0xb9, 0xfd, 0x16, 0x57, 0x74, 0xb0, 0x41, 0xbe, 0x04, 0xef, 0x69, 0x76, 0xcd, 0xaf, 0x90, 0xd0, 0xb9, 0xfd,
0xce, 0x55, 0x66, 0xba, 0xdf, 0x10, 0x99, 0x25, 0xf8, 0x1a, 0x76, 0xce, 0xb5, 0x44, 0x36, 0xf9, 0xce, 0x55, 0x66, 0xba, 0xd7, 0x10, 0x99, 0x25, 0xf8, 0x06, 0x76, 0xce, 0xb5, 0x44, 0x36, 0x79,
0x5f, 0x69, 0x1e, 0xb4, 0xc8, 0x77, 0xb0, 0x33, 0x7f, 0xe7, 0x93, 0xa3, 0x0a, 0x6b, 0xb5, 0x07, 0xad, 0x34, 0xf7, 0x5b, 0xe4, 0x7b, 0xd8, 0x99, 0xbf, 0xf3, 0xc9, 0x51, 0x85, 0xb5, 0xda, 0x03,
0x98, 0xff, 0xf6, 0xd2, 0xf8, 0xec, 0xdf, 0x7e, 0x81, 0xbd, 0x45, 0xce, 0x48, 0x70, 0x7b, 0x43, 0xcc, 0x7f, 0x67, 0x69, 0x7c, 0xf6, 0x6f, 0xbf, 0xc2, 0xde, 0x22, 0x67, 0x24, 0xb8, 0xbd, 0xa1,
0xfb, 0xef, 0xae, 0x20, 0x98, 0x60, 0x83, 0xfc, 0x5a, 0x7f, 0x41, 0x94, 0x57, 0xc3, 0xfb, 0x37, 0xfd, 0xf7, 0x56, 0x10, 0x4c, 0xb0, 0x41, 0x7e, 0xab, 0xbf, 0x20, 0xca, 0xab, 0xe1, 0x83, 0x1b,
0x64, 0xa8, 0xca, 0xc6, 0x1f, 0xd4, 0x34, 0xf1, 0xd4, 0xbc, 0x88, 0x83, 0x8d, 0x0b, 0xcf, 0x7a, 0x32, 0x54, 0x65, 0xe3, 0x0f, 0x6a, 0x9a, 0x78, 0x62, 0x5e, 0xc4, 0xc1, 0xc6, 0x85, 0x67, 0x3d,
0x3e, 0xfc, 0x37, 0x00, 0x00, 0xff, 0xff, 0x7a, 0x67, 0xe8, 0xd7, 0x4e, 0x0b, 0x00, 0x00, 0x1f, 0xfd, 0x17, 0x00, 0x00, 0xff, 0xff, 0xfe, 0xbf, 0x6d, 0x72, 0x4e, 0x0b, 0x00, 0x00,
} }
// Reference imports to suppress errors if they are not otherwise used. // Reference imports to suppress errors if they are not otherwise used.

View file

@ -160,7 +160,8 @@ disable=print-statement,
no-self-use, no-self-use,
unused-import, unused-import,
unsubscriptable-object, unsubscriptable-object,
line-too-long line-too-long,
too-many-lines
# Enable the message, report, category or checker with the given id(s). You can # Enable the message, report, category or checker with the given id(s). You can

View file

@ -13,6 +13,9 @@
# limitations under the License. # limitations under the License.
"""The Resource module, containing all resource-related definitions.""" """The Resource module, containing all resource-related definitions."""
import asyncio
from typing import Optional, List, Any, Mapping, Union, Callable, TYPE_CHECKING, cast from typing import Optional, List, Any, Mapping, Union, Callable, TYPE_CHECKING, cast
import copy import copy
@ -594,7 +597,9 @@ class Resource:
name: str, name: str,
custom: bool, custom: bool,
props: Optional['Inputs'] = None, props: Optional['Inputs'] = None,
opts: Optional[ResourceOptions] = None) -> None: opts: Optional[ResourceOptions] = None,
remote: bool = False,
dependency: bool = False) -> None:
""" """
:param str t: The type of this resource. :param str t: The type of this resource.
:param str name: The name of this resource. :param str name: The name of this resource.
@ -602,7 +607,15 @@ class Resource:
:param Optional[dict] props: An optional list of input properties to use as inputs for the resource. :param Optional[dict] props: An optional list of input properties to use as inputs for the resource.
:param Optional[ResourceOptions] opts: Optional set of :class:`pulumi.ResourceOptions` to use for this :param Optional[ResourceOptions] opts: Optional set of :class:`pulumi.ResourceOptions` to use for this
resource. resource.
:param bool remote: True if this is a remote component resource.
:param bool dependency: True if this is a synthetic resource used internally for dependency tracking.
""" """
if dependency:
self._protect = False
self._providers = {}
return
if props is None: if props is None:
props = {} props = {}
if not t: if not t:
@ -699,13 +712,13 @@ class Resource:
alias, name, t, opts.parent)) alias, name, t, opts.parent))
if opts.id is not None: if opts.id is not None:
# If this resource already exists, read its state rather than registering it anew. # If this is a custom resource that already exists, read its state from the provider.
if not custom: if not custom:
raise Exception( raise Exception(
"Cannot read an existing resource unless it has a custom provider") "Cannot read an existing resource unless it has a custom provider")
read_resource(cast('CustomResource', self), t, name, props, opts) read_resource(cast('CustomResource', self), t, name, props, opts)
else: else:
register_resource(self, t, name, custom, props, opts) register_resource(self, t, name, custom, remote, DependencyResource, props, opts)
@property @property
def urn(self) -> 'Output[str]': def urn(self) -> 'Output[str]':
@ -790,15 +803,17 @@ class CustomResource(Resource):
t: str, t: str,
name: str, name: str,
props: Optional[dict] = None, props: Optional[dict] = None,
opts: Optional[ResourceOptions] = None) -> None: opts: Optional[ResourceOptions] = None,
dependency: bool = False) -> None:
""" """
:param str t: The type of this resource. :param str t: The type of this resource.
:param str name: The name of this resource. :param str name: The name of this resource.
:param Optional[dict] props: An optional list of input properties to use as inputs for the resource. :param Optional[dict] props: An optional list of input properties to use as inputs for the resource.
:param Optional[ResourceOptions] opts: Optional set of :class:`pulumi.ResourceOptions` to use for this :param Optional[ResourceOptions] opts: Optional set of :class:`pulumi.ResourceOptions` to use for this
resource. resource.
:param bool dependency: True if this is a synthetic resource used internally for dependency tracking.
""" """
Resource.__init__(self, t, name, True, props, opts) Resource.__init__(self, t, name, True, props, opts, False, dependency)
self.__pulumi_type = t self.__pulumi_type = t
@property @property
@ -821,16 +836,18 @@ class ComponentResource(Resource):
t: str, t: str,
name: str, name: str,
props: Optional[dict] = None, props: Optional[dict] = None,
opts: Optional[ResourceOptions] = None) -> None: opts: Optional[ResourceOptions] = None,
remote: bool = False) -> None:
""" """
:param str t: The type of this resource. :param str t: The type of this resource.
:param str name: The name of this resource. :param str name: The name of this resource.
:param Optional[dict] props: An optional list of input properties to use as inputs for the resource. :param Optional[dict] props: An optional list of input properties to use as inputs for the resource.
:param Optional[ResourceOptions] opts: Optional set of :class:`pulumi.ResourceOptions` to use for this :param Optional[ResourceOptions] opts: Optional set of :class:`pulumi.ResourceOptions` to use for this
resource. resource.
:param bool remote: True if this is a remote component resource.
""" """
Resource.__init__(self, t, name, False, props, opts) Resource.__init__(self, t, name, False, props, opts, remote)
self.id = None self.__dict__["id"] = None
def register_outputs(self, outputs): def register_outputs(self, outputs):
""" """
@ -858,13 +875,15 @@ class ProviderResource(CustomResource):
pkg: str, pkg: str,
name: str, name: str,
props: Optional[dict] = None, props: Optional[dict] = None,
opts: Optional[ResourceOptions] = None) -> None: opts: Optional[ResourceOptions] = None,
dependency: bool = False) -> None:
""" """
:param str pkg: The package type of this provider resource. :param str pkg: The package type of this provider resource.
:param str name: The name of this resource. :param str name: The name of this resource.
:param Optional[dict] props: An optional list of input properties to use as inputs for the resource. :param Optional[dict] props: An optional list of input properties to use as inputs for the resource.
:param Optional[ResourceOptions] opts: Optional set of :class:`pulumi.ResourceOptions` to use for this :param Optional[ResourceOptions] opts: Optional set of :class:`pulumi.ResourceOptions` to use for this
resource. resource.
:param bool dependency: True if this is a synthetic resource used internally for dependency tracking.
""" """
if opts is not None and opts.provider is not None: if opts is not None and opts.provider is not None:
@ -872,10 +891,63 @@ class ProviderResource(CustomResource):
"Explicit providers may not be used with provider resources") "Explicit providers may not be used with provider resources")
# Provider resources are given a well-known type, prefixed with "pulumi:providers". # Provider resources are given a well-known type, prefixed with "pulumi:providers".
CustomResource.__init__( CustomResource.__init__(
self, f"pulumi:providers:{pkg}", name, props, opts) self, f"pulumi:providers:{pkg}", name, props, opts, dependency)
self.package = pkg self.package = pkg
class DependencyResource(CustomResource):
"""
A DependencyResource is a resource that is used to indicate that an Output has a dependency on a particular
resource. These resources are only created when dealing with remote component resources.
"""
def __init__(self, urn: str) -> None:
super().__init__(t="", name="", props={}, opts=None, dependency=True)
from . import Output # pylint: disable=import-outside-toplevel
urn_future: asyncio.Future[str] = asyncio.Future()
urn_known: asyncio.Future[bool] = asyncio.Future()
urn_secret: asyncio.Future[bool] = asyncio.Future()
urn_future.set_result(urn)
urn_known.set_result(True)
urn_secret.set_result(False)
self.__dict__["urn"] = Output({self}, urn_future, urn_known, urn_secret)
class DependencyProviderResource(ProviderResource):
"""
A DependencyProviderResource is a resource that is used by the provider SDK as a stand-in for a provider that
is only used for its reference. Its only valid properties are its URN and ID.
"""
def __init__(self, ref: str) -> None:
super().__init__(pkg="", name="", props={}, opts=None, dependency=True)
# Parse the URN and ID out of the provider reference.
last_sep = ref.rindex("::")
ref_urn = ref[:last_sep]
ref_id = ref[last_sep+2:]
from . import Output # pylint: disable=import-outside-toplevel
urn_future: asyncio.Future[str] = asyncio.Future()
urn_known: asyncio.Future[bool] = asyncio.Future()
urn_secret: asyncio.Future[bool] = asyncio.Future()
urn_future.set_result(ref_urn)
urn_known.set_result(True)
urn_secret.set_result(False)
self.__dict__["urn"] = Output({self}, urn_future, urn_known, urn_secret)
id_future: asyncio.Future[str] = asyncio.Future()
id_known: asyncio.Future[bool] = asyncio.Future()
id_secret: asyncio.Future[bool] = asyncio.Future()
id_future.set_result(ref_id)
id_known.set_result(True)
id_secret.set_result(False)
self.__dict__["id"] = Output({self}, id_future, id_known, id_secret)
def export(name: str, value: Any): def export(name: str, value: Any):
""" """
Exports a named stack output. Exports a named stack output.

View file

@ -21,7 +21,7 @@ DESCRIPTOR = _descriptor.FileDescriptor(
package='pulumirpc', package='pulumirpc',
syntax='proto3', syntax='proto3',
serialized_options=None, serialized_options=None,
serialized_pb=b'\n\x0eresource.proto\x12\tpulumirpc\x1a\x1bgoogle/protobuf/empty.proto\x1a\x1cgoogle/protobuf/struct.proto\x1a\x0eprovider.proto\"$\n\x16SupportsFeatureRequest\x12\n\n\x02id\x18\x01 \x01(\t\"-\n\x17SupportsFeatureResponse\x12\x12\n\nhasSupport\x18\x01 \x01(\x08\"\xfc\x01\n\x13ReadResourceRequest\x12\n\n\x02id\x18\x01 \x01(\t\x12\x0c\n\x04type\x18\x02 \x01(\t\x12\x0c\n\x04name\x18\x03 \x01(\t\x12\x0e\n\x06parent\x18\x04 \x01(\t\x12+\n\nproperties\x18\x05 \x01(\x0b\x32\x17.google.protobuf.Struct\x12\x14\n\x0c\x64\x65pendencies\x18\x06 \x03(\t\x12\x10\n\x08provider\x18\x07 \x01(\t\x12\x0f\n\x07version\x18\x08 \x01(\t\x12\x15\n\racceptSecrets\x18\t \x01(\x08\x12\x1f\n\x17\x61\x64\x64itionalSecretOutputs\x18\n \x03(\t\x12\x0f\n\x07\x61liases\x18\x0b \x03(\t\"P\n\x14ReadResourceResponse\x12\x0b\n\x03urn\x18\x01 \x01(\t\x12+\n\nproperties\x18\x02 \x01(\x0b\x32\x17.google.protobuf.Struct\"\xaf\x06\n\x17RegisterResourceRequest\x12\x0c\n\x04type\x18\x01 \x01(\t\x12\x0c\n\x04name\x18\x02 \x01(\t\x12\x0e\n\x06parent\x18\x03 \x01(\t\x12\x0e\n\x06\x63ustom\x18\x04 \x01(\x08\x12\'\n\x06object\x18\x05 \x01(\x0b\x32\x17.google.protobuf.Struct\x12\x0f\n\x07protect\x18\x06 \x01(\x08\x12\x14\n\x0c\x64\x65pendencies\x18\x07 \x03(\t\x12\x10\n\x08provider\x18\x08 \x01(\t\x12Z\n\x14propertyDependencies\x18\t \x03(\x0b\x32<.pulumirpc.RegisterResourceRequest.PropertyDependenciesEntry\x12\x1b\n\x13\x64\x65leteBeforeReplace\x18\n \x01(\x08\x12\x0f\n\x07version\x18\x0b \x01(\t\x12\x15\n\rignoreChanges\x18\x0c \x03(\t\x12\x15\n\racceptSecrets\x18\r \x01(\x08\x12\x1f\n\x17\x61\x64\x64itionalSecretOutputs\x18\x0e \x03(\t\x12\x0f\n\x07\x61liases\x18\x0f \x03(\t\x12\x10\n\x08importId\x18\x10 \x01(\t\x12I\n\x0e\x63ustomTimeouts\x18\x11 \x01(\x0b\x32\x31.pulumirpc.RegisterResourceRequest.CustomTimeouts\x12\"\n\x1a\x64\x65leteBeforeReplaceDefined\x18\x12 \x01(\x08\x12\x1d\n\x15supportsPartialValues\x18\x13 \x01(\x08\x12\x0e\n\x06remote\x18\x15 \x01(\x08\x1a$\n\x14PropertyDependencies\x12\x0c\n\x04urns\x18\x01 \x03(\t\x1a@\n\x0e\x43ustomTimeouts\x12\x0e\n\x06\x63reate\x18\x01 \x01(\t\x12\x0e\n\x06update\x18\x02 \x01(\t\x12\x0e\n\x06\x64\x65lete\x18\x03 \x01(\t\x1at\n\x19PropertyDependenciesEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\x46\n\x05value\x18\x02 \x01(\x0b\x32\x37.pulumirpc.RegisterResourceRequest.PropertyDependencies:\x02\x38\x01\"\xf7\x02\n\x18RegisterResourceResponse\x12\x0b\n\x03urn\x18\x01 \x01(\t\x12\n\n\x02id\x18\x02 \x01(\t\x12\'\n\x06object\x18\x03 \x01(\x0b\x32\x17.google.protobuf.Struct\x12\x0e\n\x06stable\x18\x04 \x01(\x08\x12\x0f\n\x07stables\x18\x05 \x03(\t\x12[\n\x14propertyDependencies\x18\x06 \x03(\x0b\x32=.pulumirpc.RegisterResourceResponse.PropertyDependenciesEntry\x1a$\n\x14PropertyDependencies\x12\x0c\n\x04urns\x18\x01 \x03(\t\x1au\n\x19PropertyDependenciesEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12G\n\x05value\x18\x02 \x01(\x0b\x32\x38.pulumirpc.RegisterResourceResponse.PropertyDependencies:\x02\x38\x01\"W\n\x1eRegisterResourceOutputsRequest\x12\x0b\n\x03urn\x18\x01 \x01(\t\x12(\n\x07outputs\x18\x02 \x01(\x0b\x32\x17.google.protobuf.Struct2\x89\x04\n\x0fResourceMonitor\x12Z\n\x0fSupportsFeature\x12!.pulumirpc.SupportsFeatureRequest\x1a\".pulumirpc.SupportsFeatureResponse\"\x00\x12?\n\x06Invoke\x12\x18.pulumirpc.InvokeRequest\x1a\x19.pulumirpc.InvokeResponse\"\x00\x12G\n\x0cStreamInvoke\x12\x18.pulumirpc.InvokeRequest\x1a\x19.pulumirpc.InvokeResponse\"\x00\x30\x01\x12Q\n\x0cReadResource\x12\x1e.pulumirpc.ReadResourceRequest\x1a\x1f.pulumirpc.ReadResourceResponse\"\x00\x12]\n\x10RegisterResource\x12\".pulumirpc.RegisterResourceRequest\x1a#.pulumirpc.RegisterResourceResponse\"\x00\x12^\n\x17RegisterResourceOutputs\x12).pulumirpc.RegisterResourceOutputsRequest\x1a\x16.google.protobuf.Empty\"\x00\x62\x06proto3' serialized_pb=b'\n\x0eresource.proto\x12\tpulumirpc\x1a\x1bgoogle/protobuf/empty.proto\x1a\x1cgoogle/protobuf/struct.proto\x1a\x0eprovider.proto\"$\n\x16SupportsFeatureRequest\x12\n\n\x02id\x18\x01 \x01(\t\"-\n\x17SupportsFeatureResponse\x12\x12\n\nhasSupport\x18\x01 \x01(\x08\"\xfc\x01\n\x13ReadResourceRequest\x12\n\n\x02id\x18\x01 \x01(\t\x12\x0c\n\x04type\x18\x02 \x01(\t\x12\x0c\n\x04name\x18\x03 \x01(\t\x12\x0e\n\x06parent\x18\x04 \x01(\t\x12+\n\nproperties\x18\x05 \x01(\x0b\x32\x17.google.protobuf.Struct\x12\x14\n\x0c\x64\x65pendencies\x18\x06 \x03(\t\x12\x10\n\x08provider\x18\x07 \x01(\t\x12\x0f\n\x07version\x18\x08 \x01(\t\x12\x15\n\racceptSecrets\x18\t \x01(\x08\x12\x1f\n\x17\x61\x64\x64itionalSecretOutputs\x18\n \x03(\t\x12\x0f\n\x07\x61liases\x18\x0b \x03(\t\"P\n\x14ReadResourceResponse\x12\x0b\n\x03urn\x18\x01 \x01(\t\x12+\n\nproperties\x18\x02 \x01(\x0b\x32\x17.google.protobuf.Struct\"\xaf\x06\n\x17RegisterResourceRequest\x12\x0c\n\x04type\x18\x01 \x01(\t\x12\x0c\n\x04name\x18\x02 \x01(\t\x12\x0e\n\x06parent\x18\x03 \x01(\t\x12\x0e\n\x06\x63ustom\x18\x04 \x01(\x08\x12\'\n\x06object\x18\x05 \x01(\x0b\x32\x17.google.protobuf.Struct\x12\x0f\n\x07protect\x18\x06 \x01(\x08\x12\x14\n\x0c\x64\x65pendencies\x18\x07 \x03(\t\x12\x10\n\x08provider\x18\x08 \x01(\t\x12Z\n\x14propertyDependencies\x18\t \x03(\x0b\x32<.pulumirpc.RegisterResourceRequest.PropertyDependenciesEntry\x12\x1b\n\x13\x64\x65leteBeforeReplace\x18\n \x01(\x08\x12\x0f\n\x07version\x18\x0b \x01(\t\x12\x15\n\rignoreChanges\x18\x0c \x03(\t\x12\x15\n\racceptSecrets\x18\r \x01(\x08\x12\x1f\n\x17\x61\x64\x64itionalSecretOutputs\x18\x0e \x03(\t\x12\x0f\n\x07\x61liases\x18\x0f \x03(\t\x12\x10\n\x08importId\x18\x10 \x01(\t\x12I\n\x0e\x63ustomTimeouts\x18\x11 \x01(\x0b\x32\x31.pulumirpc.RegisterResourceRequest.CustomTimeouts\x12\"\n\x1a\x64\x65leteBeforeReplaceDefined\x18\x12 \x01(\x08\x12\x1d\n\x15supportsPartialValues\x18\x13 \x01(\x08\x12\x0e\n\x06remote\x18\x14 \x01(\x08\x1a$\n\x14PropertyDependencies\x12\x0c\n\x04urns\x18\x01 \x03(\t\x1a@\n\x0e\x43ustomTimeouts\x12\x0e\n\x06\x63reate\x18\x01 \x01(\t\x12\x0e\n\x06update\x18\x02 \x01(\t\x12\x0e\n\x06\x64\x65lete\x18\x03 \x01(\t\x1at\n\x19PropertyDependenciesEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12\x46\n\x05value\x18\x02 \x01(\x0b\x32\x37.pulumirpc.RegisterResourceRequest.PropertyDependencies:\x02\x38\x01\"\xf7\x02\n\x18RegisterResourceResponse\x12\x0b\n\x03urn\x18\x01 \x01(\t\x12\n\n\x02id\x18\x02 \x01(\t\x12\'\n\x06object\x18\x03 \x01(\x0b\x32\x17.google.protobuf.Struct\x12\x0e\n\x06stable\x18\x04 \x01(\x08\x12\x0f\n\x07stables\x18\x05 \x03(\t\x12[\n\x14propertyDependencies\x18\x06 \x03(\x0b\x32=.pulumirpc.RegisterResourceResponse.PropertyDependenciesEntry\x1a$\n\x14PropertyDependencies\x12\x0c\n\x04urns\x18\x01 \x03(\t\x1au\n\x19PropertyDependenciesEntry\x12\x0b\n\x03key\x18\x01 \x01(\t\x12G\n\x05value\x18\x02 \x01(\x0b\x32\x38.pulumirpc.RegisterResourceResponse.PropertyDependencies:\x02\x38\x01\"W\n\x1eRegisterResourceOutputsRequest\x12\x0b\n\x03urn\x18\x01 \x01(\t\x12(\n\x07outputs\x18\x02 \x01(\x0b\x32\x17.google.protobuf.Struct2\x89\x04\n\x0fResourceMonitor\x12Z\n\x0fSupportsFeature\x12!.pulumirpc.SupportsFeatureRequest\x1a\".pulumirpc.SupportsFeatureResponse\"\x00\x12?\n\x06Invoke\x12\x18.pulumirpc.InvokeRequest\x1a\x19.pulumirpc.InvokeResponse\"\x00\x12G\n\x0cStreamInvoke\x12\x18.pulumirpc.InvokeRequest\x1a\x19.pulumirpc.InvokeResponse\"\x00\x30\x01\x12Q\n\x0cReadResource\x12\x1e.pulumirpc.ReadResourceRequest\x1a\x1f.pulumirpc.ReadResourceResponse\"\x00\x12]\n\x10RegisterResource\x12\".pulumirpc.RegisterResourceRequest\x1a#.pulumirpc.RegisterResourceResponse\"\x00\x12^\n\x17RegisterResourceOutputs\x12).pulumirpc.RegisterResourceOutputsRequest\x1a\x16.google.protobuf.Empty\"\x00\x62\x06proto3'
, ,
dependencies=[google_dot_protobuf_dot_empty__pb2.DESCRIPTOR,google_dot_protobuf_dot_struct__pb2.DESCRIPTOR,provider__pb2.DESCRIPTOR,]) dependencies=[google_dot_protobuf_dot_empty__pb2.DESCRIPTOR,google_dot_protobuf_dot_struct__pb2.DESCRIPTOR,provider__pb2.DESCRIPTOR,])
@ -482,7 +482,7 @@ _REGISTERRESOURCEREQUEST = _descriptor.Descriptor(
serialized_options=None, file=DESCRIPTOR), serialized_options=None, file=DESCRIPTOR),
_descriptor.FieldDescriptor( _descriptor.FieldDescriptor(
name='remote', full_name='pulumirpc.RegisterResourceRequest.remote', index=19, name='remote', full_name='pulumirpc.RegisterResourceRequest.remote', index=19,
number=21, type=8, cpp_type=7, label=1, number=20, type=8, cpp_type=7, label=1,
has_default_value=False, default_value=False, has_default_value=False, default_value=False,
message_type=None, enum_type=None, containing_type=None, message_type=None, enum_type=None, containing_type=None,
is_extension=False, extension_scope=None, is_extension=False, extension_scope=None,

View file

@ -228,7 +228,7 @@ def read_resource(res: 'CustomResource', ty: str, name: str, props: 'Inputs', op
def do_rpc_call(): def do_rpc_call():
if monitor is None: if monitor is None:
# If no monitor is available, we'll need to fake up a response, for testing. # If no monitor is available, we'll need to fake up a response, for testing.
return RegisterResponse(mock_urn, None, resolver.serialized_props) return RegisterResponse(mock_urn, None, resolver.serialized_props, None)
# If there is a monitor available, make the true RPC request to the engine. # If there is a monitor available, make the true RPC request to the engine.
try: try:
@ -256,19 +256,26 @@ def read_resource(res: 'CustomResource', ty: str, name: str, props: 'Inputs', op
log.debug(f"resource read successful: ty={ty}, urn={resp.urn}") log.debug(f"resource read successful: ty={ty}, urn={resp.urn}")
resolve_urn(resp.urn) resolve_urn(resp.urn)
resolve_id(resolved_id, True, None) # Read IDs are always known. resolve_id(resolved_id, True, None) # Read IDs are always known.
await rpc.resolve_outputs(res, resolver.serialized_props, resp.properties, resolvers) await rpc.resolve_outputs(res, resolver.serialized_props, resp.properties, {}, resolvers)
asyncio.ensure_future(RPC_MANAGER.do_rpc("read resource", do_read)()) asyncio.ensure_future(RPC_MANAGER.do_rpc("read resource", do_read)())
def register_resource(res: 'Resource', ty: str, name: str, custom: bool, props: 'Inputs', opts: Optional['ResourceOptions']) -> None: def register_resource(res: 'Resource',
ty: str,
name: str,
custom: bool,
remote: bool,
new_dependency: Callable[[str], 'Resource'],
props: 'Inputs',
opts: Optional['ResourceOptions']) -> None:
""" """
Registers a new resource object with a given type t and name. It returns the Registers a new resource object with a given type t and name. It returns the
auto-generated URN and the ID that will resolve after the deployment has completed. All auto-generated URN and the ID that will resolve after the deployment has completed. All
properties will be initialized to property objects that the registration operation will resolve properties will be initialized to property objects that the registration operation will resolve
at the right time (or remain unresolved for deployments). at the right time (or remain unresolved for deployments).
""" """
log.debug(f"registering resource: ty={ty}, name={name}, custom={custom}") log.debug(f"registering resource: ty={ty}, name={name}, custom={custom}, remote={remote}")
monitor = settings.get_monitor() monitor = settings.get_monitor()
from .. import Output # pylint: disable=import-outside-toplevel from .. import Output # pylint: disable=import-outside-toplevel
@ -381,6 +388,7 @@ def register_resource(res: 'Resource', ty: str, name: str, custom: bool, props:
customTimeouts=custom_timeouts, customTimeouts=custom_timeouts,
aliases=resolver.aliases, aliases=resolver.aliases,
supportsPartialValues=True, supportsPartialValues=True,
remote=remote,
) )
from ..resource import create_urn # pylint: disable=import-outside-toplevel from ..resource import create_urn # pylint: disable=import-outside-toplevel
@ -389,7 +397,7 @@ def register_resource(res: 'Resource', ty: str, name: str, custom: bool, props:
def do_rpc_call(): def do_rpc_call():
if monitor is None: if monitor is None:
# If no monitor is available, we'll need to fake up a response, for testing. # If no monitor is available, we'll need to fake up a response, for testing.
return RegisterResponse(mock_urn, None, resolver.serialized_props) return RegisterResponse(mock_urn, None, resolver.serialized_props, None)
# If there is a monitor available, make the true RPC request to the engine. # If there is a monitor available, make the true RPC request to the engine.
try: try:
@ -423,7 +431,15 @@ def register_resource(res: 'Resource', ty: str, name: str, custom: bool, props:
is_known = bool(resp.id) is_known = bool(resp.id)
resolve_id(resp.id, is_known, None) resolve_id(resp.id, is_known, None)
await rpc.resolve_outputs(res, resolver.serialized_props, resp.object, resolvers) deps = {}
rpc_deps = resp.propertyDependencies
if rpc_deps:
for k, v in rpc_deps.items():
urns = list(v.urns)
deps[k] = set(map(new_dependency, urns))
await rpc.resolve_outputs(res, resolver.serialized_props, resp.object, deps, resolvers)
asyncio.ensure_future(RPC_MANAGER.do_rpc( asyncio.ensure_future(RPC_MANAGER.do_rpc(
"register resource", do_register)()) "register resource", do_register)())
@ -464,13 +480,26 @@ def register_resource_outputs(res: 'Resource', outputs: 'Union[Inputs, Output[In
"register resource outputs", do_register_resource_outputs)()) "register resource outputs", do_register_resource_outputs)())
class PropertyDependencies:
urns: List[str]
def __init__(self, urns: List[str]):
self.urns = urns
class RegisterResponse: class RegisterResponse:
urn: str urn: str
id: str id: str
object: struct_pb2.Struct object: struct_pb2.Struct
propertyDependencies: Dict[str, PropertyDependencies]
# pylint: disable=redefined-builtin # pylint: disable=redefined-builtin
def __init__(self, urn: str, id: str, object: struct_pb2.Struct): def __init__(self,
urn: str,
id: str,
object: struct_pb2.Struct,
propertyDependencies: Dict[str, PropertyDependencies]):
self.urn = urn self.urn = urn
self.id = id self.id = id
self.object = object self.object = object
self.propertyDependencies = propertyDependencies

View file

@ -20,7 +20,7 @@ import asyncio
from collections import abc from collections import abc
import functools import functools
import inspect import inspect
from typing import List, Any, Callable, Dict, Mapping, Optional, Sequence, TYPE_CHECKING, cast from typing import List, Any, Callable, Dict, Mapping, Optional, Sequence, Set, TYPE_CHECKING, cast
from google.protobuf import struct_pb2 from google.protobuf import struct_pb2
import six import six
@ -329,7 +329,7 @@ def deserialize_property(value: Any, keep_unknowns: Optional[bool] = None) -> An
return value return value
Resolver = Callable[[Any, bool, bool, Optional[Exception]], None] Resolver = Callable[[Any, bool, bool, Optional[Set['Resource']], Optional[Exception]], None]
""" """
A Resolver is a function that takes four arguments: A Resolver is a function that takes four arguments:
1. A value, which represents the "resolved" value of a particular output (from the engine) 1. A value, which represents the "resolved" value of a particular output (from the engine)
@ -355,14 +355,24 @@ def transfer_properties(res: 'Resource', props: 'Inputs') -> Dict[str, Resolver]
resolve_value: 'asyncio.Future' = asyncio.Future() resolve_value: 'asyncio.Future' = asyncio.Future()
resolve_is_known: 'asyncio.Future' = asyncio.Future() resolve_is_known: 'asyncio.Future' = asyncio.Future()
resolve_is_secret: 'asyncio.Future' = asyncio.Future() resolve_is_secret: 'asyncio.Future' = asyncio.Future()
resolve_deps: 'asyncio.Future' = asyncio.Future()
def do_resolve(value_fut: 'asyncio.Future', def do_resolve(r: 'Resource',
value_fut: 'asyncio.Future',
known_fut: 'asyncio.Future[bool]', known_fut: 'asyncio.Future[bool]',
secret_fut: 'asyncio.Future[bool]', secret_fut: 'asyncio.Future[bool]',
deps_fut: 'asyncio.Future[Set[Resource]]',
value: Any, value: Any,
is_known: bool, is_known: bool,
is_secret: bool, is_secret: bool,
deps: Set['Resource'],
failed: Optional[Exception]): failed: Optional[Exception]):
# Create a union of deps and the resource.
deps_union = set(deps) if deps else set()
deps_union.add(r)
deps_fut.set_result(deps_union)
# Was an exception provided? If so, this is an abnormal (exceptional) resolution. Resolve the futures # Was an exception provided? If so, this is an abnormal (exceptional) resolution. Resolve the futures
# using set_exception so that any attempts to wait for their resolution will also fail. # using set_exception so that any attempts to wait for their resolution will also fail.
if failed is not None: if failed is not None:
@ -378,8 +388,8 @@ def transfer_properties(res: 'Resource', props: 'Inputs') -> Dict[str, Resolver]
# name before translation. When properties are returned from the engine, we must first translate the name # name before translation. When properties are returned from the engine, we must first translate the name
# using res.translate_output_property and then use *that* name to index into the resolvers table. # using res.translate_output_property and then use *that* name to index into the resolvers table.
log.debug(f"adding resolver {name}") log.debug(f"adding resolver {name}")
resolvers[name] = functools.partial(do_resolve, resolve_value, resolve_is_known, resolve_is_secret) resolvers[name] = functools.partial(do_resolve, res, resolve_value, resolve_is_known, resolve_is_secret, resolve_deps)
res.__dict__[name] = Output({res}, resolve_value, resolve_is_known, resolve_is_secret) res.__dict__[name] = Output(resolve_deps, resolve_value, resolve_is_known, resolve_is_secret)
return resolvers return resolvers
@ -497,6 +507,7 @@ def contains_unknowns(val: Any) -> bool:
async def resolve_outputs(res: 'Resource', async def resolve_outputs(res: 'Resource',
serialized_props: struct_pb2.Struct, serialized_props: struct_pb2.Struct,
outputs: struct_pb2.Struct, outputs: struct_pb2.Struct,
deps: Mapping[str, Set['Resource']],
resolvers: Dict[str, Resolver]): resolvers: Dict[str, Resolver]):
# Produce a combined set of property states, starting with inputs and then applying # Produce a combined set of property states, starting with inputs and then applying
@ -559,18 +570,18 @@ async def resolve_outputs(res: 'Resource',
if not settings.is_dry_run(): if not settings.is_dry_run():
# normal 'pulumi up'. resolve the output with the value we got back # normal 'pulumi up'. resolve the output with the value we got back
# from the engine. That output can always run its .apply calls. # from the engine. That output can always run its .apply calls.
resolve(value, True, is_secret, None) resolve(value, True, is_secret, deps.get(key), None)
else: else:
# We're previewing. If the engine was able to give us a reasonable value back, # We're previewing. If the engine was able to give us a reasonable value back,
# then use it. Otherwise, inform the Output that the value isn't known. # then use it. Otherwise, inform the Output that the value isn't known.
resolve(value, value is not None, is_secret, None) resolve(value, value is not None, is_secret, deps.get(key), None)
# `allProps` may not have contained a value for every resolver: for example, optional outputs may not be present. # `allProps` may not have contained a value for every resolver: for example, optional outputs may not be present.
# We will resolve all of these values as `None`, and will mark the value as known if we are not running a # We will resolve all of these values as `None`, and will mark the value as known if we are not running a
# preview. # preview.
for key, resolve in resolvers.items(): for key, resolve in resolvers.items():
if key not in all_properties: if key not in all_properties:
resolve(None, not settings.is_dry_run(), False, None) resolve(None, not settings.is_dry_run(), False, deps.get(key), None)
def resolve_outputs_due_to_exception(resolvers: Dict[str, Resolver], exn: Exception): def resolve_outputs_due_to_exception(resolvers: Dict[str, Resolver], exn: Exception):
@ -583,4 +594,4 @@ def resolve_outputs_due_to_exception(resolvers: Dict[str, Resolver], exn: Except
""" """
for key, resolve in resolvers.items(): for key, resolve in resolvers.items():
log.debug(f"sending exception to resolver for {key}") log.debug(f"sending exception to resolver for {key}")
resolve(None, False, False, exn) resolve(None, False, False, None, exn)

View file

@ -1,3 +1,5 @@
// Copyright 2016-2020, Pulumi Corporation. All rights reserved.
import * as pulumi from "@pulumi/pulumi"; import * as pulumi from "@pulumi/pulumi";
interface ComponentArgs { interface ComponentArgs {

View file

@ -1,4 +1,4 @@
// Copyright 2016-2018, Pulumi Corporation. All rights reserved. // Copyright 2016-2020, Pulumi Corporation. All rights reserved.
import { Component } from "./component"; import { Component } from "./component";

View file

@ -0,0 +1,5 @@
*.pyc
/.pulumi/
/dist/
/*.egg-info
venv/

View file

@ -0,0 +1,3 @@
name: construct_component_py
description: A program that constructs remote component resources.
runtime: python

View file

@ -0,0 +1,7 @@
# Copyright 2016-2018, Pulumi Corporation. All rights reserved.
from component import Component
component_a = Component("a", echo=42)
component_b = Component("b", echo=component_a.echo)
component_c = Component("c", echo=component_a.childId)

View file

@ -0,0 +1,15 @@
# Copyright 2016-2020, Pulumi Corporation. All rights reserved.
from typing import Any, Optional
import pulumi
class Component(pulumi.ComponentResource):
echo: pulumi.Output[Any]
childId: pulumi.Output[str]
def __init__(self, name: str, echo: pulumi.Input[Any], opts: Optional[pulumi.ResourceOptions] = None):
props = dict()
props["echo"] = echo
props["childId"] = None
super().__init__("testcomponent:index:Component", name, props, opts, True)

View file

@ -602,24 +602,6 @@ func TestLargeResourceNode(t *testing.T) {
}) })
} }
func testComponentPathEnv() (string, error) {
cwd, err := os.Getwd()
if err != nil {
return "", err
}
absCwd, err := filepath.Abs(cwd)
if err != nil {
return "", err
}
pluginDir := filepath.Join(absCwd, "construct_component", "testcomponent")
pathSeparator := ":"
if runtime.GOOS == "windows" {
pathSeparator = ";"
}
return "PATH=" + os.Getenv("PATH") + pathSeparator + pluginDir, nil
}
// Test remote component construction in Node. // Test remote component construction in Node.
func TestConstructNode(t *testing.T) { func TestConstructNode(t *testing.T) {
pathEnv, err := testComponentPathEnv() pathEnv, err := testComponentPathEnv()

View file

@ -341,3 +341,59 @@ func TestPythonPylint(t *testing.T) {
} }
integration.ProgramTest(t, opts) integration.ProgramTest(t, opts)
} }
// Test remote component construction in Python.
func TestConstructPython(t *testing.T) {
pathEnv, err := testComponentPathEnv()
if err != nil {
t.Fatalf("failed to build test component PATH: %v", err)
}
// TODO[pulumi/pulumi#5455]: Dynamic providers fail to load when used from multi-lang components.
// Until we've addressed this, set PULUMI_TEST_YARN_LINK_PULUMI, which tells the integration test
// module to run `yarn install && yarn link @pulumi/pulumi` in the Python program's directory, allowing
// the Node.js dynamic provider plugin to load.
// When the underlying issue has been fixed, the use of this environment variable inside the integration
// test module should be removed.
const testYarnLinkPulumiEnv = "PULUMI_TEST_YARN_LINK_PULUMI=true"
var opts *integration.ProgramTestOptions
opts = &integration.ProgramTestOptions{
Env: []string{pathEnv, testYarnLinkPulumiEnv},
Dir: filepath.Join("construct_component", "python"),
Dependencies: []string{
filepath.Join("..", "..", "sdk", "python", "env", "src"),
},
Quick: true,
ExtraRuntimeValidation: func(t *testing.T, stackInfo integration.RuntimeValidationStackInfo) {
assert.NotNil(t, stackInfo.Deployment)
if assert.Equal(t, 9, len(stackInfo.Deployment.Resources)) {
stackRes := stackInfo.Deployment.Resources[0]
assert.NotNil(t, stackRes)
assert.Equal(t, resource.RootStackType, stackRes.Type)
assert.Equal(t, "", string(stackRes.Parent))
// Check that dependencies flow correctly between the originating program and the remote component
// plugin.
urns := make(map[string]resource.URN)
for _, res := range stackInfo.Deployment.Resources[1:] {
assert.NotNil(t, res)
urns[string(res.URN.Name())] = res.URN
switch res.URN.Name() {
case "child-a":
for _, deps := range res.PropertyDependencies {
assert.Empty(t, deps)
}
case "child-b":
assert.Equal(t, []resource.URN{urns["a"]}, res.PropertyDependencies["echo"])
case "child-c":
assert.ElementsMatch(t, []resource.URN{urns["child-a"], urns["a"]},
res.PropertyDependencies["echo"])
}
}
}
},
}
integration.ProgramTest(t, opts)
}

View file

@ -4,7 +4,9 @@ package ints
import ( import (
"fmt" "fmt"
"os"
"path/filepath" "path/filepath"
"runtime"
"strings" "strings"
"testing" "testing"
"time" "time"
@ -563,5 +565,21 @@ func TestConfigPaths(t *testing.T) {
e.RunCommand("pulumi", "stack", "rm", "--yes") e.RunCommand("pulumi", "stack", "rm", "--yes")
} }
// The following 4 tests are testing to ensure that we can make RPC calls >4mb //nolint:golint,deadcode
// Issue: https://github.com/pulumi/pulumi/issues/4155 func testComponentPathEnv() (string, error) {
cwd, err := os.Getwd()
if err != nil {
return "", err
}
absCwd, err := filepath.Abs(cwd)
if err != nil {
return "", err
}
pluginDir := filepath.Join(absCwd, "construct_component", "testcomponent")
pathSeparator := ":"
if runtime.GOOS == "windows" {
pathSeparator = ";"
}
return "PATH=" + os.Getenv("PATH") + pathSeparator + pluginDir, nil
}