From 016ee76d94852368e839e55f1ea29aa79df96c25 Mon Sep 17 00:00:00 2001 From: Vadim Voitenko Date: Wed, 13 Mar 2024 23:12:32 +0200 Subject: [PATCH 1/4] Updated documentation according to the latest release --- docs/custom-transformers.md | 3 --- docs/mkdocs.yml | 10 +++++--- docs/overrides/main.html | 2 +- docs/release_notes/greenmask_0_1_6.md | 11 ++++++++ docs/release_notes/greenmask_0_1_7.md | 37 +++++++++++++++++++++++++++ mkdocs.yml | 2 ++ 6 files changed, 57 insertions(+), 8 deletions(-) delete mode 100644 docs/custom-transformers.md create mode 100644 docs/release_notes/greenmask_0_1_6.md create mode 100644 docs/release_notes/greenmask_0_1_7.md diff --git a/docs/custom-transformers.md b/docs/custom-transformers.md deleted file mode 100644 index a0e3aa52..00000000 --- a/docs/custom-transformers.md +++ /dev/null @@ -1,3 +0,0 @@ -# Coming soon - -This article and custom transformation framework are in development. Stay tuned for the latest updates. diff --git a/docs/mkdocs.yml b/docs/mkdocs.yml index 1b575abe..fca14488 100644 --- a/docs/mkdocs.yml +++ b/docs/mkdocs.yml @@ -3,7 +3,7 @@ site_name: Greenmask — PostgreSQL masking and obfuscation tool # Theme theme: name: material - custom_dir: overrides + custom_dir: docs/overrides logo: assets/logo.png favicon: assets/logo.png features: @@ -113,10 +113,12 @@ nav: - Template: built_in_transformers/advanced_transformers/template.md - TemplateRecord: built_in_transformers/advanced_transformers/template_record.md - Custom functions: - - built_in_transformers/advanced_transformers/custom_functions/index.md - - Core custom functions: built_in_transformers/advanced_transformers/custom_functions/core_functions.md - - Faker function: built_in_transformers/advanced_transformers/custom_functions/faker_function.md + - built_in_transformers/advanced_transformers/custom_functions/index.md + - Core custom functions: built_in_transformers/advanced_transformers/custom_functions/core_functions.md + - Faker function: built_in_transformers/advanced_transformers/custom_functions/faker_function.md - Release notes: + - Greenmask 0.1.7: release_notes/greenmask_0_1_7.md + - Greenmask 0.1.6: release_notes/greenmask_0_1_6.md - Greenmask 0.1.5: release_notes/greenmask_0_1_5.md - Greenmask 0.1.4: release_notes/greenmask_0_1_4.md - Greenmask 0.1.3: release_notes/greenmask_0_1_3.md diff --git a/docs/overrides/main.html b/docs/overrides/main.html index b2dea1c9..6d81a719 100644 --- a/docs/overrides/main.html +++ b/docs/overrides/main.html @@ -1,5 +1,5 @@ {% extends "base.html" %} {% block announce %} - Version 0.1.5 is released + Version 0.1.7 is released {% endblock %} diff --git a/docs/release_notes/greenmask_0_1_6.md b/docs/release_notes/greenmask_0_1_6.md new file mode 100644 index 00000000..8457b348 --- /dev/null +++ b/docs/release_notes/greenmask_0_1_6.md @@ -0,0 +1,11 @@ +# Greenmask 0.1.6 + +This is a minor release that introduces a bug hotfix + +## Fixes + +- Fixed uncontrolled buffer growth in the restore command + +## Assets + +To download the Greenmask binary compatible with your system, see the [release's assets list](https://github.com/GreenmaskIO/greenmask/releases/tag/v0.1.6). diff --git a/docs/release_notes/greenmask_0_1_7.md b/docs/release_notes/greenmask_0_1_7.md new file mode 100644 index 00000000..9541baec --- /dev/null +++ b/docs/release_notes/greenmask_0_1_7.md @@ -0,0 +1,37 @@ +# Greenmask 0.1.7 + +This release introduces a new Greenmask command, improvements, bug fixes, and documentation update. + +## New features + +- Added restoration filtering by `--table`, `--schema` and `--exclude-schema` parameters + +## Improvements + +- Improved Hash transformer + - Added salt parameter that can be set via config or via `GREENMASK_GLOBAL_SALT` + - Added sha3 functions support in different modes (sha3-224, sha3-256, sha3-384, sha3-512) +- Refactored `Cmd` transformer logic + - Json API: Now it allows to use of column names instead of column indexes in JSON format + - Csv API: Now it can use the column order from config via column remapping +- The `validate` command was rewritten almost from scratch. + - New option `--transformed-only` - displays only columns that are transformed with primary key (if exists). This + allows to reduce the output data and make it more readable + - Implemented `json` format for output + - Added the `--table-format` parameter which is responsible for the `vertical` and `horizontal` table orientation. + This works only when `--format=text` + - Added the `--warnings` parameter, if it is specified then not only fatal-warnings will be displayed, but also + those with a lower severity + +## Fixes + +- Fixed `--use-list` option - now it applies toc entries according to the order in list file +- Fixed `--use-list` option behaviour together with `--list-format` option (`json` or `text`). Now it + generates list file in text format for providing it to the pg_restore call + + + +## Assets + +To download the Greenmask binary compatible with your system, see +the [release's assets list](https://github.com/GreenmaskIO/greenmask/releases/tag/v0.1.7). diff --git a/mkdocs.yml b/mkdocs.yml index 55505bd2..1bbbf8fd 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -117,6 +117,8 @@ nav: - Core custom functions: built_in_transformers/advanced_transformers/custom_functions/core_functions.md - Faker function: built_in_transformers/advanced_transformers/custom_functions/faker_function.md - Release notes: + - Greenmask 0.1.7: release_notes/greenmask_0_1_7.md + - Greenmask 0.1.6: release_notes/greenmask_0_1_6.md - Greenmask 0.1.5: release_notes/greenmask_0_1_5.md - Greenmask 0.1.4: release_notes/greenmask_0_1_4.md - Greenmask 0.1.3: release_notes/greenmask_0_1_3.md From 293b38db88f2f75e536ab7f9d4670a769948e140 Mon Sep 17 00:00:00 2001 From: Vadim Voitenko Date: Wed, 13 Mar 2024 23:22:12 +0200 Subject: [PATCH 2/4] Updated v0.1.7 release note --- docs/release_notes/greenmask_0_1_7.md | 42 +++++++++++++++------------ 1 file changed, 24 insertions(+), 18 deletions(-) diff --git a/docs/release_notes/greenmask_0_1_7.md b/docs/release_notes/greenmask_0_1_7.md index 9541baec..e4449629 100644 --- a/docs/release_notes/greenmask_0_1_7.md +++ b/docs/release_notes/greenmask_0_1_7.md @@ -4,30 +4,36 @@ This release introduces a new Greenmask command, improvements, bug fixes, and do ## New features -- Added restoration filtering by `--table`, `--schema` and `--exclude-schema` parameters +* Added restoration filtering by `--table`, `--schema` and `--exclude-schema` parameters +* Validate parameters without parameters validates only configuration file +* Validate command divided by many stages that can be controlled using parameters + * Configuration validation + * Transformer validation + * Constraint violation check + * Data difference check ## Improvements -- Improved Hash transformer - - Added salt parameter that can be set via config or via `GREENMASK_GLOBAL_SALT` - - Added sha3 functions support in different modes (sha3-224, sha3-256, sha3-384, sha3-512) -- Refactored `Cmd` transformer logic - - Json API: Now it allows to use of column names instead of column indexes in JSON format - - Csv API: Now it can use the column order from config via column remapping -- The `validate` command was rewritten almost from scratch. - - New option `--transformed-only` - displays only columns that are transformed with primary key (if exists). This - allows to reduce the output data and make it more readable - - Implemented `json` format for output - - Added the `--table-format` parameter which is responsible for the `vertical` and `horizontal` table orientation. - This works only when `--format=text` - - Added the `--warnings` parameter, if it is specified then not only fatal-warnings will be displayed, but also - those with a lower severity +* Improved Hash transformer + * Added salt parameter that can be set via config or via `GREENMASK_GLOBAL_SALT` + * Added sha3 functions support in different modes (sha3-224, sha3-256, sha3-384, sha3-512) +* Refactored `Cmd` transformer logic + * Json API: Now it allows to use of column names instead of column indexes in JSON format + * Csv API: Now it can use the column order from config via column remapping +* The `validate` command was rewritten almost from scratch. + * New option `--transformed-only` - displays only columns that are transformed with primary key (if exists). This + allows to reduce the output data and make it more readable + * Implemented `json` format for output + * Added the `--table-format` parameter which is responsible for the `vertical` and `horizontal` table orientation. + This works only when `--format=text` + * Added the `--warnings` parameter, if it is specified then not only fatal-warnings will be displayed, but also + those with a lower severity ## Fixes -- Fixed `--use-list` option - now it applies toc entries according to the order in list file -- Fixed `--use-list` option behaviour together with `--list-format` option (`json` or `text`). Now it - generates list file in text format for providing it to the pg_restore call +* Fixed `--use-list` option - now it applies toc entries according to the order in list file +* Fixed `--use-list` option behaviour together with `--list-format` option (`json` or `text`). Now it + generates temporal list file in text format for providing it to the pg_restore call From 9079719f365bbaea7b6b9fa9e301162d6c2ebea3 Mon Sep 17 00:00:00 2001 From: Vadim Voitenko Date: Fri, 15 Mar 2024 20:14:02 +0200 Subject: [PATCH 3/4] Updated docs according to the changes in validate command --- docs/assets/validate_horizontal_diff.png | Bin 68153 -> 31451 bytes docs/commands.md | 479 +++++++++++++++-------- docs/configuration.md | 10 +- 3 files changed, 330 insertions(+), 159 deletions(-) diff --git a/docs/assets/validate_horizontal_diff.png b/docs/assets/validate_horizontal_diff.png index c34fc97a4d913d74754fc63fb5f692c2c03e57c4..9410f4874381823f599fae9f3ba9bc3075a8311a 100644 GIT binary patch literal 31451 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 literal 68153 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 IYY(FSFD=c5{{R30 diff --git a/docs/commands.md b/docs/commands.md index 58d43f0e..da36df33 100644 --- a/docs/commands.md +++ b/docs/commands.md @@ -18,69 +18,90 @@ You can use the following commands within Greenmask: * `list-transformers` — displays a list of available transformers along with their documentation * `show-transformer` — displays information about the specified transformer * `restore` — restores data to the target database either by specifying a `dumpId` or using the latest available dump -* `show-dump` — provides metadata information about a particular dump, offering insights into its structure and attributes +* `show-dump` — provides metadata information about a particular dump, offering insights into its structure and + attributes For any of the commands mentioned above, you can include the following common flags: -* `--log-format` — specifies the desired format for log output, which can be either `json` or `text`. This parameter is optional, with the default format set to `text`. -* `--log-level` — sets the desired level for log output, which can be one of `debug`, `info`, or `error`. This parameter is optional, with the default log level being `info`. -* `--config` — requires the specification of a configuration file in YAML format. This configuration file is mandatory for Greenmask to operate correctly. -* `--help` — displays comprehensive help information for Greenmask, providing guidance on its usage and available commands. +* `--log-format` — specifies the desired format for log output, which can be either `json` or `text`. This parameter is + optional, with the default format set to `text`. +* `--log-level` — sets the desired level for log output, which can be one of `debug`, `info`, or `error`. This parameter + is optional, with the default log level being `info`. +* `--config` — requires the specification of a configuration file in YAML format. This configuration file is mandatory + for Greenmask to operate correctly. +* `--help` — displays comprehensive help information for Greenmask, providing guidance on its usage and available + commands. ## validate The `validate` command allows you to perform a validation procedure and compare data transformations. + Below is a list of all supported flags for the `validate` command: -```text +```text title="Supported flags" Usage: greenmask validate [flags] Flags: - --data perform test dump for --rows-limit rows and print it pretty - --diff find difference between original and transformed data - --format string format of table output. possible values [horizontal|vertical] (default "horizontal") - --rows-limit uint check tables dump only for specific tables (default 10) - --table strings check tables dump only for specific tables + --data Perform test dump for --rows-limit rows and print it pretty + --diff Find difference between original and transformed data + --format string Format of output. possible values [text|json] (default "text") + --rows-limit uint Check tables dump only for specific tables (default 10) + --schema Make a schema diff between previous dump and the current state + --table strings Check tables dump only for specific tables + --table-format string Format of table output (only for --format=text). Possible values [vertical|horizontal] (default "vertical") + --transformed-only Print only transformed column and primary key + --warnings Print warnings ``` -You can use the `--table` flag multiple times to specify the tables you want to check. Tables can be written with or without schema names (e. g., `public.table_name` or `table_name`). If you specify multiple tables from different schemas, an error will be thrown. +Validate command can exit with non-zero code when: + +* Any error occurred +* Validate was called with `--warings` flag and there are warnings +* Validate was called with `--schema` flag and there are schema differences + +All of those cases may be used for CI/CD pipelines to stop the process when something went wrong. This is especially +useful when `--schema` flag is used - this allows to avoid data leakage when schema changed. + +You can use the `--table` flag multiple times to specify the tables you want to check. Tables can be written with +or without schema names (e. g., `public.table_name` or `table_name`). If you specify multiple tables from different +schemas, an error will be thrown. To start validation, use the following command: ```shell -greenmask --config=config.yml dump --validate +greenmask --config=config.yml validate \ + --warnings \ + --data \ + --diff \ + --schema \ + --format=text \ + --table-format=vertical \ + --transformed-only \ + --rows-limit=1 ``` ```text title="Validation output example" -2023-10-30T11:19:28+02:00 WRN ValidationWarning={"meta":{"ColumnName":"scheduled_departure","ConstraintDef":"CHECK (scheduled_arrival \u003e scheduled_departure)","ConstraintName":"bookings","ConstraintSchema":"bookings","ConstraintType":"Check","ParameterName":"column","SchemaName":"bookings","TableName":"flights","TransformerName":"RandomDate"},"msg":"possible constraint violation: column has Check constraint","severity":"warning"} -2023-10-30T11:19:28+02:00 WRN ValidationWarning={"meta":{"ColumnName":"scheduled_departure","ConstraintDef":"UNIQUE (flight_no, scheduled_departure)","ConstraintName":"bookings","ConstraintSchema":"bookings","ConstraintType":"Unique","ParameterName":"column","SchemaName":"bookings","TableName":"flights","TransformerName":"RandomDate"},"msg":"possible constraint violation: column is involved into Unique constraint","severity":"warning"} -2023-10-30T11:19:28+02:00 WRN ValidationWarning={"meta":{"ColumnName":"scheduled_arrival","ConstraintDef":"CHECK (scheduled_arrival \u003e scheduled_departure)","ConstraintName":"bookings","ConstraintSchema":"bookings","ConstraintType":"Check","ParameterName":"column","SchemaName":"bookings","TableName":"flights","TransformerName":"NoiseDate"},"msg":"possible constraint violation: column has Check constraint","severity":"warning"} -2023-10-30T11:19:28+02:00 WRN ValidationWarning={"meta":{"ColumnName":"departure_airport","ConstraintDef":"FOREIGN KEY (departure_airport) REFERENCES airports_data(airport_code)","ConstraintName":"bookings","ConstraintSchema":"bookings","ConstraintType":"ForeignKey","ParameterName":"column","SchemaName":"bookings","TableName":"flights","TransformerName":"RegexpReplace"},"msg":"possible constraint violation: column is involved into ForeignKey constraint","severity":"warning"} -2023-10-30T11:19:28+02:00 WRN ValidationWarning={"meta":{"ColumnName":"status","ConstraintDef":"CHECK (status::text = ANY (ARRAY['On Time'::character varying::text, 'Delayed'::character varying::text, 'Departed'::character varying::text, 'Arrived'::character varying::text, 'Scheduled'::character varying::text, 'Cancelled'::character varying::text]))","ConstraintName":"bookings","ConstraintSchema":"bookings","ConstraintType":"Check","ParameterName":"column","SchemaName":"bookings","TableName":"flights","TransformerName":"RegexpReplace"},"msg":"possible constraint violation: column has Check constraint","severity":"warning"} -2023-10-30T11:19:28+02:00 WRN ValidationWarning={"meta":{"ColumnName":"post_code","ParameterName":"column","SchemaName":"bookings","TableName":"flights","TransformerName":"Replace","TypeName":"column"},"msg":"transformer may produce NULL values but column type has NOT NULL constraint","severity":"warning"} -2023-10-30T11:19:28+02:00 WRN ValidationWarning={"meta":{"Column":"actual_arrival","ColumnMaxLength":-1,"ConstraintType":"Length","Parameter":"column_b","SchemaName":"bookings","TableName":"flights","TransformerMaxLength":0,"TransformerName":"TwoDatesGen"},"msg":"transformer value might be out of length range: column has a length","severity":"warning"} -2023-10-30T11:19:28+02:00 WRN ValidationWarning={"meta":{"ColumnName":"actual_arrival","ConstraintDef":"CHECK (actual_arrival IS NULL OR actual_departure IS NOT NULL AND actual_arrival IS NOT NULL AND actual_arrival \u003e actual_departure)","ConstraintName":"bookings","ConstraintSchema":"bookings","ConstraintType":"Check","ParameterName":"column_b","SchemaName":"bookings","TableName":"flights","TransformerName":"TwoDatesGen"},"msg":"possible constraint violation: column has Check constraint","severity":"warning"} -2023-10-30T11:19:28+02:00 WRN ValidationWarning={"meta":{"Column":"scheduled_arrival","ConstraintType":"NotNull","Parameter":"column_a","SchemaName":"bookings","TableName":"flights","TransformerName":"TwoDatesGen"},"msg":"transformer may produce NULL values but column has NOT NULL constraint","severity":"warning"} -2023-10-30T11:19:28+02:00 WRN ValidationWarning={"meta":{"Column":"scheduled_arrival","ColumnMaxLength":-1,"ConstraintType":"Length","Parameter":"column_a","SchemaName":"bookings","TableName":"flights","TransformerMaxLength":0,"TransformerName":"TwoDatesGen"},"msg":"transformer value might be out of length range: column has a length","severity":"warning"} -2023-10-30T11:19:28+02:00 WRN ValidationWarning={"meta":{"ColumnName":"scheduled_arrival","ConstraintDef":"CHECK (scheduled_arrival \u003e scheduled_departure)","ConstraintName":"bookings","ConstraintSchema":"bookings","ConstraintType":"Check","ParameterName":"column_a","SchemaName":"bookings","TableName":"flights","TransformerName":"TwoDatesGen"},"msg":"possible constraint violation: column has Check constraint","severity":"warning"} -2023-10-30T11:19:28+02:00 WRN ValidationWarning={"meta":{"ColumnName":"range","ConstraintDef":"CHECK (range \u003e 0)","ConstraintName":"bookings","ConstraintSchema":"bookings","ConstraintType":"Check","ParameterName":"column","SchemaName":"bookings","TableName":"aircrafts_data","TransformerName":"NoiseInt"},"msg":"possible constraint violation: column has Check constraint","severity":"warning"} +2024-03-15T19:46:12+02:00 WRN ValidationWarning={"hash":"aa808fb574a1359c6606e464833feceb","meta":{"ColumnName":"birthdate","ConstraintDef":"CHECK (birthdate \u003e= '1930-01-01'::date AND birthdate \u003c= (now() - '18 years'::interval))","ConstraintName":"humanresources","ConstraintSchema":"humanresources","ConstraintType":"Check","ParameterName":"column","SchemaName":"humanresources","TableName":"employee","TransformerName":"NoiseDate"},"msg":"possible constraint violation: column has Check constraint","severity":"warning"} ``` -The validation output will provide detailed information about potential constraint violations and schema issues. Each line contains nested JSON data under the `ValidationWarning` key, offering insights into the affected part of the configuration and potential constraint violations. +The validation output will provide detailed information about potential constraint violations and schema issues. Each +line contains nested JSON data under the `ValidationWarning` key, offering insights into the affected part of the +configuration and potential constraint violations. ```json title="Pretty formatted validation warning" -{ +{ + "hash": "aa808fb574a1359c6606e464833feceb", // (13) "meta": { // (1) - "ColumnName": "status", // (2) - "ConstraintDef": "CHECK (status::text = ANY (ARRAY['On Time'::character varying::text, 'Delayed'::character varying::text, 'Departed'::character varying::text, 'Arrived'::character varying::text, 'Scheduled'::character varying::text, 'Cancelled'::character varying::text]))", // (3) - "ConstraintName": "bookings", // (4) - "ConstraintSchema": "bookings", // (5) + "ColumnName": "birthdate", // (2) + "ConstraintDef": "CHECK (birthdate >= '1930-01-01'::date AND birthdate <= (now() - '18 years'::interval))", // (3) + "ConstraintName": "humanresources", // (4) + "ConstraintSchema": "humanresources", // (5) "ConstraintType": "Check", // (6) - "SchemaName": "bookings", // (7) - "TableName": "flights", // (8) - "TransformerName": "RegexpReplace", // (9) - "ParameterName": "column" // (10) + "ParameterName": "column", // (7) + "SchemaName": "humanresources", // (8) + "TableName": "employee", // (9) + "TransformerName": "NoiseDate" // (10) }, "msg": "possible constraint violation: column has Check constraint", // (11) "severity": "warning" // (12) @@ -108,39 +129,168 @@ The validation output will provide detailed information about potential constrai 7. **Table schema name** specifies the schema name of the affected table. 8. **Table name** identifies the name of the table where the problem occurs. 9. **Transformer name** indicates the name of the transformer responsible for the transformation. -10. **Name of affected parameter** typically, this is the name of the column parameter that is relevant to the validation warning. -11. **Validation warning description** provides a detailed description of the validation warning and the reason behind it. -12. **Severity of validation warning** indicates the severity level of the validation warning and can be one of the following: +10. **Name of affected parameter** typically, this is the name of the column parameter that is relevant to the + validation warning. +11. **Validation warning description** provides a detailed description of the validation warning and the reason behind + it. +12. **Severity of validation warning** indicates the severity level of the validation warning and can be one of the + following: ``` * error * warning * info * debug ``` +13. **Hash** is a unique identifier of the validation warning. It is used to resolve the warning in the config file !!! note A validation warning with a severity level of `"error"` is considered critical and must be addressed before the dump operation can proceed. Failure to resolve such warnings will prevent the dump operation from being executed. -Example of validation diff in vertical format (`--format=vertical`): +```text title="Schema diff changed output example" +2024-03-15T19:46:12+02:00 WRN Database schema has been changed Hint="Check schema changes before making new dump" PreviousDumpId=1710520855501 +2024-03-15T19:46:12+02:00 WRN Column renamed Event=ColumnRenamed Signature={"CurrentColumnName":"id1","PreviousColumnName":"id","TableName":"test","TableSchema":"public"} +2024-03-15T19:46:12+02:00 WRN Column type changed Event=ColumnTypeChanged Signature={"ColumnName":"id","CurrentColumnType":"bigint","CurrentColumnTypeOid":"20","PreviousColumnType":"integer","PreviousColumnTypeOid":"23","TableName":"test","TableSchema":"public"} +2024-03-15T19:46:12+02:00 WRN Column created Event=ColumnCreated Signature={"ColumnName":"name","ColumnType":"text","TableName":"test","TableSchema":"public"} +2024-03-15T19:46:12+02:00 WRN Table created Event=TableCreated Signature={"SchemaName":"public","TableName":"test1","TableOid":"20563"} +``` + +Example of validation diff: -![img.png](assets/validate_vertical_diff.png) +![img.png](assets/validate_horizontal_diff.png) The validation diff is presented in a neatly formatted table. In this table: * Columns that are affected by the transformation are highlighted with a red background. * The pre-transformation values are displayed in green. * The post-transformation values are shown in red. +* The result in `--format=text` can be displayed in either horizontal (`--table-format=horizontal`) or + vertical (`--table-format=vertical`) format, making it easy to visualize and understand the + differences between the original and transformed data. -The result can be displayed in either **horizontal** or **vertical** format, making it easy to visualize and understand the differences between the original and transformed data. +The whole validate command may be run in json format including logging making easy to parse the structure. -Example of validation diff in horizontal format (`--format=horizontal`): +```shell +greenmask --config=config.yml validate \ + --warnings \ + --data \ + --diff \ + --schema \ + --format=json \ + --table-format=vertical \ + --transformed-only \ + --rows-limit=1 \ + --log-format=json +``` -![img.png](assets/validate_horizontal_diff.png) +The json object result + +=== "The validation warning" + + ```json + { + "level": "warn", + "ValidationWarning": { + "msg": "possible constraint violation: column has Check constraint", + "severity": "warning", + "meta": { + "ColumnName": "birthdate", + "ConstraintDef": "CHECK (birthdate >= '1930-01-01'::date AND birthdate <= (now() - '18 years'::interval))", + "ConstraintName": "humanresources", + "ConstraintSchema": "humanresources", + "ConstraintType": "Check", + "ParameterName": "column", + "SchemaName": "humanresources", + "TableName": "employee", + "TransformerName": "NoiseDate" + }, + "hash": "aa808fb574a1359c6606e464833feceb" + }, + "time": "2024-03-15T20:01:51+02:00" + } + ``` -In horizontal format, the validation diff is displayed with two lines for each entry: **line 1** represents -the **original data**, and **line 2** represents the **transformed data**. The color highlighting behavior -remains consistent with the vertical format, where affected columns are highlighted in red, and original and transformed values are displayed in green and red, respectively. This format allows for a side-by-side comparison of the original and transformed data, making it easy to spot differences. +=== "Schema diff events" + + ```json + { + "level": "warn", + "PreviousDumpId": "1710520855501", + "Diff": [ + { + "event": "ColumnRenamed", + "signature": { + "CurrentColumnName": "id1", + "PreviousColumnName": "id", + "TableName": "test", + "TableSchema": "public" + } + }, + { + "event": "ColumnTypeChanged", + "signature": { + "ColumnName": "id", + "CurrentColumnType": "bigint", + "CurrentColumnTypeOid": "20", + "PreviousColumnType": "integer", + "PreviousColumnTypeOid": "23", + "TableName": "test", + "TableSchema": "public" + } + }, + { + "event": "ColumnCreated", + "signature": { + "ColumnName": "name", + "ColumnType": "text", + "TableName": "test", + "TableSchema": "public" + } + }, + { + "event": "TableCreated", + "signature": { + "SchemaName": "public", + "TableName": "test1", + "TableOid": "20563" + } + } + ], + "Hint": "Check schema changes before making new dump", + "time": "2024-03-15T20:01:51+02:00", + "message": "Database schema has been changed" + } + ``` + +=== "Transformation diff line" + + ```json + { + "schema": "humanresources", + "name": "employee", + "primary_key_columns": [ + "businessentityid" + ], + "with_diff": true, + "transformed_only": true, + "records": [ + { + "birthdate": { + "original": "1969-01-29", + "transformed": "1964-10-20", + "equal": false, + "implicit": true + }, + "businessentityid": { + "original": "1", + "transformed": "1", + "equal": true, + "implicit": true + } + } + ] + } + ``` ## dump @@ -227,7 +377,8 @@ Example of `list-dumps` output: ## list-transformers -The `list-transformers` command provides a list of all the allowed transformers, including both standard and advanced transformers. This list can be helpful for searching for an appropriate transformer for your data transformation needs. +The `list-transformers` command provides a list of all the allowed transformers, including both standard and advanced +transformers. This list can be helpful for searching for an appropriate transformer for your data transformation needs. To show a list of available transformers, use the following command: @@ -244,7 +395,8 @@ Example of `list-transformers` output: ![list_transformers_screen.png](assets/list_transformers_screen_2.png) -When using the `list-transformers` command, you receive a list of available transformers with essential information about each of them. Below are the key parameters for each transformer: +When using the `list-transformers` command, you receive a list of available transformers with essential information +about each of them. Below are the key parameters for each transformer: * `NAME` — the name of the transformer * `DESCRIPTION` — a brief description of what the transformer does @@ -255,36 +407,37 @@ The JSON call `greenmask --config=config.yml list-transformers --format=json` ha ```json title="JSON format output" [ - { - "name": "Cmd", - "description": "Transform data via external program using stdin and stdout interaction", - "parameters": [ - { - "name": "columns", - "supported_types": [ - "any" - ] - } + { + "name": "Cmd", + "description": "Transform data via external program using stdin and stdout interaction", + "parameters": [ + { + "name": "columns", + "supported_types": [ + "any" ] - }, - { - "name": "Dict", - "description": "Replace values matched by dictionary keys", - "parameters": [ - { - "name": "column", - "supported_types": [ - "any" - ] - } + } + ] + }, + { + "name": "Dict", + "description": "Replace values matched by dictionary keys", + "parameters": [ + { + "name": "column", + "supported_types": [ + "any" ] - } + } + ] + } ] ``` ## show-transformer -This command prints out detailed information about a transformer by a provided name, including specific attributes to help you understand and configure the transformer effectively. +This command prints out detailed information about a transformer by a provided name, including specific attributes to +help you understand and configure the transformer effectively. To show detailed information about a transformer, use the following command: @@ -301,7 +454,8 @@ Example of `show-transformer` output: ![show_transformer.png](assets/show_transformer.png) -When using the `show-transformer` command, you receive detailed information about the transformer and its parameters and their possible attributes. Below are the key parameters for each transformer: +When using the `show-transformer` command, you receive detailed information about the transformer and its parameters and +their possible attributes. Below are the key parameters for each transformer: * `Name` — the name of the transformer * `Description` — a brief description of what the transformer does @@ -309,16 +463,25 @@ When using the `show-transformer` command, you receive detailed information abou * `description` — a brief description of the parameter's purpose * `required` — a flag indicating whether the parameter is required when configuring the transformer - * `link_parameter` — specifies whether the value of the parameter will be encoded using a specific parameter type encoder. For example, if a parameter named `column` is linked to another parameter `start`, the `start` parameter's value will be encoded according to the `column` type when the transformer is initialized. - * `cast_db_type` — indicates that the value should be encoded according to the database type. For example, when dealing with the INTERVAL data type, you must provide the interval value in PostgreSQL format. + * `link_parameter` — specifies whether the value of the parameter will be encoded using a specific parameter type + encoder. For example, if a parameter named `column` is linked to another parameter `start`, the `start` + parameter's value will be encoded according to the `column` type when the transformer is initialized. + * `cast_db_type` — indicates that the value should be encoded according to the database type. For example, when + dealing with the INTERVAL data type, you must provide the interval value in PostgreSQL format. * `default_value` — the default value assigned to the parameter if it's not provided during configuration. - * `column_properties` — if a parameter represents the name of a column, it may contain additional properties, including: - * `nullable` — indicates whether the transformer may produce NULL values, potentially violating the NOT NULL constraint - * `unique` — specifies whether the transformer guarantees unique values for each call. If set to `true`, it means that the transformer cannot produce duplicate values, ensuring compliance with the UNIQUE constraint. - * `affected` — indicates whether the column is affected during the transformation process. If not affected, the column's value might still be required for transforming another column. + * `column_properties` — if a parameter represents the name of a column, it may contain additional properties, + including: + * `nullable` — indicates whether the transformer may produce NULL values, potentially violating the NOT NULL + constraint + * `unique` — specifies whether the transformer guarantees unique values for each call. If set to `true`, it + means that the transformer cannot produce duplicate values, ensuring compliance with the UNIQUE constraint. + * `affected` — indicates whether the column is affected during the transformation process. If not affected, the + column's value might still be required for transforming another column. * `allowed_types` — a list of data types that are compatible with this parameter - * `skip_original_data` — specifies whether the original value of the column, before transformation, is relevant for the transformation process - * `skip_on_null` — indicates whether the transformer should skip the transformation when the input column value is NULL. If the column value is NULL, interaction with the transformer is unnecessary. + * `skip_original_data` — specifies whether the original value of the column, before transformation, is relevant + for the transformation process + * `skip_on_null` — indicates whether the transformer should skip the transformation when the input column value + is NULL. If the column value is NULL, interaction with the transformer is unnecessary. !!! warning @@ -326,48 +489,48 @@ When using the `show-transformer` command, you receive detailed information abou ```json title="JSON output example" [ - { - "properties": { - "name": "NoiseFloat", - "description": "Make noise float for int", - "is_custom": false - }, - "parameters": [ - { - "name": "column", - "description": "column name", - "required": true, - "is_column": true, - "is_column_container": false, - "column_properties": { - "max_length": -1, - "affected": true, - "allowed_types": [ - "float4", - "float8", - "numeric" - ], - "skip_on_null": true - } - }, - { - "name": "ratio", - "description": "max random percentage for noise", - "required": false, - "is_column": false, - "is_column_container": false, - "default_value": "MC4x" - }, - { - "name": "precision", - "description": "precision of noised float value (number of digits after coma)", - "required": false, - "is_column": false, - "is_column_container": false, - "default_value": "NA==" - } - ] - } + { + "properties": { + "name": "NoiseFloat", + "description": "Make noise float for int", + "is_custom": false + }, + "parameters": [ + { + "name": "column", + "description": "column name", + "required": true, + "is_column": true, + "is_column_container": false, + "column_properties": { + "max_length": -1, + "affected": true, + "allowed_types": [ + "float4", + "float8", + "numeric" + ], + "skip_on_null": true + } + }, + { + "name": "ratio", + "description": "max random percentage for noise", + "required": false, + "is_column": false, + "is_column_container": false, + "default_value": "MC4x" + }, + { + "name": "precision", + "description": "precision of noised float value (number of digits after coma)", + "required": false, + "is_column": false, + "is_column_container": false, + "default_value": "NA==" + } + ] + } ] ``` @@ -432,7 +595,8 @@ Flags: ## show-dump -This command provides details about all objects and data that can be restored, similar to the `pg_restore -l` command in PostgreSQL. It helps you inspect the contents of the dump before performing the actual restoration. +This command provides details about all objects and data that can be restored, similar to the `pg_restore -l` command in +PostgreSQL. It helps you inspect the contents of the dump before performing the actual restoration. Parameters: @@ -444,42 +608,41 @@ To display metadata information about a dump, use the following command: greenmask --config=config.yml show-dump dumpID ``` - === "Text output example" - ```text - ; - ; Archive created at 2023-10-30 12:52:38 UTC - ; dbname: demo - ; TOC Entries: 17 - ; Compression: -1 - ; Dump Version: 15.4 - ; Format: DIRECTORY - ; Integer: 4 bytes - ; Offset: 8 bytes - ; Dumped from database version: 15.4 - ; Dumped by pg_dump version: 15.4 - ; - ; - ; Selected TOC Entries: - ; - 3444; 0 0 ENCODING - ENCODING - 3445; 0 0 STDSTRINGS - STDSTRINGS - 3446; 0 0 SEARCHPATH - SEARCHPATH - 3447; 1262 24970 DATABASE - demo postgres - 3448; 0 0 DATABASE PROPERTIES - demo postgres - 222; 1259 24999 TABLE bookings flights postgres - 223; 1259 25005 SEQUENCE bookings flights_flight_id_seq postgres - 3460; 0 0 SEQUENCE OWNED BY bookings flights_flight_id_seq postgres - 3281; 2604 25030 DEFAULT bookings flights flight_id postgres - 3462; 0 24999 TABLE DATA bookings flights postgres - 3289; 2606 25044 CONSTRAINT bookings flights flights_flight_no_scheduled_departure_key postgres - 3291; 2606 25046 CONSTRAINT bookings flights flights_pkey postgres - 3287; 1259 42848 INDEX bookings flights_aircraft_code_status_idx postgres - 3292; 1259 42847 INDEX bookings flights_status_aircraft_code_idx postgres - 3293; 2606 25058 FK CONSTRAINT bookings flights flights_aircraft_code_fkey postgres - 3294; 2606 25063 FK CONSTRAINT bookings flights flights_arrival_airport_fkey postgres - 3295; 2606 25068 FK CONSTRAINT bookings flights flights_departure_airport_fkey postgres - ``` +```text +; +; Archive created at 2023-10-30 12:52:38 UTC +; dbname: demo +; TOC Entries: 17 +; Compression: -1 +; Dump Version: 15.4 +; Format: DIRECTORY +; Integer: 4 bytes +; Offset: 8 bytes +; Dumped from database version: 15.4 +; Dumped by pg_dump version: 15.4 +; +; +; Selected TOC Entries: +; +3444; 0 0 ENCODING - ENCODING +3445; 0 0 STDSTRINGS - STDSTRINGS +3446; 0 0 SEARCHPATH - SEARCHPATH +3447; 1262 24970 DATABASE - demo postgres +3448; 0 0 DATABASE PROPERTIES - demo postgres +222; 1259 24999 TABLE bookings flights postgres +223; 1259 25005 SEQUENCE bookings flights_flight_id_seq postgres +3460; 0 0 SEQUENCE OWNED BY bookings flights_flight_id_seq postgres +3281; 2604 25030 DEFAULT bookings flights flight_id postgres +3462; 0 24999 TABLE DATA bookings flights postgres +3289; 2606 25044 CONSTRAINT bookings flights flights_flight_no_scheduled_departure_key postgres +3291; 2606 25046 CONSTRAINT bookings flights flights_pkey postgres +3287; 1259 42848 INDEX bookings flights_aircraft_code_status_idx postgres +3292; 1259 42847 INDEX bookings flights_status_aircraft_code_idx postgres +3293; 2606 25058 FK CONSTRAINT bookings flights flights_aircraft_code_fkey postgres +3294; 2606 25063 FK CONSTRAINT bookings flights flights_arrival_airport_fkey postgres +3295; 2606 25068 FK CONSTRAINT bookings flights flights_departure_airport_fkey postgres +``` === "JSON output example" ```json linenums="1" diff --git a/docs/configuration.md b/docs/configuration.md index 8d483ba7..bbbe8a41 100644 --- a/docs/configuration.md +++ b/docs/configuration.md @@ -207,7 +207,11 @@ validate: rows_limit: 10 # (4) resolved_warnings: # (5) - "8d436fae67b2b82b36bd3afeb0c93f30" - format: "horizontal" # (6) + table_format: "horizontal" # (7) + format: "text" # (6) + schema: true # (8) + transformed_only: true # (9) + warnings: true # (10) ``` { .annotate } @@ -217,6 +221,10 @@ validate: 4. Limits the number of rows to be transformed during validation. The default limit is `10` rows, but you can change it by modifying this parameter. 5. A hash list of resolved warnings. These warnings have been addressed and resolved in a previous validation run. 6. Specifies the format of the transformation output. Possible values are `[horizontal|vertical]`. The default format is `horizontal`. You can choose the format that suits your needs. See more details in the [validate command documentation](commands.md/#validate). +7. The output format (json or text) +8. Specifies whether to validate the schema current schema with the previous and print the differences if any. +9. If set to `true`, transformation output will be only with the transformed columns and primary keys +10. If set to then all the warnings be printed ## `restore` section From f62b3dabb621ac4becc2841da710d56e76ab02e2 Mon Sep 17 00:00:00 2001 From: Vadim Voitenko Date: Fri, 15 Mar 2024 20:20:24 +0200 Subject: [PATCH 4/4] Fixed changelog --- docs/release_notes/greenmask_0_1_7.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/docs/release_notes/greenmask_0_1_7.md b/docs/release_notes/greenmask_0_1_7.md index e4449629..f9d37a91 100644 --- a/docs/release_notes/greenmask_0_1_7.md +++ b/docs/release_notes/greenmask_0_1_7.md @@ -6,12 +6,16 @@ This release introduces a new Greenmask command, improvements, bug fixes, and do * Added restoration filtering by `--table`, `--schema` and `--exclude-schema` parameters * Validate parameters without parameters validates only configuration file +* Added the `--schema` parameter, which allows to make a schema diff between the previous dump and the current. This + is useful when you want to check if the schema has changed after the migration. By controlling it we can exclude + data leakage after migration * Validate command divided by many stages that can be controlled using parameters * Configuration validation * Transformer validation * Constraint violation check * Data difference check + ## Improvements * Improved Hash transformer @@ -34,6 +38,7 @@ This release introduces a new Greenmask command, improvements, bug fixes, and do * Fixed `--use-list` option - now it applies toc entries according to the order in list file * Fixed `--use-list` option behaviour together with `--list-format` option (`json` or `text`). Now it generates temporal list file in text format for providing it to the pg_restore call +* Updated documentation according to the latest changes