@@ -7,13 +7,16 @@ package migration_test
7
7
8
8
import (
9
9
"context"
10
+ "encoding/hex"
10
11
"errors"
11
12
"fmt"
12
13
"testing"
13
14
"time"
14
15
16
+ "github.com/cosi-project/runtime/pkg/controller/generic"
15
17
"github.com/cosi-project/runtime/pkg/controller/runtime"
16
18
"github.com/cosi-project/runtime/pkg/resource"
19
+ "github.com/cosi-project/runtime/pkg/resource/protobuf"
17
20
"github.com/cosi-project/runtime/pkg/resource/rtestutils"
18
21
"github.com/cosi-project/runtime/pkg/resource/typed"
19
22
"github.com/cosi-project/runtime/pkg/safe"
@@ -23,9 +26,11 @@ import (
23
26
"github.com/google/uuid"
24
27
"github.com/siderolabs/gen/pair"
25
28
"github.com/siderolabs/gen/xslices"
29
+ "github.com/siderolabs/gen/xtesting/must"
26
30
"github.com/siderolabs/go-pointer"
27
31
"github.com/siderolabs/talos/pkg/machinery/config/types/v1alpha1"
28
32
"github.com/stretchr/testify/assert"
33
+ "github.com/stretchr/testify/require"
29
34
"github.com/stretchr/testify/suite"
30
35
"go.uber.org/zap"
31
36
"go.uber.org/zap/zaptest"
@@ -86,11 +91,7 @@ func (suite *MigrationSuite) TestClusterInfo() {
86
91
87
92
cluster , machine := suite .createCluster (ctx , "c1" )
88
93
89
- suite .Require ().NoError (suite .manager .Run (ctx ), migration .WithFilter (
90
- func (name string ) bool {
91
- return name == "clusterInfo"
92
- },
93
- ))
94
+ suite .Require ().NoError (suite .manager .Run (ctx , migration .WithFilter (filterWith ("clusterInfo" , "clusterInstallImageToTalosVersion" ))))
94
95
95
96
var err error
96
97
@@ -116,11 +117,7 @@ func (suite *MigrationSuite) TestClusterInfo() {
116
117
117
118
// This shouldn't happen: create old version of the cluster again and see it not being updated
118
119
// as the DB version is already up-to-date.
119
- suite .Require ().NoError (suite .manager .Run (ctx ), migration .WithFilter (
120
- func (name string ) bool {
121
- return name == "clusterInfo"
122
- },
123
- ))
120
+ suite .Require ().NoError (suite .manager .Run (ctx , migration .WithFilter (filterWith ("clusterInfo" , "clusterInstallImageToTalosVersion" ))))
124
121
125
122
cluster , err = safe .StateGet [* omni.Cluster ](ctx , suite .state , cluster .Metadata ())
126
123
@@ -212,9 +209,7 @@ func (suite *MigrationSuite) Test_changePublicKeyOwner() {
212
209
}
213
210
214
211
// test migration in isolation
215
- suite .Require ().NoError (suite .manager .Run (ctx , migration .WithFilter (func (name string ) bool {
216
- return name == "changePublicKeyOwner"
217
- })))
212
+ suite .Require ().NoError (suite .manager .Run (ctx , migration .WithFilter (filterWith ("changePublicKeyOwner" ))))
218
213
219
214
keyVerifier := func (key * authres.PublicKey , expectedVersion int ) {
220
215
result , err := safe .StateGet [* authres.PublicKey ](ctx , suite .state , key .Metadata ())
@@ -439,9 +434,7 @@ func (suite *MigrationSuite) TestUserDefaultScopes() {
439
434
suite .Require ().NoError (suite .state .Create (ctx , user3 ))
440
435
441
436
// test migration in isolation
442
- suite .Require ().NoError (suite .manager .Run (ctx , migration .WithFilter (func (name string ) bool {
443
- return name == "addDefaultScopesToUsers"
444
- })))
437
+ suite .Require ().NoError (suite .manager .Run (ctx , migration .WithFilter (filterWith ("addDefaultScopesToUsers" ))))
445
438
446
439
user1 , err = safe .StateGet [* authres.User ](ctx , suite .state , user1 .Metadata ())
447
440
suite .Require ().NoError (err )
@@ -743,9 +736,7 @@ func (suite *MigrationSuite) TestAddServiceAccountScopesToUsers() {
743
736
suite .Require ().NoError (suite .state .Create (ctx , publicKey2 ))
744
737
745
738
// test migration in isolation
746
- suite .Require ().NoError (suite .manager .Run (ctx , migration .WithFilter (func (name string ) bool {
747
- return name == "addServiceAccountScopesToUsers"
748
- })))
739
+ suite .Require ().NoError (suite .manager .Run (ctx , migration .WithFilter (filterWith ("addServiceAccountScopesToUsers" ))))
749
740
750
741
user1 , err := safe .StateGet [* authres.User ](ctx , suite .state , user1 .Metadata ())
751
742
suite .Require ().NoError (err )
@@ -788,9 +779,7 @@ func (suite *MigrationSuite) TestMigrateLabels() {
788
779
machineLabels .Metadata ().Labels ().Set ("user-label" , "value" )
789
780
suite .Require ().NoError (suite .state .Create (ctx , machineLabels ))
790
781
791
- suite .Require ().NoError (suite .manager .Run (ctx , migration .WithFilter (func (name string ) bool {
792
- return name == "migrateLabels" || name == "dropOldLabels"
793
- })))
782
+ suite .Require ().NoError (suite .manager .Run (ctx , migration .WithFilter (filterWith ("migrateLabels" , "dropOldLabels" ))))
794
783
795
784
updatedMachineStatus , err := suite .state .Get (ctx , machineStatus .Metadata ())
796
785
suite .Require ().NoError (err )
@@ -860,9 +849,7 @@ func (suite *MigrationSuite) TestConvertScopesToRoles() {
860
849
suite .Require ().NoError (suite .state .Create (ctx , pubKeyWithUserMgmtScopes ))
861
850
suite .Require ().NoError (suite .state .Create (ctx , pubKeyWithServiceAccountScopes ))
862
851
863
- suite .Require ().NoError (suite .manager .Run (ctx , migration .WithFilter (func (name string ) bool {
864
- return name == "convertScopesToRoles"
865
- })))
852
+ suite .Require ().NoError (suite .manager .Run (ctx , migration .WithFilter (filterWith ("convertScopesToRoles" ))))
866
853
867
854
updatedUserWithNoScopes , err := safe .StateGet [* authres.User ](ctx , suite .state , userWithNoScopes .Metadata ())
868
855
suite .Require ().NoError (err )
@@ -1274,9 +1261,7 @@ func (suite *MigrationSuite) TestClearEmptyConfigPatches() {
1274
1261
suite .Require ().NoError (suite .state .Create (ctx , cp1 , state .WithCreateOwner ("MachineSetStatusController" )))
1275
1262
suite .Require ().NoError (suite .state .Create (ctx , cp2 , state .WithCreateOwner ("MachineSetStatusController" )))
1276
1263
1277
- suite .Require ().NoError (suite .manager .Run (ctx , migration .WithFilter (func (name string ) bool {
1278
- return name == "clearEmptyConfigPatches"
1279
- })))
1264
+ suite .Require ().NoError (suite .manager .Run (ctx , migration .WithFilter (filterWith ("clearEmptyConfigPatches" ))))
1280
1265
1281
1266
cp1After , err := safe .StateGetByID [* omni.ClusterMachineConfigPatches ](ctx , suite .state , "1" )
1282
1267
suite .Require ().NoError (err )
@@ -1398,9 +1383,7 @@ func (suite *MigrationSuite) TestSetMachineStatusSnapshotOwner() {
1398
1383
}
1399
1384
1400
1385
// test migration in isolation
1401
- suite .Require ().NoError (suite .manager .Run (ctx , migration .WithFilter (func (name string ) bool {
1402
- return name == "setMachineStatusSnapshotOwner"
1403
- })))
1386
+ suite .Require ().NoError (suite .manager .Run (ctx , migration .WithFilter (filterWith ("setMachineStatusSnapshotOwner" ))))
1404
1387
1405
1388
check := func (item * omni.MachineStatusSnapshot , expectedVersion int ) {
1406
1389
result , err := safe .StateGet [* omni.MachineStatusSnapshot ](ctx , suite .state , item .Metadata ())
@@ -1469,9 +1452,7 @@ func (suite *MigrationSuite) TestMigrateInstallImageConfigIntoGenOptions() {
1469
1452
suite .Require ().NoError (suite .state .Create (ctx , res , state .WithCreateOwner (res .Metadata ().Owner ())))
1470
1453
}
1471
1454
1472
- suite .Require ().NoError (suite .manager .Run (ctx , migration .WithFilter (func (name string ) bool {
1473
- return name == "migrateInstallImageConfigIntoGenOptions"
1474
- })))
1455
+ suite .Require ().NoError (suite .manager .Run (ctx , migration .WithFilter (filterWith ("migrateInstallImageConfigIntoGenOptions" ))))
1475
1456
1476
1457
genOptions , err := safe .StateGet [* omni.MachineConfigGenOptions ](ctx , suite .state , omni .NewMachineConfigGenOptions (resources .DefaultNamespace , "test" ).Metadata ())
1477
1458
suite .Require ().NoError (err )
@@ -1588,11 +1569,7 @@ func (suite *MigrationSuite) testDeleteDeprecatedResources(createRes func(id str
1588
1569
1589
1570
suite .Require ().NoError (err )
1590
1571
1591
- suite .Require ().NoError (suite .manager .Run (ctx ), migration .WithFilter (
1592
- func (name string ) bool {
1593
- return name == migrationFilter
1594
- },
1595
- ))
1572
+ suite .Require ().NoError (suite .manager .Run (ctx , migration .WithFilter (filterWith (migrationFilter ))))
1596
1573
1597
1574
list , err := suite .state .List (ctx , resource .NewMetadata (res .Metadata ().Namespace (), res .Metadata ().Type (), "" , resource .VersionUndefined ))
1598
1575
@@ -1639,11 +1616,7 @@ func (suite *MigrationSuite) TestRemoveMaintenanceConfigPatchFinalizers() {
1639
1616
suite .Require ().NoError (suite .state .Create (ctx , m2Status , state .WithCreateOwner ("MachineStatusController" )))
1640
1617
suite .Require ().NoError (suite .state .Create (ctx , m3Status , state .WithCreateOwner ("MachineStatusController" )))
1641
1618
1642
- suite .Require ().NoError (suite .manager .Run (ctx ), migration .WithFilter (
1643
- func (name string ) bool {
1644
- return name == "removeMaintenanceConfigPatchFinalizers"
1645
- },
1646
- ))
1619
+ suite .Require ().NoError (suite .manager .Run (ctx , migration .WithFilter (filterWith ("removeMaintenanceConfigPatchFinalizers" ))))
1647
1620
1648
1621
rtestutils .AssertAll (ctx , suite .T (), suite .state , func (
1649
1622
res * omni.MachineStatus , assert * assert.Assertions ,
@@ -1652,8 +1625,186 @@ func (suite *MigrationSuite) TestRemoveMaintenanceConfigPatchFinalizers() {
1652
1625
})
1653
1626
}
1654
1627
1628
+ func (suite * MigrationSuite ) TestCompressUncompressMigrations () {
1629
+ ctx , cancel := context .WithTimeout (context .Background (), 10 * time .Second )
1630
+ defer cancel ()
1631
+
1632
+ const (
1633
+ data1 = "Hello world!"
1634
+ data2 = "Hello Sidero!"
1635
+ )
1636
+
1637
+ encoded1 := must .Value (hex .DecodeString ("28b52ffd040061000048656c6c6f20776f726c6421b27dfd7f" ))(suite .T ())
1638
+ encoded2 := must .Value (hex .DecodeString ("28b52ffd040069000048656c6c6f2053696465726f211ce853bc" ))(suite .T ())
1639
+ disabled := specs .WithConfigCompressionOption (specs.CompressionConfig {Enabled : false })
1640
+
1641
+ const ns = resources .DefaultNamespace
1642
+
1643
+ checkMigrations := []func (t * testing.T ){
1644
+ startMigration (
1645
+ ctx ,
1646
+ suite .T (),
1647
+ suite .state ,
1648
+ omni .NewConfigPatch (ns , "config-patch-1" ),
1649
+ fillData [* specs.ConfigPatchSpec ](data1 , disabled ),
1650
+ checkCompressed [string , * specs.ConfigPatchSpec ](encoded1 ),
1651
+ ),
1652
+ startMigration (
1653
+ ctx ,
1654
+ suite .T (),
1655
+ suite .state ,
1656
+ omni .NewClusterMachineConfig (ns , "machine-config-1" ),
1657
+ fillData [* specs.ClusterMachineConfigSpec ](data1 , disabled ),
1658
+ checkCompressed [[]byte , * specs.ClusterMachineConfigSpec ](encoded1 ),
1659
+ ),
1660
+ startMigration (
1661
+ ctx ,
1662
+ suite .T (),
1663
+ suite .state ,
1664
+ omni .NewRedactedClusterMachineConfig (ns , "redacted-machine-config-1" ),
1665
+ fillData [* specs.RedactedClusterMachineConfigSpec ](data1 , disabled ),
1666
+ checkCompressed [string , * specs.RedactedClusterMachineConfigSpec ](encoded1 ),
1667
+ ),
1668
+ startMigration (
1669
+ ctx ,
1670
+ suite .T (),
1671
+ suite .state ,
1672
+ omni .NewConfigPatch (ns , "config-patch-2" ),
1673
+ fillData [* specs.ConfigPatchSpec ](data2 , disabled ),
1674
+ checkCompressed [string , * specs.ConfigPatchSpec ](encoded2 ),
1675
+ ),
1676
+ startMigration (
1677
+ ctx ,
1678
+ suite .T (),
1679
+ suite .state ,
1680
+ omni .NewClusterMachineConfig (ns , "machine-config-2" ),
1681
+ fillData [* specs.ClusterMachineConfigSpec ](data2 , disabled ),
1682
+ checkCompressed [[]byte , * specs.ClusterMachineConfigSpec ](encoded2 ),
1683
+ ),
1684
+ startMigration (
1685
+ ctx ,
1686
+ suite .T (),
1687
+ suite .state ,
1688
+ omni .NewClusterMachineConfigPatches (ns , "cluster-machine-config-patches-1" ),
1689
+ func (t * testing.T , spec * omni.ClusterMachineConfigPatchesSpec ) {
1690
+ require .NoError (t , spec .Value .SetUncompressedPatches ([]string {data1 , data2 }, disabled ))
1691
+ },
1692
+ func (t * assert.Assertions , spec * omni.ClusterMachineConfigPatchesSpec ) {
1693
+ uncompressed := spec .Value .GetPatches ()
1694
+ t .Empty (uncompressed )
1695
+
1696
+ patches := spec .Value .GetCompressedPatches ()
1697
+ t .NotEmpty (patches )
1698
+
1699
+ for i , data := range [][]byte {encoded1 , encoded2 } {
1700
+ t .Equalf (data , patches [i ], "%x != %x" , data , patches [i ])
1701
+ }
1702
+ },
1703
+ ),
1704
+ startMigration (
1705
+ ctx ,
1706
+ suite .T (),
1707
+ suite .state ,
1708
+ omni .NewClusterMachineConfigPatches (ns , "cluster-machine-config-patches-2" ),
1709
+ func (t * testing.T , spec * omni.ClusterMachineConfigPatchesSpec ) {
1710
+ require .NoError (t , spec .Value .SetUncompressedPatches ([]string {data2 , data1 }, disabled ))
1711
+ },
1712
+ func (t * assert.Assertions , spec * omni.ClusterMachineConfigPatchesSpec ) {
1713
+ uncompressed := spec .Value .GetPatches ()
1714
+ t .Empty (uncompressed )
1715
+
1716
+ patches := spec .Value .GetCompressedPatches ()
1717
+ t .NotEmpty (patches )
1718
+
1719
+ for i , data := range [][]byte {encoded2 , encoded1 } {
1720
+ t .Equalf (data , patches [i ], "%x != %x" , data , patches [i ])
1721
+ }
1722
+ },
1723
+ ),
1724
+ }
1725
+
1726
+ require .NoError (suite .T (), suite .manager .Run (ctx , migration .WithFilter (filterWith ("compressMachineConfigsAndPatches" ))))
1727
+
1728
+ for _ , check := range checkMigrations {
1729
+ check (suite .T ())
1730
+ }
1731
+ }
1732
+
1733
+ func startMigration [
1734
+ R interface {
1735
+ generic.ResourceWithRD
1736
+ TypedSpec () * protobuf.ResourceSpec [T , S ]
1737
+ },
1738
+ T any ,
1739
+ S protobuf.Spec [T ],
1740
+ ](
1741
+ ctx context.Context ,
1742
+ t * testing.T ,
1743
+ st state.State ,
1744
+ res R ,
1745
+ fill func (t * testing.T , spec * protobuf.ResourceSpec [T , S ]),
1746
+ check func (t * assert.Assertions , spec * protobuf.ResourceSpec [T , S ]),
1747
+ ) func (t * testing.T ) {
1748
+ fill (t , res .TypedSpec ())
1749
+
1750
+ require .NoError (t , st .Create (ctx , res ))
1751
+
1752
+ return func (t * testing.T ) {
1753
+ rtestutils .AssertResource (
1754
+ ctx ,
1755
+ t ,
1756
+ st ,
1757
+ res .Metadata ().ID (),
1758
+ func (found R , assertion * assert.Assertions ) { check (assertion , found .TypedSpec ()) },
1759
+ )
1760
+ }
1761
+ }
1762
+
1763
+ func fillData [
1764
+ S interface {
1765
+ SetUncompressedData (data []byte , opts ... specs.CompressionOption ) error
1766
+ protobuf.Spec [T ]
1767
+ },
1768
+ T any ,
1769
+ ](data string , opts ... specs.CompressionOption ) func (t * testing.T , spec * protobuf.ResourceSpec [T , S ]) {
1770
+ return func (t * testing.T , spec * protobuf.ResourceSpec [T , S ]) {
1771
+ require .NoError (t , spec .Value .SetUncompressedData ([]byte (data ), opts ... ))
1772
+ }
1773
+ }
1774
+
1775
+ func checkCompressed [
1776
+ D string | []byte ,
1777
+ S interface {
1778
+ GetData () D
1779
+ GetCompressedData () []byte
1780
+ protobuf.Spec [T ]
1781
+ },
1782
+ T any ,
1783
+ ](data []byte ) func (t * assert.Assertions , spec * protobuf.ResourceSpec [T , S ]) {
1784
+ return func (t * assert.Assertions , spec * protobuf.ResourceSpec [T , S ]) {
1785
+ uncompressed := spec .Value .GetData ()
1786
+ t .Empty (uncompressed )
1787
+
1788
+ result := spec .Value .GetCompressedData ()
1789
+ t .NotEmpty (result )
1790
+ t .Equalf (data , result , "%x != %x" , data , result )
1791
+ }
1792
+ }
1793
+
1655
1794
func TestMigrationSuite (t * testing.T ) {
1656
1795
t .Parallel ()
1657
1796
1658
1797
suite .Run (t , new (MigrationSuite ))
1659
1798
}
1799
+
1800
+ func filterWith (vals ... string ) func (string ) bool {
1801
+ return func (cur string ) bool {
1802
+ for _ , val := range vals {
1803
+ if cur == val {
1804
+ return true
1805
+ }
1806
+ }
1807
+
1808
+ return false
1809
+ }
1810
+ }
0 commit comments