// writeTfplan serializes the given plan into the protobuf-based format used
// for the "tfplan" portion of a plan file.
writeTfplan serializes the given plan into the protobuf-based format used
for the "tfplan" portion of a plan file.
// writeTfplan serializes the given plan into the protobuf - based format used // for the " tfplan " portion of a plan file .
func writeTfplan(plan *plans.Plan, w io.Writer) error {
	if plan == nil {
		return fmt.Errorf("cannot write plan file for nil plan")
	}
	if plan.Changes == nil {
		return fmt.Errorf("cannot write plan file with nil changeset")
	}
	rawPlan := &planproto.Plan{
		Version:          tfplanFormatVersion,
		TerraformVersion: version.String(),
		ProviderHashes:   map[string]*planproto.Hash{},
		Variables:       map[string]*planproto.DynamicValue{},
		OutputChanges:   []*planproto.OutputChange{},
		ResourceChanges: []*planproto.ResourceInstanceChange{},
	}
	for _, oc := range plan.Changes.Outputs {
		if !oc.Addr.Module.IsRoot() {
			continue
		}
		name := oc.Addr.OutputValue.Name
		protoChange, err := changeToTfplan(&oc.ChangeSrc)
		if err != nil {
			return fmt.Errorf("cannot write output value %q: %s", name, err)
		}
		rawPlan.OutputChanges = append(rawPlan.OutputChanges, &planproto.OutputChange{
			Name:      name,
			Change:    protoChange,
			Sensitive: oc.Sensitive,
		})
	}
	for _, rc := range plan.Changes.Resources {
		rawRC, err := resourceChangeToTfplan(rc)
		if err != nil {
			return err
		}
		rawPlan.ResourceChanges = append(rawPlan.ResourceChanges, rawRC)
	}
	for _, targetAddr := range plan.TargetAddrs {
		rawPlan.TargetAddrs = append(rawPlan.TargetAddrs, targetAddr.String())
	}
	for name, hash := range plan.ProviderSHA256s {
		rawPlan.ProviderHashes[name] = &planproto.Hash{
			Sha256: hash,
		}
	}
	for name, val := range plan.VariableValues {
		rawPlan.Variables[name] = valueToTfplan(val)
	}
	if plan.Backend.Type == "" || plan.Backend.Config == nil {
		return fmt.Errorf("plan does not have a backend configuration")
	}
	rawPlan.Backend = &planproto.Backend{
		Type:      plan.Backend.Type,
		Config:    valueToTfplan(plan.Backend.Config),
		Workspace: plan.Backend.Workspace,
	}
	src, err := proto.Marshal(rawPlan)
	if err != nil {
		return fmt.Errorf("serialization error: %s", err)
	}
	_, err = w.Write(src)
	if err != nil {
		return fmt.Errorf("failed to write plan to plan file: %s", err)
	}
	return nil
}
func writeTfplan ( plan * plans . Plan , w io . Writer ) error { if plan == nil { return fmt . Errorf ( " " ) } if plan . Changes == nil { return fmt . Errorf ( " " ) } rawPlan := & planproto . Plan { Version : tfplanFormatVersion , TerraformVersion : version . String ( ) , ProviderHashes : map [ string ] * planproto . Hash { } , Variables : map [ string ] * planproto . DynamicValue { } , OutputChanges : [ ] * planproto . OutputChange { } , ResourceChanges : [ ] * planproto . ResourceInstanceChange { } , } for _ , oc := range plan . Changes . Outputs { if ! oc . Addr . Module . IsRoot ( ) { continue } name := oc . Addr . OutputValue . Name protoChange , err := changeToTfplan ( & oc . ChangeSrc ) if err != nil { return fmt . Errorf ( " " , name , err ) } rawPlan . OutputChanges = append ( rawPlan . OutputChanges , & planproto . OutputChange { Name : name , Change : protoChange , Sensitive : oc . Sensitive , } ) } for _ , rc := range plan . Changes . Resources { rawRC , err := resourceChangeToTfplan ( rc ) if err != nil { return err } rawPlan . ResourceChanges = append ( rawPlan . ResourceChanges , rawRC ) } for _ , targetAddr := range plan . TargetAddrs { rawPlan . TargetAddrs = append ( rawPlan . TargetAddrs , targetAddr . String ( ) ) } for name , hash := range plan . ProviderSHA256s { rawPlan . ProviderHashes [ name ] = & planproto . Hash { Sha256 : hash , } } for name , val := range plan . VariableValues { rawPlan . Variables [ name ] = valueToTfplan ( val ) } if plan . Backend . Type == " " || plan . Backend . Config == nil { return fmt . Errorf ( " " ) } rawPlan . Backend = & planproto . Backend { Type : plan . Backend . Type , Config : valueToTfplan ( plan . Backend . Config ) , Workspace : plan . Backend . Workspace , } src , err := proto . Marshal ( rawPlan ) if err != nil { return fmt . Errorf ( " " , err ) } _ , err = w . Write ( src ) if err != nil { return fmt . Errorf ( " " , err ) } return nil }
writeTfplan serializes the given plan into the protobuf-based format used
for the "tfplan" portion of a plan file.
writeTfplan serializes the given plan into the protobuf - based format used for the " tfplan " portion of a plan file .
// When serializing a plan we only retain the root outputs, since // changes to these are externally-visible side effects (e.g. via // terraform_remote_state). // Writing outputs as cty.DynamicPseudoType forces the stored values // to also contain dynamic type information, so we can recover the // original type when we read the values back in readTFPlan. // This suggests a bug in the code that created the plan, since it // ought to always have a backend populated, even if it's the default // "local" backend with a local state file.