Adding count to terraform module - file

I have already deployed my VPC via this module listed below before I added a count.
This worked just fine, however do to changes in our infrastructure, I need to add a count to the module
module "core_vpc" {
source = "./modules/vpc"
count = var.environment == "qa" || var.environment == "production" ? 1 : 0
aws_region = var.aws_region
environment = var.environment
system = var.system
role = var.system
vpc_name = var.system
vpc_cidr = var.vpc_cidr
ssh_key_name = var.ssh_key_name
ssh_key_public = var.ssh_key_public
nat_subnets = var.nat_subnets
nat_azs = var.vpc_subnet_azs
}
Now Terraform wants to update my state file and destroy much of my configuration and replace it with what is shown in the example below. This is of course not just limited to route association, but all resources created within the module.I can't let this happen as I have production running and not want to mess with that.
module.K8_subnets.aws_route_table_association.subnet[0] will be destroyed
and replace it with:
module.K8_subnets[0].aws_route_table_association.subnet[0] will be created
Is there a way of preventing Terraform of making these changes? Short of changing it manually in the tf-state.
All I want is the for the VPC not to be deployed in DEV.
Thanks.

You can "move" the terraform state using tf state mv src target. Specifically you can move the old non-counter version into the new counted version at index 0:
terraform state mv 'module.K8_subnets' 'module.K8_subnets[0]'
This works for individual resources as well as for entire modules. And it works for for_each resource as well, there you would not have an index but a key to move to. And this even works the other way around, if you remove the count / for_each but want to still keep the resource(s).

Related

Have 2 hibernate.properties files

I have a Spring Boot project with Hibernate. I would like to use 2 separate hibernate.properties files: one for normal use of application, another only for test.
So, how can I do that? Or maybe it is not possible? I don't want to comment/uncomment lines in this file for tests.
Thanks for every answers and help.
#hibernate.connection.driver_class = org.postgresql.Driver
#hibernate.connection.url = jdbc:postgresql://localhost:5432/dummydb
#hibernate.connection.username = postgres
#hibernate.connection.password = postgres
#hibernate.dialect = org.hibernate.dialect.PostgreSQL91Dialect
hibernate.connection.driver_class = org.hsqldb.jdbcDriver
hibernate.connection.url = jdbc:hsqldb:mem:dummydb
hibernate.connection.username = user
hibernate.connection.password = password
hibernate.hbm2ddl.auto=create
hibernate.dialect = org.hibernate.dialect.HSQLDialect
hibernate.show_sql=true
You can use Spring profiles to separet production and test envirionments.
In your case you need to create 2 property files: application.property and application-test.property. First must contains you production env, Second envirionments for tests.
Then you need to chouse test profile when unit tests are executed. Just add #ActiveProfiles(profiles = "test") to your test classes.

Play-slick - Is default.db required?

I'm working on an application using Play and Slick. This app requires access to (at least) two databases and this is working fine when one is defined as default and other is named. Eg.,
db.default.driver = "com.mysql.jdbc.Driver"
db.default.url = "jdbc:mysql://localhost:3306/db1"
db.db2.driver = "com.mysql.jdbc.Driver"
db.db2.url = "jdbc:mysql://localhost:3306/db2"
I can then happily access each db as follows
DB.withSession { implicit session => ??? }
DB("db2").withSession { implicit session => ??? }
However, this doesn't really make sense as there is no reason DB1 should be the default. The DBs contain different types of data, neither is the default, both are important. What I would like is:
db.db1.driver = "com.mysql.jdbc.Driver"
db.db1.url = "jdbc:mysql://localhost:3306/db1"
db.db2.driver = "com.mysql.jdbc.Driver"
db.db2.url = "jdbc:mysql://localhost:3306/db2"
Play-scala barfs at this thought. It needs a default db driver and URL and it needs to be able to connect to it.
Anyone know anyway to change this behaviour or to trick play into thinking it has a default?
UPDATE
To be clear, I've greped my code to ensure that I'm not using DB.withSession anywhere. That is, every time I create a session I use DB("db1").withSession or DB("db2").withSession. However, when I run my test, I still get an exception:
Caused by: Configuration error: Configuration error[Slick error : jdbc driver not defined in application.conf for db.default.driver key]
Something somewhere is trying to load the default config.
Default is just a name, with some convenience functions (withSession and withTransaction without name), so, no you do not need to have a default connection if it does not fit your project.

How can I find the path of the current gradle script?

