Terraform BigQuery replaces table & deletes the data when schema gets updated - google-bigquery

I have somewhat below folder structure:
.
├── locals.tf
├── main.tf
├── modules
│   ├── bigquery
│   │   ├── main.tf
│   │   ├── schema
│   │   └── variables.tf
│   ├── bigquery_tables
│   │   ├── main.tf
│   │   ├── schema
│   │   └── variables.tf
│   ├── bigquery_views
│   │   ├── main.tf
│   │   ├── queries
│   │   ├── schema
│   │   └── variables.tf
│   ├── cloud_composer
│   ├── list_projects
├── providers.tf
├── storage.tf
├── variables.tf
└── versions.tf
& my main.tf in bigquery_tables is:
resource "google_bigquery_table" "bq_tables" {
for_each = { for table in var.bigquery_dataset_tables : table.table_id => table }
project = var.project_id
dataset_id = each.value.dataset_id
table_id = each.value.table_id
schema = file(format("${path.module}/schema/%v.json", each.value.file_name))
deletion_protection = false
dynamic "time_partitioning" {
for_each = try(each.value.time_partition, false) == false ? [] : [each.value.time_partition]
content {
type = each.value.partitioning_type
field = each.value.partitioning_field
}
}
}
The issue I am facing is since things are in development stage we have frequent update in schema.
Thus this change in schema is causing the BigQuery table to be replaced by terraform & also leading to data loss in BigQuery.
Can some one suggest a solution like what I should add in by resource block to avoid replacing the table & data loss?
I am unsure how can I add "external_data_configuration" in my current block as per https://github.com/hashicorp/terraform-provider-google/issues/10919.

Unfortunately if you change the schema structure of the BigQuery table, you will have this behaviour.
For the deletion_protection param, I think it's better to set it to true to prevent data loss or not set it (it' true by default).
The solution I saw, because you are in dev mode, it's using the Terraform workspace and run your schema updates in a separated workspace.
It will create a new dataset or table in each apply, example :
locals.tf file :
locals {
workspace = terraform.workspace != "default" ? "${terraform.workspace}_" : ""
}
main.tf file :
resource "google_bigquery_table" "bq_tables" {
for_each = { for table in var.bigquery_dataset_tables : table.table_id => table }
project = var.project_id
dataset_id = "${local.workspace}${each.value.dataset_id}"
table_id = each.value.table_id
schema = file(format("${path.module}/schema/%v.json", each.value.file_name))
deletion_protection = false
dynamic "time_partitioning" {
for_each = try(each.value.time_partition, false) == false ? [] : [each.value.time_partition]
content {
type = each.value.partitioning_type
field = each.value.partitioning_field
}
}
}
In this example, I used the workspace as prefix of dataset ID, if the default workspace is used, the prefix is empty, otherwise equals to the given workspace :
dataset=mydataset
- workspace=default => dataset=mydataset
- workspace=evolfeature1 => dataset=evolfeature1_mydataset

Related

How to add another page to vuepress blog?

I want to add another page to vuepress with the blog plugin.
The new page that I added does not show the content.
I expect the about page to show the content
I use basic vuePressBlog template. My tree structure is
├── examples
│   ├── about
│   │   └── Readme.md
│   └── _posts
│   ├── 2018-4-4-intro-to-vuepress.md
│   ├── 2019-6-8-intro-to-vuepress-next.md
│   ├── 2019-6-8-shanghai.md
│   ├── 2019-6-8-summary.md
│   └── 2019-6-8-vueconf.md
├── index.js
├── layouts
│   ├── GlobalLayout.vue
│   ├── Layout.vue
│   ├── Post.vue
│   └── Tag.vue
├── package.json
├── package-lock.json
└── README.md
I added the following lines to the ./example/.vuepress/config.js
module.exports = {
title: "SlimBlog",
theme: require.resolve("../../"),
themeConfig: {
// Please keep looking down to see the available options.
nav: [
{
text: "Home",
link: "/",
},
{
text: "about",
link: "/about/",
},
{},
],
},
};
I assume there might be a layout missing but I unable to find the config for this.

Terraform Outputs across modules

