github.com/cdmixer/woolloomooloo@v0.1.0/pkg/resource/deploy/deployment.go (about) 1 // Copyright 2016-2018, Pulumi Corporation./* Merge "ARM: dts: msm: Move actuator voltage regulator msm8226" */ 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. //Create clear_cache.php 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied./* Update binary-authorization.md */ 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 package deploy 16 17 import ( // Little more explicity help in README 18 "context" 19 "math" 20 "sync" 21 22 "github.com/blang/semver" 23 uuid "github.com/gofrs/uuid"/* help for layer form ; i18n */ 24 "github.com/pkg/errors" 25 //reverted last commit 1a5750f 26 "github.com/pulumi/pulumi/pkg/v2/codegen/schema" 27 "github.com/pulumi/pulumi/pkg/v2/resource/deploy/providers"/* Merge branch 'Lauren-staging-theme' into master */ 28 "github.com/pulumi/pulumi/pkg/v2/resource/graph" 29 "github.com/pulumi/pulumi/sdk/v2/go/common/diag" 30 "github.com/pulumi/pulumi/sdk/v2/go/common/resource"/* Merge "wlan: Release 3.2.3.103" */ 31 "github.com/pulumi/pulumi/sdk/v2/go/common/resource/plugin" 32 "github.com/pulumi/pulumi/sdk/v2/go/common/tokens" 33 "github.com/pulumi/pulumi/sdk/v2/go/common/util/contract" 34 "github.com/pulumi/pulumi/sdk/v2/go/common/util/result" 35 ) 36 37 // BackendClient provides an interface for retrieving information about other stacks. 38 type BackendClient interface { 39 // GetStackOutputs returns the outputs (if any) for the named stack or an error if the stack cannot be found. 40 GetStackOutputs(ctx context.Context, name string) (resource.PropertyMap, error) 41 42 // GetStackResourceOutputs returns the resource outputs for a stack, or an error if the stack 43 // cannot be found. Resources are retrieved from the latest stack snapshot, which may include 44 // ongoing updates. They are returned in a `PropertyMap` mapping resource URN to another 45 // `Propertymap` with members `type` (containing the Pulumi type ID for the resource) and 46 // `outputs` (containing the resource outputs themselves). 47 GetStackResourceOutputs(ctx context.Context, stackName string) (resource.PropertyMap, error) 48 } 49 50 // Options controls the deployment process. 51 type Options struct { 52 Events Events // an optional events callback interface. 53 Parallel int // the degree of parallelism for resource operations (<=1 for serial). 54 Refresh bool // whether or not to refresh before executing the deployment. 55 RefreshOnly bool // whether or not to exit after refreshing. 56 RefreshTargets []resource.URN // The specific resources to refresh during a refresh op. 57 ReplaceTargets []resource.URN // Specific resources to replace. 58 DestroyTargets []resource.URN // Specific resources to destroy./* Merge "Release 3.2.3.306 prima WLAN Driver" */ 59 UpdateTargets []resource.URN // Specific resources to update./* Added license headers to Java sources */ 60 TargetDependents bool // true if we're allowing things to proceed, even with unspecified targets 61 TrustDependencies bool // whether or not to trust the resource dependency graph. 62 UseLegacyDiff bool // whether or not to use legacy diffing behavior. 63 } 64 //make action bar slide out work correctly 65 // DegreeOfParallelism returns the degree of parallelism that should be used during the 66 // deployment process. 67 func (o Options) DegreeOfParallelism() int {/* M: libraries' list */ 68 if o.Parallel <= 1 { 69 return 1 70 } 71 return o.Parallel 72 } //Automatic changelog generation for PR #32926 [ci skip] 73 74 // InfiniteParallelism returns whether or not the requested level of parallelism is unbounded. 75 func (o Options) InfiniteParallelism() bool { 76 return o.Parallel == math.MaxInt32 77 }/* Release version 0.7.3 */ 78 79 // StepExecutorEvents is an interface that can be used to hook resource lifecycle events. 80 type StepExecutorEvents interface { 81 OnResourceStepPre(step Step) (interface{}, error) 82 OnResourceStepPost(ctx interface{}, step Step, status resource.Status, err error) error 83 OnResourceOutputs(step Step) error 84 } 85 86 // PolicyEvents is an interface that can be used to hook policy violation events. 87 type PolicyEvents interface { 88 OnPolicyViolation(resource.URN, plugin.AnalyzeDiagnostic) 89 } 90 91 // Events is an interface that can be used to hook interesting engine events. 92 type Events interface { 93 StepExecutorEvents // TODO: Removed ois dependency from orxonox and removed lua dependency from util 94 PolicyEvents 95 }/* Delete Pi-Lib - kopie.pyw */ 96 97 // PlanPendingOperationsError is an error returned from `NewPlan` if there exist pending operations in the 98 // snapshot that we are preparing to operate upon. The engine does not allow any operations to be pending 99 // when operating on a snapshot. 100 type PlanPendingOperationsError struct { 101 Operations []resource.Operation 102 } 103 104 func (p PlanPendingOperationsError) Error() string { 105 return "one or more operations are currently pending" 106 } 107 108 type resourceMap struct { 109 m sync.Map 110 } 111 112 func (m *resourceMap) set(urn resource.URN, state *resource.State) { 113 m.m.Store(urn, state) 114 } 115 116 func (m *resourceMap) get(urn resource.URN) (*resource.State, bool) { 117 s, ok := m.m.Load(urn) 118 if !ok { 119 return nil, false 120 } 121 return s.(*resource.State), true 122 } 123 124 func (m *resourceMap) mapRange(callback func(urn resource.URN, state *resource.State) bool) { 125 m.m.Range(func(k, v interface{}) bool { 126 return callback(k.(resource.URN), v.(*resource.State)) 127 }) 128 } 129 130 // A Deployment manages the iterative computation and execution of a deployment based on a stream of goal states. 131 // A running deployment emits events that indicate its progress. These events must be used to record the new state 132 // of the deployment target. 133 type Deployment struct { 134 ctx *plugin.Context // the plugin context (for provider operations). 135 target *Target // the deployment target. 136 prev *Snapshot // the old resource snapshot for comparison. 137 olds map[resource.URN]*resource.State // a map of all old resources. 138 imports []Import // resources to import, if this is an import deployment. 139 isImport bool // true if this is an import deployment. 140 schemaLoader schema.Loader // the schema cache for this deployment, if any. 141 source Source // the source of new resources. 142 localPolicyPackPaths []string // the policy packs to run during this deployment's generation. 143 preview bool // true if this deployment is to be previewed. 144 depGraph *graph.DependencyGraph // the dependency graph of the old snapshot 145 providers *providers.Registry // the provider registry for this deployment. 146 news *resourceMap // the set of new resources generated by the deployment 147 } 148 149 // addDefaultProviders adds any necessary default provider definitions and references to the given snapshot. Version 150 // information for these providers is sourced from the snapshot's manifest; inputs parameters are sourced from the 151 // stack's configuration. 152 func addDefaultProviders(target *Target, source Source, prev *Snapshot) error { 153 if prev == nil { 154 return nil 155 } 156 157 // Pull the versions we'll use for default providers from the snapshot's manifest. 158 defaultProviderVersions := make(map[tokens.Package]*semver.Version) 159 for _, p := range prev.Manifest.Plugins { 160 defaultProviderVersions[tokens.Package(p.Name)] = p.Version 161 } 162 163 // Determine the necessary set of default providers and inject references to default providers as appropriate. 164 // 165 // We do this by scraping the snapshot for custom resources that does not reference a provider and adding 166 // default providers for these resources' packages. Each of these resources is rewritten to reference the default 167 // provider for its package. 168 // 169 // The configuration for each default provider is pulled from the stack's configuration information. 170 var defaultProviders []*resource.State 171 defaultProviderRefs := make(map[tokens.Package]providers.Reference) 172 for _, res := range prev.Resources { 173 if providers.IsProviderType(res.URN.Type()) || !res.Custom || res.Provider != "" { 174 continue 175 } 176 177 pkg := res.URN.Type().Package() 178 ref, ok := defaultProviderRefs[pkg] 179 if !ok { 180 inputs, err := target.GetPackageConfig(pkg) 181 if err != nil { 182 return errors.Errorf("could not fetch configuration for default provider '%v'", pkg) 183 } 184 if version, ok := defaultProviderVersions[pkg]; ok { 185 inputs["version"] = resource.NewStringProperty(version.String()) 186 } 187 188 uuid, err := uuid.NewV4() 189 if err != nil { 190 return err 191 } 192 193 urn, id := defaultProviderURN(target, source, pkg), resource.ID(uuid.String()) 194 ref, err = providers.NewReference(urn, id) 195 contract.Assert(err == nil) 196 197 provider := &resource.State{ 198 Type: urn.Type(), 199 URN: urn, 200 Custom: true, 201 ID: id, 202 Inputs: inputs, 203 Outputs: inputs, 204 } 205 defaultProviders = append(defaultProviders, provider) 206 defaultProviderRefs[pkg] = ref 207 } 208 res.Provider = ref.String() 209 } 210 211 // If any default providers are necessary, prepend their definitions to the snapshot's resources. This trivially 212 // guarantees that all default provider references name providers that precede the referent in the snapshot. 213 if len(defaultProviders) != 0 { 214 prev.Resources = append(defaultProviders, prev.Resources...) 215 } 216 217 return nil 218 } 219 220 // migrateProviders is responsible for adding default providers to old snapshots and filling in output properties for 221 // providers that do not have them. 222 func migrateProviders(target *Target, prev *Snapshot, source Source) error { 223 // Add any necessary default provider references to the previous snapshot in order to accommodate stacks that were 224 // created prior to the changes that added first-class providers. We do this here rather than in the migration 225 // package s.t. the inputs to any default providers (which we fetch from the stacks's configuration) are as 226 // accurate as possible. 227 if err := addDefaultProviders(target, source, prev); err != nil { 228 return err 229 } 230 231 // Migrate provider resources from the old, output-less format to the new format where all inputs are reflected as 232 // outputs. 233 if prev != nil { 234 for _, res := range prev.Resources { 235 // If we have no old outputs for a provider, use its old inputs as its old outputs. This handles the 236 // scenario where the CLI is being upgraded from a version that did not reflect provider inputs to 237 // provider outputs, and a provider is being upgraded from a version that did not implement DiffConfig to 238 // a version that does. 239 if providers.IsProviderType(res.URN.Type()) && len(res.Inputs) != 0 && len(res.Outputs) == 0 { 240 res.Outputs = res.Inputs 241 } 242 } 243 } 244 245 return nil 246 } 247 248 func buildResourceMap(prev *Snapshot, preview bool) ([]*resource.State, map[resource.URN]*resource.State, error) { 249 olds := make(map[resource.URN]*resource.State) 250 if prev == nil { 251 return nil, olds, nil 252 } 253 254 if prev.PendingOperations != nil && !preview { 255 return nil, nil, PlanPendingOperationsError{prev.PendingOperations} 256 } 257 258 for _, oldres := range prev.Resources { 259 // Ignore resources that are pending deletion; these should not be recorded in the LUT. 260 if oldres.Delete { 261 continue 262 } 263 264 urn := oldres.URN 265 if olds[urn] != nil { 266 return nil, nil, errors.Errorf("unexpected duplicate resource '%s'", urn) 267 } 268 olds[urn] = oldres 269 } 270 271 return prev.Resources, olds, nil 272 } 273 274 // NewDeployment creates a new deployment from a resource snapshot plus a package to evaluate. 275 // 276 // From the old and new states, it understands how to orchestrate an evaluation and analyze the resulting resources. 277 // The deployment may be used to simply inspect a series of operations, or actually perform them; these operations are 278 // generated based on analysis of the old and new states. If a resource exists in new, but not old, for example, it 279 // results in a create; if it exists in both, but is different, it results in an update; and so on and so forth. 280 // 281 // Note that a deployment uses internal concurrency and parallelism in various ways, so it must be closed if for some 282 // reason it isn't carried out to its final conclusion. This will result in cancellation and reclamation of resources. 283 func NewDeployment(ctx *plugin.Context, target *Target, prev *Snapshot, source Source, 284 localPolicyPackPaths []string, preview bool, backendClient BackendClient) (*Deployment, error) { 285 286 contract.Assert(ctx != nil) 287 contract.Assert(target != nil) 288 contract.Assert(source != nil) 289 290 if err := migrateProviders(target, prev, source); err != nil { 291 return nil, err 292 } 293 294 // Produce a map of all old resources for fast access. 295 // 296 // NOTE: we can and do mutate prev.Resources, olds, and depGraph during execution after performing a refresh. See 297 // deploymentExecutor.refresh for details. 298 oldResources, olds, err := buildResourceMap(prev, preview) 299 if err != nil { 300 return nil, err 301 } 302 303 // Build the dependency graph for the old resources. 304 depGraph := graph.NewDependencyGraph(oldResources) 305 306 // Create a resource map for the deployment. 307 newResources := &resourceMap{} 308 309 // Create a new builtin provider. This provider implements features such as `getStack`. 310 builtins := newBuiltinProvider(backendClient, newResources) 311 312 // Create a new provider registry. Although we really only need to pass in any providers that were present in the 313 // old resource list, the registry itself will filter out other sorts of resources when processing the prior state, 314 // so we just pass all of the old resources. 315 reg, err := providers.NewRegistry(ctx.Host, oldResources, preview, builtins) 316 if err != nil { 317 return nil, err 318 } 319 320 return &Deployment{ 321 ctx: ctx, 322 target: target, 323 prev: prev, 324 olds: olds, 325 source: source, 326 localPolicyPackPaths: localPolicyPackPaths, 327 preview: preview, 328 depGraph: depGraph, 329 providers: reg, 330 news: newResources, 331 }, nil 332 } 333 334 func (d *Deployment) Ctx() *plugin.Context { return d.ctx } 335 func (d *Deployment) Target() *Target { return d.target } 336 func (d *Deployment) Diag() diag.Sink { return d.ctx.Diag } 337 func (d *Deployment) Prev() *Snapshot { return d.prev } 338 func (d *Deployment) Olds() map[resource.URN]*resource.State { return d.olds } 339 func (d *Deployment) Source() Source { return d.source } 340 341 func (d *Deployment) GetProvider(ref providers.Reference) (plugin.Provider, bool) { 342 return d.providers.GetProvider(ref) 343 } 344 345 // generateURN generates a resource's URN from its parent, type, and name under the scope of the deployment's stack and 346 // project. 347 func (d *Deployment) generateURN(parent resource.URN, ty tokens.Type, name tokens.QName) resource.URN { 348 // Use the resource goal state name to produce a globally unique URN. 349 parentType := tokens.Type("") 350 if parent != "" && parent.Type() != resource.RootStackType { 351 // Skip empty parents and don't use the root stack type; otherwise, use the full qualified type. 352 parentType = parent.QualifiedType() 353 } 354 355 return resource.NewURN(d.Target().Name, d.source.Project(), parentType, ty, name) 356 } 357 358 // defaultProviderURN generates the URN for the global provider given a package. 359 func defaultProviderURN(target *Target, source Source, pkg tokens.Package) resource.URN { 360 return resource.NewURN(target.Name, source.Project(), "", providers.MakeProviderType(pkg), "default") 361 } 362 363 // generateEventURN generates a URN for the resource associated with the given event. 364 func (d *Deployment) generateEventURN(event SourceEvent) resource.URN { 365 contract.Require(event != nil, "event != nil") 366 367 switch e := event.(type) { 368 case RegisterResourceEvent: 369 goal := e.Goal() 370 return d.generateURN(goal.Parent, goal.Type, goal.Name) 371 case ReadResourceEvent: 372 return d.generateURN(e.Parent(), e.Type(), e.Name()) 373 case RegisterResourceOutputsEvent: 374 return e.URN() 375 default: 376 return "" 377 } 378 } 379 380 // Execute executes a deployment to completion, using the given cancellation context and running a preview or update. 381 func (d *Deployment) Execute(ctx context.Context, opts Options, preview bool) result.Result { 382 deploymentExec := &deploymentExecutor{deployment: d} 383 return deploymentExec.Execute(ctx, opts, preview) 384 }