@intentius/chant-lexicon-gcp 0.41.20 → 0.44.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/composites/index.d.ts +2 -0
- package/dist/composites/index.d.ts.map +1 -1
- package/dist/composites/landing-zone.d.ts +67 -0
- package/dist/composites/landing-zone.d.ts.map +1 -0
- package/dist/deep-observe-hooks.d.ts +16 -3
- package/dist/deep-observe-hooks.d.ts.map +1 -1
- package/dist/deep-observe.d.ts +68 -139
- package/dist/deep-observe.d.ts.map +1 -1
- package/dist/describe-resources.d.ts +27 -3
- package/dist/describe-resources.d.ts.map +1 -1
- package/dist/governance.d.ts +101 -0
- package/dist/governance.d.ts.map +1 -0
- package/dist/index.d.ts +4 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/integrity.json +5 -2
- package/dist/lint/audit-catalog.d.ts.map +1 -1
- package/dist/lint/post-synth/index.d.ts.map +1 -1
- package/dist/lint/post-synth/wgc501.d.ts +18 -0
- package/dist/lint/post-synth/wgc501.d.ts.map +1 -0
- package/dist/lint/post-synth/wgc502.d.ts +10 -0
- package/dist/lint/post-synth/wgc502.d.ts.map +1 -0
- package/dist/lint/post-synth/wgc503.d.ts +11 -0
- package/dist/lint/post-synth/wgc503.d.ts.map +1 -0
- package/dist/manifest.json +1 -1
- package/dist/okf/index.md +519 -0
- package/dist/okf/rules/WGC001.md +15 -0
- package/dist/okf/rules/WGC002.md +16 -0
- package/dist/okf/rules/WGC003.md +15 -0
- package/dist/okf/rules/WGC101.md +16 -0
- package/dist/okf/rules/WGC102.md +15 -0
- package/dist/okf/rules/WGC103.md +15 -0
- package/dist/okf/rules/WGC104.md +15 -0
- package/dist/okf/rules/WGC105.md +15 -0
- package/dist/okf/rules/WGC106.md +15 -0
- package/dist/okf/rules/WGC107.md +15 -0
- package/dist/okf/rules/WGC108.md +15 -0
- package/dist/okf/rules/WGC109.md +11 -0
- package/dist/okf/rules/WGC110.md +15 -0
- package/dist/okf/rules/WGC111.md +15 -0
- package/dist/okf/rules/WGC112.md +15 -0
- package/dist/okf/rules/WGC113.md +16 -0
- package/dist/okf/rules/WGC201.md +15 -0
- package/dist/okf/rules/WGC202.md +11 -0
- package/dist/okf/rules/WGC203.md +11 -0
- package/dist/okf/rules/WGC204.md +15 -0
- package/dist/okf/rules/WGC301.md +15 -0
- package/dist/okf/rules/WGC302.md +15 -0
- package/dist/okf/rules/WGC303.md +15 -0
- package/dist/okf/rules/WGC401.md +15 -0
- package/dist/okf/rules/WGC402.md +15 -0
- package/dist/okf/rules/WGC403.md +15 -0
- package/dist/okf/rules/WGC501.md +15 -0
- package/dist/okf/rules/WGC502.md +11 -0
- package/dist/okf/rules/WGC503.md +15 -0
- package/dist/okf/types/API.md +21 -0
- package/dist/okf/types/APIConfig.md +15 -0
- package/dist/okf/types/APIQuotaAdjusterSettings.md +15 -0
- package/dist/okf/types/APIQuotaPreference.md +15 -0
- package/dist/okf/types/AccessBoundaryPolicy.md +15 -0
- package/dist/okf/types/AccessLevel.md +15 -0
- package/dist/okf/types/AccessLevelCondition.md +15 -0
- package/dist/okf/types/AccessPolicy.md +15 -0
- package/dist/okf/types/AddonsConfig.md +15 -0
- package/dist/okf/types/AgentPool.md +15 -0
- package/dist/okf/types/AiplatformModel.md +15 -0
- package/dist/okf/types/AistreamsCluster.md +15 -0
- package/dist/okf/types/AlertPolicy.md +15 -0
- package/dist/okf/types/AlloydbBackup.md +15 -0
- package/dist/okf/types/AlloydbCluster.md +15 -0
- package/dist/okf/types/AlloydbInstance.md +15 -0
- package/dist/okf/types/AnalyticsAccount.md +15 -0
- package/dist/okf/types/AndroidApp.md +15 -0
- package/dist/okf/types/AnywhereCache.md +15 -0
- package/dist/okf/types/ApigatewayGateway.md +15 -0
- package/dist/okf/types/ApigeeEnvironment.md +15 -0
- package/dist/okf/types/ApigeeInstance.md +15 -0
- package/dist/okf/types/ApihubDeployment.md +15 -0
- package/dist/okf/types/ApikeysKey.md +15 -0
- package/dist/okf/types/AppConnection.md +15 -0
- package/dist/okf/types/AppConnector.md +15 -0
- package/dist/okf/types/AppGateway.md +15 -0
- package/dist/okf/types/AppProfile.md +15 -0
- package/dist/okf/types/Application.md +15 -0
- package/dist/okf/types/ArtifactRegistryRepository.md +15 -0
- package/dist/okf/types/Assignment.md +15 -0
- package/dist/okf/types/Attestor.md +15 -0
- package/dist/okf/types/AuthorizationPolicy.md +15 -0
- package/dist/okf/types/AuthorizedView.md +15 -0
- package/dist/okf/types/AutokeyConfig.md +15 -0
- package/dist/okf/types/Automation.md +15 -0
- package/dist/okf/types/Autoscaler.md +15 -0
- package/dist/okf/types/AutoscalingPolicy.md +15 -0
- package/dist/okf/types/BQJob.md +15 -0
- package/dist/okf/types/BackendBucket.md +15 -0
- package/dist/okf/types/BackendBucketSignedURLKey.md +15 -0
- package/dist/okf/types/BackendService.md +15 -0
- package/dist/okf/types/BackendServiceSignedURLKey.md +15 -0
- package/dist/okf/types/BackupPlanAssociation.md +15 -0
- package/dist/okf/types/BackupPolicy.md +15 -0
- package/dist/okf/types/BackupdrBackupPlan.md +15 -0
- package/dist/okf/types/BackupdrBackupVault.md +15 -0
- package/dist/okf/types/Batch.md +15 -0
- package/dist/okf/types/BatchJob.md +15 -0
- package/dist/okf/types/BatchTask.md +15 -0
- package/dist/okf/types/BigLakeCatalog.md +15 -0
- package/dist/okf/types/BigLakeDatabase.md +15 -0
- package/dist/okf/types/BigLakeTable.md +15 -0
- package/dist/okf/types/BigQueryDataPolicy.md +15 -0
- package/dist/okf/types/BigQueryDataset.md +15 -0
- package/dist/okf/types/BigQueryExport.md +15 -0
- package/dist/okf/types/BigQueryTable.md +15 -0
- package/dist/okf/types/BigqueryconnectionConnection.md +15 -0
- package/dist/okf/types/BigquerydatatransferConfig.md +15 -0
- package/dist/okf/types/BigqueryreservationReservation.md +15 -0
- package/dist/okf/types/BigtableInstance.md +15 -0
- package/dist/okf/types/BigtableTable.md +15 -0
- package/dist/okf/types/BillingAccount.md +15 -0
- package/dist/okf/types/BinaryauthorizationPolicy.md +15 -0
- package/dist/okf/types/Brand.md +15 -0
- package/dist/okf/types/BtBackup.md +15 -0
- package/dist/okf/types/BtCluster.md +15 -0
- package/dist/okf/types/Bucket.md +15 -0
- package/dist/okf/types/BucketAccessControl.md +15 -0
- package/dist/okf/types/Budget.md +15 -0
- package/dist/okf/types/CAPool.md +15 -0
- package/dist/okf/types/CapacityCommitment.md +15 -0
- package/dist/okf/types/CertificateAuthority.md +15 -0
- package/dist/okf/types/CertificateIssuanceConfig.md +15 -0
- package/dist/okf/types/CertificateMap.md +15 -0
- package/dist/okf/types/CertificateMapEntry.md +15 -0
- package/dist/okf/types/CertificateTemplate.md +15 -0
- package/dist/okf/types/CertificatemanagerCertificate.md +15 -0
- package/dist/okf/types/ClientConnectorService.md +15 -0
- package/dist/okf/types/ClientTLSPolicy.md +15 -0
- package/dist/okf/types/CloudBatchResourceAllowance.md +15 -0
- package/dist/okf/types/CloudFunction.md +15 -0
- package/dist/okf/types/CloudRunJob.md +15 -0
- package/dist/okf/types/CloudRunService.md +15 -0
- package/dist/okf/types/CloudbuildTrigger.md +15 -0
- package/dist/okf/types/ClouddmsPrivateConnection.md +15 -0
- package/dist/okf/types/CloudidentityGroup.md +15 -0
- package/dist/okf/types/CloudidentityMembership.md +15 -0
- package/dist/okf/types/CloudidsEndpoint.md +15 -0
- package/dist/okf/types/CloudschedulerJob.md +15 -0
- package/dist/okf/types/ComposerEnvironment.md +15 -0
- package/dist/okf/types/ComputeAddress.md +15 -0
- package/dist/okf/types/ComputeDisk.md +15 -0
- package/dist/okf/types/ComputeFirewallPolicy.md +15 -0
- package/dist/okf/types/ComputeHealthCheck.md +15 -0
- package/dist/okf/types/ComputeInstance.md +19 -0
- package/dist/okf/types/ComputeNetworkPeering.md +15 -0
- package/dist/okf/types/ComputeNodeGroup.md +15 -0
- package/dist/okf/types/ComputeReservation.md +15 -0
- package/dist/okf/types/ComputeRoute.md +15 -0
- package/dist/okf/types/ComputeSnapshot.md +15 -0
- package/dist/okf/types/ConfigcontrollerInstance.md +15 -0
- package/dist/okf/types/ConnectionProfile.md +15 -0
- package/dist/okf/types/ConnectivityTest.md +15 -0
- package/dist/okf/types/Connector.md +28 -0
- package/dist/okf/types/ConsentStore.md +15 -0
- package/dist/okf/types/ConsumerGroup.md +15 -0
- package/dist/okf/types/ConsumerQuotaOverride.md +15 -0
- package/dist/okf/types/Contact.md +15 -0
- package/dist/okf/types/ContainerattachedCluster.md +15 -0
- package/dist/okf/types/ConversionWorkspace.md +15 -0
- package/dist/okf/types/CryptoKeyVersion.md +15 -0
- package/dist/okf/types/CustomClass.md +15 -0
- package/dist/okf/types/CustomConstraint.md +15 -0
- package/dist/okf/types/CustomRole.md +15 -0
- package/dist/okf/types/CustomTargetType.md +15 -0
- package/dist/okf/types/DICOMStore.md +15 -0
- package/dist/okf/types/DNSAuthorization.md +15 -0
- package/dist/okf/types/DNSManagedZone.md +15 -0
- package/dist/okf/types/DNSRecordSet.md +15 -0
- package/dist/okf/types/Dashboard.md +15 -0
- package/dist/okf/types/DataExchange.md +15 -0
- package/dist/okf/types/DataLabelingJob.md +15 -0
- package/dist/okf/types/DataPolicy.md +15 -0
- package/dist/okf/types/DataStore.md +15 -0
- package/dist/okf/types/DataStoreTargetSite.md +15 -0
- package/dist/okf/types/Database.md +15 -0
- package/dist/okf/types/DatacatalogEntryGroup.md +15 -0
- package/dist/okf/types/DataflowJob.md +15 -0
- package/dist/okf/types/DataformRepository.md +15 -0
- package/dist/okf/types/DatafusionInstance.md +15 -0
- package/dist/okf/types/DataplexEntryGroup.md +15 -0
- package/dist/okf/types/DataplexTask.md +15 -0
- package/dist/okf/types/DataprocCluster.md +15 -0
- package/dist/okf/types/DataprocJob.md +15 -0
- package/dist/okf/types/DataprocNodeGroup.md +15 -0
- package/dist/okf/types/DataprocSession.md +15 -0
- package/dist/okf/types/DatasetAccess.md +15 -0
- package/dist/okf/types/DatastoreIndex.md +15 -0
- package/dist/okf/types/DatastreamPrivateConnection.md +15 -0
- package/dist/okf/types/DatastreamRoute.md +15 -0
- package/dist/okf/types/DefaultObjectAccessControl.md +15 -0
- package/dist/okf/types/DefaultSupportedIDPConfig.md +15 -0
- package/dist/okf/types/DeidentifyTemplate.md +15 -0
- package/dist/okf/types/DeliveryPipeline.md +15 -0
- package/dist/okf/types/DenyPolicy.md +15 -0
- package/dist/okf/types/DeployPolicy.md +15 -0
- package/dist/okf/types/DeploymentResourcePool.md +15 -0
- package/dist/okf/types/DeploymentmanagerDeployment.md +15 -0
- package/dist/okf/types/Device.md +15 -0
- package/dist/okf/types/DeviceRegistry.md +15 -0
- package/dist/okf/types/DevicestreamingSession.md +15 -0
- package/dist/okf/types/DialogflowAgent.md +15 -0
- package/dist/okf/types/DialogflowEntityType.md +15 -0
- package/dist/okf/types/DialogflowIntent.md +15 -0
- package/dist/okf/types/DialogflowcxAgent.md +15 -0
- package/dist/okf/types/DialogflowcxEntityType.md +15 -0
- package/dist/okf/types/DialogflowcxIntent.md +15 -0
- package/dist/okf/types/DiscoveredService.md +15 -0
- package/dist/okf/types/DiscoveredWorkload.md +15 -0
- package/dist/okf/types/DiskResourcePolicyAttachment.md +15 -0
- package/dist/okf/types/DnsPolicy.md +15 -0
- package/dist/okf/types/Document.md +15 -0
- package/dist/okf/types/DomainMapping.md +15 -0
- package/dist/okf/types/EdgeCacheKeyset.md +15 -0
- package/dist/okf/types/EdgeCacheOrigin.md +15 -0
- package/dist/okf/types/EdgeCacheService.md +15 -0
- package/dist/okf/types/EdgecontainerCluster.md +15 -0
- package/dist/okf/types/EdgecontainerNodePool.md +15 -0
- package/dist/okf/types/EdgenetworkNetwork.md +15 -0
- package/dist/okf/types/EndpointAttachment.md +15 -0
- package/dist/okf/types/EndpointPolicy.md +15 -0
- package/dist/okf/types/Engine.md +15 -0
- package/dist/okf/types/Enrollment.md +15 -0
- package/dist/okf/types/Entitlement.md +15 -0
- package/dist/okf/types/Entry.md +15 -0
- package/dist/okf/types/EntryType.md +15 -0
- package/dist/okf/types/Envgroup.md +15 -0
- package/dist/okf/types/EnvgroupAttachment.md +15 -0
- package/dist/okf/types/EventarcChannel.md +15 -0
- package/dist/okf/types/EventarcTrigger.md +15 -0
- package/dist/okf/types/ExampleStore.md +15 -0
- package/dist/okf/types/ExternalAccessRule.md +15 -0
- package/dist/okf/types/ExternalAddress.md +15 -0
- package/dist/okf/types/ExternalVPNGateway.md +15 -0
- package/dist/okf/types/FHIRStore.md +15 -0
- package/dist/okf/types/Feature.md +15 -0
- package/dist/okf/types/FeatureMembership.md +15 -0
- package/dist/okf/types/Featurestore.md +15 -0
- package/dist/okf/types/FeaturestoreEntityType.md +15 -0
- package/dist/okf/types/FeaturestoreEntityTypeFeature.md +15 -0
- package/dist/okf/types/Federation.md +15 -0
- package/dist/okf/types/Feed.md +15 -0
- package/dist/okf/types/Field.md +15 -0
- package/dist/okf/types/FilestoreBackup.md +15 -0
- package/dist/okf/types/FilestoreInstance.md +15 -0
- package/dist/okf/types/FilestoreSnapshot.md +15 -0
- package/dist/okf/types/FirebaseProject.md +15 -0
- package/dist/okf/types/FirebasedatabaseInstance.md +15 -0
- package/dist/okf/types/FirebasehostingChannel.md +15 -0
- package/dist/okf/types/FirestoreBackupSchedule.md +15 -0
- package/dist/okf/types/FirestoreIndex.md +15 -0
- package/dist/okf/types/Firewall.md +15 -0
- package/dist/okf/types/FirewallPolicyAssociation.md +15 -0
- package/dist/okf/types/FirewallPolicyRule.md +15 -0
- package/dist/okf/types/FirewallRule.md +15 -0
- package/dist/okf/types/FlexTemplateJob.md +15 -0
- package/dist/okf/types/FlexibleAppVersion.md +15 -0
- package/dist/okf/types/Flow.md +15 -0
- package/dist/okf/types/FolderFeed.md +15 -0
- package/dist/okf/types/ForwardingRule.md +15 -0
- package/dist/okf/types/Fulfillment.md +15 -0
- package/dist/okf/types/Function.md +15 -0
- package/dist/okf/types/FutureReservation.md +15 -0
- package/dist/okf/types/GCPServiceAccount.md +15 -0
- package/dist/okf/types/GCPUserAccessBinding.md +15 -0
- package/dist/okf/types/GCPolicy.md +15 -0
- package/dist/okf/types/GKECluster.md +15 -0
- package/dist/okf/types/GRPCRoute.md +15 -0
- package/dist/okf/types/GcsFolder.md +15 -0
- package/dist/okf/types/GkebackupBackup.md +15 -0
- package/dist/okf/types/GkebackupBackupPlan.md +15 -0
- package/dist/okf/types/GkehubMembership.md +15 -0
- package/dist/okf/types/GkehubNamespace.md +15 -0
- package/dist/okf/types/GlobalNetworkEndpoint.md +15 -0
- package/dist/okf/types/GlobalNetworkEndpointGroup.md +15 -0
- package/dist/okf/types/GoogleChannelConfig.md +15 -0
- package/dist/okf/types/GuestPolicy.md +15 -0
- package/dist/okf/types/HL7V2Store.md +15 -0
- package/dist/okf/types/HMACKey.md +15 -0
- package/dist/okf/types/HTTPHealthCheck.md +15 -0
- package/dist/okf/types/HTTPRoute.md +15 -0
- package/dist/okf/types/HTTPSHealthCheck.md +15 -0
- package/dist/okf/types/HealthcareDataset.md +15 -0
- package/dist/okf/types/Hub.md +15 -0
- package/dist/okf/types/IAMAuditConfig.md +20 -0
- package/dist/okf/types/IAMPolicy.md +15 -0
- package/dist/okf/types/IAMPolicyMember.md +15 -0
- package/dist/okf/types/IdentityAwareProxyClient.md +15 -0
- package/dist/okf/types/IdentityplatformConfig.md +15 -0
- package/dist/okf/types/Image.md +15 -0
- package/dist/okf/types/ImportJob.md +15 -0
- package/dist/okf/types/InboundSAMLConfig.md +15 -0
- package/dist/okf/types/IndexEndpoint.md +15 -0
- package/dist/okf/types/InspectTemplate.md +15 -0
- package/dist/okf/types/InstanceAttachment.md +15 -0
- package/dist/okf/types/InstanceConfig.md +15 -0
- package/dist/okf/types/InstanceEndpoint.md +15 -0
- package/dist/okf/types/InstanceGroup.md +15 -0
- package/dist/okf/types/InstanceGroupManager.md +15 -0
- package/dist/okf/types/InstanceGroupNamedPort.md +15 -0
- package/dist/okf/types/InstanceTemplate.md +15 -0
- package/dist/okf/types/InterceptDeployment.md +15 -0
- package/dist/okf/types/InterceptEndpointGroup.md +15 -0
- package/dist/okf/types/Interconnect.md +15 -0
- package/dist/okf/types/InterconnectAttachment.md +15 -0
- package/dist/okf/types/InternalRange.md +15 -0
- package/dist/okf/types/JobTrigger.md +15 -0
- package/dist/okf/types/KMSCryptoKey.md +19 -0
- package/dist/okf/types/KMSKeyRing.md +15 -0
- package/dist/okf/types/KeyHandle.md +15 -0
- package/dist/okf/types/KeyRingImportJob.md +15 -0
- package/dist/okf/types/LBRouteExtension.md +15 -0
- package/dist/okf/types/Lake.md +15 -0
- package/dist/okf/types/Lien.md +15 -0
- package/dist/okf/types/Link.md +15 -0
- package/dist/okf/types/Listing.md +15 -0
- package/dist/okf/types/LocationTagBinding.md +15 -0
- package/dist/okf/types/LogBucket.md +15 -0
- package/dist/okf/types/LogExclusion.md +15 -0
- package/dist/okf/types/LogMetric.md +15 -0
- package/dist/okf/types/LogSink.md +15 -0
- package/dist/okf/types/LogView.md +15 -0
- package/dist/okf/types/LogicalView.md +15 -0
- package/dist/okf/types/Machine.md +15 -0
- package/dist/okf/types/MachineImage.md +15 -0
- package/dist/okf/types/ManagedFolder.md +15 -0
- package/dist/okf/types/ManagedSSLCertificate.md +15 -0
- package/dist/okf/types/ManagedkafkaCluster.md +15 -0
- package/dist/okf/types/ManagedkafkaTopic.md +15 -0
- package/dist/okf/types/ManagementServer.md +15 -0
- package/dist/okf/types/MaterializedView.md +15 -0
- package/dist/okf/types/MembershipBinding.md +15 -0
- package/dist/okf/types/MemcacheInstance.md +15 -0
- package/dist/okf/types/MemorystoreInstance.md +15 -0
- package/dist/okf/types/Mesh.md +15 -0
- package/dist/okf/types/MetadataStore.md +15 -0
- package/dist/okf/types/MetastoreBackup.md +15 -0
- package/dist/okf/types/MetastoreService.md +15 -0
- package/dist/okf/types/MetricDescriptor.md +15 -0
- package/dist/okf/types/MigrationJob.md +15 -0
- package/dist/okf/types/MlengineModel.md +15 -0
- package/dist/okf/types/MonGroup.md +15 -0
- package/dist/okf/types/MonService.md +15 -0
- package/dist/okf/types/MonitoredProject.md +15 -0
- package/dist/okf/types/MuteConfig.md +15 -0
- package/dist/okf/types/NATAddress.md +15 -0
- package/dist/okf/types/NetappBackupVault.md +15 -0
- package/dist/okf/types/NetworkAttachment.md +15 -0
- package/dist/okf/types/NetworkEdgeSecurityService.md +15 -0
- package/dist/okf/types/NetworkEndpoint.md +15 -0
- package/dist/okf/types/NetworkEndpointGroup.md +15 -0
- package/dist/okf/types/NetworkFirewallPolicy.md +15 -0
- package/dist/okf/types/NetworkFirewallPolicyAssociation.md +15 -0
- package/dist/okf/types/NetworkFirewallPolicyRule.md +15 -0
- package/dist/okf/types/NetworkPeeringRoutesConfig.md +15 -0
- package/dist/okf/types/NetworkPolicy.md +15 -0
- package/dist/okf/types/NetworkservicesGateway.md +15 -0
- package/dist/okf/types/Node.md +21 -0
- package/dist/okf/types/NodePool.md +15 -0
- package/dist/okf/types/NodeTemplate.md +15 -0
- package/dist/okf/types/Note.md +15 -0
- package/dist/okf/types/NotebookInstance.md +15 -0
- package/dist/okf/types/NotebooksEnvironment.md +15 -0
- package/dist/okf/types/Notification.md +15 -0
- package/dist/okf/types/NotificationChannel.md +15 -0
- package/dist/okf/types/NotificationConfig.md +15 -0
- package/dist/okf/types/OAuthIDPConfig.md +15 -0
- package/dist/okf/types/OSPolicyAssignment.md +15 -0
- package/dist/okf/types/Occurrence.md +15 -0
- package/dist/okf/types/Organization.md +15 -0
- package/dist/okf/types/OrganizationFeed.md +15 -0
- package/dist/okf/types/OrganizationSecurityPolicy.md +15 -0
- package/dist/okf/types/OrganizationSecurityPolicyAssociation.md +15 -0
- package/dist/okf/types/OrganizationSecurityPolicyRule.md +15 -0
- package/dist/okf/types/OrgpolicyPolicy.md +15 -0
- package/dist/okf/types/PacketMirroring.md +15 -0
- package/dist/okf/types/Page.md +15 -0
- package/dist/okf/types/Parameter.md +15 -0
- package/dist/okf/types/ParameterVersion.md +15 -0
- package/dist/okf/types/PartialPolicy.md +15 -0
- package/dist/okf/types/PatchDeployment.md +15 -0
- package/dist/okf/types/PeeredDNSDomain.md +15 -0
- package/dist/okf/types/PerInstanceConfig.md +15 -0
- package/dist/okf/types/PhraseSet.md +15 -0
- package/dist/okf/types/PlatformPolicy.md +15 -0
- package/dist/okf/types/PolicyTag.md +15 -0
- package/dist/okf/types/PrivateCloud.md +15 -0
- package/dist/okf/types/PrivatecaCertificate.md +15 -0
- package/dist/okf/types/Processor.md +15 -0
- package/dist/okf/types/ProcessorDefaultVersion.md +15 -0
- package/dist/okf/types/ProcessorVersion.md +15 -0
- package/dist/okf/types/ProjectDefaultConfig.md +15 -0
- package/dist/okf/types/ProjectFeed.md +15 -0
- package/dist/okf/types/ProjectMetadata.md +15 -0
- package/dist/okf/types/PubSubSnapshot.md +15 -0
- package/dist/okf/types/PubSubSubscription.md +15 -0
- package/dist/okf/types/PubSubTopic.md +15 -0
- package/dist/okf/types/PubsubliteReservation.md +15 -0
- package/dist/okf/types/PubsubliteTopic.md +15 -0
- package/dist/okf/types/RecaptchaenterpriseFirewallPolicy.md +15 -0
- package/dist/okf/types/RecaptchaenterpriseKey.md +15 -0
- package/dist/okf/types/Recognizer.md +15 -0
- package/dist/okf/types/RedisCluster.md +15 -0
- package/dist/okf/types/RedisInstance.md +15 -0
- package/dist/okf/types/RegionAutoscaler.md +15 -0
- package/dist/okf/types/RegionDiskResourcePolicyAttachment.md +15 -0
- package/dist/okf/types/RegionNetworkEndpointGroup.md +15 -0
- package/dist/okf/types/RegionPerInstanceConfig.md +15 -0
- package/dist/okf/types/RegionSSLPolicy.md +15 -0
- package/dist/okf/types/RegionalEndpoint.md +15 -0
- package/dist/okf/types/ResourceBundle.md +15 -0
- package/dist/okf/types/ResourcePolicy.md +15 -0
- package/dist/okf/types/ResourcemanagerFolder.md +15 -0
- package/dist/okf/types/ResourcemanagerPolicy.md +15 -0
- package/dist/okf/types/ResourcemanagerProject.md +15 -0
- package/dist/okf/types/ResponsePolicy.md +15 -0
- package/dist/okf/types/ResponsePolicyRule.md +15 -0
- package/dist/okf/types/Restore.md +15 -0
- package/dist/okf/types/RestorePlan.md +15 -0
- package/dist/okf/types/Router.md +15 -0
- package/dist/okf/types/RouterInterface.md +15 -0
- package/dist/okf/types/RouterNAT.md +15 -0
- package/dist/okf/types/RouterPeer.md +15 -0
- package/dist/okf/types/Routine.md +15 -0
- package/dist/okf/types/Runtime.md +15 -0
- package/dist/okf/types/RuntimeTemplate.md +15 -0
- package/dist/okf/types/SQLDatabase.md +15 -0
- package/dist/okf/types/SQLInstance.md +21 -0
- package/dist/okf/types/SQLUser.md +15 -0
- package/dist/okf/types/SSHPublicKey.md +15 -0
- package/dist/okf/types/SSLCert.md +15 -0
- package/dist/okf/types/SSLCertificate.md +15 -0
- package/dist/okf/types/SSLPolicy.md +15 -0
- package/dist/okf/types/SavedQuery.md +15 -0
- package/dist/okf/types/Schema.md +15 -0
- package/dist/okf/types/Scope.md +15 -0
- package/dist/okf/types/ScopeRBACRoleBinding.md +15 -0
- package/dist/okf/types/SecretCiphertext.md +15 -0
- package/dist/okf/types/SecretManagerSecret.md +15 -0
- package/dist/okf/types/SecretManagerSecretVersion.md +15 -0
- package/dist/okf/types/SecuresourcemanagerInstance.md +15 -0
- package/dist/okf/types/SecuresourcemanagerRepository.md +15 -0
- package/dist/okf/types/SecurityPolicy.md +15 -0
- package/dist/okf/types/ServerTLSPolicy.md +15 -0
- package/dist/okf/types/ServiceAccountKey.md +15 -0
- package/dist/okf/types/ServiceAttachment.md +15 -0
- package/dist/okf/types/ServiceBinding.md +15 -0
- package/dist/okf/types/ServiceConnectionPolicy.md +15 -0
- package/dist/okf/types/ServiceIdentity.md +15 -0
- package/dist/okf/types/ServiceLevelObjective.md +15 -0
- package/dist/okf/types/ServicePerimeter.md +19 -0
- package/dist/okf/types/ServicePerimeterResource.md +15 -0
- package/dist/okf/types/ServiceProjectAttachment.md +15 -0
- package/dist/okf/types/ServiceSplitTraffic.md +15 -0
- package/dist/okf/types/ServicedirectoryEndpoint.md +15 -0
- package/dist/okf/types/ServicedirectoryNamespace.md +15 -0
- package/dist/okf/types/ServicedirectoryService.md +15 -0
- package/dist/okf/types/ServicenetworkingConnection.md +15 -0
- package/dist/okf/types/ServiceusageService.md +15 -0
- package/dist/okf/types/Settings.md +15 -0
- package/dist/okf/types/SharedVPCHostProject.md +15 -0
- package/dist/okf/types/SharedVPCServiceProject.md +15 -0
- package/dist/okf/types/Site.md +15 -0
- package/dist/okf/types/Source.md +15 -0
- package/dist/okf/types/SourcerepoRepository.md +15 -0
- package/dist/okf/types/SpannerBackupSchedule.md +15 -0
- package/dist/okf/types/SpannerDatabase.md +15 -0
- package/dist/okf/types/SpannerInstance.md +15 -0
- package/dist/okf/types/Spoke.md +15 -0
- package/dist/okf/types/StandardAppVersion.md +15 -0
- package/dist/okf/types/StorageBucket.md +21 -0
- package/dist/okf/types/StoragetransferJob.md +15 -0
- package/dist/okf/types/StoredInfoType.md +15 -0
- package/dist/okf/types/Stream.md +15 -0
- package/dist/okf/types/Subnet.md +15 -0
- package/dist/okf/types/Subnetwork.md +15 -0
- package/dist/okf/types/Subscription.md +15 -0
- package/dist/okf/types/SyncAuthorization.md +15 -0
- package/dist/okf/types/TCPRoute.md +15 -0
- package/dist/okf/types/TLSRoute.md +15 -0
- package/dist/okf/types/Tag.md +15 -0
- package/dist/okf/types/TagBinding.md +15 -0
- package/dist/okf/types/TagKey.md +15 -0
- package/dist/okf/types/TagTemplate.md +15 -0
- package/dist/okf/types/TagValue.md +15 -0
- package/dist/okf/types/Target.md +15 -0
- package/dist/okf/types/TargetGRPCProxy.md +15 -0
- package/dist/okf/types/TargetHTTPProxy.md +15 -0
- package/dist/okf/types/TargetHTTPSProxy.md +15 -0
- package/dist/okf/types/TargetInstance.md +15 -0
- package/dist/okf/types/TargetPool.md +15 -0
- package/dist/okf/types/TargetSSLProxy.md +15 -0
- package/dist/okf/types/TargetTCPProxy.md +15 -0
- package/dist/okf/types/TargetVPNGateway.md +15 -0
- package/dist/okf/types/TasksQueue.md +15 -0
- package/dist/okf/types/Taxonomy.md +15 -0
- package/dist/okf/types/Tenant.md +15 -0
- package/dist/okf/types/TenantDefaultSupportedIDPConfig.md +15 -0
- package/dist/okf/types/TenantInboundSAMLConfig.md +15 -0
- package/dist/okf/types/TenantOAuthIDPConfig.md +15 -0
- package/dist/okf/types/Tensorboard.md +15 -0
- package/dist/okf/types/URLMap.md +15 -0
- package/dist/okf/types/UptimeCheckConfig.md +15 -0
- package/dist/okf/types/User.md +15 -0
- package/dist/okf/types/VPCNetwork.md +15 -0
- package/dist/okf/types/VPNGateway.md +15 -0
- package/dist/okf/types/VPNTunnel.md +15 -0
- package/dist/okf/types/VertexaiDataset.md +15 -0
- package/dist/okf/types/VertexaiEndpoint.md +15 -0
- package/dist/okf/types/VertexaiIndex.md +15 -0
- package/dist/okf/types/VirtualMachine.md +15 -0
- package/dist/okf/types/VmwareengineNetwork.md +15 -0
- package/dist/okf/types/VmwareengineNetworkPeering.md +15 -0
- package/dist/okf/types/VpnConnection.md +15 -0
- package/dist/okf/types/WasmPlugin.md +15 -0
- package/dist/okf/types/WebApp.md +15 -0
- package/dist/okf/types/Webhook.md +15 -0
- package/dist/okf/types/WorkerPool.md +15 -0
- package/dist/okf/types/Workflow.md +15 -0
- package/dist/okf/types/WorkflowTemplate.md +15 -0
- package/dist/okf/types/WorkflowsExecution.md +15 -0
- package/dist/okf/types/WorkforcePool.md +15 -0
- package/dist/okf/types/WorkforcePoolProvider.md +15 -0
- package/dist/okf/types/Workload.md +15 -0
- package/dist/okf/types/WorkloadIdentityPool.md +15 -0
- package/dist/okf/types/WorkloadIdentityPoolProvider.md +15 -0
- package/dist/okf/types/Workstation.md +15 -0
- package/dist/okf/types/WorkstationCluster.md +15 -0
- package/dist/okf/types/WorkstationConfig.md +15 -0
- package/dist/okf/types/Zone.md +19 -0
- package/dist/rules/wgc501.ts +73 -0
- package/dist/rules/wgc502.ts +41 -0
- package/dist/rules/wgc503.ts +56 -0
- package/dist/serializer.d.ts +12 -0
- package/dist/serializer.d.ts.map +1 -1
- package/package.json +2 -2
- package/src/composites/index.ts +6 -0
- package/src/composites/landing-zone.test.ts +67 -0
- package/src/composites/landing-zone.ts +173 -0
- package/src/deep-observe-hooks.ts +87 -21
- package/src/deep-observe.test.ts +158 -13
- package/src/deep-observe.ts +143 -142
- package/src/describe-resources.test.ts +46 -1
- package/src/describe-resources.ts +64 -13
- package/src/governance.test.ts +59 -0
- package/src/governance.ts +179 -0
- package/src/index.ts +10 -0
- package/src/lifecycle-integration.test.ts +3 -3
- package/src/lint/audit-catalog.ts +5 -0
- package/src/lint/post-synth/index.ts +6 -0
- package/src/lint/post-synth/wgc501.test.ts +87 -0
- package/src/lint/post-synth/wgc501.ts +73 -0
- package/src/lint/post-synth/wgc502.test.ts +64 -0
- package/src/lint/post-synth/wgc502.ts +41 -0
- package/src/lint/post-synth/wgc503.test.ts +77 -0
- package/src/lint/post-synth/wgc503.ts +56 -0
- package/src/plugin.test.ts +4 -1
- package/src/serializer.ts +6 -1
package/src/deep-observe.ts
CHANGED
|
@@ -1,132 +1,60 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* GCP deep observation (#1087
|
|
3
|
-
*
|
|
4
|
-
* the issue and #1173's own per-row checklist: "A Config Connector resource
|
|
5
|
-
* *is* a Kubernetes object, so it carries managed-fields for the same
|
|
6
|
-
* reason. Share the hooks rather than writing a second implementation."
|
|
2
|
+
* GCP deep observation (#1087, re-landed on direct REST by #1209/#1210) — the
|
|
3
|
+
* GCP row of the deep-observe contract (#1014).
|
|
7
4
|
*
|
|
8
|
-
* ##
|
|
5
|
+
* ## The reader is the applier's transport, pointed at reads
|
|
9
6
|
*
|
|
10
|
-
*
|
|
11
|
-
*
|
|
12
|
-
*
|
|
13
|
-
*
|
|
14
|
-
*
|
|
15
|
-
*
|
|
16
|
-
*
|
|
17
|
-
*
|
|
18
|
-
*
|
|
7
|
+
* chant applies GCP cluster-free over direct REST (#706), and since #1209 it
|
|
8
|
+
* observes the same way: every GET here is built by the same
|
|
9
|
+
* `ResourceMapper.plan().getUrl` the applier writes through (see
|
|
10
|
+
* ./api/read-client.ts), so reader and applier cannot disagree about where a
|
|
11
|
+
* resource lives. `GCP_ENDPOINT_URL` redirects the whole reader at a local
|
|
12
|
+
* floci-gcp; unset means real GCP, exactly as it does for the applier.
|
|
13
|
+
* Coverage is the applier's own dispatch table — a kind with no mapper cannot
|
|
14
|
+
* be applied either, and reports NOT-OBSERVED with `unsupported-kind` (#1089)
|
|
15
|
+
* rather than being dropped.
|
|
19
16
|
*
|
|
20
|
-
*
|
|
17
|
+
* ## Two shapes, one diff
|
|
21
18
|
*
|
|
22
|
-
*
|
|
23
|
-
*
|
|
24
|
-
*
|
|
25
|
-
*
|
|
26
|
-
*
|
|
27
|
-
*
|
|
28
|
-
*
|
|
29
|
-
*
|
|
30
|
-
*
|
|
31
|
-
*
|
|
19
|
+
* The declared side is a CNRM spec as a declarable authors it (`{ metadata:
|
|
20
|
+
* { name }, location, storageClass }`); the REST APIs return their own shapes
|
|
21
|
+
* (`name` is usually the full resource path, a bucket's `iamConfiguration`
|
|
22
|
+
* nests what CNRM flattens, a subscription's `topic` is a path where CNRM
|
|
23
|
+
* writes `topicRef`). Diffed raw, every such field drifts twice: once as
|
|
24
|
+
* `declared -> <absent>` and once as `<undeclared> -> live`.
|
|
25
|
+
* {@link restToCnrmShape} plus the per-kind {@link CNRM_REFINERS} put the live
|
|
26
|
+
* payload into the declared vocabulary before the diff runs — the same move
|
|
27
|
+
* the AWS row makes with its per-type `toModel` (#1207/#1269), and it lives
|
|
28
|
+
* next to the read for the same reason: translation is the price of the
|
|
29
|
+
* richer read, and it does not belong inside the diff.
|
|
32
30
|
*
|
|
33
|
-
*
|
|
34
|
-
* reuse them without adding a dependency on the k8s lexicon package or (never,
|
|
35
|
-
* per the issue) on `@intentius/chant-k8s-client` — this reader shells
|
|
36
|
-
* `kubectl` exactly like `./describe-resources.ts` already does. Chant
|
|
37
|
-
* #1177/#1180 kept GCP off the typed client deliberately ("a separate
|
|
38
|
-
* lexicon and a separate decision"); this row does not revisit that.
|
|
31
|
+
* ## Noise is a static table, not an ownership walk
|
|
39
32
|
*
|
|
40
|
-
*
|
|
41
|
-
*
|
|
42
|
-
*
|
|
43
|
-
*
|
|
44
|
-
*
|
|
45
|
-
* with an explicit `--field-manager`. GCP has no equivalent apply activity:
|
|
46
|
-
* every gcp example's own deploy script (e.g.
|
|
47
|
-
* `examples/cockroachdb-multi-region-gke/scripts/deploy.sh`) runs plain
|
|
48
|
-
* `kubectl apply -f dist/*.yaml` — classic client-side apply, no
|
|
49
|
-
* `--server-side`, no `--field-manager`. kubectl's own hardcoded default
|
|
50
|
-
* field manager for that command is `kubectl-client-side-apply`, identical
|
|
51
|
-
* to what a human's `kubectl apply -f their-own-file.yaml` would record.
|
|
52
|
-
* **There is no field-manager name on GCP's real deploy path that
|
|
53
|
-
* distinguishes "chant applied this" from "a person applied this".**
|
|
54
|
-
* (Config Connector's own controller is distinguishable — its reconciler
|
|
55
|
-
* records itself as `cnrm-controller-manager`, per the k8s-config-connector
|
|
56
|
-
* source's own `ControllerManagedFieldManager` constant — just chant isn't,
|
|
57
|
-
* on this path.)
|
|
58
|
-
*
|
|
59
|
-
* That sounds like it breaks question 1 of the three-question rule
|
|
60
|
-
* (`isChantManager`) below. It doesn't, because question 3 already covers
|
|
61
|
-
* it: chant's own kubectl apply always applies the *exact* built manifest, so
|
|
62
|
-
* any field chant's own most recent apply set is, by construction, also in
|
|
63
|
-
* `declaredRoot` (`props`) on the very next read — chant never authors a
|
|
64
|
-
* field it does not also declare. Working through what that means per field:
|
|
65
|
-
*
|
|
66
|
-
* - A field only chant's own applies have ever touched: not recognized as
|
|
67
|
-
* `chantOwned` (its manager is `kubectl-client-side-apply`, not `chant`),
|
|
68
|
-
* but foreign-owned *and* declared → contested → kept diffable anyway.
|
|
69
|
-
* Same outcome as being chant-owned would have been.
|
|
70
|
-
* - A field CNRM's controller sets and chant never declares: foreign-owned,
|
|
71
|
-
* undeclared → pruned. Correct regardless of whether "chant" is recognized.
|
|
72
|
-
* - A field a human sets by hand (`kubectl edit`, or their own `kubectl apply
|
|
73
|
-
* -f`) that chant *does* declare: foreign-owned (manager is `kubectl-edit`
|
|
74
|
-
* or `kubectl-client-side-apply`) and declared → contested → surfaces as
|
|
75
|
-
* drift. This is #1087's acceptance criterion 1.
|
|
76
|
-
*
|
|
77
|
-
* `isGcpChantFieldManager` below still checks the `chant`/`chant:<stack>`
|
|
78
|
-
* family, so a future GCP apply path that *does* route through server-side
|
|
79
|
-
* apply with an explicit chant field manager (matching the k8s lexicon's own
|
|
80
|
-
* path) is recognized with no change needed here. On today's plain-apply
|
|
81
|
-
* path it is inert — proven inert by this module's own test suite (the
|
|
82
|
-
* "managers-specific case") — and the contested-field rule (question 3) is
|
|
83
|
-
* what actually keeps GCP's drift semantics correct without it.
|
|
84
|
-
*
|
|
85
|
-
* ## What's genuinely GCP-specific
|
|
86
|
-
*
|
|
87
|
-
* - No typed operation surface (chant #1177's `operationFor` is a k8s
|
|
88
|
-
* lexicon/typed-client concept, generated from cluster discovery this
|
|
89
|
-
* reader never touches) — `./describe-resources.ts`'s `deriveGVK` stands in.
|
|
90
|
-
* - CNRM's own observed-state annotations (`./deep-observe-hooks.ts`'s
|
|
91
|
-
* `gcpDeepNormalizationHooks`) — bookkeeping the controller writes into
|
|
92
|
-
* `metadata.annotations` for GCP-side properties the CRD schema has no
|
|
93
|
-
* field for. See that module's doc for why the list is narrow.
|
|
94
|
-
*
|
|
95
|
-
* ## Deliberately out of scope
|
|
96
|
-
*
|
|
97
|
-
* `status.conditions` staleness as its own signal — the issue's own
|
|
98
|
-
* "Proposed" section floats this as worth *deciding*, not worth doing here.
|
|
99
|
-
* `status` is pruned outright (matching k8s, and the acceptance criteria),
|
|
100
|
-
* and a CNRM projection lagging real GCP state is a genuine gap, but
|
|
101
|
-
* detecting it means reading the actual GCP API, not the CR — a different
|
|
102
|
-
* read than this contract's "normalize what Kubernetes reports" scope.
|
|
103
|
-
* Flagged, not papered over.
|
|
33
|
+
* The kubectl-era reader pruned by CNRM `metadata.managedFields`. A REST
|
|
34
|
+
* payload never says who wrote a field, so the noise rules are static
|
|
35
|
+
* (./deep-observe-hooks.ts): server-assigned names, chant's own ownership
|
|
36
|
+
* labels, CNRM-only declared fields, and per-kind provider defaults gated on
|
|
37
|
+
* "source never declared it". Core applies the same hooks to both trees.
|
|
104
38
|
*
|
|
105
39
|
* ## The build-path boundary
|
|
106
40
|
*
|
|
107
|
-
*
|
|
108
|
-
*
|
|
109
|
-
*
|
|
110
|
-
* `
|
|
111
|
-
*
|
|
112
|
-
*
|
|
113
|
-
* `deepNormalizationHooks` is plain data with no such dependency
|
|
114
|
-
* (`./deep-observe-hooks.ts`) and is imported statically from `plugin.ts`,
|
|
115
|
-
* because core normalizes the *declared* tree with it whether or not a
|
|
116
|
-
* cluster read ever happens.
|
|
41
|
+
* `gcpPlugin.ts` reaches this file only via `await import("./deep-observe")`
|
|
42
|
+
* inside `observeResourcesDeep` — never statically — so `chant build` never
|
|
43
|
+
* resolves the live transport just to synthesize a template.
|
|
44
|
+
* `deepNormalizationHooks` is plain data (./deep-observe-hooks.ts) and is
|
|
45
|
+
* imported statically from `plugin.ts`, because core normalizes the
|
|
46
|
+
* *declared* tree with it whether or not a live read ever happens.
|
|
117
47
|
*/
|
|
118
48
|
|
|
119
49
|
import type {
|
|
120
|
-
DeepNormalizationHooks,
|
|
121
50
|
DeepObservationResult,
|
|
122
51
|
DeepResourceObservation,
|
|
123
52
|
UnobservedEntity,
|
|
124
53
|
} from "@intentius/chant/lexicon";
|
|
125
54
|
import { deepObservation, normalizeDeepProperties } from "@intentius/chant/deep-observation";
|
|
126
55
|
import { hasOwnershipMarker, type ChannelKeys } from "@intentius/chant/ownership";
|
|
127
|
-
import { deriveGVK } from "./describe-resources";
|
|
56
|
+
import { deriveGVK, manifestProjectAnnotations, resolveReadProject } from "./describe-resources";
|
|
128
57
|
import { getResource, mapperForKind, GcpReadError, isNotFound, type GcpReadClientOptions } from "./api/read-client";
|
|
129
|
-
import { resolveGcpProject } from "./op/activities/gcp-apply";
|
|
130
58
|
import { gcpDeepNormalizationHooks } from "./deep-observe-hooks";
|
|
131
59
|
|
|
132
60
|
/** The labels the applier stamps — see describe-resources.ts. */
|
|
@@ -152,38 +80,24 @@ export interface GcpDeepObserveOptions {
|
|
|
152
80
|
}
|
|
153
81
|
|
|
154
82
|
/**
|
|
155
|
-
* Reshape a GCP REST body into the
|
|
156
|
-
*
|
|
157
|
-
*
|
|
158
|
-
*
|
|
159
|
-
*
|
|
160
|
-
*
|
|
161
|
-
*
|
|
162
|
-
* again as `location: <undeclared> -> US`.
|
|
163
|
-
*
|
|
164
|
-
* Verified against floci-gcp before this existed: a bucket that matched its
|
|
165
|
-
* declaration exactly reported **7 property drifts**, all of them shape.
|
|
166
|
-
*
|
|
167
|
-
* chant has met this before. #1207 records it for AWS: Cloud Control returns
|
|
168
|
-
* the CloudFormation resource model and lines up for free, while the EC2 API
|
|
169
|
-
* returns the EC2 shape and needs mapping onto the declared shape before the
|
|
170
|
-
* diff can compare. GCP is the EC2 case.
|
|
171
|
-
*
|
|
172
|
-
* The mapping is CNRM's own convention rather than a per-kind table: identity
|
|
173
|
-
* and labels live under `metadata`, everything else is `spec`. That holds for
|
|
174
|
-
* every kind the applier can write, and a per-kind table would be a second
|
|
175
|
-
* place to forget a field.
|
|
83
|
+
* Reshape a GCP REST body into the shape the declared props are written in:
|
|
84
|
+
* identity and labels under `metadata`, everything else at the root — a CNRM
|
|
85
|
+
* spec as a chant declarable authors it (`new StorageBucket({ metadata,
|
|
86
|
+
* location, storageClass })`). Kind-specific vocabulary differences on top of
|
|
87
|
+
* it are {@link CNRM_REFINERS}' job. Verified against floci-gcp: diffed raw, a
|
|
88
|
+
* bucket that matched its declaration exactly reported every field as drift
|
|
89
|
+
* twice, once per shape.
|
|
176
90
|
*/
|
|
177
91
|
export function restToCnrmShape(body: Record<string, unknown>): Record<string, unknown> {
|
|
178
92
|
const metadata: Record<string, unknown> = {};
|
|
179
|
-
const
|
|
93
|
+
const rest: Record<string, unknown> = {};
|
|
180
94
|
for (const [key, value] of Object.entries(body)) {
|
|
181
95
|
if (key === "name" || key === "labels" || key === "annotations") metadata[key] = value;
|
|
182
|
-
else
|
|
96
|
+
else rest[key] = value;
|
|
183
97
|
}
|
|
184
98
|
return {
|
|
185
99
|
...(Object.keys(metadata).length ? { metadata } : {}),
|
|
186
|
-
...
|
|
100
|
+
...rest,
|
|
187
101
|
};
|
|
188
102
|
}
|
|
189
103
|
|
|
@@ -195,19 +109,105 @@ function propertiesTreeOf(obj: Record<string, unknown>): Record<string, unknown>
|
|
|
195
109
|
return rest;
|
|
196
110
|
}
|
|
197
111
|
|
|
112
|
+
/** What a refiner may need beyond the tree: the read's project, and the REST
|
|
113
|
+
* payload's own full resource name (`projects/p/locations/l/services/s`). */
|
|
114
|
+
interface RefineContext {
|
|
115
|
+
project: string;
|
|
116
|
+
restName?: string;
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
type CnrmTree = Record<string, unknown> & { metadata?: Record<string, unknown> };
|
|
120
|
+
|
|
121
|
+
/**
|
|
122
|
+
* Per-kind REST -> CNRM vocabulary mapping, applied after the generic
|
|
123
|
+
* {@link restToCnrmShape}. Each entry translates exactly the fields where the
|
|
124
|
+
* REST API and the CNRM schema disagree about names or nesting — kept next to
|
|
125
|
+
* the kind, like the applier's forward mapping in gcp-apply.ts, so adding a
|
|
126
|
+
* field means touching one kind in one file per direction.
|
|
127
|
+
*/
|
|
128
|
+
const CNRM_REFINERS: Record<string, (tree: CnrmTree, ctx: RefineContext) => void> = {
|
|
129
|
+
StorageBucket(tree) {
|
|
130
|
+
// CNRM flattens GCS's `iamConfiguration` envelope.
|
|
131
|
+
const iam = tree.iamConfiguration as
|
|
132
|
+
| { uniformBucketLevelAccess?: { enabled?: unknown }; publicAccessPrevention?: unknown }
|
|
133
|
+
| undefined;
|
|
134
|
+
if (iam) {
|
|
135
|
+
if (iam.uniformBucketLevelAccess?.enabled !== undefined) {
|
|
136
|
+
tree.uniformBucketLevelAccess = iam.uniformBucketLevelAccess.enabled;
|
|
137
|
+
}
|
|
138
|
+
if (iam.publicAccessPrevention !== undefined) tree.publicAccessPrevention = iam.publicAccessPrevention;
|
|
139
|
+
delete tree.iamConfiguration;
|
|
140
|
+
}
|
|
141
|
+
// `lifecycle.rule` -> `lifecycleRule`, the inverse of bucketInsertBody.
|
|
142
|
+
const lifecycle = tree.lifecycle as { rule?: unknown } | undefined;
|
|
143
|
+
if (lifecycle) {
|
|
144
|
+
if (lifecycle.rule !== undefined) tree.lifecycleRule = lifecycle.rule;
|
|
145
|
+
delete tree.lifecycle;
|
|
146
|
+
}
|
|
147
|
+
},
|
|
148
|
+
PubSubSubscription(tree, ctx) {
|
|
149
|
+
const topic = tree.topic;
|
|
150
|
+
if (typeof topic !== "string") return;
|
|
151
|
+
// The declared side writes a `topicRef`; a same-project path maps to the
|
|
152
|
+
// `name` form the manifest overwhelmingly uses, anything else to `external`.
|
|
153
|
+
const prefix = `projects/${ctx.project}/topics/`;
|
|
154
|
+
tree.topicRef = topic.startsWith(prefix) ? { name: topic.slice(prefix.length) } : { external: topic };
|
|
155
|
+
delete tree.topic;
|
|
156
|
+
},
|
|
157
|
+
SecretManagerSecret(tree) {
|
|
158
|
+
// CNRM spells automatic replication as a boolean; the REST API as `{}`.
|
|
159
|
+
const replication = tree.replication as { automatic?: unknown } | undefined;
|
|
160
|
+
if (replication && typeof replication.automatic === "object" && replication.automatic !== null) {
|
|
161
|
+
replication.automatic = true;
|
|
162
|
+
}
|
|
163
|
+
},
|
|
164
|
+
IAMServiceAccount(tree, ctx) {
|
|
165
|
+
// The REST identity is the derived email; the declared name is the account
|
|
166
|
+
// id it was derived from (see gcpServiceAccountMapper).
|
|
167
|
+
const name = tree.metadata?.name;
|
|
168
|
+
if (typeof name === "string" && name.endsWith(`@${ctx.project}.iam.gserviceaccount.com`)) {
|
|
169
|
+
tree.metadata!.name = name.slice(0, name.indexOf("@"));
|
|
170
|
+
}
|
|
171
|
+
},
|
|
172
|
+
RunService(tree, ctx) {
|
|
173
|
+
// The v2 payload carries no `location` field — it lives in the resource
|
|
174
|
+
// name. The declared side writes it as `location`.
|
|
175
|
+
const m = ctx.restName ? /\/locations\/([^/]+)\//.exec(ctx.restName) : null;
|
|
176
|
+
if (m) tree.location = m[1];
|
|
177
|
+
},
|
|
178
|
+
};
|
|
179
|
+
|
|
180
|
+
/**
|
|
181
|
+
* A REST payload as a CNRM-shaped property tree, in the declared side's
|
|
182
|
+
* vocabulary. The generic reshape runs first, then the full resource path is
|
|
183
|
+
* shortened to the declared `metadata.name` (`projects/p/topics/t` -> `t`),
|
|
184
|
+
* then the kind's own refiner translates what the two schemas name
|
|
185
|
+
* differently.
|
|
186
|
+
*/
|
|
187
|
+
export function toCnrmTree(kind: string, body: Record<string, unknown>, ctx: RefineContext): Record<string, unknown> {
|
|
188
|
+
const tree = restToCnrmShape(propertiesTreeOf(body)) as CnrmTree;
|
|
189
|
+
const restName = typeof body.name === "string" ? body.name : undefined;
|
|
190
|
+
const name = tree.metadata?.name;
|
|
191
|
+
if (typeof name === "string" && name.includes("/")) {
|
|
192
|
+
tree.metadata!.name = name.slice(name.lastIndexOf("/") + 1);
|
|
193
|
+
}
|
|
194
|
+
CNRM_REFINERS[kind]?.(tree, { ...ctx, restName });
|
|
195
|
+
return tree as Record<string, unknown>;
|
|
196
|
+
}
|
|
197
|
+
|
|
198
198
|
/**
|
|
199
|
-
* Read the live property tree for each declared entity
|
|
200
|
-
*
|
|
201
|
-
*
|
|
202
|
-
*
|
|
203
|
-
*
|
|
204
|
-
* becomes NOT-OBSERVED for every declared entity rather than an empty result.
|
|
199
|
+
* Read the live property tree for each declared entity over the applier's
|
|
200
|
+
* REST transport, normalized into the declared CNRM shape (see the module
|
|
201
|
+
* doc). A connect failure becomes NOT-OBSERVED for every declared entity
|
|
202
|
+
* rather than an empty result, and a 404 is a real absence the thin read
|
|
203
|
+
* already reports.
|
|
205
204
|
*/
|
|
206
205
|
export async function observeResourcesDeepGcp(options: GcpDeepObserveOptions): Promise<DeepObservationResult> {
|
|
207
206
|
const resources: Record<string, DeepResourceObservation> = {};
|
|
208
207
|
const unobserved: Record<string, UnobservedEntity> = {};
|
|
209
208
|
|
|
210
209
|
const endpoint = process.env.GCP_ENDPOINT_URL;
|
|
210
|
+
const manifestProjects = manifestProjectAnnotations(options.buildOutput);
|
|
211
211
|
|
|
212
212
|
const reads = [...options.entities].map(async ([entityName, { entityType, props }]) => {
|
|
213
213
|
const gvk = deriveGVK(entityType);
|
|
@@ -236,7 +236,7 @@ export async function observeResourcesDeepGcp(options: GcpDeepObserveOptions): P
|
|
|
236
236
|
let client: GcpReadClientOptions;
|
|
237
237
|
try {
|
|
238
238
|
client = {
|
|
239
|
-
project:
|
|
239
|
+
project: resolveReadProject(gvk.kind, name, metadata, manifestProjects),
|
|
240
240
|
...(endpoint ? { endpoint } : {}),
|
|
241
241
|
};
|
|
242
242
|
} catch (err) {
|
|
@@ -267,8 +267,9 @@ export async function observeResourcesDeepGcp(options: GcpDeepObserveOptions): P
|
|
|
267
267
|
|
|
268
268
|
resources[entityName] = {
|
|
269
269
|
type: entityType,
|
|
270
|
-
physicalId:
|
|
271
|
-
|
|
270
|
+
physicalId:
|
|
271
|
+
(obj.id as string | undefined) ?? (obj.selfLink as string | undefined) ?? (obj.name as string | undefined),
|
|
272
|
+
properties: normalizeDeepProperties(toCnrmTree(gvk.kind, obj, { project: client.project }), {
|
|
272
273
|
entityType,
|
|
273
274
|
side: "live",
|
|
274
275
|
// The static table is the whole prune now — there is no per-resource
|
|
@@ -23,7 +23,7 @@ const bucket = (name: string) => ({
|
|
|
23
23
|
props: { metadata: { name }, spec: { location: "US" } },
|
|
24
24
|
});
|
|
25
25
|
|
|
26
|
-
async function read(entities: ReturnType<typeof makeEntities>, opts: { owned?: boolean } = {}) {
|
|
26
|
+
async function read(entities: ReturnType<typeof makeEntities>, opts: { owned?: boolean; buildOutput?: string } = {}) {
|
|
27
27
|
return describeResources({
|
|
28
28
|
environment: "local",
|
|
29
29
|
buildOutput: "",
|
|
@@ -92,6 +92,51 @@ describe("gcp describeResources — direct REST (#1209)", () => {
|
|
|
92
92
|
expect(fetchMock).not.toHaveBeenCalled();
|
|
93
93
|
});
|
|
94
94
|
|
|
95
|
+
test("kinds resolve through the serializer's GVK map, not naive recasing", async () => {
|
|
96
|
+
// The real entity type is `GCP::Pubsub::Topic` (the generated barrel's
|
|
97
|
+
// casing); a naive `${service}${shortKind}` derives `PubsubTopic`, which
|
|
98
|
+
// matches no mapper — 4 of the 6 appliable kinds were invisible this way.
|
|
99
|
+
fetchMock.mockResolvedValue(reply(200, { name: "projects/my-project/topics/t" }));
|
|
100
|
+
const out = await read(
|
|
101
|
+
makeEntities([{ name: "t", entityType: "GCP::Pubsub::Topic", props: { metadata: { name: "t" } } }]),
|
|
102
|
+
);
|
|
103
|
+
expect(out.unobserved?.t).toBeUndefined();
|
|
104
|
+
expect(out.resources.t).toBeDefined();
|
|
105
|
+
expect(fetchMock.mock.calls[0][0]).toBe("http://localhost:4588/v1/projects/my-project/topics/t");
|
|
106
|
+
});
|
|
107
|
+
|
|
108
|
+
test("the project falls back to the built manifest's merged annotation", async () => {
|
|
109
|
+
// `defaultAnnotations` is a separate declarable the serializer merges at
|
|
110
|
+
// synthesis — the entity's own props never carry it.
|
|
111
|
+
delete process.env.GOOGLE_CLOUD_PROJECT;
|
|
112
|
+
fetchMock.mockResolvedValue(reply(200, { id: "b/b" }));
|
|
113
|
+
const buildOutput = [
|
|
114
|
+
"apiVersion: storage.cnrm.cloud.google.com/v1beta1",
|
|
115
|
+
"kind: StorageBucket",
|
|
116
|
+
"metadata:",
|
|
117
|
+
" name: b",
|
|
118
|
+
" annotations:",
|
|
119
|
+
" cnrm.cloud.google.com/project-id: manifest-project",
|
|
120
|
+
"spec:",
|
|
121
|
+
" location: US",
|
|
122
|
+
].join("\n");
|
|
123
|
+
const out = await read(
|
|
124
|
+
makeEntities([{ name: "b", entityType: "GCP::Storage::Bucket", props: { metadata: { name: "b" } } }]),
|
|
125
|
+
{ buildOutput },
|
|
126
|
+
);
|
|
127
|
+
expect(out.unobserved?.b).toBeUndefined();
|
|
128
|
+
expect(out.resources.b).toBeDefined();
|
|
129
|
+
});
|
|
130
|
+
|
|
131
|
+
test("no project from any source is a no-binding hole, never a guess", async () => {
|
|
132
|
+
delete process.env.GOOGLE_CLOUD_PROJECT;
|
|
133
|
+
const out = await read(
|
|
134
|
+
makeEntities([{ name: "b", entityType: "GCP::Storage::Bucket", props: { metadata: { name: "b" } } }]),
|
|
135
|
+
);
|
|
136
|
+
expect(out.unobserved?.b?.reason).toBe("no-binding");
|
|
137
|
+
expect(fetchMock).not.toHaveBeenCalled();
|
|
138
|
+
});
|
|
139
|
+
|
|
95
140
|
test("reads concurrently, where the kubectl path was one spawn after another", async () => {
|
|
96
141
|
fetchMock.mockResolvedValue(reply(200, {}));
|
|
97
142
|
const entities = makeEntities([
|
|
@@ -40,7 +40,8 @@ import type { ObservationResult, ResourceMetadata, UnobservedEntity } from "@int
|
|
|
40
40
|
import { observation } from "@intentius/chant/observation";
|
|
41
41
|
import { hasOwnershipMarker, classifyOwnership, type ChannelKeys } from "@intentius/chant/ownership";
|
|
42
42
|
import { getResource, mapperForKind, GcpReadError, isNotFound, type GcpReadClientOptions } from "./api/read-client";
|
|
43
|
-
import { resolveGcpProject } from "./op/activities/gcp-apply";
|
|
43
|
+
import { resolveGcpProject, parseManifest } from "./op/activities/gcp-apply";
|
|
44
|
+
import { resolveGVK } from "./serializer";
|
|
44
45
|
|
|
45
46
|
/**
|
|
46
47
|
* chant's ownership marker as GCP labels.
|
|
@@ -75,19 +76,67 @@ interface GcpRestResponse {
|
|
|
75
76
|
}
|
|
76
77
|
|
|
77
78
|
/**
|
|
78
|
-
*
|
|
79
|
-
*
|
|
80
|
-
*
|
|
79
|
+
* The CNRM group/kind for an entity type, resolved through the serializer's
|
|
80
|
+
* own GVK map so the reader and the manifest agree on the kind's casing —
|
|
81
|
+
* `GCP::Pubsub::Topic` is `PubSubTopic` in CNRM and in the applier's mapper
|
|
82
|
+
* table, while a naive `${service}${shortKind}` concatenation would produce
|
|
83
|
+
* `PubsubTopic` and silently miss the mapper for 4 of the 6 appliable kinds.
|
|
81
84
|
*/
|
|
82
85
|
export function deriveGVK(entityType: string): { group: string; kind: string } | null {
|
|
83
|
-
const
|
|
84
|
-
if (
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
86
|
+
const resolved = resolveGVK(entityType);
|
|
87
|
+
if (!resolved) return null;
|
|
88
|
+
return { group: resolved.apiVersion.split("/")[0], kind: resolved.kind };
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
/**
|
|
92
|
+
* The `cnrm.cloud.google.com/project-id` annotations in the built manifest,
|
|
93
|
+
* keyed `kind/name`.
|
|
94
|
+
*
|
|
95
|
+
* The declared entities the observe paths receive are discovery output, and a
|
|
96
|
+
* project-wide `defaultAnnotations({"cnrm.cloud.google.com/project-id": …})`
|
|
97
|
+
* is a separate declarable the serializer merges into each document at
|
|
98
|
+
* synthesis — the entity's own props never see it. The applier resolves its
|
|
99
|
+
* project from the manifest for exactly that reason, so the readers do too:
|
|
100
|
+
* without this, every entity relying on the default annotation reports
|
|
101
|
+
* `no-binding` unless the shell happens to export GOOGLE_CLOUD_PROJECT.
|
|
102
|
+
*/
|
|
103
|
+
export function manifestProjectAnnotations(buildOutput: string | undefined): Map<string, string> {
|
|
104
|
+
const out = new Map<string, string>();
|
|
105
|
+
if (!buildOutput) return out;
|
|
106
|
+
try {
|
|
107
|
+
for (const doc of parseManifest(buildOutput, "<build output>")) {
|
|
108
|
+
const project = doc.metadata?.annotations?.["cnrm.cloud.google.com/project-id"];
|
|
109
|
+
if (doc.kind && doc.metadata?.name && typeof project === "string") {
|
|
110
|
+
out.set(`${doc.kind}/${doc.metadata.name}`, project);
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
} catch {
|
|
114
|
+
// An unparsable build output resolves nothing — per-entity annotations and
|
|
115
|
+
// GOOGLE_CLOUD_PROJECT still apply, and a truly unresolvable project is
|
|
116
|
+
// still reported as `no-binding` per entity.
|
|
117
|
+
}
|
|
118
|
+
return out;
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
/**
|
|
122
|
+
* The project a read should target: `GOOGLE_CLOUD_PROJECT` / the entity's own
|
|
123
|
+
* annotation (via `resolveGcpProject`, the applier's rule), then the built
|
|
124
|
+
* manifest's merged annotation. Throws the applier's own error when nothing
|
|
125
|
+
* resolves, so the `no-binding` detail names both knobs.
|
|
126
|
+
*/
|
|
127
|
+
export function resolveReadProject(
|
|
128
|
+
kind: string,
|
|
129
|
+
name: string,
|
|
130
|
+
metadata: { annotations?: Record<string, string> } | undefined,
|
|
131
|
+
manifestProjects: Map<string, string>,
|
|
132
|
+
): string {
|
|
133
|
+
try {
|
|
134
|
+
return resolveGcpProject({ kind, metadata });
|
|
135
|
+
} catch (err) {
|
|
136
|
+
const fromManifest = manifestProjects.get(`${kind}/${name}`);
|
|
137
|
+
if (fromManifest) return fromManifest;
|
|
138
|
+
throw err;
|
|
139
|
+
}
|
|
91
140
|
}
|
|
92
141
|
|
|
93
142
|
function pruneUndefined<T extends Record<string, unknown>>(obj: T): Record<string, unknown> {
|
|
@@ -144,6 +193,8 @@ export async function describeResources(options: {
|
|
|
144
193
|
// `describe-stack-resources` returns no tags.
|
|
145
194
|
let warnedOwnership = false;
|
|
146
195
|
|
|
196
|
+
const manifestProjects = manifestProjectAnnotations(options.buildOutput);
|
|
197
|
+
|
|
147
198
|
const reads = [...options.entities].map(async ([entityName, { entityType, props }]) => {
|
|
148
199
|
const gvk = deriveGVK(entityType);
|
|
149
200
|
if (!gvk) {
|
|
@@ -179,7 +230,7 @@ export async function describeResources(options: {
|
|
|
179
230
|
let client: GcpReadClientOptions;
|
|
180
231
|
try {
|
|
181
232
|
client = {
|
|
182
|
-
project:
|
|
233
|
+
project: resolveReadProject(gvk.kind, name, metadata, manifestProjects),
|
|
183
234
|
...(endpoint ? { endpoint } : {}),
|
|
184
235
|
};
|
|
185
236
|
} catch (err) {
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import { describe, expect, test } from "vitest";
|
|
2
|
+
import { landingZoneConfig, FOUNDATION_FOLDERS } from "./governance";
|
|
3
|
+
|
|
4
|
+
describe("landingZoneConfig (#791)", () => {
|
|
5
|
+
test("the default is the recommended foundation", () => {
|
|
6
|
+
const cfg = landingZoneConfig();
|
|
7
|
+
expect(Object.keys(cfg.folders)).toEqual(["Security", "Infrastructure", "Sandbox", "Workloads"]);
|
|
8
|
+
expect(cfg.organization.orgPolicies).toEqual(["disable-sa-key-creation", "skip-default-network"]);
|
|
9
|
+
expect(Object.keys(cfg.orgPolicies).sort()).toEqual(["disable-sa-key-creation", "skip-default-network"]);
|
|
10
|
+
expect(cfg.orgPolicies["disable-sa-key-creation"].constraint).toBe("iam.disableServiceAccountKeyCreation");
|
|
11
|
+
expect(cfg.auditSinks).toBeUndefined();
|
|
12
|
+
});
|
|
13
|
+
|
|
14
|
+
test("custom folders and projects merge over the foundation (brownfield: partial trees work)", () => {
|
|
15
|
+
const cfg = landingZoneConfig({
|
|
16
|
+
folders: {
|
|
17
|
+
Workloads: {
|
|
18
|
+
children: { Prod: { projects: [{ name: "checkout" }] } },
|
|
19
|
+
},
|
|
20
|
+
},
|
|
21
|
+
});
|
|
22
|
+
// Same-name key wins over the foundation's Workloads…
|
|
23
|
+
expect(cfg.folders.Workloads.children?.Prod.projects?.[0].name).toBe("checkout");
|
|
24
|
+
// …while the rest of the foundation persists.
|
|
25
|
+
expect(cfg.folders.Security).toEqual(FOUNDATION_FOLDERS.Security);
|
|
26
|
+
|
|
27
|
+
const partial = landingZoneConfig({ foundation: false, folders: { Legacy: {} }, rootOrgPolicies: [] });
|
|
28
|
+
expect(Object.keys(partial.folders)).toEqual(["Legacy"]);
|
|
29
|
+
expect(partial.organization.orgPolicies).toBeUndefined();
|
|
30
|
+
expect(partial.orgPolicies).toEqual({});
|
|
31
|
+
});
|
|
32
|
+
|
|
33
|
+
test("allowedLocations adds a root resource-location org policy", () => {
|
|
34
|
+
const cfg = landingZoneConfig({ allowedLocations: ["in:eu-locations", "europe-west1"] });
|
|
35
|
+
expect(cfg.organization.orgPolicies).toContain("resource-location-restriction");
|
|
36
|
+
const policy = cfg.orgPolicies["resource-location-restriction"];
|
|
37
|
+
expect(policy.constraint).toBe("gcp.resourceLocations");
|
|
38
|
+
expect(JSON.stringify(policy.rules)).toContain("europe-west1");
|
|
39
|
+
});
|
|
40
|
+
|
|
41
|
+
test("auditAllServices declares the audit sink", () => {
|
|
42
|
+
const cfg = landingZoneConfig({ auditAllServices: true });
|
|
43
|
+
expect(cfg.auditSinks?.auditConfig).toEqual({
|
|
44
|
+
service: "allServices",
|
|
45
|
+
logTypes: ["ADMIN_READ", "DATA_READ", "DATA_WRITE"],
|
|
46
|
+
});
|
|
47
|
+
});
|
|
48
|
+
|
|
49
|
+
test("only attached org policies are emitted; attaching an undefined policy throws", () => {
|
|
50
|
+
const cfg = landingZoneConfig({
|
|
51
|
+
orgPolicies: { unused: { constraint: "compute.disableSerialPortAccess", rules: [{ enforce: "TRUE" }] } },
|
|
52
|
+
});
|
|
53
|
+
expect(cfg.orgPolicies.unused).toBeUndefined();
|
|
54
|
+
|
|
55
|
+
expect(() => landingZoneConfig({ folders: { Security: { orgPolicies: ["nope"] } } })).toThrowError(
|
|
56
|
+
'org policy "nope" is attached but not defined',
|
|
57
|
+
);
|
|
58
|
+
});
|
|
59
|
+
});
|