I am struggling to work out how to pass outputs from a module and to consume it an another.
My folder structure:
.
├── main.tf
├── modules
│   ├── cloudwatch-event
│   │   ├── basic_event_rule.tf
│   │   ├── basic_event_target.tf
│   │   └── variables.tf
│   └── lambda
│      ├── basic_lambda.tf
│      ├── output.tf
│      ├── lambda.py
│      └── variables.tf
├── lambda
│   ├── main.tf
│   └── variables.tf
└── terraform.tfvar
In order to add scheduling to the lambda, i need to consume the Lambda ARN in to the CloudWatch module.
The lambda - basic_lambda.tf
resource "aws_lambda_function" "lambda_function" {
The lambda - outputs.tf
output "lambda_arn" {
value = "${aws_lambda_function.lambda_function.arn}"
In my lambda application module, i have this in my main lambda/main.tf
module "cloudwatch-event" {
source = "../modules/cloudwatch-event"
lambda_arn = "${module.lambda.lambda_arn}"
module "lambda" {
source = "../modules/lambda"
My lambda/variables.tf includes the lambda_arn variable as a string
variable "lambda_arn" {
type = "string"
}
The root main file looks like this:
provider "aws" {
region = var.aws_region
}
module "accesskey-lambda" {
source = "./lambda/"
}
Running TF i get this
Error: Missing required argument
on main.tf line 5, in module "accesskey-lambda":
5: module "accesskey-lambda" {
The argument "lambda_arn" is required, but no definition was found.
then adding it to the root main file doesnt resolve my issues.
Thanks
Nick
Solved, i had a typo
in the cloudwatch/basic_event_target.tf
arn = "${var.lambda_arn}"
Then in the cloudwatch/variable
variable "lambda_arn" {
type = string
}
The module then needed
module "cloudwatch-event" {
source = "../modules/cloudwatch-event"
lambda_arn = "${module.lambda.lambda_arn}"
}

Show different sidebar based on the current page

Is it possible to show different sidebars depending on what section of the site you're in? So if I had two sections (Books and Countries) then I could show the corresponding sidebar menu object:
module.exports = {
books: {
"Children's Book": [
"books/childrens-books/winnie-the-pooh",
"books/childrens-books/harry-potter",
],
"Non-Fiction": [
"books/non-fiction/hitchikers-guide",
"books/non-fiction/a-history-of-england",
]
},
countries: {
"Europe": [
"countries/europe/england",
"countries/europe/france",
"countries/europe/spain",
],
"Asia": [
"countries/asia/china",
"countries/asia/india",
"countries/asia/laos",
],
},
}
The docs do reference that something like this could be done, but there aren't any examples to go along with it:
You can have multiple sidebars for different Markdown files by adding more top-level keys to the exported object.
The only other place I can find sidebars referenced is in docusaurus.config.js, but I'm not sure what this section is for:
presets: [
[
'#docusaurus/preset-classic',
{
docs: {
sidebarPath: require.resolve('./sidebars.js'),
},
...
Any pointers appreciated!
So the issue was that my content structure didn't match what I had in sidebar.js. This is my content structure now:
docs
├── README.md
├── books
│   ├── childrens-books
│   │   ├── harry-potter.md
│   │   └── winnie-the-pooh.md
│   └── non-fiction
│   ├── a-history-of-england.md
│   └── hitchikers-guide.md
└── countries
├── asia
│   ├── china.md
│   ├── india.md
│   └── laos.md
└── europe
├── england.md
├── france.md
└── spain.md
├── docs
├── docusaurus.config.js
├── sidebars.js
└── src
I think the issue lay in the fact that Docusaurus couldn't find the articles I was referencing, so it just didn't parse.
With this set up URLs like localhost:3000/docs/books/childrens-books/harry-potter will work fine, but localhost:3000/docs/books/childrens-books/ will return a blank page since there's no corresponding article for that URL.

List objects with AWS S3 SDK for Java 2.x

I have a bucket (logs) in Amazon S3 (us-east-1) with, unsurprisingly, logs, partitioned by application and date:
logs
├── peacekeepers
│   └── year=2018
│   ├── month=11
│   │   ├── day=01
│   │   ├── day=…
│   │   └── day=30
│   └── month=12
│   ├── day=01
│   ├── day=…
│   └── day=19
│   ├── 00:00 — 01:00.log
│   ├── …
│   └── 23:00 — 00:00.log
├── rep-hunters
├── retro-fans
└── rubber-duckies
I want to list all the objects (logs) for a particular date, month, year…
How do I do that with AWS SDK for Java 2.x?
New SDK makes it easy to work with paginated results:
S3Client client = S3Client.builder().region(Region.US_EAST_1).build();
ListObjectsV2Request request =
ListObjectsV2Request
.builder()
.bucket("logs")
.prefix("peacekeepers/year=2018/month=12")
// .prefix("peacekeepers/year=2018/month=12/day=19")
.build();
ListObjectsV2Iterable response = client.listObjectsV2Paginator(request);
for (ListObjectsV2Response page : response) {
for (S3Object object : page.contents()) {
// Consume the object
System.out.println(object.key());
}
}

How to add image from within 'content' subfolder - pelican

I got a structure
content/
├── applications
│   └── 2017
│   └── 08
│   └── 30
│   ├── article.md
│   └── forecast1.png
I want the img files to be same directories as the md files so that they can be put to:
ARTICLE_SAVE_AS = 'posts/{date:%Y}/{date:%b}/{date:%d}/{slug}/index.html'
I have STATIC_PATHS = ['static_files','content'] however, the
[alt]({attach}applications/2017/08/30/forecast1.png)
gives error:
WARNING: Unable to find `applications/2017/08/30/forecast1.png`, skipping url replacement.
How can I include image into my md file in this simple case?
EDIT
so I changed the config applications is my category to:
PATH = 'content'
STATIC_PATHS = ['static_files','applications/2017/08/30/img', 'applications/2017/09/01/img']
ARTICLE_PATHS = ['applications', 'cat2', 'cat3']
I also added the ! before the [alt]() and still the images are not copied over to output.
EDIT2
iT WORKS WHEN APPLY EDIT ABOVE AND CHANGE ({attach}img/forecast1.png)
This works for me (following this):
content/
├── p001
│ └── myArticle001.md
│ └── img001
│ └── myPic1.png
│ └── myPic2.png
├── p002
│ └── myArticle002.md
│ └── img002
│ └── myPic1.png
│ └── myPic2.png
In pelicanconfig.py set:
PATH = 'content'
STATIC_PATHS = ['p001','p002']
ARTICLE_PATHS = STATIC_PATHS
In the md-files set:
![pic_A1]({attach}img001/myPic1.png)
![pic_A2]({attach}img001/myPic2.png)
and
![pic_B1]({attach}img002/myPic1.png)
![pic_B2]({attach}img002/myPic2.png)
Probabley you missed a ! only at the begin of the command. So you might try this:
![alt]({attach}applications/2017/08/30/forecast1.png)
Or try this:
PATH = 'content'
STATIC_PATHS = ['applications']
ARTICLE_PATHS = STATIC_PATHS
...
![alt]({attach}2017/08/30/forecast1.png)