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  }