We use some Gradle base scripts on an central point. This scripts are included with "apply from:" from a large count of scripts. This base scripts need access to files relative to the script. How can I find the location of the base scripts?
Sample for one build.gradle:
apply from: "../../gradlebase/base1.gradle"
Sample for base1.gradle
println getScriptLocation()
I'm not sure if this is considered an internal interface, but DefaultScriptHandler has a getSourceFile() method, and the current instance is accessible via the buildscript property, so you can just use buildscript.sourceFile. It's a File instance pointing at the current script
I'm still not sure if I understood the question well but You can find path of current gradle script using following piece of code:
println project.buildscript.sourceFile
It gives the full path of the script that is currently running. Is that what You're looking for?
I'm pulling it off the stack.
buildscript {
def root = file('.').toString();
// We have to seek through, since groovy/gradle introduces
// a lot of abstraction that we see in the trace as extra frames.
// Fortunately, the first frame in the build dir is always going
// to be this script.
buildscript.metaClass.__script__ = file(
Thread.currentThread().stackTrace.find { ste ->
ste.fileName?.startsWith root
}.fileName
)
// later, still in buildscript
def libDir = "${buildscript.__script__.parent}/lib"
classpath files("${libDir}/custom-plugin.jar")
}
// This is important to do if you intend to use this path outside of
// buildscript{}, since everything else is pretty asynchronous, and
// they all share the buildscript object.
def __buildscripts__ = buildscript.__script__.parent;
Compact version for those who don't like clutter:
String r = file('.').toString();
buildscript.metaClass.__script__ = file(Thread.currentThread().stackTrace*.fileName?.find { it.startsWith r })
Another solution is set a property for the location of A.gradle in your global gradle settings at: {userhome}/.gradle/gradle.properties
My current workaround is to inject the path from the calling script. This is ugly hack.
The caller script must know where the base script is located. I save this path in a property before calling:
ext.scriptPath = '../../gradlebase'
apply from: "${scriptPath}/base1.gradle"
In base1.gradle I can also access the property ${scriptPath}
You could search for this scripts in the relative path like:
if(new File(rootDir,'../path/A.gradle').exists ()){
apply from: '../path/A.gradle'
}
This solution has not been tested with 'apply from', but has been tested with settings.gradle
Gradle has a Script.file(String path) function. I solved my problem by doing
def outDir = file("out")
def releaseDir = new File(outDir, "release")
And the 'out' directory is always next to the build.gradle in which this line is called.

Why does NDB context cache set a environment variable?

