@@ -5094,6 +5094,88 @@ func TestPlanResourceChange(t *testing.T) {
5094
5094
UnsafeToUseLegacyTypeSystem : true ,
5095
5095
},
5096
5096
},
5097
+ "create-writeonly-plan-modification" : {
5098
+ server : NewGRPCProviderServer (& Provider {
5099
+ ResourcesMap : map [string ]* Resource {
5100
+ "test" : {
5101
+ SchemaVersion : 4 ,
5102
+ CustomizeDiff : func (ctx context.Context , d * ResourceDiff , i interface {}) error {
5103
+ val := d .Get ("foo" )
5104
+ if val != "bar" {
5105
+ t .Fatalf ("Incorrect write-only value" )
5106
+ }
5107
+
5108
+ return nil
5109
+ },
5110
+ Schema : map [string ]* Schema {
5111
+ "foo" : {
5112
+ Type : TypeString ,
5113
+ Optional : true ,
5114
+ WriteOnly : true ,
5115
+ },
5116
+ },
5117
+ },
5118
+ },
5119
+ }),
5120
+ req : & tfprotov5.PlanResourceChangeRequest {
5121
+ TypeName : "test" ,
5122
+ PriorState : & tfprotov5.DynamicValue {
5123
+ MsgPack : mustMsgpackMarshal (
5124
+ cty .Object (map [string ]cty.Type {
5125
+ "foo" : cty .String ,
5126
+ }),
5127
+ cty .NullVal (
5128
+ cty .Object (map [string ]cty.Type {
5129
+ "foo" : cty .String ,
5130
+ }),
5131
+ ),
5132
+ ),
5133
+ },
5134
+ ProposedNewState : & tfprotov5.DynamicValue {
5135
+ MsgPack : mustMsgpackMarshal (
5136
+ cty .Object (map [string ]cty.Type {
5137
+ "id" : cty .String ,
5138
+ "foo" : cty .String ,
5139
+ }),
5140
+ cty .ObjectVal (map [string ]cty.Value {
5141
+ "id" : cty .UnknownVal (cty .String ),
5142
+ "foo" : cty .StringVal ("bar" ),
5143
+ }),
5144
+ ),
5145
+ },
5146
+ Config : & tfprotov5.DynamicValue {
5147
+ MsgPack : mustMsgpackMarshal (
5148
+ cty .Object (map [string ]cty.Type {
5149
+ "id" : cty .String ,
5150
+ "foo" : cty .String ,
5151
+ }),
5152
+ cty .ObjectVal (map [string ]cty.Value {
5153
+ "id" : cty .NullVal (cty .String ),
5154
+ "foo" : cty .StringVal ("bar" ),
5155
+ }),
5156
+ ),
5157
+ },
5158
+ },
5159
+ expected : & tfprotov5.PlanResourceChangeResponse {
5160
+ PlannedState : & tfprotov5.DynamicValue {
5161
+ MsgPack : mustMsgpackMarshal (
5162
+ cty .Object (map [string ]cty.Type {
5163
+ "id" : cty .String ,
5164
+ "foo" : cty .String ,
5165
+ }),
5166
+ cty .ObjectVal (map [string ]cty.Value {
5167
+ "id" : cty .UnknownVal (cty .String ),
5168
+ "foo" : cty .NullVal (cty .String ),
5169
+ }),
5170
+ ),
5171
+ },
5172
+ PlannedPrivate : []byte (`{"_new_extra_shim":{}}` ),
5173
+ RequiresReplace : []* tftypes.AttributePath {
5174
+ tftypes .NewAttributePath ().WithAttributeName ("id" ),
5175
+ },
5176
+ UnsafeToUseLegacyTypeSystem : true ,
5177
+ },
5178
+ },
5097
5179
}
5098
5180
5099
5181
for name , testCase := range testCases {
@@ -5528,6 +5610,239 @@ func TestApplyResourceChange_bigint(t *testing.T) {
5528
5610
}
5529
5611
}
5530
5612
5613
+ func TestApplyResourceChange_writeOnly (t * testing.T ) {
5614
+ t .Parallel ()
5615
+
5616
+ testCases := map [string ]struct {
5617
+ TestResource * Resource
5618
+ ExpectedUnsafeLegacyTypeSystem bool
5619
+ }{
5620
+ "Create" : {
5621
+ TestResource : & Resource {
5622
+ SchemaVersion : 4 ,
5623
+ Schema : map [string ]* Schema {
5624
+ "foo" : {
5625
+ Type : TypeInt ,
5626
+ Optional : true ,
5627
+ },
5628
+ "write_only_bar" : {
5629
+ Type : TypeString ,
5630
+ Optional : true ,
5631
+ WriteOnly : true ,
5632
+ },
5633
+ },
5634
+ Create : func (rd * ResourceData , _ interface {}) error {
5635
+ rd .SetId ("baz" )
5636
+ writeOnlyVal , err := rd .GetWriteOnly (cty .GetAttrPath ("write_only_bar" ))
5637
+ if err != nil {
5638
+ t .Errorf ("Unable to retrieve write only attribute, err: %s" , err )
5639
+ }
5640
+ if writeOnlyVal .AsString () != "bar" {
5641
+ t .Errorf ("Incorrect write-only value: expected bar but got %s" , writeOnlyVal )
5642
+ }
5643
+ return nil
5644
+ },
5645
+ },
5646
+ ExpectedUnsafeLegacyTypeSystem : true ,
5647
+ },
5648
+ "CreateContext" : {
5649
+ TestResource : & Resource {
5650
+ SchemaVersion : 4 ,
5651
+ Schema : map [string ]* Schema {
5652
+ "foo" : {
5653
+ Type : TypeInt ,
5654
+ Optional : true ,
5655
+ },
5656
+ "write_only_bar" : {
5657
+ Type : TypeString ,
5658
+ Optional : true ,
5659
+ WriteOnly : true ,
5660
+ },
5661
+ },
5662
+ CreateContext : func (_ context.Context , rd * ResourceData , _ interface {}) diag.Diagnostics {
5663
+ rd .SetId ("baz" )
5664
+ writeOnlyVal , err := rd .GetWriteOnly (cty .GetAttrPath ("write_only_bar" ))
5665
+ if err != nil {
5666
+ t .Errorf ("Unable to retrieve write only attribute, err: %s" , err )
5667
+ }
5668
+ if writeOnlyVal .AsString () != "bar" {
5669
+ t .Errorf ("Incorrect write-only value: expected bar but got %s" , writeOnlyVal )
5670
+ }
5671
+ return nil
5672
+ },
5673
+ },
5674
+ ExpectedUnsafeLegacyTypeSystem : true ,
5675
+ },
5676
+ "CreateWithoutTimeout" : {
5677
+ TestResource : & Resource {
5678
+ SchemaVersion : 4 ,
5679
+ Schema : map [string ]* Schema {
5680
+ "foo" : {
5681
+ Type : TypeInt ,
5682
+ Optional : true ,
5683
+ },
5684
+ "write_only_bar" : {
5685
+ Type : TypeString ,
5686
+ Optional : true ,
5687
+ WriteOnly : true ,
5688
+ },
5689
+ },
5690
+ CreateWithoutTimeout : func (_ context.Context , rd * ResourceData , _ interface {}) diag.Diagnostics {
5691
+ rd .SetId ("baz" )
5692
+ writeOnlyVal , err := rd .GetWriteOnly (cty .GetAttrPath ("write_only_bar" ))
5693
+ if err != nil {
5694
+ t .Errorf ("Unable to retrieve write only attribute, err: %s" , err )
5695
+ }
5696
+ if writeOnlyVal .AsString () != "bar" {
5697
+ t .Errorf ("Incorrect write-only value: expected bar but got %s" , writeOnlyVal )
5698
+ }
5699
+ return nil
5700
+ },
5701
+ },
5702
+ ExpectedUnsafeLegacyTypeSystem : true ,
5703
+ },
5704
+ "Create_cty" : {
5705
+ TestResource : & Resource {
5706
+ SchemaVersion : 4 ,
5707
+ Schema : map [string ]* Schema {
5708
+ "foo" : {
5709
+ Type : TypeInt ,
5710
+ Optional : true ,
5711
+ },
5712
+ "write_only_bar" : {
5713
+ Type : TypeString ,
5714
+ Optional : true ,
5715
+ WriteOnly : true ,
5716
+ },
5717
+ },
5718
+ CreateWithoutTimeout : func (_ context.Context , rd * ResourceData , _ interface {}) diag.Diagnostics {
5719
+ rd .SetId ("baz" )
5720
+ if rd .GetRawWriteOnly ().IsNull () {
5721
+ return diag .FromErr (errors .New ("null raw writeOnly val" ))
5722
+ }
5723
+ if rd .GetRawWriteOnly ().GetAttr ("write_only_bar" ).Type () != cty .String {
5724
+ return diag .FromErr (errors .New ("write_only_bar is not of the expected type string" ))
5725
+ }
5726
+ writeOnlyVal := rd .GetRawWriteOnly ().GetAttr ("write_only_bar" ).AsString ()
5727
+ if writeOnlyVal != "bar" {
5728
+ t .Errorf ("Incorrect write-only value: expected bar but got %s" , writeOnlyVal )
5729
+ }
5730
+ return nil
5731
+ },
5732
+ },
5733
+ ExpectedUnsafeLegacyTypeSystem : true ,
5734
+ },
5735
+ "CreateContext_SchemaFunc" : {
5736
+ TestResource : & Resource {
5737
+ SchemaFunc : func () map [string ]* Schema {
5738
+ return map [string ]* Schema {
5739
+ "id" : {
5740
+ Type : TypeString ,
5741
+ Computed : true ,
5742
+ },
5743
+ "write_only_bar" : {
5744
+ Type : TypeString ,
5745
+ Optional : true ,
5746
+ WriteOnly : true ,
5747
+ },
5748
+ }
5749
+ },
5750
+ CreateContext : func (_ context.Context , rd * ResourceData , _ interface {}) diag.Diagnostics {
5751
+ rd .SetId ("baz" )
5752
+ writeOnlyVal , err := rd .GetWriteOnly (cty .GetAttrPath ("write_only_bar" ))
5753
+ if err != nil {
5754
+ t .Errorf ("Unable to retrieve write only attribute, err: %s" , err )
5755
+ }
5756
+ if writeOnlyVal .AsString () != "bar" {
5757
+ t .Errorf ("Incorrect write-only value: expected bar but got %s" , writeOnlyVal )
5758
+ }
5759
+ return nil
5760
+ },
5761
+ },
5762
+ ExpectedUnsafeLegacyTypeSystem : true ,
5763
+ },
5764
+ }
5765
+
5766
+ for name , testCase := range testCases {
5767
+ name , testCase := name , testCase
5768
+
5769
+ t .Run (name , func (t * testing.T ) {
5770
+ t .Parallel ()
5771
+
5772
+ server := NewGRPCProviderServer (& Provider {
5773
+ ResourcesMap : map [string ]* Resource {
5774
+ "test" : testCase .TestResource ,
5775
+ },
5776
+ })
5777
+
5778
+ schema := testCase .TestResource .CoreConfigSchema ()
5779
+ priorState , err := msgpack .Marshal (cty .NullVal (schema .ImpliedType ()), schema .ImpliedType ())
5780
+ if err != nil {
5781
+ t .Fatal (err )
5782
+ }
5783
+
5784
+ // A proposed state with only the ID unknown will produce a nil diff, and
5785
+ // should return the proposed state value.
5786
+ plannedVal , err := schema .CoerceValue (cty .ObjectVal (map [string ]cty.Value {
5787
+ "id" : cty .UnknownVal (cty .String ),
5788
+ }))
5789
+ if err != nil {
5790
+ t .Fatal (err )
5791
+ }
5792
+ plannedState , err := msgpack .Marshal (plannedVal , schema .ImpliedType ())
5793
+ if err != nil {
5794
+ t .Fatal (err )
5795
+ }
5796
+
5797
+ config , err := schema .CoerceValue (cty .ObjectVal (map [string ]cty.Value {
5798
+ "id" : cty .NullVal (cty .String ),
5799
+ "write_only_bar" : cty .StringVal ("bar" ),
5800
+ }))
5801
+ if err != nil {
5802
+ t .Fatal (err )
5803
+ }
5804
+ configBytes , err := msgpack .Marshal (config , schema .ImpliedType ())
5805
+ if err != nil {
5806
+ t .Fatal (err )
5807
+ }
5808
+
5809
+ testReq := & tfprotov5.ApplyResourceChangeRequest {
5810
+ TypeName : "test" ,
5811
+ PriorState : & tfprotov5.DynamicValue {
5812
+ MsgPack : priorState ,
5813
+ },
5814
+ PlannedState : & tfprotov5.DynamicValue {
5815
+ MsgPack : plannedState ,
5816
+ },
5817
+ Config : & tfprotov5.DynamicValue {
5818
+ MsgPack : configBytes ,
5819
+ },
5820
+ }
5821
+
5822
+ resp , err := server .ApplyResourceChange (context .Background (), testReq )
5823
+ if err != nil {
5824
+ t .Fatal (err )
5825
+ }
5826
+
5827
+ newStateVal , err := msgpack .Unmarshal (resp .NewState .MsgPack , schema .ImpliedType ())
5828
+ if err != nil {
5829
+ t .Fatal (err )
5830
+ }
5831
+
5832
+ id := newStateVal .GetAttr ("id" ).AsString ()
5833
+ if id != "baz" {
5834
+ t .Fatalf ("incorrect final state: %#v\n " , newStateVal )
5835
+ }
5836
+
5837
+ //nolint:staticcheck // explicitly for this SDK
5838
+ if testCase .ExpectedUnsafeLegacyTypeSystem != resp .UnsafeToUseLegacyTypeSystem {
5839
+ //nolint:staticcheck // explicitly for this SDK
5840
+ t .Fatalf ("expected UnsafeLegacyTypeSystem %t, got: %t" , testCase .ExpectedUnsafeLegacyTypeSystem , resp .UnsafeToUseLegacyTypeSystem )
5841
+ }
5842
+ })
5843
+ }
5844
+ }
5845
+
5531
5846
func TestImportResourceState (t * testing.T ) {
5532
5847
t .Parallel ()
5533
5848
0 commit comments