@ -47,6 +47,22 @@ func (c *PushCommand) Run(args []string) int {
overwriteMap [ v ] = struct { } { }
}
// This is a map of variables specifically from the CLI that we want to overwrite.
// We need this because there is a chance that the user is trying to modify
// a variable we don't see in our context, but which exists in this atlas
// environment.
cliVars := make ( map [ string ] string )
for k , v := range c . variables {
if _ , ok := overwriteMap [ k ] ; ok {
if val , ok := v . ( string ) ; ok {
cliVars [ k ] = val
} else {
c . Ui . Error ( fmt . Sprintf ( "Error reading value for variable: %s" , k ) )
return 1
}
}
}
// The pwd is used for the configuration path if one is not given
pwd , err := os . Getwd ( )
if err != nil {
@ -145,19 +161,14 @@ func (c *PushCommand) Run(args []string) int {
return 1
}
// filter any overwrites from the atlas vars
for k := range overwriteMap {
delete ( atlasVars , k )
}
// Set remote variables in the context if we don't have a value here. These
// don't have to be correct, it just prevents the Input walk from prompting
// the user for input, The atlas variable may be an hcl-encoded object, but
// we're just going to set it as the raw string value.
// the user for input.
ctxVars := ctx . Variables ( )
for k , av := range atlasVars {
atlasVarSentry := "ATLAS_78AC153CA649EAA44815DAD6CBD4816D"
for k , _ := range atlasVars {
if _ , ok := ctxVars [ k ] ; ! ok {
ctx . SetVariable ( k , a v. Value )
ctx . SetVariable ( k , a tlasVarSentry )
}
}
@ -203,23 +214,47 @@ func (c *PushCommand) Run(args []string) int {
return 1
}
// Output to the user the variables that will be uploaded
// List of the vars we're uploading to display to the user.
// We always upload all vars from atlas, but only report them if they are overwritten.
var setVars [ ] string
// variables to upload
var uploadVars [ ] atlas . TFVar
// Now we can combine the vars for upload to atlas and list the variables
// we're uploading for the user
// first add all the variables we want to send which have been serialized
// from the local context.
for _ , sv := range serializedVars {
if av , ok := atlasVars [ sv . Key ] ; ok {
// this belongs to Atlas
uploadVars = append ( uploadVars , av )
} else {
// we're uploading our local version
_ , inOverwrite := overwriteMap [ sv . Key ]
_ , inAtlas := atlasVars [ sv . Key ]
// We have a variable that's not in atlas, so always send it.
if ! inAtlas {
uploadVars = append ( uploadVars , sv )
setVars = append ( setVars , sv . Key )
}
// We're overwriting an atlas variable.
// We also want to check that we
// don't send the dummy sentry value back to atlas. This could happen
// if it's specified as an overwrite on the cli, but we didn't set a
// new value.
if inAtlas && inOverwrite && sv . Value != atlasVarSentry {
uploadVars = append ( uploadVars , sv )
setVars = append ( setVars , sv . Key )
// remove this value from the atlas vars, because we're going to
// send back the remainder regardless.
delete ( atlasVars , sv . Key )
}
}
// now send back all the existing atlas vars, inserting any overwrites from the cli.
for k , av := range atlasVars {
if v , ok := cliVars [ k ] ; ok {
av . Value = v
setVars = append ( setVars , k )
}
uploadVars = append ( uploadVars , av )
}
sort . Strings ( setVars )