Script 'mail_helper' called by obssrc
Hello community,

here is the log from the commit of package opentofu for openSUSE:Factory 
checked in at 2026-10-02 23:04:30
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/opentofu (Old)
 and      /work/SRC/openSUSE:Factory/.opentofu.new.1631729 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Package is "opentofu"

Fri Oct  2 23:04:30 2026 rev:56 rq:1382000 version:1.13.1

Changes:
--------
--- /work/SRC/openSUSE:Factory/opentofu/opentofu.changes        2026-10-01 
16:49:28.932166299 +0200
+++ /work/SRC/openSUSE:Factory/.opentofu.new.1631729/opentofu.changes   
2026-10-02 23:05:42.726239531 +0200
@@ -1,0 +2,11 @@
+Fri Oct 02 05:12:51 UTC 2026 - Johannes Kastl 
<[email protected]>
+
+- Update to version 1.13.1:
+  * BUG FIXES:
+    - tofu show -json <planfile> now works again when ephemeral
+      resources are present in the configuration. (4623).
+    - Ephemeral output values are now always re-evaluated during
+      the apply phase, instead of sometimes using stale values from
+      the planning phase. (#4582)
+
+-------------------------------------------------------------------

Old:
----
  opentofu-1.13.0.obscpio

New:
----
  opentofu-1.13.1.obscpio

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Other differences:
------------------
++++++ opentofu.spec ++++++
--- /var/tmp/diff_new_pack.Sk3QrV/_old  2026-10-02 23:05:45.036336097 +0200
+++ /var/tmp/diff_new_pack.Sk3QrV/_new  2026-10-02 23:05:45.038336181 +0200
@@ -19,7 +19,7 @@
 %define executable_name tofu
 
 Name:           opentofu
-Version:        1.13.0
+Version:        1.13.1
 Release:        0
 Summary:        Declaratively manage your cloud infrastructure
 License:        MPL-2.0

++++++ _service ++++++
--- /var/tmp/diff_new_pack.Sk3QrV/_old  2026-10-02 23:05:45.242344709 +0200
+++ /var/tmp/diff_new_pack.Sk3QrV/_new  2026-10-02 23:05:45.262345545 +0200
@@ -3,7 +3,7 @@
     <param name="url">https://github.com/opentofu/opentofu.git</param>
     <param name="scm">git</param>
     <param name="exclude">.git</param>
-    <param name="revision">refs/tags/v1.13.0</param>
+    <param name="revision">refs/tags/v1.13.1</param>
     <param name="versionformat">@PARENT_TAG@</param>
     <param name="versionrewrite-pattern">v(.*)</param>
     <param name="changesgenerate">enable</param>

++++++ _servicedata ++++++
--- /var/tmp/diff_new_pack.Sk3QrV/_old  2026-10-02 23:05:45.371350101 +0200
+++ /var/tmp/diff_new_pack.Sk3QrV/_new  2026-10-02 23:05:45.390350896 +0200
@@ -3,6 +3,6 @@
                 <param name="url">https://github.com/opentofu/opentofu/</param>
               <param 
name="changesrevision">bdcbf091aab886499ed7718d7f558b428fffce39</param></service><service
 name="tar_scm">
                 <param 
name="url">https://github.com/opentofu/opentofu.git</param>
-              <param 
name="changesrevision">2b6193043d500dcfef1f3b4f4819b938b667099f</param></service></servicedata>
+              <param 
name="changesrevision">233700b795b6d2372f1c56ed57a4abaec9d36475</param></service></servicedata>
 (No newline at EOF)
 

++++++ opentofu-1.13.0.obscpio -> opentofu-1.13.1.obscpio ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/opentofu-1.13.0/CHANGELOG.md 
new/opentofu-1.13.1/CHANGELOG.md
--- old/opentofu-1.13.0/CHANGELOG.md    2026-09-30 14:59:06.000000000 +0200
+++ new/opentofu-1.13.1/CHANGELOG.md    2026-10-01 18:03:40.000000000 +0200
@@ -1,5 +1,12 @@
 The v1.13.x release series is supported until **August 1 2027**.
 
+## 1.13.1
+
+BUG FIXES:
+
+- `tofu show -json <planfile>` now works again when ephemeral resources are 
present in the configuration. 
([4623](https://github.com/opentofu/opentofu/pull/4623)).
+-  Ephemeral output values are now always re-evaluated during the apply phase, 
instead of sometimes using stale values from the planning phase. 
([#4582](https://github.com/opentofu/opentofu/issues/4582))
+
 ## 1.13.0
 
 UPGRADE NOTES:
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/opentofu-1.13.0/internal/command/e2etest/plan_test.go 
new/opentofu-1.13.1/internal/command/e2etest/plan_test.go
--- old/opentofu-1.13.0/internal/command/e2etest/plan_test.go   2026-09-30 
14:59:06.000000000 +0200
+++ new/opentofu-1.13.1/internal/command/e2etest/plan_test.go   2026-10-01 
18:03:40.000000000 +0200
@@ -7,11 +7,14 @@
 
 import (
        "path/filepath"
+       "slices"
        "strings"
        "testing"
 
        "github.com/google/go-cmp/cmp"
+       "github.com/opentofu/opentofu/internal/addrs"
        "github.com/opentofu/opentofu/internal/e2e"
+       "github.com/opentofu/opentofu/internal/plans"
 )
 
 // The tests in this file are for the following sequence:
@@ -165,3 +168,86 @@
                }
        })
 }
+
+// TestPlanShowWithEmbeddedSchema is a regression test for [the 
bug](https://github.com/opentofu/opentofu/issues/4622) where
+// a configuration containing ephemeral is shown correctly in json format with 
the embedded schema in the plan.
+func TestPlanShowWithEmbeddedSchema(t *testing.T) {
+       t.Parallel()
+
+       workdir := "testdata/plan-with-embedded-ephemeral-config"
+       buildSimpleProvider(t, "6", workdir, "simple")
+       tf := e2e.NewBinary(t, tofuBin, workdir)
+
+       { // INIT
+               _, stderr, err := tf.Run("init", "-plugin-dir=cache")
+               if err != nil {
+                       t.Fatalf("unexpected init error: %s\nstderr:\n%s", err, 
stderr)
+               }
+       }
+
+       { // PLAN
+               stdout, stderr, err := tf.Run("plan", "-out=tfplan")
+               if err != nil {
+                       t.Fatalf("unexpected plan error: %s\nstderr:\n%s", err, 
stderr)
+               }
+               expectedChangesOutput := ``
+
+               checker := outputEntriesChecker{
+                       
outputCheckContains{[]string{"ephemeral.simple_resource.test_ephemeral: 
Opening..."}, true},
+                       
outputCheckContains{[]string{"ephemeral.simple_resource.test_ephemeral: Open 
complete after"}, true},
+                       
outputCheckContains{[]string{"ephemeral.simple_resource.test_ephemeral: 
Closing..."}, true},
+                       
outputCheckContains{[]string{"ephemeral.simple_resource.test_ephemeral: Close 
complete after"}, true},
+                       outputCheckContains{[]string{`+ resource 
"simple_resource" "test_res"`}, true},
+               }
+               out := stripAnsi(stdout)
+
+               if !strings.Contains(out, expectedChangesOutput) {
+                       t.Errorf("wrong plan output:\nstdout:%s\nstderr:%s", 
stdout, stderr)
+                       t.Log(cmp.Diff(out, expectedChangesOutput))
+               }
+               checker.check(t, "plan", out)
+
+               // assert plan file content
+               plan, err := tf.Plan("tfplan")
+               if err != nil {
+                       t.Fatalf("failed to read the plan file: %s", err)
+               }
+               idx := slices.IndexFunc(plan.Changes.Resources, func(src 
*plans.ResourceInstanceChangeSrc) bool {
+                       return src.Addr.Resource.Resource.Mode == 
addrs.EphemeralResourceMode
+               })
+               if idx >= 0 {
+                       t.Fatalf("ephemeral resource found in the plan file. 
expected to have no ephemeral resource")
+               }
+       }
+       { // SHOW -json
+               stdout, stderr, err := tf.Run("show", "-json", "tfplan")
+               if err != nil {
+                       t.Fatalf("unexpected plan error: %s\nstderr:\n%s", err, 
stderr)
+               }
+               // a better way to do this would be to enhance `jsonconfig` 
package with capabilities to unmarshal the generated output and do better 
checks on the structured data.
+               // But to add such a complex logic strictly for this particular 
test does not worth right now. If we'll find more use cases where that would be 
useful
+               // we can create that later and replace this assertion.
+               checker := outputEntriesChecker{
+                       outputCheckNumberOfOccurrences{
+                               token:             
`{"address":"ephemeral.simple_resource.test_ephemeral","mode":"ephemeral","type":"simple_resource","name":"test_ephemeral","provider_config_key":"simple"`,
+                               wantedOccurrences: 1,
+                       },
+               }
+               out := stripAnsi(stdout)
+               checker.check(t, "show -json", out)
+       }
+       { // SHOW (human)
+               stdout, stderr, err := tf.Run("show", "tfplan")
+               if err != nil {
+                       t.Fatalf("unexpected plan error: %s\nstderr:\n%s", err, 
stderr)
+               }
+               checker := outputEntriesChecker{
+                       outputCheckNumberOfOccurrences{
+                               token:             `+ resource 
"simple_resource" "test_res"`,
+                               wantedOccurrences: 1,
+                       },
+               }
+               out := stripAnsi(stdout)
+               checker.check(t, "show", out)
+       }
+}
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/opentofu-1.13.0/internal/command/e2etest/primary_test.go 
new/opentofu-1.13.1/internal/command/e2etest/primary_test.go
--- old/opentofu-1.13.0/internal/command/e2etest/primary_test.go        
2026-09-30 14:59:06.000000000 +0200
+++ new/opentofu-1.13.1/internal/command/e2etest/primary_test.go        
2026-10-01 18:03:40.000000000 +0200
@@ -796,6 +796,23 @@
        }
 }
 
+type outputCheckNumberOfOccurrences struct {
+       token             string
+       wantedOccurrences int
+}
+
+func (oe outputCheckNumberOfOccurrences) check(t *testing.T, hint, in string) {
+       var found int
+       for line := range strings.SplitSeq(in, "\n") {
+               if strings.Contains(line, oe.token) {
+                       found++
+               }
+       }
+       if oe.wantedOccurrences != found {
+               t.Errorf("[%s] different number of occurrences %q. Wanted %d 
but got %d\nout:%s", hint, oe.token, oe.wantedOccurrences, found, in)
+       }
+}
+
 type outputCheckContains struct {
        variants []string
        strict   bool
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/opentofu-1.13.0/internal/command/e2etest/testdata/plan-with-embedded-ephemeral-config/main.tf
 
new/opentofu-1.13.1/internal/command/e2etest/testdata/plan-with-embedded-ephemeral-config/main.tf
--- 
old/opentofu-1.13.0/internal/command/e2etest/testdata/plan-with-embedded-ephemeral-config/main.tf
   1970-01-01 01:00:00.000000000 +0100
+++ 
new/opentofu-1.13.1/internal/command/e2etest/testdata/plan-with-embedded-ephemeral-config/main.tf
   2026-10-01 18:03:40.000000000 +0200
@@ -0,0 +1,17 @@
+// the provider-plugin tests uses the -plugin-cache flag so terraform pulls the
+// test binaries instead of reaching out to the registry.
+terraform {
+  required_providers {
+    simple = {
+      source = "registry.opentofu.org/hashicorp/simple"
+    }
+  }
+}
+
+resource "simple_resource" "test_res" {
+  value    = "test value"
+}
+
+ephemeral "simple_resource" "test_ephemeral" {
+  value = "ephemeral value"
+}
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/opentofu-1.13.0/internal/plans/internal/planproto/planfile.pb.go 
new/opentofu-1.13.1/internal/plans/internal/planproto/planfile.pb.go
--- old/opentofu-1.13.0/internal/plans/internal/planproto/planfile.pb.go        
2026-09-30 14:59:06.000000000 +0200
+++ new/opentofu-1.13.1/internal/plans/internal/planproto/planfile.pb.go        
2026-10-01 18:03:40.000000000 +0200
@@ -1719,12 +1719,13 @@
 // ProviderSchema is a trimmed-down subset of a single provider's schema,
 // containing only the parts needed to render a particular saved plan.
 type ProviderSchema struct {
-       state                protoimpl.MessageState     `protogen:"open.v1"`
-       ProviderConfig       *Schema                    
`protobuf:"bytes,1,opt,name=provider_config,json=providerConfig,proto3" 
json:"provider_config,omitempty"`
-       ManagedResourceTypes map[string]*ResourceSchema 
`protobuf:"bytes,2,rep,name=managed_resource_types,json=managedResourceTypes,proto3"
 json:"managed_resource_types,omitempty" protobuf_key:"bytes,1,opt,name=key" 
protobuf_val:"bytes,2,opt,name=value"`
-       DataSources          map[string]*ResourceSchema 
`protobuf:"bytes,3,rep,name=data_sources,json=dataSources,proto3" 
json:"data_sources,omitempty" protobuf_key:"bytes,1,opt,name=key" 
protobuf_val:"bytes,2,opt,name=value"`
-       unknownFields        protoimpl.UnknownFields
-       sizeCache            protoimpl.SizeCache
+       state                  protoimpl.MessageState     `protogen:"open.v1"`
+       ProviderConfig         *Schema                    
`protobuf:"bytes,1,opt,name=provider_config,json=providerConfig,proto3" 
json:"provider_config,omitempty"`
+       ManagedResourceTypes   map[string]*ResourceSchema 
`protobuf:"bytes,2,rep,name=managed_resource_types,json=managedResourceTypes,proto3"
 json:"managed_resource_types,omitempty" protobuf_key:"bytes,1,opt,name=key" 
protobuf_val:"bytes,2,opt,name=value"`
+       DataSources            map[string]*ResourceSchema 
`protobuf:"bytes,3,rep,name=data_sources,json=dataSources,proto3" 
json:"data_sources,omitempty" protobuf_key:"bytes,1,opt,name=key" 
protobuf_val:"bytes,2,opt,name=value"`
+       EphemeralResourceTypes map[string]*ResourceSchema 
`protobuf:"bytes,4,rep,name=ephemeral_resource_types,json=ephemeralResourceTypes,proto3"
 json:"ephemeral_resource_types,omitempty" protobuf_key:"bytes,1,opt,name=key" 
protobuf_val:"bytes,2,opt,name=value"`
+       unknownFields          protoimpl.UnknownFields
+       sizeCache              protoimpl.SizeCache
 }
 
 func (x *ProviderSchema) Reset() {
@@ -1778,6 +1779,13 @@
        return nil
 }
 
+func (x *ProviderSchema) GetEphemeralResourceTypes() 
map[string]*ResourceSchema {
+       if x != nil {
+               return x.EphemeralResourceTypes
+       }
+       return nil
+}
+
 // Schemas is the root message for the "tfschemas" entry in the plan file
 // archive: a map from provider source address (e.g.
 // "registry.opentofu.org/hashicorp/aws") to the trimmed schema for that
@@ -2156,16 +2164,20 @@
        "\x04body\x18\x02 
\x01(\v2\x14.tfplan.SchemaObjectR\x04body\"\x81\x01\n" +
        "\x0eResourceSchema\x12&\n" +
        "\x06schema\x18\x01 \x01(\v2\x0e.tfplan.SchemaR\x06schema\x12G\n" +
-       "\x0fidentity_schema\x18\x02 
\x01(\v2\x1e.tfplan.ResourceIdentitySchemaR\x0eidentitySchema\"\xb6\x03\n" +
+       "\x0fidentity_schema\x18\x02 
\x01(\v2\x1e.tfplan.ResourceIdentitySchemaR\x0eidentitySchema\"\x87\x05\n" +
        "\x0eProviderSchema\x127\n" +
        "\x0fprovider_config\x18\x01 
\x01(\v2\x0e.tfplan.SchemaR\x0eproviderConfig\x12f\n" +
        "\x16managed_resource_types\x18\x02 
\x03(\v20.tfplan.ProviderSchema.ManagedResourceTypesEntryR\x14managedResourceTypes\x12J\n"
 +
-       "\fdata_sources\x18\x03 
\x03(\v2'.tfplan.ProviderSchema.DataSourcesEntryR\vdataSources\x1a_\n" +
+       "\fdata_sources\x18\x03 
\x03(\v2'.tfplan.ProviderSchema.DataSourcesEntryR\vdataSources\x12l\n" +
+       "\x18ephemeral_resource_types\x18\x04 
\x03(\v22.tfplan.ProviderSchema.EphemeralResourceTypesEntryR\x16ephemeralResourceTypes\x1a_\n"
 +
        "\x19ManagedResourceTypesEntry\x12\x10\n" +
        "\x03key\x18\x01 \x01(\tR\x03key\x12,\n" +
        "\x05value\x18\x02 
\x01(\v2\x16.tfplan.ResourceSchemaR\x05value:\x028\x01\x1aV\n" +
        "\x10DataSourcesEntry\x12\x10\n" +
        "\x03key\x18\x01 \x01(\tR\x03key\x12,\n" +
+       "\x05value\x18\x02 
\x01(\v2\x16.tfplan.ResourceSchemaR\x05value:\x028\x01\x1aa\n" +
+       "\x1bEphemeralResourceTypesEntry\x12\x10\n" +
+       "\x03key\x18\x01 \x01(\tR\x03key\x12,\n" +
        "\x05value\x18\x02 
\x01(\v2\x16.tfplan.ResourceSchemaR\x05value:\x028\x01\"\x9d\x01\n" +
        "\aSchemas\x12<\n" +
        "\tproviders\x18\x01 
\x03(\v2\x1e.tfplan.Schemas.ProvidersEntryR\tproviders\x1aT\n" +
@@ -2232,7 +2244,7 @@
 }
 
 var file_planfile_proto_enumTypes = make([]protoimpl.EnumInfo, 6)
-var file_planfile_proto_msgTypes = make([]protoimpl.MessageInfo, 25)
+var file_planfile_proto_msgTypes = make([]protoimpl.MessageInfo, 26)
 var file_planfile_proto_goTypes = []any{
        (Mode)(0),                         // 0: tfplan.Mode
        (Action)(0),                       // 1: tfplan.Action
@@ -2264,7 +2276,8 @@
        (*Path_Step)(nil),                 // 27: tfplan.Path.Step
        nil,                               // 28: 
tfplan.ProviderSchema.ManagedResourceTypesEntry
        nil,                               // 29: 
tfplan.ProviderSchema.DataSourcesEntry
-       nil,                               // 30: tfplan.Schemas.ProvidersEntry
+       nil,                               // 30: 
tfplan.ProviderSchema.EphemeralResourceTypesEntry
+       nil,                               // 31: tfplan.Schemas.ProvidersEntry
 }
 var file_planfile_proto_depIdxs = []int32{
        0,  // 0: tfplan.Plan.ui_mode:type_name -> tfplan.Mode
@@ -2306,19 +2319,21 @@
        19, // 36: tfplan.ProviderSchema.provider_config:type_name -> 
tfplan.Schema
        28, // 37: tfplan.ProviderSchema.managed_resource_types:type_name -> 
tfplan.ProviderSchema.ManagedResourceTypesEntry
        29, // 38: tfplan.ProviderSchema.data_sources:type_name -> 
tfplan.ProviderSchema.DataSourcesEntry
-       30, // 39: tfplan.Schemas.providers:type_name -> 
tfplan.Schemas.ProvidersEntry
-       12, // 40: tfplan.Plan.VariablesEntry.value:type_name -> 
tfplan.DynamicValue
-       13, // 41: tfplan.Plan.resource_attr.attr:type_name -> tfplan.Path
-       4,  // 42: tfplan.CheckResults.ObjectResult.status:type_name -> 
tfplan.CheckResults.Status
-       12, // 43: tfplan.Path.Step.element_key:type_name -> tfplan.DynamicValue
-       21, // 44: 
tfplan.ProviderSchema.ManagedResourceTypesEntry.value:type_name -> 
tfplan.ResourceSchema
-       21, // 45: tfplan.ProviderSchema.DataSourcesEntry.value:type_name -> 
tfplan.ResourceSchema
-       22, // 46: tfplan.Schemas.ProvidersEntry.value:type_name -> 
tfplan.ProviderSchema
-       47, // [47:47] is the sub-list for method output_type
-       47, // [47:47] is the sub-list for method input_type
-       47, // [47:47] is the sub-list for extension type_name
-       47, // [47:47] is the sub-list for extension extendee
-       0,  // [0:47] is the sub-list for field type_name
+       30, // 39: tfplan.ProviderSchema.ephemeral_resource_types:type_name -> 
tfplan.ProviderSchema.EphemeralResourceTypesEntry
+       31, // 40: tfplan.Schemas.providers:type_name -> 
tfplan.Schemas.ProvidersEntry
+       12, // 41: tfplan.Plan.VariablesEntry.value:type_name -> 
tfplan.DynamicValue
+       13, // 42: tfplan.Plan.resource_attr.attr:type_name -> tfplan.Path
+       4,  // 43: tfplan.CheckResults.ObjectResult.status:type_name -> 
tfplan.CheckResults.Status
+       12, // 44: tfplan.Path.Step.element_key:type_name -> tfplan.DynamicValue
+       21, // 45: 
tfplan.ProviderSchema.ManagedResourceTypesEntry.value:type_name -> 
tfplan.ResourceSchema
+       21, // 46: tfplan.ProviderSchema.DataSourcesEntry.value:type_name -> 
tfplan.ResourceSchema
+       21, // 47: 
tfplan.ProviderSchema.EphemeralResourceTypesEntry.value:type_name -> 
tfplan.ResourceSchema
+       22, // 48: tfplan.Schemas.ProvidersEntry.value:type_name -> 
tfplan.ProviderSchema
+       49, // [49:49] is the sub-list for method output_type
+       49, // [49:49] is the sub-list for method input_type
+       49, // [49:49] is the sub-list for extension type_name
+       49, // [49:49] is the sub-list for extension extendee
+       0,  // [0:49] is the sub-list for field type_name
 }
 
 func init() { file_planfile_proto_init() }
@@ -2336,7 +2351,7 @@
                        GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
                        RawDescriptor: 
unsafe.Slice(unsafe.StringData(file_planfile_proto_rawDesc), 
len(file_planfile_proto_rawDesc)),
                        NumEnums:      6,
-                       NumMessages:   25,
+                       NumMessages:   26,
                        NumExtensions: 0,
                        NumServices:   0,
                },
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/opentofu-1.13.0/internal/plans/internal/planproto/planfile.proto 
new/opentofu-1.13.1/internal/plans/internal/planproto/planfile.proto
--- old/opentofu-1.13.0/internal/plans/internal/planproto/planfile.proto        
2026-09-30 14:59:06.000000000 +0200
+++ new/opentofu-1.13.1/internal/plans/internal/planproto/planfile.proto        
2026-10-01 18:03:40.000000000 +0200
@@ -452,6 +452,7 @@
     Schema provider_config = 1;
     map<string, ResourceSchema> managed_resource_types = 2;
     map<string, ResourceSchema> data_sources = 3;
+    map<string, ResourceSchema> ephemeral_resource_types = 4;
 }
 
 // Schemas is the root message for the "tfschemas" entry in the plan file
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/opentofu-1.13.0/internal/plans/planfile/schema_convert.go 
new/opentofu-1.13.1/internal/plans/planfile/schema_convert.go
--- old/opentofu-1.13.0/internal/plans/planfile/schema_convert.go       
2026-09-30 14:59:06.000000000 +0200
+++ new/opentofu-1.13.1/internal/plans/planfile/schema_convert.go       
2026-10-01 18:03:40.000000000 +0200
@@ -236,9 +236,10 @@
 // into its protobuf representation.
 func providerSchemaToProto(s providers.ProviderSchema) 
*planproto.ProviderSchema {
        ps := &planproto.ProviderSchema{
-               ProviderConfig:       schemaToProto(s.Provider),
-               ManagedResourceTypes: 
make(map[string]*planproto.ResourceSchema, len(s.ResourceTypes)),
-               DataSources:          
make(map[string]*planproto.ResourceSchema, len(s.DataSources)),
+               ProviderConfig:         schemaToProto(s.Provider),
+               ManagedResourceTypes:   
make(map[string]*planproto.ResourceSchema, len(s.ResourceTypes)),
+               DataSources:            
make(map[string]*planproto.ResourceSchema, len(s.DataSources)),
+               EphemeralResourceTypes: 
make(map[string]*planproto.ResourceSchema, len(s.EphemeralResources)),
        }
        for name, schema := range s.ResourceTypes {
                ps.ManagedResourceTypes[name] = resourceSchemaToProto(schema)
@@ -246,14 +247,18 @@
        for name, schema := range s.DataSources {
                ps.DataSources[name] = resourceSchemaToProto(schema)
        }
+       for name, schema := range s.EphemeralResources {
+               ps.EphemeralResourceTypes[name] = resourceSchemaToProto(schema)
+       }
        return ps
 }
 
 func providerSchemaFromProto(ps *planproto.ProviderSchema) 
providers.ProviderSchema {
        s := providers.ProviderSchema{
-               Provider:      schemaFromProto(ps.ProviderConfig),
-               ResourceTypes: make(map[string]providers.Schema, 
len(ps.ManagedResourceTypes)),
-               DataSources:   make(map[string]providers.Schema, 
len(ps.DataSources)),
+               Provider:           schemaFromProto(ps.ProviderConfig),
+               ResourceTypes:      make(map[string]providers.Schema, 
len(ps.ManagedResourceTypes)),
+               DataSources:        make(map[string]providers.Schema, 
len(ps.DataSources)),
+               EphemeralResources: make(map[string]providers.Schema, 
len(ps.EphemeralResourceTypes)),
        }
        for name, rs := range ps.ManagedResourceTypes {
                s.ResourceTypes[name] = resourceSchemaFromProto(rs)
@@ -261,5 +266,8 @@
        for name, rs := range ps.DataSources {
                s.DataSources[name] = resourceSchemaFromProto(rs)
        }
+       for name, rs := range ps.EphemeralResourceTypes {
+               s.EphemeralResources[name] = resourceSchemaFromProto(rs)
+       }
        return s
 }
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/opentofu-1.13.0/internal/plans/planfile/schema_trim.go 
new/opentofu-1.13.1/internal/plans/planfile/schema_trim.go
--- old/opentofu-1.13.0/internal/plans/planfile/schema_trim.go  2026-09-30 
14:59:06.000000000 +0200
+++ new/opentofu-1.13.1/internal/plans/planfile/schema_trim.go  2026-10-01 
18:03:40.000000000 +0200
@@ -21,14 +21,16 @@
 // plan (its configuration, prior state, or proposed changes).
 // We dont need ephemeral as they dont get stored in the config
 type referencedTypes struct {
-       managed map[string]struct{}
-       data    map[string]struct{}
+       managed   map[string]struct{}
+       data      map[string]struct{}
+       ephemeral map[string]struct{}
 }
 
 func newReferencedTypes() *referencedTypes {
        return &referencedTypes{
-               managed: make(map[string]struct{}),
-               data:    make(map[string]struct{}),
+               managed:   make(map[string]struct{}),
+               data:      make(map[string]struct{}),
+               ephemeral: make(map[string]struct{}),
        }
 }
 
@@ -38,6 +40,8 @@
                rt.managed[typeName] = struct{}{}
        case addrs.DataResourceMode:
                rt.data[typeName] = struct{}{}
+       case addrs.EphemeralResourceMode:
+               rt.ephemeral[typeName] = struct{}{}
        default:
        }
 }
@@ -71,6 +75,9 @@
                        for _, r := range c.Module.DataResources {
                                get(r.Provider).addType(r.Mode, r.Type)
                        }
+                       for _, r := range c.Module.EphemeralResources {
+                               get(r.Provider).addType(r.Mode, r.Type)
+                       }
                }
        }
 
@@ -138,9 +145,10 @@
                }
 
                trimmed := providers.ProviderSchema{
-                       Provider:      full.Provider,
-                       ResourceTypes: make(map[string]providers.Schema, 
len(rt.managed)),
-                       DataSources:   make(map[string]providers.Schema, 
len(rt.data)),
+                       Provider:           full.Provider,
+                       ResourceTypes:      make(map[string]providers.Schema, 
len(rt.managed)),
+                       DataSources:        make(map[string]providers.Schema, 
len(rt.data)),
+                       EphemeralResources: make(map[string]providers.Schema, 
len(rt.ephemeral)),
                }
 
                for typeName := range rt.managed {
@@ -155,6 +163,12 @@
                                missing = append(missing, fmt.Sprintf("data 
source %q of provider %s", typeName, provider))
                        }
                }
+               for typeName := range rt.ephemeral {
+                       trimmed.EphemeralResources[typeName], ok = 
full.EphemeralResources[typeName]
+                       if !ok {
+                               missing = append(missing, 
fmt.Sprintf("ephemeral resource type %q of provider %s", typeName, provider))
+                       }
+               }
 
                result[provider] = trimmed
        }
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/opentofu-1.13.0/internal/plans/planfile/testdata/test-config/root.tf 
new/opentofu-1.13.1/internal/plans/planfile/testdata/test-config/root.tf
--- old/opentofu-1.13.0/internal/plans/planfile/testdata/test-config/root.tf    
2026-09-30 14:59:06.000000000 +0200
+++ new/opentofu-1.13.1/internal/plans/planfile/testdata/test-config/root.tf    
2026-10-01 18:03:40.000000000 +0200
@@ -8,3 +8,7 @@
   source = "example.com/foo/bar_b/baz"
   version = ">= 1.0.0"
 }
+
+resource "test_resource" "res_test" {}
+data "test_data" "data_test" {}
+ephemeral "test_ephemeral" "ephemeral_test" {}
\ No newline at end of file
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/opentofu-1.13.0/internal/tofu/context_apply2_test.go 
new/opentofu-1.13.1/internal/tofu/context_apply2_test.go
--- old/opentofu-1.13.0/internal/tofu/context_apply2_test.go    2026-09-30 
14:59:06.000000000 +0200
+++ new/opentofu-1.13.1/internal/tofu/context_apply2_test.go    2026-10-01 
18:03:40.000000000 +0200
@@ -7353,3 +7353,109 @@
 
        }
 }
+
+// TestContext2Apply_ephemeralOutputCrossModuleWriteOnly checks that a value 
produced
+// by an ephemeral resource and shared via an `ephemeral = true` module output 
is
+// exporting identically at two different write-only attribute consumers: one 
in the
+// same module as the ephemeral resource, and one in a different module 
reached only
+// through the output.
+func TestContext2Apply_ephemeralOutputCrossModuleWriteOnly(t *testing.T) {
+       SkipExperimental(t, ExperimentalFlagUnknown)
+
+       m := testModuleInline(t, map[string]string{
+               "child/main.tf": `
+                       ephemeral "test_ephemeral_resource" "generate" {
+                               input = "seed"
+                       }
+
+                       resource "test_instance" "child" {
+                               vpc_id   = "child"
+                               value_wo = 
ephemeral.test_ephemeral_resource.generate.secret
+                       }
+
+                       output "secret" {
+                               ephemeral = true
+                               value     = 
ephemeral.test_ephemeral_resource.generate.secret
+                       }
+               `,
+               "main.tf": `
+                       module "child" {
+                               source = "./child"
+                       }
+
+                       resource "test_instance" "root" {
+                               vpc_id   = "root"
+                               value_wo = module.child.secret
+                       }
+               `,
+       })
+
+       provider := testProvider("test")
+
+       openCount := 0
+       provider.OpenEphemeralResourceFn = func(req 
providers.OpenEphemeralResourceRequest) providers.OpenEphemeralResourceResponse 
{
+               openCount++
+               return providers.OpenEphemeralResourceResponse{
+                       Result: cty.ObjectVal(map[string]cty.Value{
+                               "id":     cty.StringVal("id"),
+                               "secret": 
cty.StringVal(fmt.Sprintf("generated-%d", openCount)),
+                               "input":  req.Config.GetAttr("input"),
+                       }),
+               }
+       }
+
+       // Write-only attributes must never appear in planned state, so null it 
out here
+       provider.PlanResourceChangeFn = func(req 
providers.PlanResourceChangeRequest) providers.PlanResourceChangeResponse {
+               planned := req.ProposedNewState.AsValueMap()
+               if _, ok := planned["value_wo"]; ok {
+                       planned["value_wo"] = cty.NullVal(cty.String)
+               }
+               if planned["id"].IsNull() {
+                       planned["id"] = cty.UnknownVal(cty.String)
+               }
+               return providers.PlanResourceChangeResponse{
+                       PlannedState: cty.ObjectVal(planned),
+               }
+       }
+
+       // Capture the write-only value actually sent to ApplyResourceChange 
for each of the two resources
+       applied := map[string]string{}
+       provider.ApplyResourceChangeFn = func(req 
providers.ApplyResourceChangeRequest) providers.ApplyResourceChangeResponse {
+               newState := req.PlannedState.AsValueMap()
+               vpcID := newState["vpc_id"].AsString()
+               newState["id"] = cty.StringVal("id-" + vpcID)
+
+               wo := req.Config.GetAttr("value_wo")
+               if !wo.IsNull() {
+                       applied[vpcID] = wo.AsString()
+               }
+
+               return providers.ApplyResourceChangeResponse{
+                       NewState: cty.ObjectVal(newState),
+               }
+       }
+
+       ctx := testContext2(t, &ContextOpts{
+               Plugins: 
plugins.NewLibrary(map[addrs.Provider]providers.Factory{
+                       addrs.NewDefaultProvider("test"): 
testProviderFuncFixed(provider),
+               }, nil),
+       })
+
+       plan, diags := ctx.Plan(context.Background(), m, states.NewState(), 
&PlanOpts{
+               Mode: plans.NormalMode,
+       })
+       assertNoErrors(t, diags)
+
+       _, diags = ctx.Apply(context.Background(), plan, m, nil)
+       assertNoErrors(t, diags)
+
+       if applied["child"] == "" || applied["root"] == "" {
+               t.Fatalf("did not capture write-only values for both resources: 
%#v", applied)
+       }
+       if applied["child"] != applied["root"] {
+               t.Errorf(
+                       "write-only values diverged across the module boundary: 
child=%q root=%q (ephemeral resource opened %d times)",
+                       applied["child"], applied["root"], openCount,
+               )
+       }
+}
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/opentofu-1.13.0/internal/tofu/node_output.go 
new/opentofu-1.13.1/internal/tofu/node_output.go
--- old/opentofu-1.13.0/internal/tofu/node_output.go    2026-09-30 
14:59:06.000000000 +0200
+++ new/opentofu-1.13.1/internal/tofu/node_output.go    2026-10-01 
18:03:40.000000000 +0200
@@ -344,8 +344,12 @@
        }
 
        // If there was no change recorded, or the recorded change was not 
wholly
-       // known, then we need to re-evaluate the output
-       if !changeRecorded || !val.IsWhollyKnown() {
+       // known, then we need to re-evaluate the output.
+       //
+       // Ephemeral outputs must also always be re-evaluated, so their value 
stays
+       // consistent with other consumers of the same ephemeral resource in 
this apply,
+       // instead of exporting a stale plan-time value across the module 
boundary.
+       if !changeRecorded || !val.IsWhollyKnown() || n.Config.Ephemeral {
                switch {
                // If the module is not being overridden, we proceed normally
                case !n.Config.IsOverridden:
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/opentofu-1.13.0/version/VERSION 
new/opentofu-1.13.1/version/VERSION
--- old/opentofu-1.13.0/version/VERSION 2026-09-30 14:59:06.000000000 +0200
+++ new/opentofu-1.13.1/version/VERSION 2026-10-01 18:03:40.000000000 +0200
@@ -1 +1 @@
-1.13.0
+1.13.1

++++++ opentofu.obsinfo ++++++
--- /var/tmp/diff_new_pack.Sk3QrV/_old  2026-10-02 23:05:51.927624166 +0200
+++ /var/tmp/diff_new_pack.Sk3QrV/_new  2026-10-02 23:05:51.937624584 +0200
@@ -1,5 +1,5 @@
 name: opentofu
-version: 1.13.0
-mtime: 1790773146
-commit: 2b6193043d500dcfef1f3b4f4819b938b667099f
+version: 1.13.1
+mtime: 1790870620
+commit: 233700b795b6d2372f1c56ed57a4abaec9d36475
 

++++++ vendor.tar.gz ++++++
/work/SRC/openSUSE:Factory/opentofu/vendor.tar.gz 
/work/SRC/openSUSE:Factory/.opentofu.new.1631729/vendor.tar.gz differ: char 
134, line 3

Reply via email to