github.com/kanishk98/terraform@v1.3.0-dev.0.20220917174235-661ca8088a6a/internal/experiments/experiment.go (about)

     1  package experiments
     2  
     3  // Experiment represents a particular experiment, which can be activated
     4  // independently of all other experiments.
     5  type Experiment string
     6  
     7  // All active and defunct experiments must be represented by constants whose
     8  // internal string values are unique.
     9  //
    10  // Each of these declared constants must also be registered as either a
    11  // current or a defunct experiment in the init() function below.
    12  //
    13  // Each experiment is represented by a string that must be a valid HCL
    14  // identifier so that it can be specified in configuration.
    15  const (
    16  	VariableValidation             = Experiment("variable_validation")
    17  	ModuleVariableOptionalAttrs    = Experiment("module_variable_optional_attrs")
    18  	SuppressProviderSensitiveAttrs = Experiment("provider_sensitive_attrs")
    19  	ConfigDrivenMove               = Experiment("config_driven_move")
    20  	PreconditionsPostconditions    = Experiment("preconditions_postconditions")
    21  )
    22  
    23  func init() {
    24  	// Each experiment constant defined above must be registered here as either
    25  	// a current or a concluded experiment.
    26  	registerConcludedExperiment(VariableValidation, "Custom variable validation can now be used by default, without enabling an experiment.")
    27  	registerConcludedExperiment(SuppressProviderSensitiveAttrs, "Provider-defined sensitive attributes are now redacted by default, without enabling an experiment.")
    28  	registerConcludedExperiment(ConfigDrivenMove, "Declarations of moved resource instances using \"moved\" blocks can now be used by default, without enabling an experiment.")
    29  	registerConcludedExperiment(PreconditionsPostconditions, "Condition blocks can now be used by default, without enabling an experiment.")
    30  	registerConcludedExperiment(ModuleVariableOptionalAttrs, "The final feature corresponding to this experiment differs from the experimental form and is available in the Terraform language from Terraform v1.3.0 onwards.")
    31  }
    32  
    33  // GetCurrent takes an experiment name and returns the experiment value
    34  // representing that expression if and only if it is a current experiment.
    35  //
    36  // If the selected experiment is concluded, GetCurrent will return an
    37  // error of type ConcludedError whose message hopefully includes some guidance
    38  // for users of the experiment on how to migrate to a stable feature that
    39  // succeeded it.
    40  //
    41  // If the selected experiment is not known at all, GetCurrent will return an
    42  // error of type UnavailableError.
    43  func GetCurrent(name string) (Experiment, error) {
    44  	exp := Experiment(name)
    45  	if currentExperiments.Has(exp) {
    46  		return exp, nil
    47  	}
    48  
    49  	if msg, concluded := concludedExperiments[exp]; concluded {
    50  		return Experiment(""), ConcludedError{ExperimentName: name, Message: msg}
    51  	}
    52  
    53  	return Experiment(""), UnavailableError{ExperimentName: name}
    54  }
    55  
    56  // Keyword returns the keyword that would be used to activate this experiment
    57  // in the configuration.
    58  func (e Experiment) Keyword() string {
    59  	return string(e)
    60  }
    61  
    62  // IsCurrent returns true if the receiver is considered a currently-selectable
    63  // experiment.
    64  func (e Experiment) IsCurrent() bool {
    65  	return currentExperiments.Has(e)
    66  }
    67  
    68  // IsConcluded returns true if the receiver is a concluded experiment.
    69  func (e Experiment) IsConcluded() bool {
    70  	_, exists := concludedExperiments[e]
    71  	return exists
    72  }
    73  
    74  // currentExperiments are those which are available to activate in the current
    75  // version of Terraform.
    76  //
    77  // Members of this set are registered in the init function above.
    78  var currentExperiments = make(Set)
    79  
    80  // concludedExperiments are those which were available to activate in an earlier
    81  // version of Terraform but are no longer available, either because the feature
    82  // in question has been implemented or because the experiment failed and the
    83  // feature was abandoned. Each experiment maps to a message describing the
    84  // outcome, so we can give users feedback about what they might do in modules
    85  // using concluded experiments.
    86  //
    87  // After an experiment has been concluded for a whole major release span it can
    88  // be removed, since we expect users to perform upgrades one major release at
    89  // at time without skipping and thus they will see the concludedness error
    90  // message as they upgrade through a prior major version.
    91  //
    92  // Members of this map are registered in the init function above.
    93  var concludedExperiments = make(map[Experiment]string)
    94  
    95  //lint:ignore U1000 No experiments are active
    96  func registerCurrentExperiment(exp Experiment) {
    97  	currentExperiments.Add(exp)
    98  }
    99  
   100  func registerConcludedExperiment(exp Experiment, message string) {
   101  	concludedExperiments[exp] = message
   102  }