github.com/juju/juju@v0.0.0-20240430160146-1752b71fcf00/state/migration_internal_test.go (about) 1 // Copyright 2015 Canonical Ltd. 2 // Licensed under the AGPLv3, see LICENCE file for details. 3 4 package state 5 6 import ( 7 "github.com/juju/charm/v12" 8 "github.com/juju/collections/set" 9 gc "gopkg.in/check.v1" 10 11 "github.com/juju/juju/testing" 12 ) 13 14 type MigrationSuite struct{} 15 16 var _ = gc.Suite(&MigrationSuite{}) 17 18 func (s *MigrationSuite) TestKnownCollections(c *gc.C) { 19 completedCollections := set.NewStrings( 20 annotationsC, 21 blocksC, 22 cloudimagemetadataC, 23 constraintsC, 24 modelsC, 25 modelUsersC, 26 modelUserLastConnectionC, 27 permissionsC, 28 settingsC, 29 generationsC, 30 sequenceC, 31 sshHostKeysC, 32 statusesC, 33 statusesHistoryC, 34 35 // machine 36 instanceDataC, 37 machineUpgradeSeriesLocksC, 38 machinesC, 39 openedPortsC, 40 41 // application / unit 42 applicationsC, 43 unitsC, 44 meterStatusC, // red / green status for metrics of units 45 payloadsC, 46 resourcesC, 47 48 // relation 49 relationsC, 50 relationScopesC, 51 52 // networking 53 endpointBindingsC, 54 ipAddressesC, 55 spacesC, 56 linkLayerDevicesC, 57 subnetsC, 58 59 // storage 60 blockDevicesC, 61 62 // cloudimagemetadata 63 cloudimagemetadataC, 64 65 // actions 66 actionsC, 67 operationsC, 68 69 // storage 70 filesystemsC, 71 filesystemAttachmentsC, 72 storageAttachmentsC, 73 storageConstraintsC, 74 storageInstancesC, 75 volumesC, 76 volumeAttachmentsC, 77 78 // caas 79 podSpecsC, 80 cloudContainersC, 81 cloudServicesC, 82 deviceConstraintsC, 83 84 // crossmodelrelations 85 remoteApplicationsC, 86 applicationOffersC, 87 offerConnectionsC, 88 relationNetworksC, 89 remoteEntitiesC, 90 externalControllersC, 91 92 // secrets 93 secretMetadataC, 94 secretRevisionsC, 95 secretRotateC, 96 secretConsumersC, 97 secretRemoteConsumersC, 98 secretPermissionsC, 99 ) 100 101 ignoredCollections := set.NewStrings( 102 // Precheck ensures that there are no cleanup docs or pending 103 // machine removals. 104 cleanupsC, 105 machineRemovalsC, 106 // The autocert cache is non-critical. After migration 107 // you'll just need to acquire new certificates. 108 autocertCacheC, 109 // We don't export the controller model at this stage. 110 controllersC, 111 controllerNodesC, 112 // Clouds aren't migrated. They must exist in the 113 // target controller already. 114 cloudsC, 115 // Cloud credentials aren't migrated. They must exist in the 116 // target controller already. 117 cloudCredentialsC, 118 // Users aren't migrated. 119 usersC, 120 userLastLoginC, 121 // Controller users contain extra data about users therefore 122 // are not migrated either. 123 controllerUsersC, 124 // userenvnameC is just to provide a unique key constraint. 125 usermodelnameC, 126 // Metrics aren't migrated. 127 metricsC, 128 // reference counts are implementation details that should be 129 // reconstructed on the other side. 130 refcountsC, 131 globalRefcountsC, 132 // upgradeInfoC is used to coordinate upgrades and schema migrations, 133 // and aren't needed for model migrations. 134 upgradeInfoC, 135 // Not exported, but the tools will possibly need to be either bundled 136 // with the representation or sent separately. 137 toolsmetadataC, 138 // Bakery storage items are non-critical. We store root keys for 139 // temporary credentials in there; after migration you'll just have 140 // to log back in. 141 bakeryStorageItemsC, 142 // Transaction stuff. 143 "txns", 144 "txns.log", 145 "sstxns.log", 146 147 // We don't import any of the migration collections. 148 migrationsC, 149 migrationsStatusC, 150 migrationsActiveC, 151 migrationsMinionSyncC, 152 153 // The container ref document is primarily there to keep track 154 // of a particular machine's containers. The migration format 155 // uses object containment for this purpose. 156 containerRefsC, 157 // The min units collection is only used to trigger a watcher 158 // in order to have the application add or remove units if the minimum 159 // number of units is changed. The Application doc has all we need 160 // for migratino. 161 minUnitsC, 162 // This is a transitory collection of units that need to be assigned 163 // to machines. 164 assignUnitC, 165 166 // The model entity references collection will be repopulated 167 // after importing the model. It does not need to be migrated 168 // separately. 169 modelEntityRefsC, 170 171 // This is marked as deprecated, and should probably be removed. 172 actionresultsC, 173 174 // These are recreated whilst migrating other network entities. 175 providerIDsC, 176 177 // Recreated whilst migrating actions. 178 actionNotificationsC, 179 180 // Global settings store controller specific configuration settings 181 // and are not to be migrated. 182 globalSettingsC, 183 184 // There is a precheck to ensure that there are no pending reboots 185 // for the model being migrated, and as such, there is no need to 186 // migrate that information. 187 rebootC, 188 189 // Charms are added into the migrated model during the binary transfer 190 // phase after the initial model migration. 191 charmsC, 192 193 // Metrics manager maintains controller specific state relating to 194 // the store and forward of charm metrics. Nothing to migrate here. 195 metricsManagerC, 196 197 // The global clock is not migrated; each controller has its own 198 // independent global clock. 199 globalClockC, 200 201 // Volume attachment plans are ignored if missing. A missing collection 202 // simply defaults to the old code path. 203 volumeAttachmentPlanC, 204 205 // Resources are transferred separately 206 "storedResources", 207 208 // Unit state entries will be automatically created when the 209 // operator framework code mutates the state for the charm 210 // running within a unit. This is a new feature that is not 211 // backwards compatible with older controllers. 212 unitStatesC, 213 214 // Secret backends are per controller. 215 secretBackendsC, 216 secretBackendsRotateC, 217 ) 218 219 // THIS SET WILL BE REMOVED WHEN MIGRATIONS ARE COMPLETE 220 todoCollections := set.NewStrings( 221 dockerResourcesC, 222 ) 223 224 modelCollections := set.NewStrings() 225 for name := range allCollections() { 226 modelCollections.Add(name) 227 } 228 229 known := completedCollections.Union(ignoredCollections) 230 231 remainder := modelCollections.Difference(known) 232 remainder = remainder.Difference(todoCollections) 233 234 // If this test fails, it means that a new collection has been added 235 // but migrations for it has not been done. This is a Bad Thing™. 236 // Beware, if your collection is something controller-related it might 237 // not need migration (such as Users or ControllerUsers) in that 238 // case they only need to be accounted for among the ignored collections. 239 c.Assert(remainder, gc.HasLen, 0) 240 } 241 242 func (s *MigrationSuite) TestModelDocFields(c *gc.C) { 243 fields := set.NewStrings( 244 // UUID and Name are constructed from the model config. 245 "UUID", 246 "Name", 247 // Life will always be alive, or we won't be migrating. 248 "Life", 249 // ForceDestroyed is only relevant for models that are being 250 // removed. 251 "ForceDestroyed", 252 // DestroyTimeout is only relevant for models that are being 253 // removed. 254 "DestroyTimeout", 255 // ControllerUUID is recreated when the new model is created 256 // in the new controller (yay name changes). 257 "ControllerUUID", 258 259 "Type", 260 "MigrationMode", 261 "Owner", 262 "Cloud", 263 "CloudRegion", 264 "CloudCredential", 265 "LatestAvailableTools", 266 "SLA", 267 "MeterStatus", 268 "EnvironVersion", 269 "PasswordHash", 270 ) 271 s.AssertExportedFields(c, modelDoc{}, fields) 272 } 273 274 func (s *MigrationSuite) TestUserAccessDocFields(c *gc.C) { 275 fields := set.NewStrings( 276 // ID is the same as UserName (but lowercased) 277 "ID", 278 // ObjectUUID shouldn't be exported, and is inherited 279 // from the model definition. 280 "ObjectUUID", 281 // Tracked fields: 282 "UserName", 283 "DisplayName", 284 "CreatedBy", 285 "DateCreated", 286 ) 287 s.AssertExportedFields(c, userAccessDoc{}, fields) 288 } 289 290 func (s *MigrationSuite) TestPermissionDocFields(c *gc.C) { 291 fields := set.NewStrings( 292 "ID", 293 "ObjectGlobalKey", 294 "SubjectGlobalKey", 295 "Access", 296 ) 297 s.AssertExportedFields(c, permissionDoc{}, fields) 298 } 299 300 func (s *MigrationSuite) TestModelUserLastConnectionDocFields(c *gc.C) { 301 fields := set.NewStrings( 302 // ID is the same as UserName (but lowercased) 303 "ID", 304 // ModelUUID shouldn't be exported, and is inherited 305 // from the model definition. 306 "ModelUUID", 307 // UserName is captured in the migration.User. 308 "UserName", 309 "LastConnection", 310 ) 311 s.AssertExportedFields(c, modelUserLastConnectionDoc{}, fields) 312 } 313 314 func (s *MigrationSuite) TestMachineDocFields(c *gc.C) { 315 ignored := set.NewStrings( 316 // DocID is the model + machine id 317 "DocID", 318 // ID is the machine id 319 "Id", 320 // ModelUUID shouldn't be exported, and is inherited 321 // from the model definition. 322 "ModelUUID", 323 // Life is always alive, confirmed by export precheck. 324 "Life", 325 // ForceDestroyed is only true for dying/dead machines. 326 "ForceDestroyed", 327 // Ignored; they get populated on demand when the agent restarts 328 "AgentStartedAt", 329 "Hostname", 330 ) 331 migrated := set.NewStrings( 332 "Addresses", 333 "Base", 334 "ContainerType", 335 "Jobs", 336 "MachineAddresses", 337 "Nonce", 338 "PasswordHash", 339 "Clean", 340 "Volumes", 341 "Filesystems", 342 "Placement", 343 "PreferredPrivateAddress", 344 "PreferredPublicAddress", 345 "Principals", 346 "SupportedContainers", 347 "SupportedContainersKnown", 348 "Tools", 349 ) 350 s.AssertExportedFields(c, machineDoc{}, migrated.Union(ignored)) 351 } 352 353 func (s *MigrationSuite) TestInstanceDataFields(c *gc.C) { 354 ignored := set.NewStrings( 355 // KeepInstance is only set when a machine is 356 // dying/dead (to be removed). 357 "KeepInstance", 358 ) 359 migrated := set.NewStrings( 360 // DocID is the model + machine id 361 "DocID", 362 "MachineId", 363 // ModelUUID shouldn't be exported, and is inherited 364 // from the model definition. 365 "ModelUUID", 366 367 "InstanceId", 368 "DisplayName", 369 "Arch", 370 "Mem", 371 "RootDisk", 372 "RootDiskSource", 373 "CpuCores", 374 "CpuPower", 375 "Tags", 376 "AvailZone", 377 "VirtType", 378 "CharmProfiles", 379 ) 380 s.AssertExportedFields(c, instanceData{}, migrated.Union(ignored)) 381 } 382 383 func (s *MigrationSuite) TestApplicationDocFields(c *gc.C) { 384 ignored := set.NewStrings( 385 // DocID is the model + name 386 "DocID", 387 // ModelUUID shouldn't be exported, and is inherited 388 // from the model definition. 389 "ModelUUID", 390 // Always alive, not explicitly exported. 391 "Life", 392 // TxnRevno is mgo internals and should not be migrated. 393 "TxnRevno", 394 // UnitCount is handled by the number of units for the exported application. 395 "UnitCount", 396 // RelationCount is handled by the number of times the application name 397 // appears in relation endpoints. 398 "RelationCount", 399 ) 400 migrated := set.NewStrings( 401 "Name", 402 "Subordinate", 403 "CharmURL", 404 "CharmModifiedVersion", 405 "CharmOrigin", 406 "ForceCharm", 407 "Exposed", 408 "ExposedEndpoints", 409 "MinUnits", 410 "MetricCredentials", 411 "PasswordHash", 412 "Tools", 413 "DesiredScale", 414 "Placement", 415 "HasResources", 416 "ProvisioningState", 417 ) 418 s.AssertExportedFields(c, applicationDoc{}, migrated.Union(ignored)) 419 } 420 421 func (s *MigrationSuite) TestUnitDocFields(c *gc.C) { 422 ignored := set.NewStrings( 423 "ModelUUID", 424 "DocID", 425 "Life", 426 // Application is implicit in the migration structure through containment. 427 "Application", 428 // Resolved is not migrated as we check that all is good before we start. 429 "Resolved", 430 // Base and CharmURL also come from the application. 431 "Base", 432 "CharmURL", 433 ) 434 migrated := set.NewStrings( 435 "Name", 436 "Principal", 437 "Subordinates", 438 "StorageAttachmentCount", 439 "MachineId", 440 "Tools", 441 "PasswordHash", 442 ) 443 s.AssertExportedFields(c, unitDoc{}, migrated.Union(ignored)) 444 } 445 446 func (s *MigrationSuite) TestMachinePortRangesDocFields(c *gc.C) { 447 fields := set.NewStrings( 448 // DocID itself isn't migrated 449 "DocID", 450 // ModelUUID shouldn't be exported, and is inherited 451 // from the model definition. 452 "ModelUUID", 453 // MachineID is implicit in the migration structure through containment. 454 "MachineID", 455 "UnitRanges", 456 // TxnRevno isn't migrated. 457 "TxnRevno", 458 ) 459 s.AssertExportedFields(c, machinePortRangesDoc{}, fields) 460 } 461 462 func (s *MigrationSuite) TestMeterStatusDocFields(c *gc.C) { 463 fields := set.NewStrings( 464 // DocID itself isn't migrated 465 "DocID", 466 // ModelUUID shouldn't be exported, and is inherited 467 // from the model definition. 468 "ModelUUID", 469 "Code", 470 "Info", 471 ) 472 s.AssertExportedFields(c, meterStatusDoc{}, fields) 473 } 474 475 func (s *MigrationSuite) TestRelationDocFields(c *gc.C) { 476 fields := set.NewStrings( 477 // DocID itself isn't migrated 478 "DocID", 479 // ModelUUID shouldn't be exported, and is inherited 480 // from the model definition. 481 "ModelUUID", 482 "Key", 483 "Id", 484 "Endpoints", 485 "Suspended", 486 "SuspendedReason", 487 // Life isn't exported, only alive. 488 "Life", 489 // UnitCount isn't explicitly exported, but defined by the stored 490 // unit settings data for the relation endpoint. 491 "UnitCount", 492 ) 493 s.AssertExportedFields(c, relationDoc{}, fields) 494 // We also need to check the Endpoint and nested charm.Relation field. 495 endpointFields := set.NewStrings("ApplicationName", "Relation") 496 s.AssertExportedFields(c, Endpoint{}, endpointFields) 497 charmRelationFields := set.NewStrings( 498 "Name", 499 "Role", 500 "Interface", 501 "Optional", 502 "Limit", 503 "Scope", 504 ) 505 s.AssertExportedFields(c, charm.Relation{}, charmRelationFields) 506 } 507 508 func (s *MigrationSuite) TestRelationScopeDocFields(c *gc.C) { 509 fields := set.NewStrings( 510 // DocID itself isn't migrated 511 "DocID", 512 // ModelUUID shouldn't be exported, and is inherited 513 // from the model definition. 514 "ModelUUID", 515 "Key", 516 // Departing isn't exported as we only deal with live, stable systems. 517 "Departing", 518 ) 519 s.AssertExportedFields(c, relationScopeDoc{}, fields) 520 } 521 522 func (s *MigrationSuite) TestAnnotatorDocFields(c *gc.C) { 523 fields := set.NewStrings( 524 // ModelUUID shouldn't be exported, and is inherited 525 // from the model definition. 526 "ModelUUID", 527 "GlobalKey", 528 "Tag", 529 "Annotations", 530 ) 531 s.AssertExportedFields(c, annotatorDoc{}, fields) 532 } 533 534 func (s *MigrationSuite) TestBlockDocFields(c *gc.C) { 535 ignored := set.NewStrings( 536 // The doc id is a sequence value that has no meaning. 537 // It really doesn't need to be a sequence. 538 "DocID", 539 // ModelUUID shouldn't be exported, and is inherited 540 // from the model definition. 541 "ModelUUID", 542 // Tag is just string representation of the model tag, 543 // which also contains the model-uuid. 544 "Tag", 545 ) 546 migrated := set.NewStrings( 547 "Type", 548 "Message", 549 ) 550 fields := migrated.Union(ignored) 551 s.AssertExportedFields(c, blockDoc{}, fields) 552 } 553 554 func (s *MigrationSuite) TestSequenceDocFields(c *gc.C) { 555 fields := set.NewStrings( 556 // ModelUUID shouldn't be exported, and is inherited 557 // from the model definition. 558 "ModelUUID", 559 "DocID", 560 "Name", 561 "Counter", 562 ) 563 s.AssertExportedFields(c, sequenceDoc{}, fields) 564 } 565 566 func (s *MigrationSuite) TestConstraintsDocFields(c *gc.C) { 567 fields := set.NewStrings( 568 // ModelUUID shouldn't be exported, and is inherited 569 // from the model definition. 570 "ModelUUID", 571 "DocID", 572 "Arch", 573 "CpuCores", 574 "CpuPower", 575 "Mem", 576 "RootDisk", 577 "RootDiskSource", 578 "InstanceRole", 579 "InstanceType", 580 "Container", 581 "Tags", 582 "Spaces", 583 "VirtType", 584 "Zones", 585 "AllocatePublicIP", 586 "ImageID", 587 ) 588 s.AssertExportedFields(c, constraintsDoc{}, fields) 589 } 590 591 func (s *MigrationSuite) TestHistoricalStatusDocFields(c *gc.C) { 592 fields := set.NewStrings( 593 // ModelUUID shouldn't be exported, and is inherited 594 // from the model definition. 595 "ModelUUID", 596 "GlobalKey", 597 "Status", 598 "StatusInfo", 599 "StatusData", 600 "Updated", 601 ) 602 s.AssertExportedFields(c, historicalStatusDoc{}, fields) 603 } 604 605 func (s *MigrationSuite) TestSpaceDocFields(c *gc.C) { 606 ignored := set.NewStrings( 607 "DocId", 608 // Always alive, not explicitly exported. 609 "Life", 610 ) 611 migrated := set.NewStrings( 612 "Id", 613 "Name", 614 "IsPublic", 615 "ProviderId", 616 ) 617 s.AssertExportedFields(c, spaceDoc{}, migrated.Union(ignored)) 618 } 619 620 func (s *MigrationSuite) TestBlockDeviceFields(c *gc.C) { 621 ignored := set.NewStrings( 622 "DocID", 623 "ModelUUID", 624 // We manage machine through containment. 625 "Machine", 626 ) 627 migrated := set.NewStrings( 628 "BlockDevices", 629 ) 630 s.AssertExportedFields(c, blockDevicesDoc{}, migrated.Union(ignored)) 631 // The meat is in the type stored in "BlockDevices". 632 migrated = set.NewStrings( 633 "DeviceName", 634 "DeviceLinks", 635 "Label", 636 "UUID", 637 "HardwareId", 638 "WWN", 639 "BusAddress", 640 "Size", 641 "FilesystemType", 642 "InUse", 643 "MountPoint", 644 "SerialId", 645 ) 646 s.AssertExportedFields(c, BlockDeviceInfo{}, migrated) 647 } 648 649 func (s *MigrationSuite) TestSubnetDocFields(c *gc.C) { 650 ignored := set.NewStrings( 651 // DocID is the model + name 652 "DocID", 653 // TxnRevno is mgo internals and should not be migrated. 654 "TxnRevno", 655 // ModelUUID shouldn't be exported, and is inherited 656 // from the model definition. 657 "ModelUUID", 658 // Always alive, not explicitly exported. 659 "Life", 660 ) 661 migrated := set.NewStrings( 662 "CIDR", 663 "ID", 664 "VLANTag", 665 "SpaceID", 666 "ProviderId", 667 "AvailabilityZones", 668 "ProviderNetworkId", 669 "FanLocalUnderlay", 670 "FanOverlay", 671 "IsPublic", 672 ) 673 s.AssertExportedFields(c, subnetDoc{}, migrated.Union(ignored)) 674 } 675 676 func (s *MigrationSuite) TestIPAddressDocFields(c *gc.C) { 677 ignored := set.NewStrings( 678 "DocID", 679 "ModelUUID", 680 ) 681 migrated := set.NewStrings( 682 "DeviceName", 683 "MachineID", 684 "DNSSearchDomains", 685 "GatewayAddress", 686 "IsDefaultGateway", 687 "ProviderID", 688 "ProviderNetworkID", 689 "ProviderSubnetID", 690 "DNSServers", 691 "SubnetCIDR", 692 "ConfigMethod", 693 "Value", 694 "Origin", 695 "IsShadow", 696 "IsSecondary", 697 ) 698 s.AssertExportedFields(c, ipAddressDoc{}, migrated.Union(ignored)) 699 } 700 701 func (s *MigrationSuite) TestLinkLayerDeviceDocFields(c *gc.C) { 702 ignored := set.NewStrings( 703 "ModelUUID", 704 "DocID", 705 ) 706 migrated := set.NewStrings( 707 "MachineID", 708 "ProviderID", 709 "Name", 710 "MTU", 711 "Type", 712 "MACAddress", 713 "IsAutoStart", 714 "IsUp", 715 "ParentName", 716 "VirtualPortType", 717 ) 718 s.AssertExportedFields(c, linkLayerDeviceDoc{}, migrated.Union(ignored)) 719 } 720 721 func (s *MigrationSuite) TestSSHHostKeyDocFields(c *gc.C) { 722 ignored := set.NewStrings() 723 migrated := set.NewStrings( 724 "Keys", 725 ) 726 s.AssertExportedFields(c, sshHostKeysDoc{}, migrated.Union(ignored)) 727 } 728 729 func (s *MigrationSuite) TestActionDocFields(c *gc.C) { 730 ignored := set.NewStrings( 731 "ModelUUID", 732 ) 733 migrated := set.NewStrings( 734 "DocId", 735 "Receiver", 736 "Name", 737 "Operation", 738 "Enqueued", 739 "Started", 740 "Completed", 741 "Parameters", 742 "Results", 743 "Message", 744 "Status", 745 "Logs", 746 "Parallel", 747 "ExecutionGroup", 748 ) 749 s.AssertExportedFields(c, actionDoc{}, migrated.Union(ignored)) 750 } 751 752 func (s *MigrationSuite) TestOperationDocFields(c *gc.C) { 753 ignored := set.NewStrings( 754 "ModelUUID", 755 "CompleteTaskCount", 756 ) 757 migrated := set.NewStrings( 758 "DocId", 759 "Summary", 760 "Enqueued", 761 "Started", 762 "Completed", 763 "Status", 764 "Fail", 765 "SpawnedTaskCount", 766 ) 767 s.AssertExportedFields(c, operationDoc{}, migrated.Union(ignored)) 768 } 769 770 func (s *MigrationSuite) TestVolumeDocFields(c *gc.C) { 771 ignored := set.NewStrings( 772 "ModelUUID", 773 "DocID", 774 "Life", 775 "HostId", // recreated from pool properties 776 "Releasing", // only when dying; can't migrate dying storage 777 ) 778 migrated := set.NewStrings( 779 "Name", 780 "StorageId", 781 "AttachmentCount", // through count of attachment instances 782 "Info", 783 "Params", 784 ) 785 s.AssertExportedFields(c, volumeDoc{}, migrated.Union(ignored)) 786 // The info and params fields ar structs. 787 s.AssertExportedFields(c, VolumeInfo{}, set.NewStrings( 788 "HardwareId", "WWN", "Size", "Pool", "VolumeId", "Persistent")) 789 s.AssertExportedFields(c, VolumeParams{}, set.NewStrings( 790 "Size", "Pool")) 791 } 792 793 func (s *MigrationSuite) TestVolumeAttachmentDocFields(c *gc.C) { 794 ignored := set.NewStrings( 795 "ModelUUID", 796 "DocID", 797 "Life", 798 ) 799 migrated := set.NewStrings( 800 "Volume", 801 "Host", 802 "Info", 803 "Params", 804 ) 805 s.AssertExportedFields(c, volumeAttachmentDoc{}, migrated.Union(ignored)) 806 // The info and params fields ar structs. 807 s.AssertExportedFields(c, VolumeAttachmentInfo{}, set.NewStrings( 808 "DeviceName", "DeviceLink", "BusAddress", "ReadOnly", "PlanInfo")) 809 s.AssertExportedFields(c, VolumeAttachmentParams{}, set.NewStrings( 810 "ReadOnly")) 811 } 812 813 func (s *MigrationSuite) TestFilesystemDocFields(c *gc.C) { 814 ignored := set.NewStrings( 815 "ModelUUID", 816 "DocID", 817 "Life", 818 "HostId", // recreated from pool properties 819 "Releasing", // only when dying; can't migrate dying storage 820 ) 821 migrated := set.NewStrings( 822 "FilesystemId", 823 "StorageId", 824 "VolumeId", 825 "AttachmentCount", // through count of attachment instances 826 "Info", 827 "Params", 828 ) 829 s.AssertExportedFields(c, filesystemDoc{}, migrated.Union(ignored)) 830 // The info and params fields ar structs. 831 s.AssertExportedFields(c, FilesystemInfo{}, set.NewStrings( 832 "Size", "Pool", "FilesystemId")) 833 s.AssertExportedFields(c, FilesystemParams{}, set.NewStrings( 834 "Size", "Pool")) 835 } 836 837 func (s *MigrationSuite) TestFilesystemAttachmentDocFields(c *gc.C) { 838 ignored := set.NewStrings( 839 "ModelUUID", 840 "DocID", 841 "Life", 842 ) 843 migrated := set.NewStrings( 844 "Filesystem", 845 "Host", 846 "Info", 847 "Params", 848 ) 849 s.AssertExportedFields(c, filesystemAttachmentDoc{}, migrated.Union(ignored)) 850 // The info and params fields ar structs. 851 s.AssertExportedFields(c, FilesystemAttachmentInfo{}, set.NewStrings( 852 "MountPoint", "ReadOnly")) 853 s.AssertExportedFields(c, FilesystemAttachmentParams{}, set.NewStrings( 854 "Location", "ReadOnly")) 855 } 856 857 func (s *MigrationSuite) TestStorageInstanceDocFields(c *gc.C) { 858 ignored := set.NewStrings( 859 "ModelUUID", 860 "DocID", 861 "Life", 862 "Releasing", // only when dying; can't migrate dying storage 863 ) 864 migrated := set.NewStrings( 865 "Id", 866 "Kind", 867 "Owner", 868 "StorageName", 869 "AttachmentCount", // through count of attachment instances 870 "Constraints", 871 ) 872 s.AssertExportedFields(c, storageInstanceDoc{}, migrated.Union(ignored)) 873 } 874 875 func (s *MigrationSuite) TestStorageAttachmentDocFields(c *gc.C) { 876 ignored := set.NewStrings( 877 "ModelUUID", 878 "DocID", 879 "Life", 880 ) 881 migrated := set.NewStrings( 882 "Unit", 883 "StorageInstance", 884 ) 885 s.AssertExportedFields(c, storageAttachmentDoc{}, migrated.Union(ignored)) 886 } 887 888 func (s *MigrationSuite) TestStorageConstraintsDocFields(c *gc.C) { 889 ignored := set.NewStrings( 890 "ModelUUID", 891 "DocID", 892 ) 893 migrated := set.NewStrings( 894 "Constraints", 895 ) 896 s.AssertExportedFields(c, storageConstraintsDoc{}, migrated.Union(ignored)) 897 } 898 899 func (s *MigrationSuite) TestPayloadDocFields(c *gc.C) { 900 definedThroughContainment := set.NewStrings( 901 "UnitID", 902 "MachineID", 903 ) 904 migrated := set.NewStrings( 905 "Name", 906 "Type", 907 "RawID", 908 "State", 909 "Labels", 910 ) 911 s.AssertExportedFields(c, payloadDoc{}, migrated.Union(definedThroughContainment)) 912 } 913 914 func (s *MigrationSuite) TestEndpointBindingFields(c *gc.C) { 915 definedThroughContainment := set.NewStrings( 916 "DocID", 917 ) 918 migrated := set.NewStrings( 919 "Bindings", 920 ) 921 ignored := set.NewStrings( 922 "TxnRevno", 923 ) 924 fields := definedThroughContainment.Union(migrated).Union(ignored) 925 s.AssertExportedFields(c, endpointBindingsDoc{}, fields) 926 } 927 928 func (s *MigrationSuite) AssertExportedFields(c *gc.C, doc interface{}, fields set.Strings) { 929 expected := testing.GetExportedFields(doc) 930 unknown := expected.Difference(fields) 931 removed := fields.Difference(expected) 932 // If this test fails, it means that extra fields have been added to the 933 // doc without thinking about the migration implications. 934 c.Check(unknown, gc.HasLen, 0) 935 c.Assert(removed, gc.HasLen, 0) 936 } 937 938 func (s *MigrationSuite) TestSecretMetadataDocFields(c *gc.C) { 939 ignored := set.NewStrings( 940 "DocID", 941 942 // These are not exported but instead 943 // calculated from the revisions. 944 "LatestRevision", 945 "LatestExpireTime", 946 ) 947 migrated := set.NewStrings( 948 "Version", 949 "OwnerTag", 950 "Description", 951 "Label", 952 "RotatePolicy", 953 "AutoPrune", 954 "CreateTime", 955 "UpdateTime", 956 ) 957 s.AssertExportedFields(c, secretMetadataDoc{}, migrated.Union(ignored)) 958 } 959 960 func (s *MigrationSuite) TestSecretRevisionDocFields(c *gc.C) { 961 ignored := set.NewStrings( 962 "DocID", 963 "TxnRevno", 964 ) 965 migrated := set.NewStrings( 966 "Revision", 967 "CreateTime", 968 "UpdateTime", 969 "ExpireTime", 970 "Obsolete", 971 "ValueRef", 972 "Data", 973 "OwnerTag", 974 "PendingDelete", 975 ) 976 s.AssertExportedFields(c, secretRevisionDoc{}, migrated.Union(ignored)) 977 } 978 979 func (s *MigrationSuite) TestSecretRotationDocFields(c *gc.C) { 980 ignored := set.NewStrings( 981 "DocID", 982 "TxnRevno", 983 ) 984 migrated := set.NewStrings( 985 "NextRotateTime", 986 "OwnerTag", 987 ) 988 s.AssertExportedFields(c, secretRotationDoc{}, migrated.Union(ignored)) 989 } 990 991 func (s *MigrationSuite) TestSecretConsumerDocFields(c *gc.C) { 992 ignored := set.NewStrings( 993 "DocID", 994 ) 995 migrated := set.NewStrings( 996 "ConsumerTag", 997 "Label", 998 "CurrentRevision", 999 "LatestRevision", 1000 ) 1001 s.AssertExportedFields(c, secretConsumerDoc{}, migrated.Union(ignored)) 1002 }