Looking though the Google NDB code, I can´t quite seem to work out why the context cache sets a environment variable.
The code in quesiton:
https://code.google.com/p/googleappengine/source/browse/trunk/python/google/appengine/ext/ndb/tasklets.py
_CONTEXT_KEY = '__CONTEXT__'
def get_context():
# XXX Docstring
ctx = None
if os.getenv(_CONTEXT_KEY):
ctx = _state.current_context
if ctx is None:
ctx = make_default_context()
set_context(ctx)
return ctx
(...)
def set_context(new_context):
# XXX Docstring
os.environ[_CONTEXT_KEY] = '1'
_state.current_context = new_context
I know what it does, but why? (Speculation on my side removed, I don´t want to mislead answers)
Update:
The _state is based on this code:
class _State(utils.threading_local):
"""Hold thread-local state."""
current_context = None
(...)
https://code.google.com/p/googleappengine/source/browse/trunk/python/google/appengine/ext/ndb/utils.py
# Define a base class for classes that need to be thread-local.
# This is pretty subtle; we want to use threading.local if threading
# is supported, but object if it is not.
if threading.local.__module__ == 'thread':
logging_debug('Using threading.local')
threading_local = threading.local
else:
logging_debug('Not using threading.local')
threading_local = object
Environment variables are specific/scoped to the request, so that provides a way of getting the context anywhere in your code without having to refer to a specific object/entity or provide a request specific lookup mechanism.
Some environment variables are set before the request is processed from the real environment, app.yaml.
Then for each request the environment variables are set from appengine_config.py , then the WSGI environment for the request, then the handler, and then other components contribute (ie your code may populate the environment), this is specific to each request.
So the environment is considered threadsafe (ie won't leak things across concurrent requests)

How to delete a File in Google Drive?

How do I write a Google Apps Script that deletes files?
This finds files:
var ExistingFiles = DocsList.find(fileName);
But DocsList.deleteFile does not exist to delete a file.
Is there a way to move those files to another Folder or to Trash?
The other workaround I would consider is to be able to override an existing file with the same name.
Currently when I want to create a file with a name already used in MyDrive then it creates a second file with the same name. I would like to keep 1 file (the new one is kept and the old one is lost).
There are 3 services available to delete a file.
DriveApp - Built-in to Apps Script
Advanced Drive Service - Built-in to Apps Script but must be enabled. Has more capability than DriveApp
Google Drive API - Not built-in to Apps Script, but can be used from Apps Script using the Drive REST API together with UrlFetchApp.fetch(url,options)
The DocsList service is now deprecated.
The Advanced Drive Service can be used to delete a file without sending it to the trash. Seriously consider the risk of not being able to retrieve the deleted file. The Advanced Drive Service has a remove method which removes a file without sending it to the trash folder. Advanced services have many of the same capabilities as the API's, without needing to make an HTTPS GET or POST request, and not needing an OAuth library.
function delteFile(myFileName) {
var allFiles, idToDLET, myFolder, rtrnFromDLET, thisFile;
myFolder = DriveApp.getFolderById('Put_The_Folder_ID_Here');
allFiles = myFolder.getFilesByName(myFileName);
while (allFiles.hasNext()) {//If there is another element in the iterator
thisFile = allFiles.next();
idToDLET = thisFile.getId();
//Logger.log('idToDLET: ' + idToDLET);
rtrnFromDLET = Drive.Files.remove(idToDLET);
};
};
This combines the DriveApp service and the Drive API to delete the file without sending it to the trash. The Drive API method .remove(id) needs the file ID. If the file ID is not available, but the file name is, then the file can first be looked up by name, and then get the file ID.
In order to use DriveAPI, you need to add it through the Resources, Advanced Google Services menu. Set the Drive API to ON. AND make sure that the Drive API is turned on in your Google Cloud Platform. If it's not turned on in BOTH places, it won't be available.
Now you may use the following if the file is as a spreadsheet, doc etc.:
DriveApp.getFileById(spreadsheet.getId()).setTrashed(true);
or if you already have the file instead of a spreadsheet, doc etc. you may use:
file.setTrashed(true);
This code uses the DocsList Class which is now deprecated.
try this :
function test(){
deleteDocByName('Name-of-the-file-to-delete')
}
function deleteDocByName(fileName){
var docs=DocsList.find(fileName)
for(n=0;n<docs.length;++n){
if(docs[n].getName() == fileName){
var ID = docs[n].getId()
DocsList.getFileById(ID).setTrashed(true)
}
}
}
since you can have many docs with the same name I used a for loop to get all the docs in the array of documents and delete them one by one if necessary.
I used a function with the filename as parameter to simplify its use in a script, use test function to try it.
Note : be aware that all files with this name will be trashed (and recoverable ;-)
About the last part of your question about keeping the most recent and deleting the old one, it would be doable (by reading the last accessed date & time) but I think it is a better idea to delete the old file before creating a new one with the same name... far more logical and safe !
Though the The service DocsList is now deprecated, as from the Class Folder references, the settrashed method is still valid:
https://developers.google.com/apps-script/reference/drive/folder#settrashedtrashed
So should work simply this:
ExistingFiles.settrashed(true);
Here is another way to do it without the need of Drive API. (based on Allan response).
function deleteFile(fileName, folderName) {
var myFolder, allFiles, file;
myFolder = DriveApp.getFoldersByName(folderName).next();
allFiles = myFolder.getFilesByName(fileName);
while (allFiles.hasNext()) {
file = allFiles.next();
file.getParents().next().removeFile(file);
}
}
Here is a slightly modified version using the above. This will backup said file to specified folder, also remove any old previous backups with the same name so there are no duplicates.
The idea is here to backup once per day, and will retain 1 month of backups in your backup folder of choice. Remember to set your trigger to daily in your Apps Script.
https://gist.github.com/fmarais/a962a8b54ce3f53f0ed57100112b453c
function archiveCopy() {
var file = DriveApp.getFileById("original_file_id_to_backup");
var destination = DriveApp.getFolderById("backup_folder_name");
var timeZone = Session.getScriptTimeZone();
var formattedDate = Utilities.formatDate(new Date(),timeZone,"dd"); // 1 month backup, one per day
var name = SpreadsheetApp.getActiveSpreadsheet().getName()+"_"+formattedDate;
// remove old backup
var allFiles = destination.getFilesByName(name);
while (allFiles.hasNext()) {
var thisFile = allFiles.next();
thisFile.setTrashed(true);
};
// make new backup
file.makeCopy(name,destination);
}

Resources