426 lines
14 KiB
Bash
426 lines
14 KiB
Bash
#!/usr/bin/env bats
|
|
|
|
setup() {
|
|
load 'test_helper/common-setup'
|
|
DB_NAME="$(unique_name glue-catalog-db)"
|
|
TABLE_NAME="catalog_table"
|
|
SECOND_TABLE_NAME="catalog_table_second"
|
|
FUNCTION_NAME="catalog_function"
|
|
}
|
|
|
|
teardown() {
|
|
aws_cmd glue delete-user-defined-function \
|
|
--database-name "$DB_NAME" \
|
|
--function-name "$FUNCTION_NAME" >/dev/null 2>&1 || true
|
|
aws_cmd glue delete-table \
|
|
--database-name "$DB_NAME" \
|
|
--name "$SECOND_TABLE_NAME" >/dev/null 2>&1 || true
|
|
aws_cmd glue delete-table \
|
|
--database-name "$DB_NAME" \
|
|
--name "$TABLE_NAME" >/dev/null 2>&1 || true
|
|
aws_cmd glue delete-database \
|
|
--name "$DB_NAME" >/dev/null 2>&1 || true
|
|
}
|
|
|
|
create_database() {
|
|
aws_cmd glue create-database \
|
|
--database-input "{\"Name\":\"$DB_NAME\",\"Description\":\"catalog compatibility database\"}" >/dev/null
|
|
}
|
|
|
|
table_input() {
|
|
local name="${1:-$TABLE_NAME}"
|
|
local description="$2"
|
|
jq -n \
|
|
--arg name "$name" \
|
|
--arg description "$description" \
|
|
--arg location "s3://floci-glue-catalog/$DB_NAME/$name/" \
|
|
'{
|
|
Name: $name,
|
|
Description: $description,
|
|
Parameters: {
|
|
classification: "json"
|
|
},
|
|
StorageDescriptor: {
|
|
Location: $location,
|
|
InputFormat: "org.apache.hadoop.mapred.TextInputFormat",
|
|
OutputFormat: "org.apache.hadoop.hive.ql.io.HiveIgnoreKeyTextOutputFormat",
|
|
SerdeInfo: {
|
|
SerializationLibrary: "org.openx.data.jsonserde.JsonSerDe",
|
|
Parameters: {
|
|
"serialization.format": "1"
|
|
}
|
|
},
|
|
Columns: [
|
|
{
|
|
Name: "id",
|
|
Type: "int",
|
|
Parameters: {
|
|
comment: "identifier"
|
|
}
|
|
}
|
|
]
|
|
},
|
|
PartitionKeys: [
|
|
{
|
|
Name: "year",
|
|
Type: "int"
|
|
}
|
|
]
|
|
}'
|
|
}
|
|
|
|
create_table() {
|
|
local name="${1:-$TABLE_NAME}"
|
|
local description="${2:-created}"
|
|
aws_cmd glue create-table \
|
|
--database-name "$DB_NAME" \
|
|
--table-input "$(table_input "$name" "$description")" >/dev/null
|
|
}
|
|
|
|
column_statistics_input() {
|
|
jq -n '[
|
|
{
|
|
ColumnName: "id",
|
|
ColumnType: "int",
|
|
AnalyzedTime: "2026-06-08T00:00:00Z",
|
|
StatisticsData: {
|
|
Type: "LONG",
|
|
LongColumnStatisticsData: {
|
|
MinimumValue: 1,
|
|
MaximumValue: 10,
|
|
NumberOfNulls: 0,
|
|
NumberOfDistinctValues: 10
|
|
}
|
|
}
|
|
}
|
|
]'
|
|
}
|
|
|
|
function_input() {
|
|
local owner="$1"
|
|
jq -n \
|
|
--arg name "$FUNCTION_NAME" \
|
|
--arg owner "$owner" \
|
|
'{
|
|
FunctionName: $name,
|
|
ClassName: "CatalogFunction",
|
|
OwnerName: $owner,
|
|
OwnerType: "USER",
|
|
ResourceUris: [
|
|
{
|
|
ResourceType: "FILE",
|
|
Uri: "s3://floci-glue-catalog/function.jar"
|
|
}
|
|
]
|
|
}'
|
|
}
|
|
|
|
@test "Glue catalog: database lifecycle" {
|
|
run create_database
|
|
assert_success
|
|
|
|
run aws_cmd glue get-database --name "$DB_NAME"
|
|
assert_success
|
|
name=$(json_get "$output" '.Database.Name')
|
|
[ "$name" = "$DB_NAME" ]
|
|
|
|
run aws_cmd glue get-databases
|
|
assert_success
|
|
found=$(echo "$output" | jq --arg name "$DB_NAME" '.DatabaseList | any(.Name == $name)')
|
|
[ "$found" = "true" ]
|
|
|
|
run aws_cmd glue update-database \
|
|
--name "$DB_NAME" \
|
|
--database-input "{\"Name\":\"$DB_NAME\",\"Description\":\"updated database\",\"LocationUri\":\"s3://floci-glue-catalog/$DB_NAME/\"}"
|
|
assert_success
|
|
|
|
run aws_cmd glue get-database --name "$DB_NAME"
|
|
assert_success
|
|
description=$(json_get "$output" '.Database.Description')
|
|
location=$(json_get "$output" '.Database.LocationUri')
|
|
[ "$description" = "updated database" ]
|
|
[ "$location" = "s3://floci-glue-catalog/$DB_NAME/" ]
|
|
|
|
run aws_cmd glue update-database \
|
|
--name "$DB_NAME" \
|
|
--database-input "{\"Name\":\"${DB_NAME}-renamed\",\"Description\":\"renamed database\"}"
|
|
assert_failure
|
|
[[ "$output" == *"InvalidInputException"* ]]
|
|
[[ "$output" == *"Database cannot be renamed"* ]]
|
|
|
|
run aws_cmd glue delete-database --name "$DB_NAME"
|
|
assert_success
|
|
|
|
run aws_cmd glue get-database --name "$DB_NAME"
|
|
assert_failure
|
|
}
|
|
|
|
@test "Glue catalog: table and partition lifecycle" {
|
|
run create_database
|
|
assert_success
|
|
|
|
run create_table
|
|
assert_success
|
|
|
|
run aws_cmd glue get-table \
|
|
--database-name "$DB_NAME" \
|
|
--name "$TABLE_NAME"
|
|
assert_success
|
|
name=$(json_get "$output" '.Table.Name')
|
|
version_id=$(json_get "$output" '.Table.VersionId')
|
|
column_comment=$(json_get "$output" '.Table.StorageDescriptor.Columns[0].Parameters.comment')
|
|
[ "$name" = "$TABLE_NAME" ]
|
|
[ "$version_id" = "0" ]
|
|
[ "$column_comment" = "identifier" ]
|
|
|
|
run aws_cmd glue get-tables --database-name "$DB_NAME"
|
|
assert_success
|
|
found=$(echo "$output" | jq --arg name "$TABLE_NAME" '.TableList | any(.Name == $name)')
|
|
[ "$found" = "true" ]
|
|
|
|
run aws_cmd glue update-table \
|
|
--database-name "$DB_NAME" \
|
|
--version-id "$version_id" \
|
|
--table-input "$(table_input "$TABLE_NAME" updated)"
|
|
assert_success
|
|
|
|
run aws_cmd glue get-table \
|
|
--database-name "$DB_NAME" \
|
|
--name "$TABLE_NAME"
|
|
assert_success
|
|
description=$(json_get "$output" '.Table.Description')
|
|
version_id=$(json_get "$output" '.Table.VersionId')
|
|
[ "$description" = "updated" ]
|
|
[ "$version_id" = "1" ]
|
|
|
|
run aws_cmd glue get-table-versions \
|
|
--database-name "$DB_NAME" \
|
|
--table-name "$TABLE_NAME"
|
|
assert_success
|
|
version_count=$(echo "$output" | jq '.TableVersions | length')
|
|
current_version=$(json_get "$output" '.TableVersions[0].VersionId')
|
|
current_description=$(json_get "$output" '.TableVersions[0].Table.Description')
|
|
archived_version=$(json_get "$output" '.TableVersions[1].VersionId')
|
|
archived_description=$(json_get "$output" '.TableVersions[1].Table.Description')
|
|
[ "$version_count" = "2" ]
|
|
[ "$current_version" = "1" ]
|
|
[ "$current_description" = "updated" ]
|
|
[ "$archived_version" = "0" ]
|
|
[ "$archived_description" = "created" ]
|
|
|
|
run aws_cmd glue update-column-statistics-for-table \
|
|
--database-name "$DB_NAME" \
|
|
--table-name "$TABLE_NAME" \
|
|
--column-statistics-list "$(column_statistics_input)"
|
|
assert_success
|
|
|
|
run aws_cmd glue get-column-statistics-for-table \
|
|
--database-name "$DB_NAME" \
|
|
--table-name "$TABLE_NAME" \
|
|
--column-names id missing
|
|
assert_success
|
|
column_name=$(json_get "$output" '.ColumnStatisticsList[0].ColumnName')
|
|
statistics_type=$(json_get "$output" '.ColumnStatisticsList[0].StatisticsData.Type')
|
|
minimum_value=$(json_get "$output" '.ColumnStatisticsList[0].StatisticsData.LongColumnStatisticsData.MinimumValue')
|
|
missing_column_name=$(json_get "$output" '.Errors[0].ColumnName')
|
|
error_code=$(json_get "$output" '.Errors[0].Error.ErrorCode')
|
|
[ "$column_name" = "id" ]
|
|
[ "$statistics_type" = "LONG" ]
|
|
[ "$minimum_value" = "1" ]
|
|
[ "$missing_column_name" = "missing" ]
|
|
[ "$error_code" = "EntityNotFoundException" ]
|
|
|
|
run aws_cmd glue delete-column-statistics-for-table \
|
|
--database-name "$DB_NAME" \
|
|
--table-name "$TABLE_NAME" \
|
|
--column-name id
|
|
assert_success
|
|
|
|
run aws_cmd glue delete-column-statistics-for-table \
|
|
--database-name "$DB_NAME" \
|
|
--table-name "$TABLE_NAME" \
|
|
--column-name id
|
|
assert_success
|
|
|
|
run aws_cmd glue get-column-statistics-for-table \
|
|
--database-name "$DB_NAME" \
|
|
--table-name "$TABLE_NAME" \
|
|
--column-names id
|
|
assert_success
|
|
deleted_statistics_count=$(json_get "$output" '.ColumnStatisticsList | length')
|
|
deleted_error_code=$(json_get "$output" '.Errors[0].Error.ErrorCode')
|
|
[ "$deleted_statistics_count" = "0" ]
|
|
[ "$deleted_error_code" = "EntityNotFoundException" ]
|
|
|
|
run aws_cmd glue create-partition \
|
|
--database-name "$DB_NAME" \
|
|
--table-name "$TABLE_NAME" \
|
|
--partition-input '{"Values":["2026"]}'
|
|
assert_success
|
|
|
|
run aws_cmd glue batch-create-partition \
|
|
--database-name "$DB_NAME" \
|
|
--table-name "$TABLE_NAME" \
|
|
--partition-input-list '[{"Values":["2027"]},{"Values":["2028"]}]'
|
|
assert_success
|
|
batch_create_error_count=$(json_get "$output" '.Errors | length')
|
|
[ "$batch_create_error_count" = "0" ]
|
|
|
|
run aws_cmd glue batch-create-partition \
|
|
--database-name "$DB_NAME" \
|
|
--table-name "$TABLE_NAME" \
|
|
--partition-input-list '[{"Values":["2027"]}]'
|
|
assert_success
|
|
duplicate_partition_value=$(json_get "$output" '.Errors[0].PartitionValues[0]')
|
|
duplicate_error_code=$(json_get "$output" '.Errors[0].ErrorDetail.ErrorCode')
|
|
[ "$duplicate_partition_value" = "2027" ]
|
|
[ "$duplicate_error_code" = "AlreadyExistsException" ]
|
|
|
|
batch_update_entries='[
|
|
{"PartitionValueList":["2026"],"PartitionInput":{"Values":["2026"],"Parameters":{"after":"yes"}}},
|
|
{"PartitionValueList":["missing"],"PartitionInput":{"Values":["missing"]}}
|
|
]'
|
|
run aws_cmd glue batch-update-partition \
|
|
--database-name "$DB_NAME" \
|
|
--table-name "$TABLE_NAME" \
|
|
--entries "$batch_update_entries"
|
|
assert_success
|
|
updated_missing_partition_value=$(json_get "$output" '.Errors[0].PartitionValueList[0]')
|
|
updated_missing_error_code=$(json_get "$output" '.Errors[0].ErrorDetail.ErrorCode')
|
|
[ "$updated_missing_partition_value" = "missing" ]
|
|
[ "$updated_missing_error_code" = "EntityNotFoundException" ]
|
|
|
|
run aws_cmd glue update-partition \
|
|
--database-name "$DB_NAME" \
|
|
--table-name "$TABLE_NAME" \
|
|
--partition-value-list 2027 \
|
|
--partition-input '{"Values":["2027"],"Parameters":{"updated":"yes"}}'
|
|
assert_success
|
|
|
|
run aws_cmd glue update-partition \
|
|
--database-name "$DB_NAME" \
|
|
--table-name "$TABLE_NAME" \
|
|
--partition-value-list missing \
|
|
--partition-input '{"Values":["missing"]}'
|
|
assert_failure
|
|
[[ "$output" == *"EntityNotFoundException"* ]]
|
|
|
|
run aws_cmd glue get-partitions \
|
|
--database-name "$DB_NAME" \
|
|
--table-name "$TABLE_NAME"
|
|
assert_success
|
|
value=$(json_get "$output" '.Partitions[0].Values[0]')
|
|
parameter=$(json_get "$output" '.Partitions[0].Parameters.after')
|
|
[ "$value" = "2026" ]
|
|
[ "$parameter" = "yes" ]
|
|
|
|
run aws_cmd glue get-partitions \
|
|
--database-name "$DB_NAME" \
|
|
--table-name "$TABLE_NAME" \
|
|
--expression "year >= 2026 AND year <= 2027"
|
|
assert_success
|
|
filtered_count=$(json_get "$output" '.Partitions | length')
|
|
[ "$filtered_count" = "2" ]
|
|
|
|
run aws_cmd glue get-partitions \
|
|
--database-name "$DB_NAME" \
|
|
--table-name "$TABLE_NAME" \
|
|
--expression "year in (2026, 2028)"
|
|
assert_success
|
|
filtered_count=$(json_get "$output" '.Partitions | length')
|
|
[ "$filtered_count" = "2" ]
|
|
|
|
run aws_cmd glue delete-table \
|
|
--database-name "$DB_NAME" \
|
|
--name "$TABLE_NAME"
|
|
assert_success
|
|
|
|
run aws_cmd glue get-table \
|
|
--database-name "$DB_NAME" \
|
|
--name "$TABLE_NAME"
|
|
assert_failure
|
|
|
|
run aws_cmd glue delete-table \
|
|
--database-name "$DB_NAME" \
|
|
--name "$TABLE_NAME"
|
|
assert_failure
|
|
[[ "$output" == *"EntityNotFoundException"* ]]
|
|
}
|
|
|
|
@test "Glue catalog: batch delete table" {
|
|
run create_database
|
|
assert_success
|
|
|
|
run create_table "$TABLE_NAME" "batch delete first table"
|
|
assert_success
|
|
|
|
run create_table "$SECOND_TABLE_NAME" "batch delete second table"
|
|
assert_success
|
|
|
|
run aws_cmd glue batch-delete-table \
|
|
--database-name "$DB_NAME" \
|
|
--tables-to-delete "$TABLE_NAME" "$SECOND_TABLE_NAME"
|
|
assert_success
|
|
error_count=$(echo "$output" | jq '.Errors | length')
|
|
[ "$error_count" = "0" ]
|
|
|
|
run aws_cmd glue get-table \
|
|
--database-name "$DB_NAME" \
|
|
--name "$TABLE_NAME"
|
|
assert_failure
|
|
|
|
run aws_cmd glue get-table \
|
|
--database-name "$DB_NAME" \
|
|
--name "$SECOND_TABLE_NAME"
|
|
assert_failure
|
|
}
|
|
|
|
@test "Glue catalog: user-defined function lifecycle" {
|
|
run create_database
|
|
assert_success
|
|
|
|
run aws_cmd glue create-user-defined-function \
|
|
--database-name "$DB_NAME" \
|
|
--function-input "$(function_input created-owner)"
|
|
assert_success
|
|
|
|
run aws_cmd glue get-user-defined-function \
|
|
--database-name "$DB_NAME" \
|
|
--function-name "$FUNCTION_NAME"
|
|
assert_success
|
|
name=$(json_get "$output" '.UserDefinedFunction.FunctionName')
|
|
owner=$(json_get "$output" '.UserDefinedFunction.OwnerName')
|
|
[ "$name" = "$FUNCTION_NAME" ]
|
|
[ "$owner" = "created-owner" ]
|
|
|
|
run aws_cmd glue get-user-defined-functions \
|
|
--database-name "$DB_NAME" \
|
|
--pattern "catalog_.*"
|
|
assert_success
|
|
found=$(echo "$output" | jq --arg name "$FUNCTION_NAME" '.UserDefinedFunctions | any(.FunctionName == $name)')
|
|
[ "$found" = "true" ]
|
|
|
|
run aws_cmd glue update-user-defined-function \
|
|
--database-name "$DB_NAME" \
|
|
--function-name "$FUNCTION_NAME" \
|
|
--function-input "$(function_input updated-owner)"
|
|
assert_success
|
|
|
|
run aws_cmd glue get-user-defined-function \
|
|
--database-name "$DB_NAME" \
|
|
--function-name "$FUNCTION_NAME"
|
|
assert_success
|
|
owner=$(json_get "$output" '.UserDefinedFunction.OwnerName')
|
|
[ "$owner" = "updated-owner" ]
|
|
|
|
run aws_cmd glue delete-user-defined-function \
|
|
--database-name "$DB_NAME" \
|
|
--function-name "$FUNCTION_NAME"
|
|
assert_success
|
|
|
|
run aws_cmd glue get-user-defined-function \
|
|
--database-name "$DB_NAME" \
|
|
--function-name "$FUNCTION_NAME"
|
|
assert_failure
|
|
}
|