Read Karate config from YAML - karate

I would like to define environment-specific properties in a .yml/.yaml file. Therefore I created the following test.yaml:
baseUrl: 'http://localhost:1234'
Next, I wrote this karate-config.js:
function() {
var env = karate.env;
if (!env) {
env = 'test'; // default is test
}
// config = read(env + '.yaml')
var config = read('/home/user/git/karate-poc/src/test/java/test.yaml');
// var config = read('test.yaml');
// var config = read('classpath:test.yaml');
return config;
}
As seen here https://github.com/intuit/karate#reading-files the read() function should be known by Karate, however I'm not sure if this only applies to .feature files or the karate-config.js too.
Unfortunately, none of the above read()s work, as I'm getting this error:
Caused by: com.intuit.karate.exception.KarateException: javascript function call failed: could not find or read file: /home/user/git/karate-poc/src/test/java/test.yaml, prefix: NONE
at com.intuit.karate.Script.evalFunctionCall(Script.java:1602)
I'm sure that the file exists and is readable.
Am I doing something wrong or is my approach not supported? If it's not supported, what would be the recommended way to read the configuration based on the environment from a YAML file (once) in order to use it in (multiple) .feature files?
Thank you very much
Edit: Tree structure of the project:
.
├── build.gradle
├── gradle
│   └── wrapper
│   ├── gradle-wrapper.jar
│   └── gradle-wrapper.properties
├── gradle.properties
├── gradlew
├── gradlew.bat
└── src
   └── test
   └── java
   ├── karate
   │   └── rest
   │   ├── rest.feature
   │   └── RestRunner.java
   ├── karate-config.js
   └── test.yaml
Run with ./gradlew test

In JS, use the karate object, which is explained here: https://github.com/intuit/karate#the-karate-object
So this should work:
var config = karate.read('classpath:test.yaml');

Related

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

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

Why can't files introduced by require.context() be dynamically updated in Vue?

I am building an static markdown blog website using Vue3,and I am using require.context() to load markdown files.
This is the project structure,and I load files from static/posts.
├── dist
│   ├── assets
│   │   └── static
│   │   └── posts
│   │   ├── dev-first-vue3-todolist.md
│   │   ├── dev-fix-missing-xcrun.md
├── package.json
├── src
│   ├── App.vue
│   ├── main.js
├── static
│   └── posts
│   ├── dev-first-vue3-todolist.md
│   ├── dev-fix-missing-xcrun.md
└── vue.config.js
Here's how I load these markdown files.
let context = require.context("../static/posts", true, /\.md$/, "sync");
let keys = context.keys();
// the markdown file list
const postRawList = [];
keys.forEach((key) => {
const raw = context(key).default;
postRawList.push(raw);
});
It worked well. I can read postRawList from static/posts and render them by markdown parser.
The point is, I want my blog website static, so when I build this Vue app I use copy-webpack-plugin to copy these markdown files from static/posts to dist/assets/static/posts and it worked well.
config.plugins.push(
new CopyWebpackPlugin({
patterns: [
{
from: path.resolve(__dirname, "static/posts"),
to: path.resolve(__dirname, "dist/assets/static/posts"),
},
],
})
);
I want to manage my markdown posts only by adding or deleting markdown files in dist/assets/static/posts.
But after I changing the markdown files in dist/assets/static/posts(like delete dev-first-vue3-todolist.md) ,the markdown object list(postRawList) doesn't be updated.
The markdown list is the same as the markdown list in static/posts , and no matter how I change files in this 2 posts folder,it does't be updated.
I guess it is caused by "require cache", and I had tried to delete cache after changing the files, but it did't work.
delete require.cache[context.id];
So I want to know why the file objects not be updated after I built the app and change the files in markdown directory(loaded by require.context()).
This is my first time asking questions on stackoverflow,and I feel sorry if I didn't make it clear.

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}"
}

How to ignore custom elements in VuePress to avoid the "Unknown custom element" error?

I am creating documentation for a W3C web components library (Vanilla JavaScript) using VuePress. However, my "custom" web components are generating an error due to VuePress trying to "recognize" them as Vue components the very first time the page loads.
Once the page is loaded my web components work as expected, but the error is there anyway.
This is the error I am getting:
vue.runtime.esm.js?2b0e:619 [Vue warn]: Unknown custom element: <nova-timeline> - did you register the component correctly? For recursive components, make sure to provide the "name" option.
found in
---> <TimeLineWrapper> at docs/.vuepress/components/TimeLineWrapper.vue
I have created the following structure related to Vuepress
.
├── docs
│   ├── .vuepress
│   │   ├── components
│   │   │   ├── TimeLineWrapper.vue
│   │   ├── config.js
│   │   └── theme
│   ├── README.md
│   ├── components
│   │   ├── README.md
│   │   └── Timeline.md
And this is part of my code:
// docs/.vuepress/components/TimeLineWrapper.vue
<template>
<nova-timeline ref="timeline"></nova-timeline>
</template>
<script>
import timeLineJson from "./data/TimeLineData";
export default {
data() {
return {
timeLineJson: timeLineJson
};
},
mounted() {
this.$refs.timeline.data = this.timeLineJson.data;
this.$refs.timeline.configuration = this.timeLineJson.configuration;
}
};
</script>
// This is my W3C web component:
<nova-timeline ref="timeline"></nova-timeline>
What I like to know is how to "ignore custom components", I mean where or how to do this kind of configuration using the VuePress way.
Vue.config.ignoredElements = [
// Use a `RegExp` to ignore all elements that start with "nova-"
// 2.5+ only
/^nova-/
]
https://v2.vuejs.org/v2/api/#ignoredElements
Thanks in advance.
I finally manage to find how to add my ignored elements,
1) Create a file named enhanceApp.js in docs/.vuepress/theme
2) Place this content inside of it:
// https://vuepress.vuejs.org/guide/custom-themes.html#app-level-enhancements
export default ({ Vue, options, router, siteData }) => {
Vue.config.ignoredElements = [
// Use a `RegExp` to ignore all elements that start with "nova-"
// 2.5+ only
/^nova-/
];
}
Now, the error will disappear since Vue will ignore our custom web components.