Merge branch 'master' into gh-pages
This commit is contained in:
commit
edd3fe00b4
|
|
@ -9,7 +9,7 @@ assignees: ''
|
|||
|
||||
Please, answer some short questions which should help us to understand your problem / question better?
|
||||
|
||||
- **Which image of the operator are you using?** e.g. registry.opensource.zalan.do/acid/postgres-operator:v1.6.2
|
||||
- **Which image of the operator are you using?** e.g. registry.opensource.zalan.do/acid/postgres-operator:v1.6.3
|
||||
- **Where do you run it - cloud or metal? Kubernetes or OpenShift?** [AWS K8s | GCP ... | Bare Metal K8s]
|
||||
- **Are you running Postgres Operator in production?** [yes | no]
|
||||
- **Type of issue?** [Bug report, question, feature request, etc.]
|
||||
|
|
|
|||
2
Makefile
2
Makefile
|
|
@ -85,7 +85,7 @@ mocks:
|
|||
GO111MODULE=on go generate ./...
|
||||
|
||||
tools:
|
||||
GO111MODULE=on go get k8s.io/client-go@kubernetes-1.20.2
|
||||
GO111MODULE=on go get k8s.io/client-go@kubernetes-1.20.6
|
||||
GO111MODULE=on go get github.com/golang/mock/mockgen@v1.4.4
|
||||
GO111MODULE=on go mod tidy
|
||||
|
||||
|
|
|
|||
|
|
@ -15,7 +15,8 @@ pipelines with no access to Kubernetes API directly, promoting infrastructure as
|
|||
|
||||
* Rolling updates on Postgres cluster changes, incl. quick minor version updates
|
||||
* Live volume resize without pod restarts (AWS EBS, PVC)
|
||||
* Database connection pooler with PGBouncer
|
||||
* Database connection pooling with PGBouncer
|
||||
* Support fast in place major version upgrade to PG13. Supports global upgrade of all clusters.
|
||||
* Restore and cloning Postgres clusters (incl. major version upgrade)
|
||||
* Additionally logical backups to S3 bucket can be configured
|
||||
* Standby cluster from S3 WAL archive
|
||||
|
|
@ -24,11 +25,11 @@ pipelines with no access to Kubernetes API directly, promoting infrastructure as
|
|||
* Support for custom TLS certificates
|
||||
* UI to create and edit Postgres cluster manifests
|
||||
* Works well on Amazon AWS, Google Cloud, OpenShift and locally on Kind
|
||||
* Support for AWS EBS gp3 migration
|
||||
* Support for AWS EBS gp2 to gp3 migration, supporting iops and throughput configuration
|
||||
|
||||
### PostgreSQL features
|
||||
|
||||
* Supports PostgreSQL 13, starting from 9.5+
|
||||
* Supports PostgreSQL 13, starting from 9.6+
|
||||
* Streaming replication cluster via Patroni
|
||||
* Point-In-Time-Recovery with
|
||||
[pg_basebackup](https://www.postgresql.org/docs/11/app-pgbasebackup.html) /
|
||||
|
|
@ -65,7 +66,7 @@ We introduce the major version into the backup path to smoothen the [major versi
|
|||
The new operator configuration can set a compatibility flag *enable_spilo_wal_path_compat* to make Spilo look for wal segments in the current path but also old format paths.
|
||||
This comes at potential performance costs and should be disabled after a few days.
|
||||
|
||||
The newest Spilo 13 image is: `registry.opensource.zalan.do/acid/spilo-13:2.0-p6`
|
||||
The newest Spilo 13 image is: `registry.opensource.zalan.do/acid/spilo-13:2.0-p7`
|
||||
|
||||
The last Spilo 12 image is: `registry.opensource.zalan.do/acid/spilo-12:1.6-p5`
|
||||
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
apiVersion: v1
|
||||
name: postgres-operator-ui
|
||||
version: 1.6.2
|
||||
appVersion: 1.6.2
|
||||
version: 1.6.3
|
||||
appVersion: 1.6.3
|
||||
home: https://github.com/zalando/postgres-operator
|
||||
description: Postgres Operator UI provides a graphical interface for a convenient database-as-a-service user experience
|
||||
keywords:
|
||||
|
|
|
|||
|
|
@ -1,9 +1,31 @@
|
|||
apiVersion: v1
|
||||
entries:
|
||||
postgres-operator-ui:
|
||||
- apiVersion: v1
|
||||
appVersion: 1.6.3
|
||||
created: "2021-05-27T19:04:33.425637932+02:00"
|
||||
description: Postgres Operator UI provides a graphical interface for a convenient database-as-a-service user experience
|
||||
digest: 08b810aa632dcc719e4785ef184e391267f7c460caa99677f2d00719075aac78
|
||||
home: https://github.com/zalando/postgres-operator
|
||||
keywords:
|
||||
- postgres
|
||||
- operator
|
||||
- ui
|
||||
- cloud-native
|
||||
- patroni
|
||||
- spilo
|
||||
maintainers:
|
||||
- email: opensource@zalando.de
|
||||
name: Zalando
|
||||
name: postgres-operator-ui
|
||||
sources:
|
||||
- https://github.com/zalando/postgres-operator
|
||||
urls:
|
||||
- postgres-operator-ui-1.6.3.tgz
|
||||
version: 1.6.3
|
||||
- apiVersion: v1
|
||||
appVersion: 1.6.2
|
||||
created: "2021-04-06T16:47:40.993908218+02:00"
|
||||
created: "2021-05-27T19:04:33.422124263+02:00"
|
||||
description: Postgres Operator UI provides a graphical interface for a convenient database-as-a-service user experience
|
||||
digest: 14d1559bb0bd1e1e828f2daaaa6f6ac9ffc268d79824592c3589b55dd39241f6
|
||||
home: https://github.com/zalando/postgres-operator
|
||||
|
|
@ -25,7 +47,7 @@ entries:
|
|||
version: 1.6.2
|
||||
- apiVersion: v1
|
||||
appVersion: 1.6.1
|
||||
created: "2021-04-06T16:47:40.993378451+02:00"
|
||||
created: "2021-05-27T19:04:33.419640902+02:00"
|
||||
description: Postgres Operator UI provides a graphical interface for a convenient database-as-a-service user experience
|
||||
digest: 3d321352f2f1e7bb7450aa8876e3d818aa9f9da9bd4250507386f0490f2c1969
|
||||
home: https://github.com/zalando/postgres-operator
|
||||
|
|
@ -47,7 +69,7 @@ entries:
|
|||
version: 1.6.1
|
||||
- apiVersion: v1
|
||||
appVersion: 1.6.0
|
||||
created: "2021-04-06T16:47:40.992871656+02:00"
|
||||
created: "2021-05-27T19:04:33.41788193+02:00"
|
||||
description: Postgres Operator UI provides a graphical interface for a convenient database-as-a-service user experience
|
||||
digest: 1e0aa1e7db3c1daa96927ffbf6fdbcdb434562f961833cb5241ddbe132220ee4
|
||||
home: https://github.com/zalando/postgres-operator
|
||||
|
|
@ -69,7 +91,7 @@ entries:
|
|||
version: 1.6.0
|
||||
- apiVersion: v1
|
||||
appVersion: 1.5.0
|
||||
created: "2021-04-06T16:47:40.992346484+02:00"
|
||||
created: "2021-05-27T19:04:33.416056821+02:00"
|
||||
description: Postgres Operator UI provides a graphical interface for a convenient database-as-a-service user experience
|
||||
digest: c91ea39e6d51d57f4048fb1b6ec53b40823f2690eb88e4e4f1a036367b9fdd61
|
||||
home: https://github.com/zalando/postgres-operator
|
||||
|
|
@ -89,4 +111,4 @@ entries:
|
|||
urls:
|
||||
- postgres-operator-ui-1.5.0.tgz
|
||||
version: 1.5.0
|
||||
generated: "2021-04-06T16:47:40.991668273+02:00"
|
||||
generated: "2021-05-27T19:04:33.41380858+02:00"
|
||||
|
|
|
|||
Binary file not shown.
|
|
@ -8,7 +8,7 @@ replicaCount: 1
|
|||
image:
|
||||
registry: registry.opensource.zalan.do
|
||||
repository: acid/postgres-operator-ui
|
||||
tag: v1.6.2
|
||||
tag: v1.6.3
|
||||
pullPolicy: "IfNotPresent"
|
||||
|
||||
# Optionally specify an array of imagePullSecrets.
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
apiVersion: v1
|
||||
name: postgres-operator
|
||||
version: 1.6.2
|
||||
appVersion: 1.6.2
|
||||
version: 1.6.3
|
||||
appVersion: 1.6.3
|
||||
home: https://github.com/zalando/postgres-operator
|
||||
description: Postgres Operator creates and manages PostgreSQL clusters running in Kubernetes
|
||||
keywords:
|
||||
|
|
|
|||
|
|
@ -65,7 +65,7 @@ spec:
|
|||
properties:
|
||||
docker_image:
|
||||
type: string
|
||||
default: "registry.opensource.zalan.do/acid/spilo-13:2.0-p6"
|
||||
default: "registry.opensource.zalan.do/acid/spilo-13:2.0-p7"
|
||||
enable_crd_validation:
|
||||
type: boolean
|
||||
default: true
|
||||
|
|
@ -397,7 +397,7 @@ spec:
|
|||
properties:
|
||||
logical_backup_docker_image:
|
||||
type: string
|
||||
default: "registry.opensource.zalan.do/acid/logical-backup:v1.6.2"
|
||||
default: "registry.opensource.zalan.do/acid/logical-backup:v1.6.3"
|
||||
logical_backup_google_application_credentials:
|
||||
type: string
|
||||
logical_backup_job_prefix:
|
||||
|
|
@ -443,6 +443,9 @@ spec:
|
|||
enable_postgres_team_crd_superusers:
|
||||
type: boolean
|
||||
default: false
|
||||
enable_team_member_deprecation:
|
||||
type: boolean
|
||||
default: false
|
||||
enable_team_superuser:
|
||||
type: boolean
|
||||
default: false
|
||||
|
|
@ -465,6 +468,9 @@ spec:
|
|||
type: string
|
||||
default:
|
||||
- admin
|
||||
role_deletion_suffix:
|
||||
type: string
|
||||
default: "_deleted"
|
||||
team_admin_role:
|
||||
type: string
|
||||
default: "admin"
|
||||
|
|
|
|||
|
|
@ -27,7 +27,7 @@ spec:
|
|||
additionalPrinterColumns:
|
||||
- name: Team
|
||||
type: string
|
||||
description: Team responsible for Postgres CLuster
|
||||
description: Team responsible for Postgres cluster
|
||||
jsonPath: .spec.teamId
|
||||
- name: Version
|
||||
type: string
|
||||
|
|
|
|||
|
|
@ -1,9 +1,30 @@
|
|||
apiVersion: v1
|
||||
entries:
|
||||
postgres-operator:
|
||||
- apiVersion: v1
|
||||
appVersion: 1.6.3
|
||||
created: "2021-05-27T19:04:25.199523943+02:00"
|
||||
description: Postgres Operator creates and manages PostgreSQL clusters running in Kubernetes
|
||||
digest: ea08f991bf23c9ad114bca98ebcbe3e2fa15beab163061399394905eaee89b35
|
||||
home: https://github.com/zalando/postgres-operator
|
||||
keywords:
|
||||
- postgres
|
||||
- operator
|
||||
- cloud-native
|
||||
- patroni
|
||||
- spilo
|
||||
maintainers:
|
||||
- email: opensource@zalando.de
|
||||
name: Zalando
|
||||
name: postgres-operator
|
||||
sources:
|
||||
- https://github.com/zalando/postgres-operator
|
||||
urls:
|
||||
- postgres-operator-1.6.3.tgz
|
||||
version: 1.6.3
|
||||
- apiVersion: v1
|
||||
appVersion: 1.6.2
|
||||
created: "2021-03-30T17:00:50.171986449+02:00"
|
||||
created: "2021-05-27T19:04:25.198182197+02:00"
|
||||
description: Postgres Operator creates and manages PostgreSQL clusters running in Kubernetes
|
||||
digest: d886f8a0879ca07d1e5246ee7bc55710e1c872f3977280fe495db6fc2057a7f4
|
||||
home: https://github.com/zalando/postgres-operator
|
||||
|
|
@ -24,7 +45,7 @@ entries:
|
|||
version: 1.6.2
|
||||
- apiVersion: v1
|
||||
appVersion: 1.6.1
|
||||
created: "2021-03-30T17:00:50.170294515+02:00"
|
||||
created: "2021-05-27T19:04:25.19687586+02:00"
|
||||
description: Postgres Operator creates and manages PostgreSQL clusters running in Kubernetes
|
||||
digest: 4ba5972cd486dcaa2d11c5613a6f97f6b7b831822e610fe9e10a57ea1db23556
|
||||
home: https://github.com/zalando/postgres-operator
|
||||
|
|
@ -45,7 +66,7 @@ entries:
|
|||
version: 1.6.1
|
||||
- apiVersion: v1
|
||||
appVersion: 1.6.0
|
||||
created: "2021-03-30T17:00:50.168493689+02:00"
|
||||
created: "2021-05-27T19:04:25.195600766+02:00"
|
||||
description: Postgres Operator creates and manages PostgreSQL clusters running in Kubernetes
|
||||
digest: f52149718ea364f46b4b9eec9a65f6253ad182bb78df541d14cd5277b9c8a8c3
|
||||
home: https://github.com/zalando/postgres-operator
|
||||
|
|
@ -66,7 +87,7 @@ entries:
|
|||
version: 1.6.0
|
||||
- apiVersion: v1
|
||||
appVersion: 1.5.0
|
||||
created: "2021-03-30T17:00:50.166722286+02:00"
|
||||
created: "2021-05-27T19:04:25.193985032+02:00"
|
||||
description: Postgres Operator creates and manages PostgreSQL clusters running in Kubernetes
|
||||
digest: 198351d5db52e65cdf383d6f3e1745d91ac1e2a01121f8476f8b1be728b09531
|
||||
home: https://github.com/zalando/postgres-operator
|
||||
|
|
@ -85,4 +106,4 @@ entries:
|
|||
urls:
|
||||
- postgres-operator-1.5.0.tgz
|
||||
version: 1.5.0
|
||||
generated: "2021-03-30T17:00:50.165166707+02:00"
|
||||
generated: "2021-05-27T19:04:25.191897769+02:00"
|
||||
|
|
|
|||
Binary file not shown.
|
|
@ -1,7 +1,7 @@
|
|||
image:
|
||||
registry: registry.opensource.zalan.do
|
||||
repository: acid/postgres-operator
|
||||
tag: v1.6.2
|
||||
tag: v1.6.3
|
||||
pullPolicy: "IfNotPresent"
|
||||
|
||||
# Optionally specify an array of imagePullSecrets.
|
||||
|
|
@ -32,7 +32,7 @@ configGeneral:
|
|||
# Select if setup uses endpoints (default), or configmaps to manage leader (DCS=k8s)
|
||||
# kubernetes_use_configmaps: false
|
||||
# Spilo docker image
|
||||
docker_image: registry.opensource.zalan.do/acid/spilo-13:2.0-p6
|
||||
docker_image: registry.opensource.zalan.do/acid/spilo-13:2.0-p7
|
||||
# min number of instances in Postgres cluster. -1 = no limit
|
||||
min_instances: -1
|
||||
# max number of instances in Postgres cluster. -1 = no limit
|
||||
|
|
@ -263,7 +263,7 @@ configAwsOrGcp:
|
|||
# configure K8s cron job managed by the operator
|
||||
configLogicalBackup:
|
||||
# image for pods of the logical backup job (example runs pg_dumpall)
|
||||
logical_backup_docker_image: "registry.opensource.zalan.do/acid/logical-backup:v1.6.2"
|
||||
logical_backup_docker_image: "registry.opensource.zalan.do/acid/logical-backup:v1.6.3"
|
||||
# path of google cloud service account json file
|
||||
# logical_backup_google_application_credentials: ""
|
||||
|
||||
|
|
@ -289,13 +289,13 @@ configLogicalBackup:
|
|||
# automate creation of human users with teams API service
|
||||
configTeamsApi:
|
||||
# team_admin_role will have the rights to grant roles coming from PG manifests
|
||||
# enable_admin_role_for_users: true
|
||||
|
||||
enable_admin_role_for_users: true
|
||||
# operator watches for PostgresTeam CRs to assign additional teams and members to clusters
|
||||
enable_postgres_team_crd: false
|
||||
# toogle to create additional superuser teams from PostgresTeam CRs
|
||||
# enable_postgres_team_crd_superusers: false
|
||||
|
||||
enable_postgres_team_crd_superusers: false
|
||||
# toggle to automatically rename roles of former team members and deny LOGIN
|
||||
enable_team_member_deprecation: false
|
||||
# toggle to grant superuser to team members created from the Teams API
|
||||
enable_team_superuser: false
|
||||
# toggles usage of the Teams API by the operator
|
||||
|
|
@ -306,12 +306,13 @@ configTeamsApi:
|
|||
# operator will add all team member roles to this group and add a pg_hba line
|
||||
pam_role_name: zalandos
|
||||
# List of teams which members need the superuser role in each Postgres cluster
|
||||
# postgres_superuser_teams:
|
||||
# - postgres_superusers
|
||||
|
||||
postgres_superuser_teams:
|
||||
- postgres_superusers
|
||||
# List of roles that cannot be overwritten by an application, team or infrastructure role
|
||||
protected_role_names:
|
||||
- admin
|
||||
# Suffix to add if members are removed from TeamsAPI or PostgresTeam CRD
|
||||
role_deletion_suffix: "_deleted"
|
||||
# role name to grant to team members created from the Teams API
|
||||
team_admin_role: admin
|
||||
# postgres config parameters to apply to each team member role
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
image:
|
||||
registry: registry.opensource.zalan.do
|
||||
repository: acid/postgres-operator
|
||||
tag: v1.6.2
|
||||
tag: v1.6.3
|
||||
pullPolicy: "IfNotPresent"
|
||||
|
||||
# Optionally specify an array of imagePullSecrets.
|
||||
|
|
@ -35,7 +35,7 @@ configGeneral:
|
|||
# Select if setup uses endpoints (default), or configmaps to manage leader (DCS=k8s)
|
||||
# kubernetes_use_configmaps: "false"
|
||||
# Spilo docker image
|
||||
docker_image: registry.opensource.zalan.do/acid/spilo-13:2.0-p6
|
||||
docker_image: registry.opensource.zalan.do/acid/spilo-13:2.0-p7
|
||||
# min number of instances in Postgres cluster. -1 = no limit
|
||||
min_instances: "-1"
|
||||
# max number of instances in Postgres cluster. -1 = no limit
|
||||
|
|
@ -253,7 +253,7 @@ configAwsOrGcp:
|
|||
# configure K8s cron job managed by the operator
|
||||
configLogicalBackup:
|
||||
# image for pods of the logical backup job (example runs pg_dumpall)
|
||||
logical_backup_docker_image: "registry.opensource.zalan.do/acid/logical-backup:v1.6.2"
|
||||
logical_backup_docker_image: "registry.opensource.zalan.do/acid/logical-backup:v1.6.3"
|
||||
# path of google cloud service account json file
|
||||
# logical_backup_google_application_credentials: ""
|
||||
|
||||
|
|
@ -280,36 +280,32 @@ configLogicalBackup:
|
|||
# automate creation of human users with teams API service
|
||||
configTeamsApi:
|
||||
# team_admin_role will have the rights to grant roles coming from PG manifests
|
||||
# enable_admin_role_for_users: "true"
|
||||
|
||||
enable_admin_role_for_users: "true"
|
||||
# operator watches for PostgresTeam CRs to assign additional teams and members to clusters
|
||||
enable_postgres_team_crd: "false"
|
||||
# toogle to create additional superuser teams from PostgresTeam CRs
|
||||
# enable_postgres_team_crd_superusers: "false"
|
||||
|
||||
enable_postgres_team_crd_superusers: "false"
|
||||
# toggle to automatically rename roles of former team members and deny LOGIN
|
||||
enable_team_member_deprecation: "false"
|
||||
# toggle to grant superuser to team members created from the Teams API
|
||||
# enable_team_superuser: "false"
|
||||
|
||||
enable_team_superuser: "false"
|
||||
# toggles usage of the Teams API by the operator
|
||||
enable_teams_api: "false"
|
||||
# should contain a URL to use for authentication (username and token)
|
||||
# pam_configuration: https://info.example.com/oauth2/tokeninfo?access_token= uid realm=/employees
|
||||
|
||||
# operator will add all team member roles to this group and add a pg_hba line
|
||||
# pam_role_name: zalandos
|
||||
|
||||
pam_role_name: "zalandos"
|
||||
# List of teams which members need the superuser role in each Postgres cluster
|
||||
# postgres_superuser_teams: "postgres_superusers"
|
||||
|
||||
postgres_superuser_teams: "postgres_superusers"
|
||||
# List of roles that cannot be overwritten by an application, team or infrastructure role
|
||||
# protected_role_names: "admin"
|
||||
|
||||
protected_role_names: "admin"
|
||||
# Suffix to add if members are removed from TeamsAPI or PostgresTeam CRD
|
||||
role_deletion_suffix: "_deleted"
|
||||
# role name to grant to team members created from the Teams API
|
||||
# team_admin_role: "admin"
|
||||
|
||||
team_admin_role: "admin"
|
||||
# postgres config parameters to apply to each team member role
|
||||
# team_api_role_configuration: "log_statement:all"
|
||||
|
||||
team_api_role_configuration: "log_statement:all"
|
||||
# URL of the Teams API service
|
||||
# teams_api_url: http://fake-teams-api.default.svc.cluster.local
|
||||
|
||||
|
|
|
|||
|
|
@ -950,7 +950,7 @@ make docker
|
|||
|
||||
# build in image in minikube docker env
|
||||
eval $(minikube docker-env)
|
||||
docker build -t registry.opensource.zalan.do/acid/postgres-operator-ui:v1.6.2 .
|
||||
docker build -t registry.opensource.zalan.do/acid/postgres-operator-ui:v1.6.3 .
|
||||
|
||||
# apply UI manifests next to a running Postgres Operator
|
||||
kubectl apply -f manifests/
|
||||
|
|
|
|||
|
|
@ -593,7 +593,7 @@ grouped under the `logical_backup` key.
|
|||
runs `pg_dumpall` on a replica if possible and uploads compressed results to
|
||||
an S3 bucket under the key `/spilo/pg_cluster_name/cluster_k8s_uuid/logical_backups`.
|
||||
The default image is the same image built with the Zalando-internal CI
|
||||
pipeline. Default: "registry.opensource.zalan.do/acid/logical-backup:v1.6.2"
|
||||
pipeline. Default: "registry.opensource.zalan.do/acid/logical-backup:v1.6.3"
|
||||
|
||||
* **logical_backup_google_application_credentials**
|
||||
Specifies the path of the google cloud service account json file. Default is empty.
|
||||
|
|
@ -704,6 +704,19 @@ key.
|
|||
cluster to administer Postgres and maintain infrastructure built around it.
|
||||
The default is empty.
|
||||
|
||||
* **role_deletion_suffix**
|
||||
defines a suffix that - when `enable_team_member_deprecation` is set to
|
||||
`true` - will be appended to database role names of team members that were
|
||||
removed from either the team in the Teams API or a `PostgresTeam` custom
|
||||
resource (additionalMembers). When re-added, the operator will rename roles
|
||||
with the defined suffix back to the original role name.
|
||||
The default is `_deleted`.
|
||||
|
||||
* **enable_team_member_deprecation**
|
||||
if `true` database roles of former team members will be renamed by appending
|
||||
the configured `role_deletion_suffix` and `LOGIN` privilege will be revoked.
|
||||
The default is `false`.
|
||||
|
||||
* **enable_postgres_team_crd**
|
||||
toggle to make the operator watch for created or updated `PostgresTeam` CRDs
|
||||
and create roles for specified additional teams and members.
|
||||
|
|
|
|||
17
docs/user.md
17
docs/user.md
|
|
@ -407,6 +407,23 @@ spec:
|
|||
- "briggs"
|
||||
```
|
||||
|
||||
#### Removed members
|
||||
|
||||
The Postgres Operator does not delete database roles when users are removed
|
||||
from manifests. But, using the `PostgresTeam` custom resource or Teams API it
|
||||
is very easy to add roles to many clusters. Manually reverting such a change
|
||||
is cumbersome. Therefore, if members are removed from a `PostgresTeam` or the
|
||||
Teams API the operator can rename roles appending a configured suffix to the
|
||||
name (see `role_deletion_suffix` option) and revoke the `LOGIN` privilege.
|
||||
The suffix makes it easy then for a cleanup script to remove those deprecated
|
||||
roles completely. Switch `enable_team_member_deprecation` to `true` to enable
|
||||
this behavior.
|
||||
|
||||
When a role is re-added to a `PostgresTeam` manifest (or to the source behind
|
||||
the Teams API) the operator will check for roles with the configured suffix
|
||||
and if found, rename the role back to the original name and grant `LOGIN`
|
||||
again.
|
||||
|
||||
## Prepared databases with roles and default privileges
|
||||
|
||||
The `users` section in the manifests only allows for creating database roles
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
kubernetes==11.0.0
|
||||
timeout_decorator==0.4.1
|
||||
pyyaml==5.3.1
|
||||
pyyaml==5.4.1
|
||||
|
|
|
|||
|
|
@ -197,7 +197,9 @@ class EndToEndTestCase(unittest.TestCase):
|
|||
enable_postgres_team_crd = {
|
||||
"data": {
|
||||
"enable_postgres_team_crd": "true",
|
||||
"resync_period": "15s",
|
||||
"enable_team_member_deprecation": "true",
|
||||
"role_deletion_suffix": "_delete_me",
|
||||
"resync_period": "15s"
|
||||
},
|
||||
}
|
||||
self.k8s.update_config(enable_postgres_team_crd)
|
||||
|
|
@ -222,18 +224,60 @@ class EndToEndTestCase(unittest.TestCase):
|
|||
}
|
||||
})
|
||||
|
||||
# make sure we let one sync pass and the new user being added
|
||||
time.sleep(15)
|
||||
|
||||
leader = self.k8s.get_cluster_leader_pod()
|
||||
user_query = """
|
||||
SELECT usename
|
||||
FROM pg_catalog.pg_user
|
||||
WHERE usename IN ('elephant', 'kind');
|
||||
SELECT rolname
|
||||
FROM pg_catalog.pg_roles
|
||||
WHERE rolname IN ('elephant', 'kind');
|
||||
"""
|
||||
users = self.query_database(leader.metadata.name, "postgres", user_query)
|
||||
self.eventuallyEqual(lambda: len(users), 2,
|
||||
"Not all additional users found in database: {}".format(users))
|
||||
self.eventuallyEqual(lambda: len(self.query_database(leader.metadata.name, "postgres", user_query)), 2,
|
||||
"Not all additional users found in database", 10, 5)
|
||||
|
||||
# replace additional member and check if the removed member's role is renamed
|
||||
self.k8s.api.custom_objects_api.patch_namespaced_custom_object(
|
||||
'acid.zalan.do', 'v1', 'default',
|
||||
'postgresteams', 'custom-team-membership',
|
||||
{
|
||||
'spec': {
|
||||
'additionalMembers': {
|
||||
'e2e': [
|
||||
'tester'
|
||||
]
|
||||
},
|
||||
}
|
||||
})
|
||||
|
||||
user_query = """
|
||||
SELECT rolname
|
||||
FROM pg_catalog.pg_roles
|
||||
WHERE (rolname = 'tester' AND rolcanlogin)
|
||||
OR (rolname = 'kind_delete_me' AND NOT rolcanlogin);
|
||||
"""
|
||||
self.eventuallyEqual(lambda: len(self.query_database(leader.metadata.name, "postgres", user_query)), 2,
|
||||
"Database role of replaced member in PostgresTeam not renamed", 10, 5)
|
||||
|
||||
# re-add additional member and check if the role is renamed back
|
||||
self.k8s.api.custom_objects_api.patch_namespaced_custom_object(
|
||||
'acid.zalan.do', 'v1', 'default',
|
||||
'postgresteams', 'custom-team-membership',
|
||||
{
|
||||
'spec': {
|
||||
'additionalMembers': {
|
||||
'e2e': [
|
||||
'kind'
|
||||
]
|
||||
},
|
||||
}
|
||||
})
|
||||
|
||||
user_query = """
|
||||
SELECT rolname
|
||||
FROM pg_catalog.pg_roles
|
||||
WHERE (rolname = 'kind' AND rolcanlogin)
|
||||
OR (rolname = 'tester_delete_me' AND NOT rolcanlogin);
|
||||
"""
|
||||
self.eventuallyEqual(lambda: len(self.query_database(leader.metadata.name, "postgres", user_query)), 2,
|
||||
"Database role of recreated member in PostgresTeam not renamed back to original name", 10, 5)
|
||||
|
||||
# revert config change
|
||||
revert_resync = {
|
||||
|
|
@ -407,9 +451,9 @@ class EndToEndTestCase(unittest.TestCase):
|
|||
|
||||
leader = k8s.get_cluster_leader_pod()
|
||||
schemas_query = """
|
||||
select schema_name
|
||||
from information_schema.schemata
|
||||
where schema_name = 'pooler'
|
||||
SELECT schema_name
|
||||
FROM information_schema.schemata
|
||||
WHERE schema_name = 'pooler'
|
||||
"""
|
||||
|
||||
db_list = self.list_databases(leader.metadata.name)
|
||||
|
|
@ -529,6 +573,7 @@ class EndToEndTestCase(unittest.TestCase):
|
|||
"Parameters": None,
|
||||
"AdminRole": "",
|
||||
"Origin": 2,
|
||||
"Deleted": False
|
||||
})
|
||||
return True
|
||||
except:
|
||||
|
|
@ -1417,7 +1462,7 @@ class EndToEndTestCase(unittest.TestCase):
|
|||
k8s = self.k8s
|
||||
result_set = []
|
||||
db_list = []
|
||||
db_list_query = "select datname from pg_database"
|
||||
db_list_query = "SELECT datname FROM pg_database"
|
||||
exec_query = r"psql -tAq -c \"{}\" -d {}"
|
||||
|
||||
try:
|
||||
|
|
|
|||
11
go.mod
11
go.mod
|
|
@ -12,11 +12,10 @@ require (
|
|||
github.com/stretchr/testify v1.6.1
|
||||
golang.org/x/crypto v0.0.0-20201203163018-be400aefbc4c
|
||||
golang.org/x/mod v0.4.0 // indirect
|
||||
golang.org/x/tools v0.0.0-20201207204333-a835c872fcea // indirect
|
||||
gopkg.in/yaml.v2 v2.4.0
|
||||
k8s.io/api v0.20.2
|
||||
k8s.io/apiextensions-apiserver v0.19.4
|
||||
k8s.io/apimachinery v0.20.2
|
||||
k8s.io/client-go v0.20.2
|
||||
k8s.io/code-generator v0.19.4
|
||||
k8s.io/api v0.20.6
|
||||
k8s.io/apiextensions-apiserver v0.20.6
|
||||
k8s.io/apimachinery v0.20.6
|
||||
k8s.io/client-go v0.20.6
|
||||
k8s.io/code-generator v0.20.6
|
||||
)
|
||||
|
|
|
|||
200
go.sum
200
go.sum
|
|
@ -6,7 +6,6 @@ cloud.google.com/go v0.44.2/go.mod h1:60680Gw3Yr4ikxnPRS/oxxkBccT6SA1yMk63TGekxK
|
|||
cloud.google.com/go v0.45.1/go.mod h1:RpBamKRgapWJb87xiFSdk4g1CME7QZg3uwTez+TSTjc=
|
||||
cloud.google.com/go v0.46.3/go.mod h1:a6bKKbmY7er1mI7TEI4lsAkts/mkhTSZK8w33B4RAg0=
|
||||
cloud.google.com/go v0.50.0/go.mod h1:r9sluTvynVuxRIOHXQEHMFffphuXHOMZMycpNR5e6To=
|
||||
cloud.google.com/go v0.51.0/go.mod h1:hWtGJ6gnXH+KgDv+V0zFGDvpi07n3z8ZNj3T1RW0Gcw=
|
||||
cloud.google.com/go v0.52.0/go.mod h1:pXajvRH/6o3+F9jDHZWQ5PbGhn+o8w9qiu/CffaVdO4=
|
||||
cloud.google.com/go v0.53.0/go.mod h1:fp/UouUEsRkN6ryDKNW/Upv/JBKnv6WDthjR6+vze6M=
|
||||
cloud.google.com/go v0.54.0/go.mod h1:1rq2OEkV3YMf6n/9ZvGWI3GWw0VoqH/1x2nd8Is/bPc=
|
||||
|
|
@ -15,6 +14,7 @@ cloud.google.com/go/bigquery v1.3.0/go.mod h1:PjpwJnslEMmckchkHFfq+HTD2DmtT67aNF
|
|||
cloud.google.com/go/bigquery v1.4.0/go.mod h1:S8dzgnTigyfTmLBfrtrhyYhwRxG72rYxvftPBK2Dvzc=
|
||||
cloud.google.com/go/datastore v1.0.0/go.mod h1:LXYbyblFSglQ5pkeyhO+Qmw7ukd3C+pD7TKLgZqpHYE=
|
||||
cloud.google.com/go/datastore v1.1.0/go.mod h1:umbIZjpQpHh4hmRpGhH4tLFup+FVzqBi1b3c64qFpCk=
|
||||
cloud.google.com/go/firestore v1.1.0/go.mod h1:ulACoGHTpvq5r8rxGJ4ddJZBZqakUQqClKRT5SZwBmk=
|
||||
cloud.google.com/go/pubsub v1.0.1/go.mod h1:R0Gpsv3s54REJCy4fxDixWD93lHJMoZTyQ2kNxGRt3I=
|
||||
cloud.google.com/go/pubsub v1.1.0/go.mod h1:EwwdRX2sKPjnvnqCa270oGRyludottCI76h+R3AArQw=
|
||||
cloud.google.com/go/pubsub v1.2.0/go.mod h1:jhfEVHT8odbXTkndysNHCcx0awwzvfOlguIAii9o8iA=
|
||||
|
|
@ -24,44 +24,29 @@ cloud.google.com/go/storage v1.6.0/go.mod h1:N7U0C8pVQ/+NIKOBQyamJIeKQKkZ+mxpohl
|
|||
dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU=
|
||||
github.com/Azure/go-ansiterm v0.0.0-20170929234023-d6e3b3328b78/go.mod h1:LmzpDX56iTiv29bbRTIsUNlaFfuhWRQBWjQdVyAevI8=
|
||||
github.com/Azure/go-autorest v14.2.0+incompatible/go.mod h1:r+4oMnoxhatjLLJ6zxSWATqVooLgysK6ZNox3g/xq24=
|
||||
github.com/Azure/go-autorest/autorest v0.9.0/go.mod h1:xyHB1BMZT0cuDHU7I0+g046+BFDTQ8rEZB0s4Yfa6bI=
|
||||
github.com/Azure/go-autorest/autorest v0.9.6/go.mod h1:/FALq9T/kS7b5J5qsQ+RSTUdAmGFqi0vUdVNNx8q630=
|
||||
github.com/Azure/go-autorest/autorest v0.11.1/go.mod h1:JFgpikqFJ/MleTTxwepExTKnFUKKszPS8UavbQYUMuw=
|
||||
github.com/Azure/go-autorest/autorest/adal v0.5.0/go.mod h1:8Z9fGy2MpX0PvDjB1pEgQTmVqjGhiHBW7RJJEciWzS0=
|
||||
github.com/Azure/go-autorest/autorest/adal v0.8.2/go.mod h1:ZjhuQClTqx435SRJ2iMlOxPYt3d2C/T/7TiQCVZSn3Q=
|
||||
github.com/Azure/go-autorest/autorest/adal v0.9.0/go.mod h1:/c022QCutn2P7uY+/oQWWNcK9YU+MH96NgK+jErpbcg=
|
||||
github.com/Azure/go-autorest/autorest/adal v0.9.5/go.mod h1:B7KF7jKIeC9Mct5spmyCB/A8CG/sEz1vwIRGv/bbw7A=
|
||||
github.com/Azure/go-autorest/autorest/date v0.1.0/go.mod h1:plvfp3oPSKwf2DNjlBjWF/7vwR+cUD/ELuzDCXwHUVA=
|
||||
github.com/Azure/go-autorest/autorest/date v0.2.0/go.mod h1:vcORJHLJEh643/Ioh9+vPmf1Ij9AEBM5FuBIXLmIy0g=
|
||||
github.com/Azure/go-autorest/autorest/date v0.3.0/go.mod h1:BI0uouVdmngYNUzGWeSYnokU+TrmwEsOqdt8Y6sso74=
|
||||
github.com/Azure/go-autorest/autorest/mocks v0.1.0/go.mod h1:OTyCOPRA2IgIlWxVYxBee2F5Gr4kF2zd2J5cFRaIDN0=
|
||||
github.com/Azure/go-autorest/autorest/mocks v0.2.0/go.mod h1:OTyCOPRA2IgIlWxVYxBee2F5Gr4kF2zd2J5cFRaIDN0=
|
||||
github.com/Azure/go-autorest/autorest/mocks v0.3.0/go.mod h1:a8FDP3DYzQ4RYfVAxAN3SVSiiO77gL2j2ronKKP0syM=
|
||||
github.com/Azure/go-autorest/autorest/mocks v0.4.0/go.mod h1:LTp+uSrOhSkaKrUy935gNZuuIPPVsHlr9DSOxSayd+k=
|
||||
github.com/Azure/go-autorest/autorest/mocks v0.4.1/go.mod h1:LTp+uSrOhSkaKrUy935gNZuuIPPVsHlr9DSOxSayd+k=
|
||||
github.com/Azure/go-autorest/logger v0.1.0/go.mod h1:oExouG+K6PryycPJfVSxi/koC6LSNgds39diKLz7Vrc=
|
||||
github.com/Azure/go-autorest/logger v0.2.0/go.mod h1:T9E3cAhj2VqvPOtCYAvby9aBXkZmbF5NWuPV8+WeEW8=
|
||||
github.com/Azure/go-autorest/tracing v0.5.0/go.mod h1:r/s2XiOKccPW3HrqB+W0TQzfbtp2fGCgRFtBroKn4Dk=
|
||||
github.com/Azure/go-autorest/tracing v0.6.0/go.mod h1:+vhtPC754Xsa23ID7GlGsrdKBpUA79WCAKPPZVC2DeU=
|
||||
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
|
||||
github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo=
|
||||
github.com/NYTimes/gziphandler v0.0.0-20170623195520-56545f4a5d46/go.mod h1:3wb06e3pkSAbeQ52E9H9iFoQsEEwGN64994WTCIhntQ=
|
||||
github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU=
|
||||
github.com/PuerkitoBio/purell v1.0.0/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbtSwDGJws/X0=
|
||||
github.com/PuerkitoBio/purell v1.1.0/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbtSwDGJws/X0=
|
||||
github.com/PuerkitoBio/purell v1.1.1 h1:WEQqlqaGbrPkxLJWfBwQmfEAE1Z7ONdDLqrN38tNFfI=
|
||||
github.com/PuerkitoBio/purell v1.1.1/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbtSwDGJws/X0=
|
||||
github.com/PuerkitoBio/urlesc v0.0.0-20160726150825-5bd2802263f2/go.mod h1:uGdkoq3SwY9Y+13GIhn11/XLaGBb4BfwItxLd5jeuXE=
|
||||
github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578 h1:d+Bc7a5rLufV/sSk/8dngufqelfh6jnri85riMAaF/M=
|
||||
github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578/go.mod h1:uGdkoq3SwY9Y+13GIhn11/XLaGBb4BfwItxLd5jeuXE=
|
||||
github.com/agnivade/levenshtein v1.0.1/go.mod h1:CURSv5d9Uaml+FovSIICkLbAUZ9S4RqaHDIsdSBg7lM=
|
||||
github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
|
||||
github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
|
||||
github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
|
||||
github.com/alecthomas/units v0.0.0-20190717042225-c3de453c63f4/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
|
||||
github.com/andreyvit/diff v0.0.0-20170406064948-c7f18ee00883/go.mod h1:rCTlJbsFo29Kk6CurOXKm700vrz8f0KW0JNfpkRJY/8=
|
||||
github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6/go.mod h1:grANhF5doyWs3UAsr3K4I6qtAmlQcZDesFNEHPZAzj8=
|
||||
github.com/asaskevich/govalidator v0.0.0-20180720115003-f9ffefc3facf/go.mod h1:lB+ZfQJz7igIIfQNfa7Ml4HSf2uFQQRzpGGRXenZAgY=
|
||||
github.com/armon/circbuf v0.0.0-20150827004946-bbbad097214e/go.mod h1:3U/XgcO3hCbHZ8TKRvWD2dDTCfh9M9ya+I9JpbB7O8o=
|
||||
github.com/armon/go-metrics v0.0.0-20180917152333-f0300d1749da/go.mod h1:Q73ZrmVTwzkszR9V5SSuryQ31EELlFMUz1kKyl939pY=
|
||||
github.com/armon/go-radix v0.0.0-20180808171621-7fddfc383310/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8=
|
||||
github.com/asaskevich/govalidator v0.0.0-20190424111038-f61b66f89f4a/go.mod h1:lB+ZfQJz7igIIfQNfa7Ml4HSf2uFQQRzpGGRXenZAgY=
|
||||
github.com/aws/aws-sdk-go v1.36.29 h1:lM1G3AF1+7vzFm0n7hfH8r2+750BTo+6Lo6FtPB7kzk=
|
||||
github.com/aws/aws-sdk-go v1.36.29/go.mod h1:hcU610XS61/+aQV88ixoOzUoG7v3b31pl2zKMmprdro=
|
||||
|
|
@ -69,7 +54,8 @@ github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24
|
|||
github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8=
|
||||
github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw=
|
||||
github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs=
|
||||
github.com/blang/semver v3.5.0+incompatible/go.mod h1:kRBLl5iJ+tD4TcOOxsy/0fnwebNt5EWlYSAyrTnjyyk=
|
||||
github.com/bketelsen/crypt v0.0.3-0.20200106085610-5cbc8cc4026c/go.mod h1:MKsuJmJgSg28kpZDP6UIiPt0e0Oz0kqKNGyRaWEPv84=
|
||||
github.com/blang/semver v3.5.1+incompatible/go.mod h1:kRBLl5iJ+tD4TcOOxsy/0fnwebNt5EWlYSAyrTnjyyk=
|
||||
github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
|
||||
github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc=
|
||||
github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
|
||||
|
|
@ -79,7 +65,7 @@ github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMn
|
|||
github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
|
||||
github.com/cockroachdb/datadriven v0.0.0-20190809214429-80d97fb3cbaa/go.mod h1:zn76sxSg3SzpJ0PPJaLDCu+Bu0Lg3sKTORVIj19EIF8=
|
||||
github.com/coreos/bbolt v1.3.2/go.mod h1:iRUV2dpdMOn7Bo10OQBFzIJO9kkE559Wcmn+qkEiiKk=
|
||||
github.com/coreos/etcd v3.3.10+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE=
|
||||
github.com/coreos/etcd v3.3.13+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE=
|
||||
github.com/coreos/go-oidc v2.1.0+incompatible/go.mod h1:CgnwVTmzoESiwO9qyAFEMiHoZ1nMCKZlZ9V6mm3/LKc=
|
||||
github.com/coreos/go-semver v0.2.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk=
|
||||
github.com/coreos/go-semver v0.3.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk=
|
||||
|
|
@ -94,8 +80,6 @@ github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c
|
|||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ=
|
||||
github.com/dgryski/go-sip13 v0.0.0-20181026042036-e10d5fee7954/go.mod h1:vAd38F8PWV+bWy6jNmig1y/TA+kYO4g3RSRF0IAv0no=
|
||||
github.com/docker/go-units v0.3.3/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk=
|
||||
github.com/docker/go-units v0.4.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk=
|
||||
github.com/docker/spdystream v0.0.0-20160310174837-449fdfce4d96 h1:cenwrSVm+Z7QLSV/BsnenAOcDXdX4cMv4wP0B/5QbPg=
|
||||
github.com/docker/spdystream v0.0.0-20160310174837-449fdfce4d96/go.mod h1:Qh8CwZgvJUkLughtfhJv5dyTYa91l1fOUCrgjqmcifM=
|
||||
github.com/docopt/docopt-go v0.0.0-20180111231733-ee0de3bc6815/go.mod h1:WwZ+bS3ebgob9U8Nd0kOddGdZWjyMGR8Wziv+TBNwSE=
|
||||
|
|
@ -117,8 +101,6 @@ github.com/fsnotify/fsnotify v1.4.9 h1:hsms1Qyu0jgnwNXIxa+/V/PDsU6CfLf6CNO8H7IWo
|
|||
github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ=
|
||||
github.com/ghodss/yaml v0.0.0-20150909031657-73d445a93680/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
|
||||
github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
|
||||
github.com/globalsign/mgo v0.0.0-20180905125535-1ca0a4f7cbcb/go.mod h1:xkRDCp4j0OGD1HRkm4kmhM+pmpv3AKq5SU7GMg4oO/Q=
|
||||
github.com/globalsign/mgo v0.0.0-20181015135952-eeefdecb41b8/go.mod h1:xkRDCp4j0OGD1HRkm4kmhM+pmpv3AKq5SU7GMg4oO/Q=
|
||||
github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU=
|
||||
github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8=
|
||||
github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8=
|
||||
|
|
@ -129,58 +111,22 @@ github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V
|
|||
github.com/go-logr/logr v0.1.0/go.mod h1:ixOQHD9gLJUVQQ2ZOR7zLEifBX6tGkNJF4QyIY7sIas=
|
||||
github.com/go-logr/logr v0.2.0 h1:QvGt2nLcHH0WK9orKa+ppBPAxREcH364nPUedEpK0TY=
|
||||
github.com/go-logr/logr v0.2.0/go.mod h1:z6/tIYblkpsD+a4lm/fGIIU9mZ+XfAiaFtq7xTgseGU=
|
||||
github.com/go-openapi/analysis v0.0.0-20180825180245-b006789cd277/go.mod h1:k70tL6pCuVxPJOHXQ+wIac1FUrvNkHolPie/cLEU6hI=
|
||||
github.com/go-openapi/analysis v0.17.0/go.mod h1:IowGgpVeD0vNm45So8nr+IcQ3pxVtpRoBWb8PVZO0ik=
|
||||
github.com/go-openapi/analysis v0.18.0/go.mod h1:IowGgpVeD0vNm45So8nr+IcQ3pxVtpRoBWb8PVZO0ik=
|
||||
github.com/go-openapi/analysis v0.19.2/go.mod h1:3P1osvZa9jKjb8ed2TPng3f0i/UY9snX6gxi44djMjk=
|
||||
github.com/go-openapi/analysis v0.19.5/go.mod h1:hkEAkxagaIvIP7VTn8ygJNkd4kAYON2rCu0v0ObL0AU=
|
||||
github.com/go-openapi/errors v0.17.0/go.mod h1:LcZQpmvG4wyF5j4IhA73wkLFQg+QJXOQHVjmcZxhka0=
|
||||
github.com/go-openapi/errors v0.18.0/go.mod h1:LcZQpmvG4wyF5j4IhA73wkLFQg+QJXOQHVjmcZxhka0=
|
||||
github.com/go-openapi/errors v0.19.2/go.mod h1:qX0BLWsyaKfvhluLejVpVNwNRdXZhEbTA4kxxpKBC94=
|
||||
github.com/go-openapi/jsonpointer v0.0.0-20160704185906-46af16f9f7b1/go.mod h1:+35s3my2LFTysnkMfxsJBAMHj/DoqoB9knIWoYG/Vk0=
|
||||
github.com/go-openapi/jsonpointer v0.17.0/go.mod h1:cOnomiV+CVVwFLk0A/MExoFMjwdsUdVpsRhURCKh+3M=
|
||||
github.com/go-openapi/jsonpointer v0.18.0/go.mod h1:cOnomiV+CVVwFLk0A/MExoFMjwdsUdVpsRhURCKh+3M=
|
||||
github.com/go-openapi/jsonpointer v0.19.2/go.mod h1:3akKfEdA7DF1sugOqz1dVQHBcuDBPKZGEoHC/NkiQRg=
|
||||
github.com/go-openapi/jsonpointer v0.19.3 h1:gihV7YNZK1iK6Tgwwsxo2rJbD1GTbdm72325Bq8FI3w=
|
||||
github.com/go-openapi/jsonpointer v0.19.3/go.mod h1:Pl9vOtqEWErmShwVjC8pYs9cog34VGT37dQOVbmoatg=
|
||||
github.com/go-openapi/jsonreference v0.0.0-20160704190145-13c6e3589ad9/go.mod h1:W3Z9FmVs9qj+KR4zFKmDPGiLdk1D9Rlm7cyMvf57TTg=
|
||||
github.com/go-openapi/jsonreference v0.17.0/go.mod h1:g4xxGn04lDIRh0GJb5QlpE3HfopLOL6uZrK/VgnsK9I=
|
||||
github.com/go-openapi/jsonreference v0.18.0/go.mod h1:g4xxGn04lDIRh0GJb5QlpE3HfopLOL6uZrK/VgnsK9I=
|
||||
github.com/go-openapi/jsonreference v0.19.2/go.mod h1:jMjeRr2HHw6nAVajTXJ4eiUwohSTlpa0o73RUL1owJc=
|
||||
github.com/go-openapi/jsonreference v0.19.3 h1:5cxNfTy0UVC3X8JL5ymxzyoUZmo8iZb+jeTWn7tUa8o=
|
||||
github.com/go-openapi/jsonreference v0.19.3/go.mod h1:rjx6GuL8TTa9VaixXglHmQmIL98+wF9xc8zWvFonSJ8=
|
||||
github.com/go-openapi/loads v0.17.0/go.mod h1:72tmFy5wsWx89uEVddd0RjRWPZm92WRLhf7AC+0+OOU=
|
||||
github.com/go-openapi/loads v0.18.0/go.mod h1:72tmFy5wsWx89uEVddd0RjRWPZm92WRLhf7AC+0+OOU=
|
||||
github.com/go-openapi/loads v0.19.0/go.mod h1:72tmFy5wsWx89uEVddd0RjRWPZm92WRLhf7AC+0+OOU=
|
||||
github.com/go-openapi/loads v0.19.2/go.mod h1:QAskZPMX5V0C2gvfkGZzJlINuP7Hx/4+ix5jWFxsNPs=
|
||||
github.com/go-openapi/loads v0.19.4/go.mod h1:zZVHonKd8DXyxyw4yfnVjPzBjIQcLt0CCsn0N0ZrQsk=
|
||||
github.com/go-openapi/runtime v0.0.0-20180920151709-4f900dc2ade9/go.mod h1:6v9a6LTXWQCdL8k1AO3cvqx5OtZY/Y9wKTgaoP6YRfA=
|
||||
github.com/go-openapi/runtime v0.19.0/go.mod h1:OwNfisksmmaZse4+gpV3Ne9AyMOlP1lt4sK4FXt0O64=
|
||||
github.com/go-openapi/runtime v0.19.4/go.mod h1:X277bwSUBxVlCYR3r7xgZZGKVvBd/29gLDlFGtJ8NL4=
|
||||
github.com/go-openapi/spec v0.0.0-20160808142527-6aced65f8501/go.mod h1:J8+jY1nAiCcj+friV/PDoE1/3eeccG9LYBs0tYvLOWc=
|
||||
github.com/go-openapi/spec v0.17.0/go.mod h1:XkF/MOi14NmjsfZ8VtAKf8pIlbZzyoTvZsdfssdxcBI=
|
||||
github.com/go-openapi/spec v0.18.0/go.mod h1:XkF/MOi14NmjsfZ8VtAKf8pIlbZzyoTvZsdfssdxcBI=
|
||||
github.com/go-openapi/spec v0.19.2/go.mod h1:sCxk3jxKgioEJikev4fgkNmwS+3kuYdJtcsZsD5zxMY=
|
||||
github.com/go-openapi/spec v0.19.3 h1:0XRyw8kguri6Yw4SxhsQA/atC88yqrk0+G4YhI2wabc=
|
||||
github.com/go-openapi/spec v0.19.3/go.mod h1:FpwSN1ksY1eteniUU7X0N/BgJ7a4WvBFVA8Lj9mJglo=
|
||||
github.com/go-openapi/strfmt v0.17.0/go.mod h1:P82hnJI0CXkErkXi8IKjPbNBM6lV6+5pLP5l494TcyU=
|
||||
github.com/go-openapi/strfmt v0.18.0/go.mod h1:P82hnJI0CXkErkXi8IKjPbNBM6lV6+5pLP5l494TcyU=
|
||||
github.com/go-openapi/strfmt v0.19.0/go.mod h1:+uW+93UVvGGq2qGaZxdDeJqSAqBqBdl+ZPMF/cC8nDY=
|
||||
github.com/go-openapi/strfmt v0.19.3/go.mod h1:0yX7dbo8mKIvc3XSKp7MNfxw4JytCfCD6+bY1AVL9LU=
|
||||
github.com/go-openapi/swag v0.0.0-20160704191624-1d0bd113de87/go.mod h1:DXUve3Dpr1UfpPtxFw+EFuQ41HhCWZfha5jSVRG7C7I=
|
||||
github.com/go-openapi/swag v0.17.0/go.mod h1:AByQ+nYG6gQg71GINrmuDXCPWdL640yX49/kXLo40Tg=
|
||||
github.com/go-openapi/swag v0.18.0/go.mod h1:AByQ+nYG6gQg71GINrmuDXCPWdL640yX49/kXLo40Tg=
|
||||
github.com/go-openapi/swag v0.19.2/go.mod h1:POnQmlKehdgb5mhVOsnJFsivZCEZ/vjK9gh66Z9tfKk=
|
||||
github.com/go-openapi/swag v0.19.5 h1:lTz6Ys4CmqqCQmZPBlbQENR1/GucA2bzYTE12Pw4tFY=
|
||||
github.com/go-openapi/swag v0.19.5/go.mod h1:POnQmlKehdgb5mhVOsnJFsivZCEZ/vjK9gh66Z9tfKk=
|
||||
github.com/go-openapi/validate v0.18.0/go.mod h1:Uh4HdOzKt19xGIGm1qHf/ofbX1YQ4Y+MYsct2VUrAJ4=
|
||||
github.com/go-openapi/validate v0.19.2/go.mod h1:1tRCw7m3jtI8eNWEEliiAqUIcBztB2KDnRCRMUi7GTA=
|
||||
github.com/go-openapi/validate v0.19.5/go.mod h1:8DJv2CVJQ6kGNpFW6eV9N3JviE1C85nY1c2z52x1Gk4=
|
||||
github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY=
|
||||
github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ=
|
||||
github.com/gogo/protobuf v1.2.1/go.mod h1:hp+jE20tsWTFYpLwKvXlhS1hjn+gTNwPg2I6zVXpSg4=
|
||||
github.com/gogo/protobuf v1.3.1 h1:DqDEcV5aeaTmdFBePNpYsp3FlcVH/2ISVVM9Qf8PSls=
|
||||
github.com/gogo/protobuf v1.3.1/go.mod h1:SlYgWuQ5SjCEi6WLHjHCa1yvBfUnHcTbrrZtXPKa29o=
|
||||
github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q=
|
||||
github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q=
|
||||
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
|
||||
github.com/golang/groupcache v0.0.0-20160516000752-02826c3e7903/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
|
||||
github.com/golang/groupcache v0.0.0-20190129154638-5b532d6fd5ef/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
|
||||
|
|
@ -236,18 +182,36 @@ github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+
|
|||
github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk=
|
||||
github.com/googleapis/gnostic v0.4.1 h1:DLJCy1n/vrD4HPjOvYcT8aYQXpPIzoRZONaYwyycI+I=
|
||||
github.com/googleapis/gnostic v0.4.1/go.mod h1:LRhVm6pbyptWbWbuZ38d1eyptfvIytN3ir6b65WBswg=
|
||||
github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY=
|
||||
github.com/gorilla/websocket v0.0.0-20170926233335-4201258b820c/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ=
|
||||
github.com/gorilla/websocket v1.4.0/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ=
|
||||
github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
|
||||
github.com/gregjones/httpcache v0.0.0-20180305231024-9cad4c3443a7/go.mod h1:FecbI9+v66THATjSRHfNgh1IVFe/9kFxbXtjV0ctIMA=
|
||||
github.com/grpc-ecosystem/go-grpc-middleware v1.0.0/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs=
|
||||
github.com/grpc-ecosystem/go-grpc-middleware v1.0.1-0.20190118093823-f849b5445de4/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs=
|
||||
github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgfV/d3M/q6VIi02HzZEHgUlZvzk=
|
||||
github.com/grpc-ecosystem/grpc-gateway v1.9.0/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY=
|
||||
github.com/grpc-ecosystem/grpc-gateway v1.9.5/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY=
|
||||
github.com/hashicorp/consul/api v1.1.0/go.mod h1:VmuI/Lkw1nC05EYQWNKwWGbkg+FbDBtguAZLlVdkD9Q=
|
||||
github.com/hashicorp/consul/sdk v0.1.1/go.mod h1:VKf9jXwCTEY1QZP2MOLRhb5i/I/ssyNV1vwHyQBF0x8=
|
||||
github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4=
|
||||
github.com/hashicorp/go-cleanhttp v0.5.1/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtngrth3wmdIIUrZ80=
|
||||
github.com/hashicorp/go-immutable-radix v1.0.0/go.mod h1:0y9vanUI8NX6FsYoO3zeMjhV/C5i9g4Q3DwcSNZ4P60=
|
||||
github.com/hashicorp/go-msgpack v0.5.3/go.mod h1:ahLV/dePpqEmjfWmKiqvPkv/twdG7iPBM1vqhUKIvfM=
|
||||
github.com/hashicorp/go-multierror v1.0.0/go.mod h1:dHtQlpGsu+cZNNAkkCN/P3hoUDHhCYQXV3UM06sGGrk=
|
||||
github.com/hashicorp/go-rootcerts v1.0.0/go.mod h1:K6zTfqpRlCUIjkwsN4Z+hiSfzSTQa6eBIzfwKfwNnHU=
|
||||
github.com/hashicorp/go-sockaddr v1.0.0/go.mod h1:7Xibr9yA9JjQq1JpNB2Vw7kxv8xerXegt+ozgdvDeDU=
|
||||
github.com/hashicorp/go-syslog v1.0.0/go.mod h1:qPfqrKkXGihmCqbJM2mZgkZGvKG1dFdvsLplgctolz4=
|
||||
github.com/hashicorp/go-uuid v1.0.0/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro=
|
||||
github.com/hashicorp/go-uuid v1.0.1/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro=
|
||||
github.com/hashicorp/go.net v0.0.1/go.mod h1:hjKkEWcCURg++eb33jQU7oqQcI9XDCnUzHA0oac0k90=
|
||||
github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
|
||||
github.com/hashicorp/golang-lru v0.5.1 h1:0hERBMJE1eitiLkihrMvRVBYAkpHzc/J3QdDN+dAcgU=
|
||||
github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
|
||||
github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ=
|
||||
github.com/hashicorp/logutils v1.0.0/go.mod h1:QIAnNjmIWmVIIkWDTG1z5v++HQmx9WQRO+LraFDTW64=
|
||||
github.com/hashicorp/mdns v1.0.0/go.mod h1:tL+uN++7HEJ6SQLQ2/p+z2pH24WQKWjBPkE0mNTz8vQ=
|
||||
github.com/hashicorp/memberlist v0.1.3/go.mod h1:ajVTdAv/9Im8oMAAj5G31PhhMCZJV2pPBoIllUwCN7I=
|
||||
github.com/hashicorp/serf v0.8.2/go.mod h1:6hOLApaqBFA1NXqRQAsxw9QxuDEvNxSQRwA/JwenrHc=
|
||||
github.com/hpcloud/tail v1.0.0 h1:nfCOvKYfkgYP8hkirhJocXT2+zOD8yUNjXaWfTlyFKI=
|
||||
github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=
|
||||
github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc=
|
||||
|
|
@ -265,9 +229,10 @@ github.com/json-iterator/go v1.1.10 h1:Kz6Cvnvv2wGdaG/V8yMvfkmNiXq9Ya2KUv4rouJJr
|
|||
github.com/json-iterator/go v1.1.10/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
|
||||
github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU=
|
||||
github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/XSXhF0NWZEnDohbsk=
|
||||
github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU=
|
||||
github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w=
|
||||
github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvWXihfKN4Q=
|
||||
github.com/kisielk/errcheck v1.2.0/go.mod h1:/BMXB+zMLi60iA8Vv6Ksmxu/1UDYcXs4uQLJ+jE2L00=
|
||||
github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8=
|
||||
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
|
||||
github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
|
||||
github.com/konsorten/go-windows-terminal-sequences v1.0.3/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
|
||||
|
|
@ -281,20 +246,25 @@ github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE=
|
|||
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
|
||||
github.com/lib/pq v1.9.0 h1:L8nSXQQzAYByakOFMTwpjRoHsMJklur4Gi59b6VivR8=
|
||||
github.com/lib/pq v1.9.0/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o=
|
||||
github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ=
|
||||
github.com/mailru/easyjson v0.0.0-20160728113105-d5b7844b561a/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc=
|
||||
github.com/mailru/easyjson v0.0.0-20180823135443-60711f1a8329/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc=
|
||||
github.com/mailru/easyjson v0.0.0-20190312143242-1de009706dbe/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc=
|
||||
github.com/magiconair/properties v1.8.1/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ=
|
||||
github.com/mailru/easyjson v0.0.0-20190614124828-94de47d64c63/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc=
|
||||
github.com/mailru/easyjson v0.0.0-20190626092158-b2ccc519800e/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc=
|
||||
github.com/mailru/easyjson v0.7.0 h1:aizVhC/NAAcKWb+5QsU1iNOZb4Yws5UO2I+aIprQITM=
|
||||
github.com/mailru/easyjson v0.7.0/go.mod h1:KAzv3t3aY1NaHWoQz1+4F1ccyAH66Jk7yos7ldAVICs=
|
||||
github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU=
|
||||
github.com/mattn/go-isatty v0.0.3/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4=
|
||||
github.com/mattn/go-isatty v0.0.4/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4=
|
||||
github.com/mattn/go-runewidth v0.0.2/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU=
|
||||
github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0=
|
||||
github.com/matttproud/golang_protobuf_extensions v1.0.2-0.20181231171920-c182affec369/go.mod h1:BSXmuO+STAnVfrANrmjBb36TMTDstsz7MSK+HVaYKv4=
|
||||
github.com/miekg/dns v1.0.14/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg=
|
||||
github.com/mitchellh/cli v1.0.0/go.mod h1:hNIlj7HEI86fIcpObd7a0FcrxTWetlwJDGcceTlRvqc=
|
||||
github.com/mitchellh/go-homedir v1.0.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=
|
||||
github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=
|
||||
github.com/mitchellh/go-testing-interface v1.0.0/go.mod h1:kRemZodwjscx+RGhAo8eIhFbs2+BFgRtFPeD/KE+zxI=
|
||||
github.com/mitchellh/gox v0.4.0/go.mod h1:Sd9lOJ0+aimLBi73mGofS1ycjY8lL3uZM3JPS42BGNg=
|
||||
github.com/mitchellh/iochan v1.0.0/go.mod h1:JwYml1nuB7xOzsp52dPpHFffvOCDupsG0QubkSMEySY=
|
||||
github.com/mitchellh/mapstructure v0.0.0-20160808181253-ca63d7c062ee/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
|
||||
github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
|
||||
github.com/moby/term v0.0.0-20200312100748-672ec06f55cd/go.mod h1:DdlQx2hp0Ss5/fLikoLlEeIYiATotOjgB//nb973jeo=
|
||||
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
|
||||
|
|
@ -318,7 +288,7 @@ github.com/onsi/ginkgo v1.11.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+
|
|||
github.com/onsi/gomega v0.0.0-20170829124025-dcabb60a477c/go.mod h1:C1qb7wdrVGGVU+Z6iS04AVkA3Q65CEZX59MT0QO5uiA=
|
||||
github.com/onsi/gomega v1.7.0 h1:XPnZz8VVBHjVsy1vzJmRwIcSwiUO+JFfrv/xGiigmME=
|
||||
github.com/onsi/gomega v1.7.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY=
|
||||
github.com/pborman/uuid v1.2.0/go.mod h1:X/NO0urCmaxf9VXbdlT7C2Yzkj2IKimNn4k+gtPdI/k=
|
||||
github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc=
|
||||
github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic=
|
||||
github.com/peterbourgon/diskv v2.0.1+incompatible/go.mod h1:uqqh8zWWbv1HBMNONnaR/tNboyR3/BZd58JJSHlUSCU=
|
||||
github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||
|
|
@ -327,6 +297,7 @@ github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
|
|||
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||
github.com/posener/complete v1.1.1/go.mod h1:em0nMJCgc9GFtwrmVmEMR/ZL6WyhyjMBndrE9hABlRI=
|
||||
github.com/pquerna/cachecontrol v0.0.0-20171018203845-0dec1b30a021/go.mod h1:prYjPmNq4d1NPVmpShWobRqXY3q7Vp+80DqgxxUrUIA=
|
||||
github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw=
|
||||
github.com/prometheus/client_golang v0.9.3/go.mod h1:/TN21ttK/J9q6uSwhBd54HahCDft0ttaMvbicHlPoso=
|
||||
|
|
@ -344,33 +315,37 @@ github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R
|
|||
github.com/prometheus/procfs v0.0.0-20190507164030-5867b95ac084/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA=
|
||||
github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA=
|
||||
github.com/prometheus/procfs v0.1.3/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU=
|
||||
github.com/prometheus/procfs v0.2.0/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU=
|
||||
github.com/prometheus/tsdb v0.7.1/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40TwIPHuXU=
|
||||
github.com/r3labs/diff v1.1.0 h1:V53xhrbTHrWFWq3gI4b94AjgEJOerO1+1l0xyHOBi8M=
|
||||
github.com/r3labs/diff v1.1.0/go.mod h1:7WjXasNzi0vJetRcB/RqNl5dlIsmXcTTLmF5IoH6Xig=
|
||||
github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg=
|
||||
github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
|
||||
github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
|
||||
github.com/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAmXWZgo=
|
||||
github.com/ryanuber/columnize v0.0.0-20160712163229-9b3edd62028f/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts=
|
||||
github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg65j358z/aeFdxmN0P9QXhEzd20vsDc=
|
||||
github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc=
|
||||
github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo=
|
||||
github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE=
|
||||
github.com/sirupsen/logrus v1.6.0/go.mod h1:7uNnSEd1DgxDLC74fIahvMZmmYsHGZGEOFrfsX/uA88=
|
||||
github.com/sirupsen/logrus v1.7.0 h1:ShrD1U9pZB12TX0cVy0DtePoCH97K8EtX+mg7ZARUtM=
|
||||
github.com/sirupsen/logrus v1.7.0/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0=
|
||||
github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc=
|
||||
github.com/smartystreets/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA=
|
||||
github.com/soheilhy/cmux v0.1.4/go.mod h1:IM3LyeVVIOuxMH7sFAkER9+bJ4dT7Ms6E4xg4kGIyLM=
|
||||
github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA=
|
||||
github.com/spf13/afero v1.1.2/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B0CQ=
|
||||
github.com/spf13/afero v1.2.2/go.mod h1:9ZxEEn6pIJ8Rxe320qSDBk6AsU0r9pR7Q4OcevTdifk=
|
||||
github.com/spf13/cast v1.3.0/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE=
|
||||
github.com/spf13/cobra v0.0.3/go.mod h1:1l0Ry5zgKvJasoi3XT1TypsSe7PqH0Sj9dhYf7v3XqQ=
|
||||
github.com/spf13/cobra v1.0.0/go.mod h1:/6GTrnGXV9HjY+aR4k0oJ5tcvakLuG6EuKReYlHNrgE=
|
||||
github.com/spf13/cobra v1.1.1/go.mod h1:WnodtKOvamDL/PwE2M4iKs8aMDBZ5Q5klgD3qfVJQMI=
|
||||
github.com/spf13/jwalterweatherman v1.0.0/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb68N+wFjFa4jdeBTo=
|
||||
github.com/spf13/pflag v0.0.0-20170130214245-9ff6c6923cff/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4=
|
||||
github.com/spf13/pflag v1.0.1/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4=
|
||||
github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4=
|
||||
github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA=
|
||||
github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
|
||||
github.com/spf13/viper v1.4.0/go.mod h1:PTJ7Z/lr49W6bUbkmS1V3by4uWynFiR9p7+dSq/yZzE=
|
||||
github.com/spf13/viper v1.7.0/go.mod h1:8WkrPz2fc9jxqZNCJI/76HCieCp4Q8HaLFoCha5qpdg=
|
||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||
github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||
github.com/stretchr/objx v0.2.0/go.mod h1:qt09Ya8vawLte6SNmTgCsAVtYtaKzEcn8ATUoHMkEqE=
|
||||
|
|
@ -380,23 +355,17 @@ github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81P
|
|||
github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA=
|
||||
github.com/stretchr/testify v1.6.1 h1:hDPOHmpOpP40lSULcqw7IrRb/u7w6RpDC9399XyoNd0=
|
||||
github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||
github.com/tidwall/pretty v1.0.0/go.mod h1:XNkn88O1ChpSDQmQeStsy+sBenx6DDtFZJxhVysOjyk=
|
||||
github.com/subosito/gotenv v1.2.0/go.mod h1:N0PQaV/YGNqwC0u51sEeR/aUtSLEXKX9iv69rRypqCw=
|
||||
github.com/tmc/grpc-websocket-proxy v0.0.0-20170815181823-89b8d40f7ca8/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U=
|
||||
github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U=
|
||||
github.com/ugorji/go v1.1.4/go.mod h1:uQMGLiO92mf5W77hV/PUCpI3pbzQx3CRekS0kk+RGrc=
|
||||
github.com/urfave/cli v1.20.0/go.mod h1:70zkFmudgCuE/ngEzBv17Jvp/497gISqfk5gWijbERA=
|
||||
github.com/vektah/gqlparser v1.1.2/go.mod h1:1ycwN7Ij5njmMkPPAOaRFY4rET2Enx7IkVv3vaXspKw=
|
||||
github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU=
|
||||
github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77/go.mod h1:aYKd//L2LvnjZzWKhF00oedf4jCCReLcmhLdhm1A27Q=
|
||||
github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
||||
github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
||||
go.etcd.io/bbolt v1.3.2/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU=
|
||||
go.etcd.io/bbolt v1.3.3/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU=
|
||||
go.etcd.io/bbolt v1.3.5/go.mod h1:G5EMThwa9y8QZGBClrRx5EY+Yw9kAhnjy3bSjsnlVTQ=
|
||||
go.etcd.io/etcd v0.5.0-alpha.5.0.20200819165624-17cef6e3e9d5/go.mod h1:skWido08r9w6Lq/w70DO5XYIKMu4QFu1+4VsqLQuJy8=
|
||||
go.mongodb.org/mongo-driver v1.0.3/go.mod h1:u7ryQJ+DOzQmeO7zB6MHyr8jkEQvC8vH7qLUO4lqsUM=
|
||||
go.mongodb.org/mongo-driver v1.1.1/go.mod h1:u7ryQJ+DOzQmeO7zB6MHyr8jkEQvC8vH7qLUO4lqsUM=
|
||||
go.mongodb.org/mongo-driver v1.1.2/go.mod h1:u7ryQJ+DOzQmeO7zB6MHyr8jkEQvC8vH7qLUO4lqsUM=
|
||||
go.etcd.io/etcd v0.5.0-alpha.5.0.20200910180754-dd1b699fc489/go.mod h1:yVHk9ub3CSBatqGNg7GRmsnfLWtoW60w4eDYfh7vHDg=
|
||||
go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU=
|
||||
go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8=
|
||||
go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
|
||||
|
|
@ -406,14 +375,12 @@ go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE=
|
|||
go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0=
|
||||
go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q=
|
||||
golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
|
||||
golang.org/x/crypto v0.0.0-20181029021203-45a5f77698d3/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
|
||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||
golang.org/x/crypto v0.0.0-20190320223903-b7391e95e576/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||
golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||
golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||
golang.org/x/crypto v0.0.0-20190611184440-5c40567a22f8/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||
golang.org/x/crypto v0.0.0-20190617133340-57b3e21c3d56/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||
golang.org/x/crypto v0.0.0-20191206172530-e9b2fee46413/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||
golang.org/x/crypto v0.0.0-20201002170205-7f63de1d35b0/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||
golang.org/x/crypto v0.0.0-20201203163018-be400aefbc4c h1:9HhBz5L/UjnK9XLtiZhYAdue5BVKep3PMmS2LuPDt8k=
|
||||
|
|
@ -453,17 +420,16 @@ golang.org/x/mod v0.4.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
|||
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20181005035420-146acd28ed58/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20181023162649-9b4f9f5ad519/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20181201002055-351d144fa1fc/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20181220203305-927f97764cc3/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||
golang.org/x/net v0.0.0-20190320064053-1272bf9dcd53/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||
golang.org/x/net v0.0.0-20190501004415-9ce7a6920f09/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||
golang.org/x/net v0.0.0-20190503192946-f4e77d36d62c/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||
golang.org/x/net v0.0.0-20190522155817-f3200d17e092/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks=
|
||||
golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks=
|
||||
golang.org/x/net v0.0.0-20190613194153-d28f0bde5980/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
|
|
@ -477,7 +443,6 @@ golang.org/x/net v0.0.0-20200222125558-5a598a2470a0/go.mod h1:z5CRVTTTmAJ677TzLL
|
|||
golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20200301022130-244492dfa37a/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
|
||||
golang.org/x/net v0.0.0-20200707034311-ab3426394381/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
|
||||
golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
|
||||
golang.org/x/net v0.0.0-20201110031124-69a78807bb2b h1:uwuIcX0g4Yl1NC5XAz37xsr2lTtcqevgzYNVt49waME=
|
||||
golang.org/x/net v0.0.0-20201110031124-69a78807bb2b/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
|
||||
|
|
@ -494,14 +459,15 @@ golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJ
|
|||
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20181026203630-95b1ffbd15a5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20181107165924-66b7b1311ac8/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20190321052220-f7bb7a8bee54/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20190502145724-3ef323f4f1fd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
|
|
@ -525,7 +491,6 @@ golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7w
|
|||
golang.org/x/sys v0.0.0-20200302150141-5c8b2ff67527/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200615200032-f1bc736245b1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200622214017-ed371f2e16b4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20201112073958-5cba982894dd h1:5CtCZbICpIOFdgO940moixOPjc0178IU44m4EjOO5IY=
|
||||
golang.org/x/sys v0.0.0-20201112073958-5cba982894dd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
|
|
@ -546,26 +511,24 @@ golang.org/x/time v0.0.0-20200630173020-3af7569d3a1e h1:EHBhcS0mlXEAVwNyO2dLfjTo
|
|||
golang.org/x/time v0.0.0-20200630173020-3af7569d3a1e/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||
golang.org/x/tools v0.0.0-20180221164845-07fd8470d635/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
golang.org/x/tools v0.0.0-20181011042414-1f849cf54d09/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
golang.org/x/tools v0.0.0-20181030221726-6c7e314b6563/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
golang.org/x/tools v0.0.0-20190125232054-d66bd3c5d5a6/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY=
|
||||
golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
|
||||
golang.org/x/tools v0.0.0-20190312151545-0bb0c0a6e846/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
|
||||
golang.org/x/tools v0.0.0-20190312170243-e65039ee4138/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
|
||||
golang.org/x/tools v0.0.0-20190328211700-ab21143f2384/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
|
||||
golang.org/x/tools v0.0.0-20190425150028-36563e24a262/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
|
||||
golang.org/x/tools v0.0.0-20190506145303-2d16b83fe98c/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
|
||||
golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
|
||||
golang.org/x/tools v0.0.0-20190606124116-d0a3d012864b/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
|
||||
golang.org/x/tools v0.0.0-20190614205625-5aca471b1d59/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
|
||||
golang.org/x/tools v0.0.0-20190617190820-da514acc4774/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
|
||||
golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
|
||||
golang.org/x/tools v0.0.0-20190624222133-a101b041ded4/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
|
||||
golang.org/x/tools v0.0.0-20190628153133-6cdbf07be9d0/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
|
||||
golang.org/x/tools v0.0.0-20190816200558-6889da9d5479/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||
golang.org/x/tools v0.0.0-20190911174233-4f2ddba30aff/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||
golang.org/x/tools v0.0.0-20191012152004-8de300cfc20a/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||
golang.org/x/tools v0.0.0-20191112195655-aa38f8e97acc/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||
golang.org/x/tools v0.0.0-20191113191852-77e3bb0ad9e7/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||
golang.org/x/tools v0.0.0-20191115202509-3a792d9c32b2/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||
|
|
@ -581,9 +544,10 @@ golang.org/x/tools v0.0.0-20200207183749-b753a1ba74fa/go.mod h1:TB2adYChydJhpapK
|
|||
golang.org/x/tools v0.0.0-20200212150539-ea181f53ac56/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
|
||||
golang.org/x/tools v0.0.0-20200224181240-023911ca70b2/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
|
||||
golang.org/x/tools v0.0.0-20200304193943-95d2e580d8eb/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw=
|
||||
golang.org/x/tools v0.0.0-20200616133436-c1934b75d054/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
|
||||
golang.org/x/tools v0.0.0-20201207204333-a835c872fcea h1:LgKM3cNs8xO6GK1ZVK0nasPn7IN39Sz9EBTwQLyishk=
|
||||
golang.org/x/tools v0.0.0-20201207204333-a835c872fcea/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
|
||||
golang.org/x/tools v0.0.0-20200505023115-26f46d2f7ef8/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
|
||||
golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
|
||||
golang.org/x/tools v0.0.0-20210106214847-113979e3529a h1:CB3a9Nez8M13wwlr/E2YtwoU+qYHKfC+JrDa45RXXoQ=
|
||||
golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
|
||||
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
|
|
@ -624,9 +588,9 @@ google.golang.org/genproto v0.0.0-20200212174721-66ed5ce911ce/go.mod h1:55QSHmfG
|
|||
google.golang.org/genproto v0.0.0-20200224152610-e50cd9704f63/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
|
||||
google.golang.org/genproto v0.0.0-20200305110556-506484158171/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
|
||||
google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo=
|
||||
google.golang.org/genproto v0.0.0-20201110150050-8816d57aaa9a/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
|
||||
google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
|
||||
google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38=
|
||||
google.golang.org/grpc v1.21.0/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM=
|
||||
google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM=
|
||||
google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg=
|
||||
google.golang.org/grpc v1.26.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=
|
||||
|
|
@ -654,6 +618,7 @@ gopkg.in/fsnotify.v1 v1.4.7 h1:xOHLXZwVvI9hhs+cLKq5+I5onOuwQLhQwiu63xxlHs4=
|
|||
gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys=
|
||||
gopkg.in/inf.v0 v0.9.1 h1:73M5CoZyi3ZLMOyDlQh031Cx6N9NDJ2Vvfl76EDAgDc=
|
||||
gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw=
|
||||
gopkg.in/ini.v1 v1.51.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k=
|
||||
gopkg.in/natefinch/lumberjack.v2 v2.0.0/go.mod h1:l0ndWWf7gzL7RNwBG7wST/UCcT4T24xpD6X8LsfU/+k=
|
||||
gopkg.in/resty.v1 v1.12.0/go.mod h1:mDo4pnntr5jdWRML875a/NmxYqAlA73dVijT2AXvQQo=
|
||||
gopkg.in/square/go-jose.v2 v2.2.2/go.mod h1:M9dMgbHiYLoDGQrXy7OpJDJWiKiU//h+vD76mk0e1AI=
|
||||
|
|
@ -677,41 +642,36 @@ honnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a/go.mod h1:rf3lG4BRIbNafJWh
|
|||
honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
||||
honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg=
|
||||
honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k=
|
||||
k8s.io/api v0.19.4/go.mod h1:SbtJ2aHCItirzdJ36YslycFNzWADYH3tgOhvBEFtZAk=
|
||||
k8s.io/api v0.20.2 h1:y/HR22XDZY3pniu9hIFDLpUCPq2w5eQ6aV/VFQ7uJMw=
|
||||
k8s.io/api v0.20.2/go.mod h1:d7n6Ehyzx+S+cE3VhTGfVNNqtGc/oL9DCdYYahlurV8=
|
||||
k8s.io/apiextensions-apiserver v0.19.4 h1:D9ak9T012tb3vcGFWYmbQuj9SCC8YM4zhA4XZqsAQC4=
|
||||
k8s.io/apiextensions-apiserver v0.19.4/go.mod h1:B9rpH/nu4JBCtuUp3zTTk8DEjZUupZTBEec7/2zNRYw=
|
||||
k8s.io/apimachinery v0.19.4/go.mod h1:DnPGDnARWFvYa3pMHgSxtbZb7gpzzAZ1pTfaUNDVlmA=
|
||||
k8s.io/apimachinery v0.20.2 h1:hFx6Sbt1oG0n6DZ+g4bFt5f6BoMkOjKWsQFu077M3Vg=
|
||||
k8s.io/apimachinery v0.20.2/go.mod h1:WlLqWAHZGg07AeltaI0MV5uk1Omp8xaN0JGLY6gkRpU=
|
||||
k8s.io/apiserver v0.19.4/go.mod h1:X8WRHCR1UGZDd7HpV0QDc1h/6VbbpAeAGyxSh8yzZXw=
|
||||
k8s.io/client-go v0.19.4/go.mod h1:ZrEy7+wj9PjH5VMBCuu/BDlvtUAku0oVFk4MmnW9mWA=
|
||||
k8s.io/client-go v0.20.2 h1:uuf+iIAbfnCSw8IGAv/Rg0giM+2bOzHLOsbbrwrdhNQ=
|
||||
k8s.io/client-go v0.20.2/go.mod h1:kH5brqWqp7HDxUFKoEgiI4v8G1xzbe9giaCenUWJzgE=
|
||||
k8s.io/code-generator v0.19.4 h1:c8IL7RgTgJaYgr2bYMgjN0WikHnohbBhEgajfIkuP5I=
|
||||
k8s.io/code-generator v0.19.4/go.mod h1:moqLn7w0t9cMs4+5CQyxnfA/HV8MF6aAVENF+WZZhgk=
|
||||
k8s.io/component-base v0.19.4/go.mod h1:ZzuSLlsWhajIDEkKF73j64Gz/5o0AgON08FgRbEPI70=
|
||||
k8s.io/api v0.20.6 h1:bgdZrW++LqgrLikWYNruIKAtltXbSCX2l5mJu11hrVE=
|
||||
k8s.io/api v0.20.6/go.mod h1:X9e8Qag6JV/bL5G6bU8sdVRltWKmdHsFUGS3eVndqE8=
|
||||
k8s.io/apiextensions-apiserver v0.20.6 h1:3ZJiXMif7W/32RnfyHN8HygTAZaN7o+FvHxCyuQ7VOo=
|
||||
k8s.io/apiextensions-apiserver v0.20.6/go.mod h1:qO8YMqeMmZH+lV21LUNzV41vfpoE9QVAJRA+MNqj0mo=
|
||||
k8s.io/apimachinery v0.20.6 h1:R5p3SlhaABYShQSO6LpPsYHjV05Q+79eBUR0Ut/f4tk=
|
||||
k8s.io/apimachinery v0.20.6/go.mod h1:ejZXtW1Ra6V1O5H8xPBGz+T3+4gfkTCeExAHKU57MAc=
|
||||
k8s.io/apiserver v0.20.6/go.mod h1:QIJXNt6i6JB+0YQRNcS0hdRHJlMhflFmsBDeSgT1r8Q=
|
||||
k8s.io/client-go v0.20.6 h1:nJZOfolnsVtDtbGJNCxzOtKUAu7zvXjB8+pMo9UNxZo=
|
||||
k8s.io/client-go v0.20.6/go.mod h1:nNQMnOvEUEsOzRRFIIkdmYOjAZrC8bgq0ExboWSU1I0=
|
||||
k8s.io/code-generator v0.20.6 h1:kp65Y6kF6A4+5PvSNvXWSI5p5vuA9tUxEqEZciPw+7Q=
|
||||
k8s.io/code-generator v0.20.6/go.mod h1:i6FmG+QxaLxvJsezvZp0q/gAEzzOz3U53KFibghWToU=
|
||||
k8s.io/component-base v0.20.6/go.mod h1:6f1MPBAeI+mvuts3sIdtpjljHWBQ2cIy38oBIWMYnrM=
|
||||
k8s.io/gengo v0.0.0-20200413195148-3a45101e95ac/go.mod h1:ezvh/TsK7cY6rbqRK0oQQ8IAqLxYwwyPxAX1Pzy0ii0=
|
||||
k8s.io/gengo v0.0.0-20200428234225-8167cfdcfc14 h1:t4L10Qfx/p7ASH3gXCdIUtPbbIuegCoUJf3TMSFekjw=
|
||||
k8s.io/gengo v0.0.0-20200428234225-8167cfdcfc14/go.mod h1:ezvh/TsK7cY6rbqRK0oQQ8IAqLxYwwyPxAX1Pzy0ii0=
|
||||
k8s.io/gengo v0.0.0-20201113003025-83324d819ded h1:JApXBKYyB7l9xx+DK7/+mFjC7A9Bt5A93FPvFD0HIFE=
|
||||
k8s.io/gengo v0.0.0-20201113003025-83324d819ded/go.mod h1:FiNAH4ZV3gBg2Kwh89tzAEV2be7d5xI0vBa/VySYy3E=
|
||||
k8s.io/klog/v2 v2.0.0/go.mod h1:PBfzABfn139FHAV07az/IF9Wp1bkk3vpT2XSJ76fSDE=
|
||||
k8s.io/klog/v2 v2.2.0/go.mod h1:Od+F08eJP+W3HUb4pSrPpgp9DGU4GzlpG/TmITuYh/Y=
|
||||
k8s.io/klog/v2 v2.4.0 h1:7+X0fUguPyrKEC4WjH8iGDg3laWgMo5tMnRTIGTTxGQ=
|
||||
k8s.io/klog/v2 v2.4.0/go.mod h1:Od+F08eJP+W3HUb4pSrPpgp9DGU4GzlpG/TmITuYh/Y=
|
||||
k8s.io/kube-openapi v0.0.0-20200805222855-6aeccd4b50c6/go.mod h1:UuqjUnNftUyPE5H64/qeyjQoUZhGpeFDVdxjTeEVN2o=
|
||||
k8s.io/kube-openapi v0.0.0-20201113171705-d219536bb9fd h1:sOHNzJIkytDF6qadMNKhhDRpc6ODik8lVC6nOur7B2c=
|
||||
k8s.io/kube-openapi v0.0.0-20201113171705-d219536bb9fd/go.mod h1:WOJ3KddDSol4tAGcJo0Tvi+dK12EcqSLqcWsryKMpfM=
|
||||
k8s.io/utils v0.0.0-20200729134348-d5654de09c73/go.mod h1:jPW/WVKK9YHAvNhRxK0md/EJ228hCsBRufyofKtW8HA=
|
||||
k8s.io/utils v0.0.0-20201110183641-67b214c5f920 h1:CbnUZsM497iRC5QMVkHwyl8s2tB3g7yaSHkYPkpgelw=
|
||||
k8s.io/utils v0.0.0-20201110183641-67b214c5f920/go.mod h1:jPW/WVKK9YHAvNhRxK0md/EJ228hCsBRufyofKtW8HA=
|
||||
rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8=
|
||||
rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0=
|
||||
rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA=
|
||||
sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.0.9/go.mod h1:dzAXnQbTRyDlZPJX2SUPEqvnB+j7AJjtlox7PEwigU0=
|
||||
sigs.k8s.io/structured-merge-diff/v4 v4.0.1/go.mod h1:bJZC9H9iH24zzfZ/41RGcq60oK1F7G282QMXDPYydCw=
|
||||
sigs.k8s.io/structured-merge-diff/v4 v4.0.2 h1:YHQV7Dajm86OuqnIR6zAelnDWBRjo+YhYV9PmGrh1s8=
|
||||
sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.0.15/go.mod h1:LEScyzhFmoF5pso/YSeBstl57mOzx9xlU9n85RGrDQg=
|
||||
sigs.k8s.io/structured-merge-diff/v4 v4.0.2/go.mod h1:bJZC9H9iH24zzfZ/41RGcq60oK1F7G282QMXDPYydCw=
|
||||
sigs.k8s.io/structured-merge-diff/v4 v4.0.3 h1:4oyYo8NREp49LBBhKxEqCulFjg26rawYKrnCmg+Sr6c=
|
||||
sigs.k8s.io/structured-merge-diff/v4 v4.0.3/go.mod h1:bJZC9H9iH24zzfZ/41RGcq60oK1F7G282QMXDPYydCw=
|
||||
sigs.k8s.io/yaml v1.1.0/go.mod h1:UJmg0vDUVViEyp3mgSv9WPwZCDxu4rQW1olrI1uml+o=
|
||||
sigs.k8s.io/yaml v1.2.0 h1:kr/MCeFWJWTwyaHoR9c8EjH9OumOmoF9YGiZd7lFm/Q=
|
||||
sigs.k8s.io/yaml v1.2.0/go.mod h1:yfXDCHCao9+ENCvLSE62v9VSji2MKu5jeNfTrofGhJc=
|
||||
|
|
|
|||
|
|
@ -71,7 +71,7 @@ func addDb(dbName string, dbOwner string, clusterName string) {
|
|||
|
||||
var dbOwnerExists bool
|
||||
dbUsers := postgresql.Spec.Users
|
||||
for key, _ := range dbUsers {
|
||||
for key := range dbUsers {
|
||||
if key == dbOwner {
|
||||
dbOwnerExists = true
|
||||
}
|
||||
|
|
|
|||
|
|
@ -23,13 +23,14 @@ THE SOFTWARE.
|
|||
package cmd
|
||||
|
||||
import (
|
||||
"log"
|
||||
"os"
|
||||
user "os/user"
|
||||
|
||||
"github.com/spf13/cobra"
|
||||
"k8s.io/client-go/kubernetes"
|
||||
"k8s.io/client-go/rest"
|
||||
"k8s.io/client-go/tools/remotecommand"
|
||||
"log"
|
||||
"os"
|
||||
user "os/user"
|
||||
)
|
||||
|
||||
// connectCmd represents the kubectl pg connect command
|
||||
|
|
@ -80,13 +81,13 @@ kubectl pg connect -c cluster -p -u user01 -d db01
|
|||
|
||||
func connect(clusterName string, master bool, replica string, psql bool, user string, dbName string) {
|
||||
config := getConfig()
|
||||
client, er := kubernetes.NewForConfig(config)
|
||||
if er != nil {
|
||||
log.Fatal(er)
|
||||
client, err := kubernetes.NewForConfig(config)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
podName := getPodName(clusterName, master, replica)
|
||||
execRequest := &rest.Request{}
|
||||
var execRequest *rest.Request
|
||||
|
||||
if psql {
|
||||
execRequest = client.CoreV1().RESTClient().Post().Resource("pods").
|
||||
|
|
|
|||
|
|
@ -53,6 +53,9 @@ kubectl pg create -f cluster-manifest.yaml
|
|||
func create(fileName string) {
|
||||
config := getConfig()
|
||||
postgresConfig, err := PostgresqlLister.NewForConfig(config)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
ymlFile, err := ioutil.ReadFile(fileName)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
|
|
|
|||
|
|
@ -67,7 +67,7 @@ func extVolume(increasedVolumeSize string, clusterName string) {
|
|||
namespace := getCurrentNamespace()
|
||||
postgresql, err := postgresConfig.Postgresqls(namespace).Get(context.TODO(), clusterName, metav1.GetOptions{})
|
||||
if err != nil {
|
||||
log.Fatalf("hii %v", err)
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
oldSize, err := resource.ParseQuantity(postgresql.Spec.Volume.Size)
|
||||
|
|
|
|||
|
|
@ -31,7 +31,6 @@ import (
|
|||
|
||||
"github.com/spf13/cobra"
|
||||
PostgresqlLister "github.com/zalando/postgres-operator/pkg/generated/clientset/versioned/typed/acid.zalan.do/v1"
|
||||
v1 "k8s.io/api/apps/v1"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/types"
|
||||
"k8s.io/client-go/kubernetes"
|
||||
|
|
@ -46,6 +45,9 @@ var scaleCmd = &cobra.Command{
|
|||
Scaling to 0 leads to down time.`,
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
clusterName, err := cmd.Flags().GetString("cluster")
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
namespace, err := cmd.Flags().GetString("namespace")
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
|
|
@ -129,8 +131,7 @@ func allowedMinMaxInstances(config *rest.Config) (int32, int32) {
|
|||
log.Fatal(err)
|
||||
}
|
||||
|
||||
var operator *v1.Deployment
|
||||
operator = getPostgresOperator(k8sClient)
|
||||
operator := getPostgresOperator(k8sClient)
|
||||
|
||||
operatorContainer := operator.Spec.Template.Spec.Containers
|
||||
var configMapName, operatorConfigName string
|
||||
|
|
|
|||
|
|
@ -57,6 +57,9 @@ kubectl pg update -f cluster-manifest.yaml
|
|||
func updatePgResources(fileName string) {
|
||||
config := getConfig()
|
||||
postgresConfig, err := PostgresqlLister.NewForConfig(config)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
ymlFile, err := ioutil.ReadFile(fileName)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
|
|
|
|||
|
|
@ -99,9 +99,9 @@ func confirmAction(clusterName string, namespace string) {
|
|||
|
||||
func getPodName(clusterName string, master bool, replicaNumber string) string {
|
||||
config := getConfig()
|
||||
client, er := kubernetes.NewForConfig(config)
|
||||
if er != nil {
|
||||
log.Fatal(er)
|
||||
client, err := kubernetes.NewForConfig(config)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
postgresConfig, err := PostgresqlLister.NewForConfig(config)
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@ metadata:
|
|||
# "delete-date": "2020-08-31" # can only be deleted on that day if "delete-date "key is configured
|
||||
# "delete-clustername": "acid-test-cluster" # can only be deleted when name matches if "delete-clustername" key is configured
|
||||
spec:
|
||||
dockerImage: registry.opensource.zalan.do/acid/spilo-13:2.0-p6
|
||||
dockerImage: registry.opensource.zalan.do/acid/spilo-13:2.0-p7
|
||||
teamId: "acid"
|
||||
numberOfInstances: 2
|
||||
users: # Application/Robot users
|
||||
|
|
|
|||
|
|
@ -32,7 +32,7 @@ data:
|
|||
# default_memory_request: 100Mi
|
||||
# delete_annotation_date_key: delete-date
|
||||
# delete_annotation_name_key: delete-clustername
|
||||
docker_image: registry.opensource.zalan.do/acid/spilo-13:2.0-p6
|
||||
docker_image: registry.opensource.zalan.do/acid/spilo-13:2.0-p7
|
||||
# downscaler_annotations: "deployment-time,downscaler/*"
|
||||
# enable_admin_role_for_users: "true"
|
||||
# enable_crd_validation: "true"
|
||||
|
|
@ -51,6 +51,7 @@ data:
|
|||
# enable_shm_volume: "true"
|
||||
# enable_sidecars: "true"
|
||||
enable_spilo_wal_path_compat: "true"
|
||||
enable_team_member_deprecation: "false"
|
||||
# enable_team_superuser: "false"
|
||||
enable_teams_api: "false"
|
||||
# etcd_host: ""
|
||||
|
|
@ -63,7 +64,7 @@ data:
|
|||
# inherited_labels: application,environment
|
||||
# kube_iam_role: ""
|
||||
# log_s3_bucket: ""
|
||||
logical_backup_docker_image: "registry.opensource.zalan.do/acid/logical-backup:v1.6.2"
|
||||
logical_backup_docker_image: "registry.opensource.zalan.do/acid/logical-backup:v1.6.3"
|
||||
# logical_backup_google_application_credentials: ""
|
||||
logical_backup_job_prefix: "logical-backup-"
|
||||
logical_backup_provider: "s3"
|
||||
|
|
@ -111,6 +112,7 @@ data:
|
|||
resource_check_timeout: 10m
|
||||
resync_period: 30m
|
||||
ring_log_lines: "100"
|
||||
role_deletion_suffix: "_deleted"
|
||||
secret_name_template: "{username}.{cluster}.credentials"
|
||||
# sidecar_docker_images: ""
|
||||
# set_memory_request_to_limit: "false"
|
||||
|
|
|
|||
|
|
@ -61,7 +61,7 @@ spec:
|
|||
properties:
|
||||
docker_image:
|
||||
type: string
|
||||
default: "registry.opensource.zalan.do/acid/spilo-13:2.0-p6"
|
||||
default: "registry.opensource.zalan.do/acid/spilo-13:2.0-p7"
|
||||
enable_crd_validation:
|
||||
type: boolean
|
||||
default: true
|
||||
|
|
@ -393,7 +393,7 @@ spec:
|
|||
properties:
|
||||
logical_backup_docker_image:
|
||||
type: string
|
||||
default: "registry.opensource.zalan.do/acid/logical-backup:v1.6.2"
|
||||
default: "registry.opensource.zalan.do/acid/logical-backup:v1.6.3"
|
||||
logical_backup_google_application_credentials:
|
||||
type: string
|
||||
logical_backup_job_prefix:
|
||||
|
|
@ -439,6 +439,9 @@ spec:
|
|||
enable_postgres_team_crd_superusers:
|
||||
type: boolean
|
||||
default: false
|
||||
enable_team_member_deprecation:
|
||||
type: boolean
|
||||
default: false
|
||||
enable_team_superuser:
|
||||
type: boolean
|
||||
default: false
|
||||
|
|
@ -461,6 +464,9 @@ spec:
|
|||
type: string
|
||||
default:
|
||||
- admin
|
||||
role_deletion_suffix:
|
||||
type: string
|
||||
default: "_deleted"
|
||||
team_admin_role:
|
||||
type: string
|
||||
default: "admin"
|
||||
|
|
|
|||
|
|
@ -19,7 +19,7 @@ spec:
|
|||
serviceAccountName: postgres-operator
|
||||
containers:
|
||||
- name: postgres-operator
|
||||
image: registry.opensource.zalan.do/acid/postgres-operator:v1.6.2
|
||||
image: registry.opensource.zalan.do/acid/postgres-operator:v1.6.3
|
||||
imagePullPolicy: IfNotPresent
|
||||
resources:
|
||||
requests:
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@ kind: OperatorConfiguration
|
|||
metadata:
|
||||
name: postgresql-operator-default-configuration
|
||||
configuration:
|
||||
docker_image: registry.opensource.zalan.do/acid/spilo-13:2.0-p6
|
||||
docker_image: registry.opensource.zalan.do/acid/spilo-13:2.0-p7
|
||||
# enable_crd_validation: true
|
||||
# enable_lazy_spilo_upgrade: false
|
||||
enable_pgversion_env_var: true
|
||||
|
|
@ -123,7 +123,7 @@ configuration:
|
|||
# wal_gs_bucket: ""
|
||||
# wal_s3_bucket: ""
|
||||
logical_backup:
|
||||
logical_backup_docker_image: "registry.opensource.zalan.do/acid/logical-backup:v1.6.2"
|
||||
logical_backup_docker_image: "registry.opensource.zalan.do/acid/logical-backup:v1.6.3"
|
||||
# logical_backup_google_application_credentials: ""
|
||||
logical_backup_job_prefix: "logical-backup-"
|
||||
logical_backup_provider: "s3"
|
||||
|
|
@ -141,6 +141,7 @@ configuration:
|
|||
# enable_admin_role_for_users: true
|
||||
# enable_postgres_team_crd: false
|
||||
# enable_postgres_team_crd_superusers: false
|
||||
enable_team_member_deprecation: false
|
||||
enable_team_superuser: false
|
||||
enable_teams_api: false
|
||||
# pam_configuration: ""
|
||||
|
|
@ -149,6 +150,7 @@ configuration:
|
|||
# - postgres_superusers
|
||||
protected_role_names:
|
||||
- admin
|
||||
role_deletion_suffix: "_deleted"
|
||||
team_admin_role: admin
|
||||
team_api_role_configuration:
|
||||
log_statement: all
|
||||
|
|
|
|||
|
|
@ -23,7 +23,7 @@ spec:
|
|||
additionalPrinterColumns:
|
||||
- name: Team
|
||||
type: string
|
||||
description: Team responsible for Postgres CLuster
|
||||
description: Team responsible for Postgres cluster
|
||||
jsonPath: .spec.teamId
|
||||
- name: Version
|
||||
type: string
|
||||
|
|
|
|||
|
|
@ -1377,6 +1377,9 @@ var OperatorConfigCRDResourceValidation = apiextv1.CustomResourceValidation{
|
|||
"enable_postgres_team_crd_superusers": {
|
||||
Type: "boolean",
|
||||
},
|
||||
"enable_team_member_deprecation": {
|
||||
Type: "boolean",
|
||||
},
|
||||
"enable_team_superuser": {
|
||||
Type: "boolean",
|
||||
},
|
||||
|
|
@ -1405,6 +1408,9 @@ var OperatorConfigCRDResourceValidation = apiextv1.CustomResourceValidation{
|
|||
},
|
||||
},
|
||||
},
|
||||
"role_deletion_suffix": {
|
||||
Type: "string",
|
||||
},
|
||||
"team_admin_role": {
|
||||
Type: "string",
|
||||
},
|
||||
|
|
|
|||
|
|
@ -159,6 +159,8 @@ type TeamsAPIConfiguration struct {
|
|||
PostgresSuperuserTeams []string `json:"postgres_superuser_teams,omitempty"`
|
||||
EnablePostgresTeamCRD bool `json:"enable_postgres_team_crd,omitempty"`
|
||||
EnablePostgresTeamCRDSuperusers bool `json:"enable_postgres_team_crd_superusers,omitempty"`
|
||||
EnableTeamMemberDeprecation bool `json:"enable_team_member_deprecation,omitempty"`
|
||||
RoleDeletionSuffix string `json:"role_deletion_suffix,omitempty"`
|
||||
}
|
||||
|
||||
// LoggingRESTAPIConfiguration defines Logging API conf
|
||||
|
|
|
|||
|
|
@ -74,6 +74,7 @@ type Cluster struct {
|
|||
eventRecorder record.EventRecorder
|
||||
patroni patroni.Interface
|
||||
pgUsers map[string]spec.PgUser
|
||||
pgUsersCache map[string]spec.PgUser
|
||||
systemUsers map[string]spec.PgUser
|
||||
podSubscribers map[spec.NamespacedName]chan PodEvent
|
||||
podSubscribersMu sync.RWMutex
|
||||
|
|
@ -129,7 +130,9 @@ func New(cfg Config, kubeClient k8sutil.KubernetesClient, pgSpec acidv1.Postgres
|
|||
Secrets: make(map[types.UID]*v1.Secret),
|
||||
Services: make(map[PostgresRole]*v1.Service),
|
||||
Endpoints: make(map[PostgresRole]*v1.Endpoints)},
|
||||
userSyncStrategy: users.DefaultUserSyncStrategy{PasswordEncryption: passwordEncryption},
|
||||
userSyncStrategy: users.DefaultUserSyncStrategy{
|
||||
PasswordEncryption: passwordEncryption,
|
||||
RoleDeletionSuffix: cfg.OpConfig.RoleDeletionSuffix},
|
||||
deleteOptions: metav1.DeleteOptions{PropagationPolicy: &deletePropagationPolicy},
|
||||
podEventsQueue: podEventsQueue,
|
||||
KubeClient: kubeClient,
|
||||
|
|
@ -190,6 +193,17 @@ func (c *Cluster) isNewCluster() bool {
|
|||
func (c *Cluster) initUsers() error {
|
||||
c.setProcessName("initializing users")
|
||||
|
||||
// if team member deprecation is enabled save current state of pgUsers
|
||||
// to check for deleted roles
|
||||
c.pgUsersCache = map[string]spec.PgUser{}
|
||||
if c.OpConfig.EnableTeamMemberDeprecation {
|
||||
for k, v := range c.pgUsers {
|
||||
if v.Origin == spec.RoleOriginTeamsAPI {
|
||||
c.pgUsersCache[k] = v
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// clear our the previous state of the cluster users (in case we are
|
||||
// running a sync).
|
||||
c.systemUsers = map[string]spec.PgUser{}
|
||||
|
|
@ -361,6 +375,7 @@ func (c *Cluster) compareStatefulSetWith(statefulSet *appsv1.StatefulSet) *compa
|
|||
}
|
||||
if !reflect.DeepEqual(c.Statefulset.Annotations, statefulSet.Annotations) {
|
||||
match = false
|
||||
needsReplace = true
|
||||
reasons = append(reasons, "new statefulset's annotations do not match the current one")
|
||||
}
|
||||
|
||||
|
|
@ -445,6 +460,11 @@ func (c *Cluster) compareStatefulSetWith(statefulSet *appsv1.StatefulSet) *compa
|
|||
}
|
||||
}
|
||||
|
||||
if len(c.Statefulset.Spec.Template.Spec.Volumes) != len(statefulSet.Spec.Template.Spec.Volumes) {
|
||||
needsReplace = true
|
||||
reasons = append(reasons, "new statefulset's volumes contains different number of volumes to the old one")
|
||||
}
|
||||
|
||||
// we assume any change in priority happens by rolling out a new priority class
|
||||
// changing the priority value in an existing class is not supproted
|
||||
if c.Statefulset.Spec.Template.Spec.PriorityClassName != statefulSet.Spec.Template.Spec.PriorityClassName {
|
||||
|
|
@ -456,7 +476,9 @@ func (c *Cluster) compareStatefulSetWith(statefulSet *appsv1.StatefulSet) *compa
|
|||
|
||||
// lazy Spilo update: modify the image in the statefulset itself but let its pods run with the old image
|
||||
// until they are re-created for other reasons, for example node rotation
|
||||
if c.OpConfig.EnableLazySpiloUpgrade && !reflect.DeepEqual(c.Statefulset.Spec.Template.Spec.Containers[0].Image, statefulSet.Spec.Template.Spec.Containers[0].Image) {
|
||||
effectivePodImage := getPostgresContainer(&c.Statefulset.Spec.Template.Spec).Image
|
||||
desiredImage := getPostgresContainer(&statefulSet.Spec.Template.Spec).Image
|
||||
if c.OpConfig.EnableLazySpiloUpgrade && !reflect.DeepEqual(effectivePodImage, desiredImage) {
|
||||
needsReplace = true
|
||||
reasons = append(reasons, "lazy Spilo update: new statefulset's pod image does not match the current one")
|
||||
}
|
||||
|
|
@ -502,6 +524,8 @@ func (c *Cluster) compareContainers(description string, setA, setB []v1.Containe
|
|||
func(a, b v1.Container) bool { return !reflect.DeepEqual(a.EnvFrom, b.EnvFrom) }),
|
||||
newCheck("new statefulset %s's %s (index %d) security context does not match the current one",
|
||||
func(a, b v1.Container) bool { return !reflect.DeepEqual(a.SecurityContext, b.SecurityContext) }),
|
||||
newCheck("new statefulset %s's %s (index %d) volume mounts do not match the current one",
|
||||
func(a, b v1.Container) bool { return !reflect.DeepEqual(a.VolumeMounts, b.VolumeMounts) }),
|
||||
}
|
||||
|
||||
if !c.OpConfig.EnableLazySpiloUpgrade {
|
||||
|
|
@ -598,7 +622,7 @@ func (c *Cluster) enforceMinResourceLimits(spec *acidv1.PostgresSpec) error {
|
|||
// for a cluster that had no such job before. In this case a missing job is not an error.
|
||||
func (c *Cluster) Update(oldSpec, newSpec *acidv1.Postgresql) error {
|
||||
updateFailed := false
|
||||
syncStatetfulSet := false
|
||||
syncStatefulSet := false
|
||||
|
||||
c.mu.Lock()
|
||||
defer c.mu.Unlock()
|
||||
|
|
@ -619,7 +643,7 @@ func (c *Cluster) Update(oldSpec, newSpec *acidv1.Postgresql) error {
|
|||
if IsBiggerPostgresVersion(oldSpec.Spec.PostgresqlParam.PgVersion, c.GetDesiredMajorVersion()) {
|
||||
c.logger.Infof("postgresql version increased (%s -> %s), depending on config manual upgrade needed",
|
||||
oldSpec.Spec.PostgresqlParam.PgVersion, newSpec.Spec.PostgresqlParam.PgVersion)
|
||||
syncStatetfulSet = true
|
||||
syncStatefulSet = true
|
||||
} else {
|
||||
c.logger.Infof("postgresql major version unchanged or smaller, no changes needed")
|
||||
// sticking with old version, this will also advance GetDesiredVersion next time.
|
||||
|
|
@ -642,7 +666,7 @@ func (c *Cluster) Update(oldSpec, newSpec *acidv1.Postgresql) error {
|
|||
needConnectionPooler := needMasterConnectionPoolerWorker(&newSpec.Spec) ||
|
||||
needReplicaConnectionPoolerWorker(&newSpec.Spec)
|
||||
if !sameUsers || needConnectionPooler {
|
||||
c.logger.Debugf("syncing secrets")
|
||||
c.logger.Debugf("initialize users")
|
||||
if err := c.initUsers(); err != nil {
|
||||
c.logger.Errorf("could not init users: %v", err)
|
||||
updateFailed = true
|
||||
|
|
@ -688,9 +712,9 @@ func (c *Cluster) Update(oldSpec, newSpec *acidv1.Postgresql) error {
|
|||
updateFailed = true
|
||||
return
|
||||
}
|
||||
if syncStatetfulSet || !reflect.DeepEqual(oldSs, newSs) || !reflect.DeepEqual(oldSpec.Annotations, newSpec.Annotations) {
|
||||
if syncStatefulSet || !reflect.DeepEqual(oldSs, newSs) || !reflect.DeepEqual(oldSpec.Annotations, newSpec.Annotations) {
|
||||
c.logger.Debugf("syncing statefulsets")
|
||||
syncStatetfulSet = false
|
||||
syncStatefulSet = false
|
||||
// TODO: avoid generating the StatefulSet object twice by passing it to syncStatefulSet
|
||||
if err := c.syncStatefulSet(); err != nil {
|
||||
c.logger.Errorf("could not sync statefulsets: %v", err)
|
||||
|
|
@ -1163,7 +1187,7 @@ func (c *Cluster) initHumanUsers() error {
|
|||
for _, superuserTeam := range superuserTeams {
|
||||
err := c.initTeamMembers(superuserTeam, true)
|
||||
if err != nil {
|
||||
return fmt.Errorf("Cannot initialize members for team %q of Postgres superusers: %v", superuserTeam, err)
|
||||
return fmt.Errorf("cannot initialize members for team %q of Postgres superusers: %v", superuserTeam, err)
|
||||
}
|
||||
if superuserTeam == c.Spec.TeamID {
|
||||
clusterIsOwnedBySuperuserTeam = true
|
||||
|
|
@ -1176,7 +1200,7 @@ func (c *Cluster) initHumanUsers() error {
|
|||
if !(util.SliceContains(superuserTeams, additionalTeam)) {
|
||||
err := c.initTeamMembers(additionalTeam, false)
|
||||
if err != nil {
|
||||
return fmt.Errorf("Cannot initialize members for additional team %q for cluster owned by %q: %v", additionalTeam, c.Spec.TeamID, err)
|
||||
return fmt.Errorf("cannot initialize members for additional team %q for cluster owned by %q: %v", additionalTeam, c.Spec.TeamID, err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1189,7 +1213,7 @@ func (c *Cluster) initHumanUsers() error {
|
|||
|
||||
err := c.initTeamMembers(c.Spec.TeamID, false)
|
||||
if err != nil {
|
||||
return fmt.Errorf("Cannot initialize members for team %q who owns the Postgres cluster: %v", c.Spec.TeamID, err)
|
||||
return fmt.Errorf("cannot initialize members for team %q who owns the Postgres cluster: %v", c.Spec.TeamID, err)
|
||||
}
|
||||
|
||||
return nil
|
||||
|
|
|
|||
|
|
@ -420,9 +420,7 @@ func (c *Cluster) deleteConnectionPooler(role PostgresRole) (err error) {
|
|||
|
||||
// Clean up the deployment object. If deployment resource we've remembered
|
||||
// is somehow empty, try to delete based on what would we generate
|
||||
var deployment *appsv1.Deployment
|
||||
deployment = c.ConnectionPooler[role].Deployment
|
||||
|
||||
deployment := c.ConnectionPooler[role].Deployment
|
||||
policy := metav1.DeletePropagationForeground
|
||||
options := metav1.DeleteOptions{PropagationPolicy: &policy}
|
||||
|
||||
|
|
@ -445,8 +443,7 @@ func (c *Cluster) deleteConnectionPooler(role PostgresRole) (err error) {
|
|||
}
|
||||
|
||||
// Repeat the same for the service object
|
||||
var service *v1.Service
|
||||
service = c.ConnectionPooler[role].Service
|
||||
service := c.ConnectionPooler[role].Service
|
||||
if service == nil {
|
||||
c.logger.Debugf("no connection pooler service object to delete")
|
||||
} else {
|
||||
|
|
@ -566,7 +563,7 @@ func needSyncConnectionPoolerSpecs(oldSpec, newSpec *acidv1.ConnectionPooler, lo
|
|||
|
||||
// Check if we need to synchronize connection pooler deployment due to new
|
||||
// defaults, that are different from what we see in the DeploymentSpec
|
||||
func needSyncConnectionPoolerDefaults(Config *Config, spec *acidv1.ConnectionPooler, deployment *appsv1.Deployment) (sync bool, reasons []string) {
|
||||
func (c *Cluster) needSyncConnectionPoolerDefaults(Config *Config, spec *acidv1.ConnectionPooler, deployment *appsv1.Deployment) (sync bool, reasons []string) {
|
||||
|
||||
reasons = []string{}
|
||||
sync = false
|
||||
|
|
@ -619,14 +616,14 @@ func needSyncConnectionPoolerDefaults(Config *Config, spec *acidv1.ConnectionPoo
|
|||
ref := env.ValueFrom.SecretKeyRef.LocalObjectReference
|
||||
secretName := Config.OpConfig.SecretNameTemplate.Format(
|
||||
"username", strings.Replace(config.User, "_", "-", -1),
|
||||
"cluster", deployment.ClusterName,
|
||||
"cluster", c.Name,
|
||||
"tprkind", acidv1.PostgresCRDResourceKind,
|
||||
"tprgroup", acidzalando.GroupName)
|
||||
|
||||
if ref.Name != secretName {
|
||||
sync = true
|
||||
msg := fmt.Sprintf("pooler user is different (having %s, required %s)",
|
||||
ref.Name, config.User)
|
||||
msg := fmt.Sprintf("pooler user and secret are different (having %s, required %s)",
|
||||
ref.Name, secretName)
|
||||
reasons = append(reasons, msg)
|
||||
}
|
||||
}
|
||||
|
|
@ -747,7 +744,7 @@ func (c *Cluster) syncConnectionPooler(oldSpec, newSpec *acidv1.Postgresql, Look
|
|||
Deployment: nil,
|
||||
Service: nil,
|
||||
Name: c.connectionPoolerName(role),
|
||||
ClusterName: c.ClusterName,
|
||||
ClusterName: c.Name,
|
||||
Namespace: c.Namespace,
|
||||
LookupFunction: false,
|
||||
Role: role,
|
||||
|
|
@ -878,7 +875,7 @@ func (c *Cluster) syncConnectionPoolerWorker(oldSpec, newSpec *acidv1.Postgresql
|
|||
specSync, specReason = needSyncConnectionPoolerSpecs(oldConnectionPooler, newConnectionPooler, c.logger)
|
||||
}
|
||||
|
||||
defaultsSync, defaultsReason := needSyncConnectionPoolerDefaults(&c.Config, newConnectionPooler, deployment)
|
||||
defaultsSync, defaultsReason := c.needSyncConnectionPoolerDefaults(&c.Config, newConnectionPooler, deployment)
|
||||
reason := append(specReason, defaultsReason...)
|
||||
|
||||
if specSync || defaultsSync {
|
||||
|
|
|
|||
|
|
@ -198,6 +198,7 @@ func (c *Cluster) readPgUsersFromDatabase(userNames []string) (users spec.PgUser
|
|||
rolname, rolpassword string
|
||||
rolsuper, rolinherit, rolcreaterole, rolcreatedb, rolcanlogin bool
|
||||
roloptions, memberof []string
|
||||
roldeleted bool
|
||||
)
|
||||
err := rows.Scan(&rolname, &rolpassword, &rolsuper, &rolinherit,
|
||||
&rolcreaterole, &rolcreatedb, &rolcanlogin, pq.Array(&roloptions), pq.Array(&memberof))
|
||||
|
|
@ -216,7 +217,11 @@ func (c *Cluster) readPgUsersFromDatabase(userNames []string) (users spec.PgUser
|
|||
parameters[fields[0]] = fields[1]
|
||||
}
|
||||
|
||||
users[rolname] = spec.PgUser{Name: rolname, Password: rolpassword, Flags: flags, MemberOf: memberof, Parameters: parameters}
|
||||
if strings.HasSuffix(rolname, c.OpConfig.RoleDeletionSuffix) {
|
||||
roldeleted = true
|
||||
}
|
||||
|
||||
users[rolname] = spec.PgUser{Name: rolname, Password: rolpassword, Flags: flags, MemberOf: memberof, Parameters: parameters, Deleted: roldeleted}
|
||||
}
|
||||
|
||||
return users, nil
|
||||
|
|
|
|||
|
|
@ -66,10 +66,6 @@ type spiloConfiguration struct {
|
|||
Bootstrap pgBootstrap `json:"bootstrap"`
|
||||
}
|
||||
|
||||
func (c *Cluster) containerName() string {
|
||||
return "postgres"
|
||||
}
|
||||
|
||||
func (c *Cluster) statefulSetName() string {
|
||||
return c.Name
|
||||
}
|
||||
|
|
@ -213,10 +209,10 @@ PatroniInitDBParams:
|
|||
for _, k := range initdbOptionNames {
|
||||
v := patroni.InitDB[k]
|
||||
for i, defaultParam := range config.Bootstrap.Initdb {
|
||||
switch defaultParam.(type) {
|
||||
switch t := defaultParam.(type) {
|
||||
case map[string]string:
|
||||
{
|
||||
for k1 := range defaultParam.(map[string]string) {
|
||||
for k1 := range t {
|
||||
if k1 == k {
|
||||
(config.Bootstrap.Initdb[i]).(map[string]string)[k] = v
|
||||
continue PatroniInitDBParams
|
||||
|
|
@ -226,7 +222,7 @@ PatroniInitDBParams:
|
|||
case string:
|
||||
{
|
||||
/* if the option already occurs in the list */
|
||||
if defaultParam.(string) == v {
|
||||
if t == v {
|
||||
continue PatroniInitDBParams
|
||||
}
|
||||
}
|
||||
|
|
@ -264,7 +260,7 @@ PatroniInitDBParams:
|
|||
if patroni.SynchronousMode {
|
||||
config.Bootstrap.DCS.SynchronousMode = patroni.SynchronousMode
|
||||
}
|
||||
if patroni.SynchronousModeStrict != false {
|
||||
if patroni.SynchronousModeStrict {
|
||||
config.Bootstrap.DCS.SynchronousModeStrict = patroni.SynchronousModeStrict
|
||||
}
|
||||
|
||||
|
|
@ -336,7 +332,7 @@ func nodeAffinity(nodeReadinessLabel map[string]string, nodeAffinity *v1.NodeAff
|
|||
if len(nodeReadinessLabel) == 0 && nodeAffinity == nil {
|
||||
return nil
|
||||
}
|
||||
nodeAffinityCopy := *&v1.NodeAffinity{}
|
||||
nodeAffinityCopy := v1.NodeAffinity{}
|
||||
if nodeAffinity != nil {
|
||||
nodeAffinityCopy = *nodeAffinity.DeepCopy()
|
||||
}
|
||||
|
|
@ -1157,10 +1153,10 @@ func (c *Cluster) generateStatefulSet(spec *acidv1.PostgresSpec) (*appsv1.Statef
|
|||
c.logger.Debugf("Generating Spilo container, environment variables")
|
||||
c.logger.Debugf("%v", spiloEnvVars)
|
||||
|
||||
spiloContainer := generateContainer(c.containerName(),
|
||||
spiloContainer := generateContainer(constants.PostgresContainerName,
|
||||
&effectiveDockerImage,
|
||||
resourceRequirements,
|
||||
deduplicateEnvVars(spiloEnvVars, c.containerName(), c.logger),
|
||||
deduplicateEnvVars(spiloEnvVars, constants.PostgresContainerName, c.logger),
|
||||
volumeMounts,
|
||||
c.OpConfig.Resources.SpiloPrivileged,
|
||||
c.OpConfig.Resources.SpiloAllowPrivilegeEscalation,
|
||||
|
|
@ -1279,15 +1275,12 @@ func (c *Cluster) generateStatefulSet(spec *acidv1.PostgresSpec) (*appsv1.Statef
|
|||
return nil, fmt.Errorf("could not set the pod management policy to the unknown value: %v", c.OpConfig.PodManagementPolicy)
|
||||
}
|
||||
|
||||
stsAnnotations := make(map[string]string)
|
||||
stsAnnotations = c.AnnotationsToPropagate(c.annotationsSet(nil))
|
||||
|
||||
statefulSet := &appsv1.StatefulSet{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: c.statefulSetName(),
|
||||
Namespace: c.Namespace,
|
||||
Labels: c.labelsSet(true),
|
||||
Annotations: stsAnnotations,
|
||||
Annotations: c.AnnotationsToPropagate(c.annotationsSet(nil)),
|
||||
},
|
||||
Spec: appsv1.StatefulSetSpec{
|
||||
Replicas: &numberOfInstances,
|
||||
|
|
@ -1395,6 +1388,9 @@ func (c *Cluster) getNumberOfInstances(spec *acidv1.PostgresSpec) int32 {
|
|||
//
|
||||
// see https://docs.okd.io/latest/dev_guide/shared_memory.html
|
||||
func addShmVolume(podSpec *v1.PodSpec) {
|
||||
|
||||
postgresContainerIdx := 0
|
||||
|
||||
volumes := append(podSpec.Volumes, v1.Volume{
|
||||
Name: constants.ShmVolumeName,
|
||||
VolumeSource: v1.VolumeSource{
|
||||
|
|
@ -1404,14 +1400,20 @@ func addShmVolume(podSpec *v1.PodSpec) {
|
|||
},
|
||||
})
|
||||
|
||||
pgIdx := constants.PostgresContainerIdx
|
||||
mounts := append(podSpec.Containers[pgIdx].VolumeMounts,
|
||||
for i, container := range podSpec.Containers {
|
||||
if container.Name == constants.PostgresContainerName {
|
||||
postgresContainerIdx = i
|
||||
}
|
||||
}
|
||||
|
||||
mounts := append(podSpec.Containers[postgresContainerIdx].VolumeMounts,
|
||||
v1.VolumeMount{
|
||||
Name: constants.ShmVolumeName,
|
||||
MountPath: constants.ShmVolumePath,
|
||||
})
|
||||
|
||||
podSpec.Containers[0].VolumeMounts = mounts
|
||||
podSpec.Containers[postgresContainerIdx].VolumeMounts = mounts
|
||||
|
||||
podSpec.Volumes = volumes
|
||||
}
|
||||
|
||||
|
|
@ -1442,54 +1444,55 @@ func (c *Cluster) addAdditionalVolumes(podSpec *v1.PodSpec,
|
|||
|
||||
volumes := podSpec.Volumes
|
||||
mountPaths := map[string]acidv1.AdditionalVolume{}
|
||||
for i, v := range additionalVolumes {
|
||||
if previousVolume, exist := mountPaths[v.MountPath]; exist {
|
||||
for i, additionalVolume := range additionalVolumes {
|
||||
if previousVolume, exist := mountPaths[additionalVolume.MountPath]; exist {
|
||||
msg := "Volume %+v cannot be mounted to the same path as %+v"
|
||||
c.logger.Warningf(msg, v, previousVolume)
|
||||
c.logger.Warningf(msg, additionalVolume, previousVolume)
|
||||
continue
|
||||
}
|
||||
|
||||
if v.MountPath == constants.PostgresDataMount {
|
||||
if additionalVolume.MountPath == constants.PostgresDataMount {
|
||||
msg := "Cannot mount volume on postgresql data directory, %+v"
|
||||
c.logger.Warningf(msg, v)
|
||||
c.logger.Warningf(msg, additionalVolume)
|
||||
continue
|
||||
}
|
||||
|
||||
if v.TargetContainers == nil {
|
||||
spiloContainer := podSpec.Containers[0]
|
||||
additionalVolumes[i].TargetContainers = []string{spiloContainer.Name}
|
||||
// if no target container is defined assign it to postgres container
|
||||
if len(additionalVolume.TargetContainers) == 0 {
|
||||
postgresContainer := getPostgresContainer(podSpec)
|
||||
additionalVolumes[i].TargetContainers = []string{postgresContainer.Name}
|
||||
}
|
||||
|
||||
for _, target := range v.TargetContainers {
|
||||
if target == "all" && len(v.TargetContainers) != 1 {
|
||||
for _, target := range additionalVolume.TargetContainers {
|
||||
if target == "all" && len(additionalVolume.TargetContainers) != 1 {
|
||||
msg := `Target containers could be either "all" or a list
|
||||
of containers, mixing those is not allowed, %+v`
|
||||
c.logger.Warningf(msg, v)
|
||||
c.logger.Warningf(msg, additionalVolume)
|
||||
continue
|
||||
}
|
||||
}
|
||||
|
||||
volumes = append(volumes,
|
||||
v1.Volume{
|
||||
Name: v.Name,
|
||||
VolumeSource: v.VolumeSource,
|
||||
Name: additionalVolume.Name,
|
||||
VolumeSource: additionalVolume.VolumeSource,
|
||||
},
|
||||
)
|
||||
|
||||
mountPaths[v.MountPath] = v
|
||||
mountPaths[additionalVolume.MountPath] = additionalVolume
|
||||
}
|
||||
|
||||
c.logger.Infof("Mount additional volumes: %+v", additionalVolumes)
|
||||
|
||||
for i := range podSpec.Containers {
|
||||
mounts := podSpec.Containers[i].VolumeMounts
|
||||
for _, v := range additionalVolumes {
|
||||
for _, target := range v.TargetContainers {
|
||||
for _, additionalVolume := range additionalVolumes {
|
||||
for _, target := range additionalVolume.TargetContainers {
|
||||
if podSpec.Containers[i].Name == target || target == "all" {
|
||||
mounts = append(mounts, v1.VolumeMount{
|
||||
Name: v.Name,
|
||||
MountPath: v.MountPath,
|
||||
SubPath: v.SubPath,
|
||||
Name: additionalVolume.Name,
|
||||
MountPath: additionalVolume.MountPath,
|
||||
SubPath: additionalVolume.SubPath,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -11,6 +11,7 @@ import (
|
|||
"github.com/stretchr/testify/assert"
|
||||
|
||||
acidv1 "github.com/zalando/postgres-operator/pkg/apis/acid.zalan.do/v1"
|
||||
fakeacidv1 "github.com/zalando/postgres-operator/pkg/generated/clientset/versioned/fake"
|
||||
"github.com/zalando/postgres-operator/pkg/spec"
|
||||
"github.com/zalando/postgres-operator/pkg/util"
|
||||
"github.com/zalando/postgres-operator/pkg/util/config"
|
||||
|
|
@ -24,9 +25,21 @@ import (
|
|||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/types"
|
||||
"k8s.io/apimachinery/pkg/util/intstr"
|
||||
"k8s.io/client-go/kubernetes/fake"
|
||||
v1core "k8s.io/client-go/kubernetes/typed/core/v1"
|
||||
)
|
||||
|
||||
func newFakeK8sTestClient() (k8sutil.KubernetesClient, *fake.Clientset) {
|
||||
acidClientSet := fakeacidv1.NewSimpleClientset()
|
||||
clientSet := fake.NewSimpleClientset()
|
||||
|
||||
return k8sutil.KubernetesClient{
|
||||
PodsGetter: clientSet.CoreV1(),
|
||||
PostgresqlsGetter: acidClientSet.AcidV1(),
|
||||
StatefulSetsGetter: clientSet.AppsV1(),
|
||||
}, clientSet
|
||||
}
|
||||
|
||||
// For testing purposes
|
||||
type ExpectedValue struct {
|
||||
envIndex int
|
||||
|
|
@ -412,6 +425,7 @@ func TestShmVolume(t *testing.T) {
|
|||
Volumes: []v1.Volume{{}},
|
||||
Containers: []v1.Container{
|
||||
{
|
||||
Name: "postgres",
|
||||
VolumeMounts: []v1.VolumeMount{
|
||||
{},
|
||||
},
|
||||
|
|
@ -423,9 +437,10 @@ func TestShmVolume(t *testing.T) {
|
|||
}
|
||||
for _, tt := range tests {
|
||||
addShmVolume(tt.podSpec)
|
||||
postgresContainer := getPostgresContainer(tt.podSpec)
|
||||
|
||||
volumeName := tt.podSpec.Volumes[tt.shmPos].Name
|
||||
volumeMountName := tt.podSpec.Containers[0].VolumeMounts[tt.shmPos].Name
|
||||
volumeMountName := postgresContainer.VolumeMounts[tt.shmPos].Name
|
||||
|
||||
if volumeName != constants.ShmVolumeName {
|
||||
t.Errorf("%s %s: Expected volume %s was not created, have %s instead",
|
||||
|
|
@ -597,8 +612,9 @@ func TestSecretVolume(t *testing.T) {
|
|||
for _, tt := range tests {
|
||||
additionalSecretMount := "aws-iam-s3-role"
|
||||
additionalSecretMountPath := "/meta/credentials"
|
||||
postgresContainer := getPostgresContainer(tt.podSpec)
|
||||
|
||||
numMounts := len(tt.podSpec.Containers[0].VolumeMounts)
|
||||
numMounts := len(postgresContainer.VolumeMounts)
|
||||
|
||||
addSecretVolume(tt.podSpec, additionalSecretMount, additionalSecretMountPath)
|
||||
|
||||
|
|
@ -618,7 +634,8 @@ func TestSecretVolume(t *testing.T) {
|
|||
}
|
||||
}
|
||||
|
||||
numMountsCheck := len(tt.podSpec.Containers[0].VolumeMounts)
|
||||
postgresContainer = getPostgresContainer(tt.podSpec)
|
||||
numMountsCheck := len(postgresContainer.VolumeMounts)
|
||||
|
||||
if numMountsCheck != numMounts+1 {
|
||||
t.Errorf("Unexpected number of VolumeMounts: got %v instead of %v",
|
||||
|
|
@ -850,7 +867,8 @@ func testEnvs(cluster *Cluster, podSpec *v1.PodTemplateSpec, role PostgresRole)
|
|||
"CONNECTION_POOLER_PORT": false,
|
||||
}
|
||||
|
||||
envs := podSpec.Spec.Containers[0].Env
|
||||
container := getPostgresContainer(&podSpec.Spec)
|
||||
envs := container.Env
|
||||
for _, env := range envs {
|
||||
required[env.Name] = true
|
||||
}
|
||||
|
|
@ -930,15 +948,6 @@ func TestNodeAffinity(t *testing.T) {
|
|||
assert.Equal(t, s.Spec.Template.Spec.Affinity.NodeAffinity, nodeAff, "cluster template has correct node affinity")
|
||||
}
|
||||
|
||||
func testCustomPodTemplate(cluster *Cluster, podSpec *v1.PodTemplateSpec) error {
|
||||
if podSpec.ObjectMeta.Name != "test-pod-template" {
|
||||
return fmt.Errorf("Custom pod template is not used, current spec %+v",
|
||||
podSpec)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func testDeploymentOwnerReference(cluster *Cluster, deployment *appsv1.Deployment) error {
|
||||
owner := deployment.ObjectMeta.OwnerReferences[0]
|
||||
|
||||
|
|
@ -962,16 +971,23 @@ func testServiceOwnerReference(cluster *Cluster, service *v1.Service, role Postg
|
|||
}
|
||||
|
||||
func TestTLS(t *testing.T) {
|
||||
var err error
|
||||
var spec acidv1.PostgresSpec
|
||||
var cluster *Cluster
|
||||
var spiloRunAsUser = int64(101)
|
||||
var spiloRunAsGroup = int64(103)
|
||||
var spiloFSGroup = int64(103)
|
||||
var additionalVolumes = spec.AdditionalVolumes
|
||||
|
||||
makeSpec := func(tls acidv1.TLSDescription) acidv1.PostgresSpec {
|
||||
return acidv1.PostgresSpec{
|
||||
client, _ := newFakeK8sTestClient()
|
||||
clusterName := "acid-test-cluster"
|
||||
namespace := "default"
|
||||
tlsSecretName := "my-secret"
|
||||
spiloRunAsUser := int64(101)
|
||||
spiloRunAsGroup := int64(103)
|
||||
spiloFSGroup := int64(103)
|
||||
defaultMode := int32(0640)
|
||||
mountPath := "/tls"
|
||||
|
||||
pg := acidv1.Postgresql{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: clusterName,
|
||||
Namespace: namespace,
|
||||
},
|
||||
Spec: acidv1.PostgresSpec{
|
||||
TeamID: "myapp", NumberOfInstances: 1,
|
||||
Resources: acidv1.Resources{
|
||||
ResourceRequests: acidv1.ResourceDescription{CPU: "1", Memory: "10"},
|
||||
|
|
@ -980,11 +996,24 @@ func TestTLS(t *testing.T) {
|
|||
Volume: acidv1.Volume{
|
||||
Size: "1G",
|
||||
},
|
||||
TLS: &tls,
|
||||
}
|
||||
TLS: &acidv1.TLSDescription{
|
||||
SecretName: tlsSecretName, CAFile: "ca.crt"},
|
||||
AdditionalVolumes: []acidv1.AdditionalVolume{
|
||||
acidv1.AdditionalVolume{
|
||||
Name: tlsSecretName,
|
||||
MountPath: mountPath,
|
||||
VolumeSource: v1.VolumeSource{
|
||||
Secret: &v1.SecretVolumeSource{
|
||||
SecretName: tlsSecretName,
|
||||
DefaultMode: &defaultMode,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
cluster = New(
|
||||
var cluster = New(
|
||||
Config{
|
||||
OpConfig: config.Config{
|
||||
PodManagementPolicy: "ordered_ready",
|
||||
|
|
@ -999,28 +1028,14 @@ func TestTLS(t *testing.T) {
|
|||
SpiloFSGroup: &spiloFSGroup,
|
||||
},
|
||||
},
|
||||
}, k8sutil.KubernetesClient{}, acidv1.Postgresql{}, logger, eventRecorder)
|
||||
spec = makeSpec(acidv1.TLSDescription{SecretName: "my-secret", CAFile: "ca.crt"})
|
||||
s, err := cluster.generateStatefulSet(&spec)
|
||||
if err != nil {
|
||||
assert.NoError(t, err)
|
||||
}
|
||||
}, client, pg, logger, eventRecorder)
|
||||
|
||||
// create a statefulset
|
||||
sts, err := cluster.createStatefulSet()
|
||||
assert.NoError(t, err)
|
||||
|
||||
fsGroup := int64(103)
|
||||
assert.Equal(t, &fsGroup, s.Spec.Template.Spec.SecurityContext.FSGroup, "has a default FSGroup assigned")
|
||||
|
||||
defaultMode := int32(0640)
|
||||
mountPath := "/tls"
|
||||
additionalVolumes = append(additionalVolumes, acidv1.AdditionalVolume{
|
||||
Name: spec.TLS.SecretName,
|
||||
MountPath: mountPath,
|
||||
VolumeSource: v1.VolumeSource{
|
||||
Secret: &v1.SecretVolumeSource{
|
||||
SecretName: spec.TLS.SecretName,
|
||||
DefaultMode: &defaultMode,
|
||||
},
|
||||
},
|
||||
})
|
||||
assert.Equal(t, &fsGroup, sts.Spec.Template.Spec.SecurityContext.FSGroup, "has a default FSGroup assigned")
|
||||
|
||||
volume := v1.Volume{
|
||||
Name: "my-secret",
|
||||
|
|
@ -1031,182 +1046,134 @@ func TestTLS(t *testing.T) {
|
|||
},
|
||||
},
|
||||
}
|
||||
assert.Contains(t, s.Spec.Template.Spec.Volumes, volume, "the pod gets a secret volume")
|
||||
assert.Contains(t, sts.Spec.Template.Spec.Volumes, volume, "the pod gets a secret volume")
|
||||
|
||||
assert.Contains(t, s.Spec.Template.Spec.Containers[0].VolumeMounts, v1.VolumeMount{
|
||||
postgresContainer := getPostgresContainer(&sts.Spec.Template.Spec)
|
||||
assert.Contains(t, postgresContainer.VolumeMounts, v1.VolumeMount{
|
||||
MountPath: "/tls",
|
||||
Name: "my-secret",
|
||||
}, "the volume gets mounted in /tls")
|
||||
|
||||
assert.Contains(t, s.Spec.Template.Spec.Containers[0].Env, v1.EnvVar{Name: "SSL_CERTIFICATE_FILE", Value: "/tls/tls.crt"})
|
||||
assert.Contains(t, s.Spec.Template.Spec.Containers[0].Env, v1.EnvVar{Name: "SSL_PRIVATE_KEY_FILE", Value: "/tls/tls.key"})
|
||||
assert.Contains(t, s.Spec.Template.Spec.Containers[0].Env, v1.EnvVar{Name: "SSL_CA_FILE", Value: "/tls/ca.crt"})
|
||||
assert.Contains(t, postgresContainer.Env, v1.EnvVar{Name: "SSL_CERTIFICATE_FILE", Value: "/tls/tls.crt"})
|
||||
assert.Contains(t, postgresContainer.Env, v1.EnvVar{Name: "SSL_PRIVATE_KEY_FILE", Value: "/tls/tls.key"})
|
||||
assert.Contains(t, postgresContainer.Env, v1.EnvVar{Name: "SSL_CA_FILE", Value: "/tls/ca.crt"})
|
||||
}
|
||||
|
||||
func TestAdditionalVolume(t *testing.T) {
|
||||
testName := "TestAdditionalVolume"
|
||||
tests := []struct {
|
||||
subTest string
|
||||
podSpec *v1.PodSpec
|
||||
volumePos int
|
||||
}{
|
||||
|
||||
client, _ := newFakeK8sTestClient()
|
||||
clusterName := "acid-test-cluster"
|
||||
namespace := "default"
|
||||
sidecarName := "sidecar"
|
||||
additionalVolumes := []acidv1.AdditionalVolume{
|
||||
{
|
||||
subTest: "empty PodSpec",
|
||||
podSpec: &v1.PodSpec{
|
||||
Volumes: []v1.Volume{},
|
||||
Containers: []v1.Container{
|
||||
{
|
||||
VolumeMounts: []v1.VolumeMount{},
|
||||
},
|
||||
},
|
||||
Name: "test1",
|
||||
MountPath: "/test1",
|
||||
TargetContainers: []string{"all"},
|
||||
VolumeSource: v1.VolumeSource{
|
||||
EmptyDir: &v1.EmptyDirVolumeSource{},
|
||||
},
|
||||
volumePos: 0,
|
||||
},
|
||||
{
|
||||
subTest: "non empty PodSpec",
|
||||
podSpec: &v1.PodSpec{
|
||||
Volumes: []v1.Volume{{}},
|
||||
Containers: []v1.Container{
|
||||
{
|
||||
Name: "postgres",
|
||||
VolumeMounts: []v1.VolumeMount{
|
||||
{
|
||||
Name: "data",
|
||||
ReadOnly: false,
|
||||
MountPath: "/data",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
Name: "test2",
|
||||
MountPath: "/test2",
|
||||
TargetContainers: []string{sidecarName},
|
||||
VolumeSource: v1.VolumeSource{
|
||||
EmptyDir: &v1.EmptyDirVolumeSource{},
|
||||
},
|
||||
volumePos: 1,
|
||||
},
|
||||
{
|
||||
subTest: "non empty PodSpec with sidecar",
|
||||
podSpec: &v1.PodSpec{
|
||||
Volumes: []v1.Volume{{}},
|
||||
Containers: []v1.Container{
|
||||
{
|
||||
Name: "postgres",
|
||||
VolumeMounts: []v1.VolumeMount{
|
||||
{
|
||||
Name: "data",
|
||||
ReadOnly: false,
|
||||
MountPath: "/data",
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
Name: "sidecar",
|
||||
VolumeMounts: []v1.VolumeMount{
|
||||
{
|
||||
Name: "data",
|
||||
ReadOnly: false,
|
||||
MountPath: "/data",
|
||||
},
|
||||
},
|
||||
},
|
||||
Name: "test3",
|
||||
MountPath: "/test3",
|
||||
TargetContainers: []string{}, // should mount only to postgres
|
||||
VolumeSource: v1.VolumeSource{
|
||||
EmptyDir: &v1.EmptyDirVolumeSource{},
|
||||
},
|
||||
},
|
||||
{
|
||||
Name: "test4",
|
||||
MountPath: "/test4",
|
||||
TargetContainers: nil, // should mount only to postgres
|
||||
VolumeSource: v1.VolumeSource{
|
||||
EmptyDir: &v1.EmptyDirVolumeSource{},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
pg := acidv1.Postgresql{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: clusterName,
|
||||
Namespace: namespace,
|
||||
},
|
||||
Spec: acidv1.PostgresSpec{
|
||||
TeamID: "myapp", NumberOfInstances: 1,
|
||||
Resources: acidv1.Resources{
|
||||
ResourceRequests: acidv1.ResourceDescription{CPU: "1", Memory: "10"},
|
||||
ResourceLimits: acidv1.ResourceDescription{CPU: "1", Memory: "10"},
|
||||
},
|
||||
Volume: acidv1.Volume{
|
||||
Size: "1G",
|
||||
},
|
||||
AdditionalVolumes: additionalVolumes,
|
||||
Sidecars: []acidv1.Sidecar{
|
||||
{
|
||||
Name: sidecarName,
|
||||
},
|
||||
},
|
||||
volumePos: 1,
|
||||
},
|
||||
}
|
||||
|
||||
var cluster = New(
|
||||
Config{
|
||||
OpConfig: config.Config{
|
||||
ProtectedRoles: []string{"admin"},
|
||||
Auth: config.Auth{
|
||||
SuperUsername: superUserName,
|
||||
ReplicationUsername: replicationUserName,
|
||||
PodManagementPolicy: "ordered_ready",
|
||||
Resources: config.Resources{
|
||||
ClusterLabels: map[string]string{"application": "spilo"},
|
||||
ClusterNameLabel: "cluster-name",
|
||||
DefaultCPURequest: "300m",
|
||||
DefaultCPULimit: "300m",
|
||||
DefaultMemoryRequest: "300Mi",
|
||||
DefaultMemoryLimit: "300Mi",
|
||||
PodRoleLabel: "spilo-role",
|
||||
},
|
||||
},
|
||||
}, k8sutil.KubernetesClient{}, acidv1.Postgresql{}, logger, eventRecorder)
|
||||
}, client, pg, logger, eventRecorder)
|
||||
|
||||
for _, tt := range tests {
|
||||
// Test with additional volume mounted in all containers
|
||||
additionalVolumeMount := []acidv1.AdditionalVolume{
|
||||
{
|
||||
Name: "test",
|
||||
MountPath: "/test",
|
||||
TargetContainers: []string{"all"},
|
||||
VolumeSource: v1.VolumeSource{
|
||||
EmptyDir: &v1.EmptyDirVolumeSource{},
|
||||
},
|
||||
},
|
||||
}
|
||||
// create a statefulset
|
||||
sts, err := cluster.createStatefulSet()
|
||||
assert.NoError(t, err)
|
||||
|
||||
numMounts := len(tt.podSpec.Containers[0].VolumeMounts)
|
||||
|
||||
cluster.addAdditionalVolumes(tt.podSpec, additionalVolumeMount)
|
||||
volumeName := tt.podSpec.Volumes[tt.volumePos].Name
|
||||
|
||||
if volumeName != additionalVolumeMount[0].Name {
|
||||
t.Errorf("%s %s: Expected volume %v was not created, have %s instead",
|
||||
testName, tt.subTest, additionalVolumeMount, volumeName)
|
||||
}
|
||||
|
||||
for i := range tt.podSpec.Containers {
|
||||
volumeMountName := tt.podSpec.Containers[i].VolumeMounts[tt.volumePos].Name
|
||||
|
||||
if volumeMountName != additionalVolumeMount[0].Name {
|
||||
t.Errorf("%s %s: Expected mount %v was not created, have %s instead",
|
||||
testName, tt.subTest, additionalVolumeMount, volumeMountName)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
numMountsCheck := len(tt.podSpec.Containers[0].VolumeMounts)
|
||||
|
||||
if numMountsCheck != numMounts+1 {
|
||||
t.Errorf("Unexpected number of VolumeMounts: got %v instead of %v",
|
||||
numMountsCheck, numMounts+1)
|
||||
}
|
||||
tests := []struct {
|
||||
subTest string
|
||||
container string
|
||||
expectedMounts []string
|
||||
}{
|
||||
{
|
||||
subTest: "checking volume mounts of postgres container",
|
||||
container: constants.PostgresContainerName,
|
||||
expectedMounts: []string{"pgdata", "test1", "test3", "test4"},
|
||||
},
|
||||
{
|
||||
subTest: "checking volume mounts of sidecar container",
|
||||
container: "sidecar",
|
||||
expectedMounts: []string{"pgdata", "test1", "test2"},
|
||||
},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
// Test with additional volume mounted only in first container
|
||||
additionalVolumeMount := []acidv1.AdditionalVolume{
|
||||
{
|
||||
Name: "test",
|
||||
MountPath: "/test",
|
||||
TargetContainers: []string{"postgres"},
|
||||
VolumeSource: v1.VolumeSource{
|
||||
EmptyDir: &v1.EmptyDirVolumeSource{},
|
||||
},
|
||||
},
|
||||
}
|
||||
for _, container := range sts.Spec.Template.Spec.Containers {
|
||||
if container.Name != tt.container {
|
||||
continue
|
||||
}
|
||||
mounts := []string{}
|
||||
for _, volumeMounts := range container.VolumeMounts {
|
||||
mounts = append(mounts, volumeMounts.Name)
|
||||
}
|
||||
|
||||
numMounts := len(tt.podSpec.Containers[0].VolumeMounts)
|
||||
|
||||
cluster.addAdditionalVolumes(tt.podSpec, additionalVolumeMount)
|
||||
volumeName := tt.podSpec.Volumes[tt.volumePos].Name
|
||||
|
||||
if volumeName != additionalVolumeMount[0].Name {
|
||||
t.Errorf("%s %s: Expected volume %v was not created, have %s instead",
|
||||
testName, tt.subTest, additionalVolumeMount, volumeName)
|
||||
}
|
||||
|
||||
for _, container := range tt.podSpec.Containers {
|
||||
if container.Name == "postgres" {
|
||||
volumeMountName := container.VolumeMounts[tt.volumePos].Name
|
||||
|
||||
if volumeMountName != additionalVolumeMount[0].Name {
|
||||
t.Errorf("%s %s: Expected mount %v was not created, have %s instead",
|
||||
testName, tt.subTest, additionalVolumeMount, volumeMountName)
|
||||
}
|
||||
|
||||
numMountsCheck := len(container.VolumeMounts)
|
||||
if numMountsCheck != numMounts+1 {
|
||||
t.Errorf("Unexpected number of VolumeMounts: got %v instead of %v",
|
||||
numMountsCheck, numMounts+1)
|
||||
}
|
||||
} else {
|
||||
numMountsCheck := len(container.VolumeMounts)
|
||||
if numMountsCheck == numMounts+1 {
|
||||
t.Errorf("Unexpected number of VolumeMounts: got %v instead of %v",
|
||||
numMountsCheck, numMounts)
|
||||
}
|
||||
if !util.IsEqualIgnoreOrder(mounts, tt.expectedMounts) {
|
||||
t.Errorf("%s %s: different volume mounts: got %v, epxected %v",
|
||||
testName, tt.subTest, mounts, tt.expectedMounts)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -19,8 +19,8 @@ var VersionMap = map[string]int{
|
|||
|
||||
// IsBiggerPostgresVersion Compare two Postgres version numbers
|
||||
func IsBiggerPostgresVersion(old string, new string) bool {
|
||||
oldN, _ := VersionMap[old]
|
||||
newN, _ := VersionMap[new]
|
||||
oldN := VersionMap[old]
|
||||
newN := VersionMap[new]
|
||||
return newN > oldN
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -147,25 +147,6 @@ func (c *Cluster) preScaleDown(newStatefulSet *appsv1.StatefulSet) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
func (c *Cluster) updateStatefulSetAnnotations(annotations map[string]string) (*appsv1.StatefulSet, error) {
|
||||
c.logger.Debugf("patching statefulset annotations")
|
||||
patchData, err := metaAnnotationsPatch(annotations)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("could not form patch for the statefulset metadata: %v", err)
|
||||
}
|
||||
result, err := c.KubeClient.StatefulSets(c.Statefulset.Namespace).Patch(
|
||||
context.TODO(),
|
||||
c.Statefulset.Name,
|
||||
types.MergePatchType,
|
||||
[]byte(patchData),
|
||||
metav1.PatchOptions{},
|
||||
"")
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("could not patch statefulset annotations %q: %v", patchData, err)
|
||||
}
|
||||
return result, nil
|
||||
}
|
||||
|
||||
func (c *Cluster) updateStatefulSet(newStatefulSet *appsv1.StatefulSet) error {
|
||||
c.setProcessName("updating statefulset")
|
||||
if c.Statefulset == nil {
|
||||
|
|
@ -197,13 +178,6 @@ func (c *Cluster) updateStatefulSet(newStatefulSet *appsv1.StatefulSet) error {
|
|||
return fmt.Errorf("could not patch statefulset spec %q: %v", statefulSetName, err)
|
||||
}
|
||||
|
||||
if newStatefulSet.Annotations != nil {
|
||||
statefulSet, err = c.updateStatefulSetAnnotations(newStatefulSet.Annotations)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
c.Statefulset = statefulSet
|
||||
|
||||
return nil
|
||||
|
|
|
|||
|
|
@ -11,7 +11,6 @@ import (
|
|||
"github.com/zalando/postgres-operator/pkg/util"
|
||||
"github.com/zalando/postgres-operator/pkg/util/constants"
|
||||
"github.com/zalando/postgres-operator/pkg/util/k8sutil"
|
||||
appsv1 "k8s.io/api/apps/v1"
|
||||
batchv1beta1 "k8s.io/api/batch/v1beta1"
|
||||
v1 "k8s.io/api/core/v1"
|
||||
policybeta1 "k8s.io/api/policy/v1beta1"
|
||||
|
|
@ -260,28 +259,6 @@ func (c *Cluster) syncPodDisruptionBudget(isUpdate bool) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
func (c *Cluster) mustUpdatePodsAfterLazyUpdate(desiredSset *appsv1.StatefulSet) (bool, error) {
|
||||
|
||||
pods, err := c.listPods()
|
||||
if err != nil {
|
||||
return false, fmt.Errorf("could not list pods of the statefulset: %v", err)
|
||||
}
|
||||
|
||||
for _, pod := range pods {
|
||||
|
||||
effectivePodImage := pod.Spec.Containers[0].Image
|
||||
ssImage := desiredSset.Spec.Template.Spec.Containers[0].Image
|
||||
|
||||
if ssImage != effectivePodImage {
|
||||
c.logger.Infof("not all pods were re-started when the lazy upgrade was enabled; forcing the rolling upgrade now")
|
||||
return true, nil
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return false, nil
|
||||
}
|
||||
|
||||
func (c *Cluster) syncStatefulSet() error {
|
||||
|
||||
podsToRecreate := make([]v1.Pod, 0)
|
||||
|
|
@ -373,8 +350,6 @@ func (c *Cluster) syncStatefulSet() error {
|
|||
}
|
||||
}
|
||||
|
||||
c.updateStatefulSetAnnotations(c.AnnotationsToPropagate(c.annotationsSet(c.Statefulset.Annotations)))
|
||||
|
||||
if len(podsToRecreate) == 0 && !c.OpConfig.EnableLazySpiloUpgrade {
|
||||
// even if the desired and the running statefulsets match
|
||||
// there still may be not up-to-date pods on condition
|
||||
|
|
@ -382,8 +357,8 @@ func (c *Cluster) syncStatefulSet() error {
|
|||
// and
|
||||
// (b) some of the pods were not restarted when the lazy update was still in place
|
||||
for _, pod := range pods {
|
||||
effectivePodImage := pod.Spec.Containers[0].Image
|
||||
stsImage := desiredSts.Spec.Template.Spec.Containers[0].Image
|
||||
effectivePodImage := getPostgresContainer(&pod.Spec).Image
|
||||
stsImage := getPostgresContainer(&desiredSts.Spec.Template.Spec).Image
|
||||
|
||||
if stsImage != effectivePodImage {
|
||||
if err = c.markRollingUpdateFlagForPod(&pod, "pod not yet restarted due to lazy update"); err != nil {
|
||||
|
|
@ -576,10 +551,29 @@ func (c *Cluster) syncRoles() (err error) {
|
|||
}
|
||||
}()
|
||||
|
||||
// mapping between original role name and with deletion suffix
|
||||
deletedUsers := map[string]string{}
|
||||
|
||||
// create list of database roles to query
|
||||
for _, u := range c.pgUsers {
|
||||
userNames = append(userNames, u.Name)
|
||||
// add team member role name with rename suffix in case we need to rename it back
|
||||
if u.Origin == spec.RoleOriginTeamsAPI && c.OpConfig.EnableTeamMemberDeprecation {
|
||||
deletedUsers[u.Name+c.OpConfig.RoleDeletionSuffix] = u.Name
|
||||
userNames = append(userNames, u.Name+c.OpConfig.RoleDeletionSuffix)
|
||||
}
|
||||
}
|
||||
|
||||
// add team members that exist only in cache
|
||||
// to trigger a rename of the role in ProduceSyncRequests
|
||||
for _, cachedUser := range c.pgUsersCache {
|
||||
if _, exists := c.pgUsers[cachedUser.Name]; !exists {
|
||||
userNames = append(userNames, cachedUser.Name)
|
||||
}
|
||||
}
|
||||
|
||||
// add pooler user to list of pgUsers, too
|
||||
// to check if the pooler user exists or has to be created
|
||||
if needMasterConnectionPooler(&c.Spec) || needReplicaConnectionPooler(&c.Spec) {
|
||||
connectionPoolerUser := c.systemUsers[constants.ConnectionPoolerUserKeyName]
|
||||
userNames = append(userNames, connectionPoolerUser.Name)
|
||||
|
|
@ -594,6 +588,16 @@ func (c *Cluster) syncRoles() (err error) {
|
|||
return fmt.Errorf("error getting users from the database: %v", err)
|
||||
}
|
||||
|
||||
// update pgUsers where a deleted role was found
|
||||
// so that they are skipped in ProduceSyncRequests
|
||||
for _, dbUser := range dbUsers {
|
||||
if originalUser, exists := deletedUsers[dbUser.Name]; exists {
|
||||
recreatedUser := c.pgUsers[originalUser]
|
||||
recreatedUser.Deleted = true
|
||||
c.pgUsers[originalUser] = recreatedUser
|
||||
}
|
||||
}
|
||||
|
||||
pgSyncRequests := c.userSyncStrategy.ProduceSyncRequests(dbUsers, c.pgUsers)
|
||||
if err = c.userSyncStrategy.ExecuteSyncRequests(pgSyncRequests, c.pgDb); err != nil {
|
||||
return fmt.Errorf("error executing sync statements: %v", err)
|
||||
|
|
|
|||
|
|
@ -0,0 +1,115 @@
|
|||
package cluster
|
||||
|
||||
import (
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"context"
|
||||
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/types"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
acidv1 "github.com/zalando/postgres-operator/pkg/apis/acid.zalan.do/v1"
|
||||
fakeacidv1 "github.com/zalando/postgres-operator/pkg/generated/clientset/versioned/fake"
|
||||
"github.com/zalando/postgres-operator/pkg/util/config"
|
||||
"github.com/zalando/postgres-operator/pkg/util/k8sutil"
|
||||
"k8s.io/client-go/kubernetes/fake"
|
||||
)
|
||||
|
||||
func newFakeK8sSyncClient() (k8sutil.KubernetesClient, *fake.Clientset) {
|
||||
acidClientSet := fakeacidv1.NewSimpleClientset()
|
||||
clientSet := fake.NewSimpleClientset()
|
||||
|
||||
return k8sutil.KubernetesClient{
|
||||
PodsGetter: clientSet.CoreV1(),
|
||||
PostgresqlsGetter: acidClientSet.AcidV1(),
|
||||
StatefulSetsGetter: clientSet.AppsV1(),
|
||||
}, clientSet
|
||||
}
|
||||
|
||||
func TestSyncStatefulSetsAnnotations(t *testing.T) {
|
||||
testName := "test syncing statefulsets annotations"
|
||||
client, _ := newFakeK8sSyncClient()
|
||||
clusterName := "acid-test-cluster"
|
||||
namespace := "default"
|
||||
inheritedAnnotation := "environment"
|
||||
|
||||
pg := acidv1.Postgresql{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: clusterName,
|
||||
Namespace: namespace,
|
||||
Annotations: map[string]string{inheritedAnnotation: "test"},
|
||||
},
|
||||
Spec: acidv1.PostgresSpec{
|
||||
Volume: acidv1.Volume{
|
||||
Size: "1Gi",
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
var cluster = New(
|
||||
Config{
|
||||
OpConfig: config.Config{
|
||||
PodManagementPolicy: "ordered_ready",
|
||||
Resources: config.Resources{
|
||||
ClusterLabels: map[string]string{"application": "spilo"},
|
||||
ClusterNameLabel: "cluster-name",
|
||||
DefaultCPURequest: "300m",
|
||||
DefaultCPULimit: "300m",
|
||||
DefaultMemoryRequest: "300Mi",
|
||||
DefaultMemoryLimit: "300Mi",
|
||||
InheritedAnnotations: []string{inheritedAnnotation},
|
||||
PodRoleLabel: "spilo-role",
|
||||
ResourceCheckInterval: time.Duration(3),
|
||||
ResourceCheckTimeout: time.Duration(10),
|
||||
},
|
||||
},
|
||||
}, client, pg, logger, eventRecorder)
|
||||
|
||||
cluster.Name = clusterName
|
||||
cluster.Namespace = namespace
|
||||
|
||||
// create a statefulset
|
||||
_, err := cluster.createStatefulSet()
|
||||
assert.NoError(t, err)
|
||||
|
||||
// patch statefulset and add annotation
|
||||
patchData, err := metaAnnotationsPatch(map[string]string{"test-anno": "true"})
|
||||
assert.NoError(t, err)
|
||||
|
||||
newSts, err := cluster.KubeClient.StatefulSets(namespace).Patch(
|
||||
context.TODO(),
|
||||
clusterName,
|
||||
types.MergePatchType,
|
||||
[]byte(patchData),
|
||||
metav1.PatchOptions{},
|
||||
"")
|
||||
assert.NoError(t, err)
|
||||
|
||||
cluster.Statefulset = newSts
|
||||
|
||||
// first compare running with desired statefulset - they should not match
|
||||
// because no inherited annotations or downscaler annotations are configured
|
||||
desiredSts, err := cluster.generateStatefulSet(&cluster.Postgresql.Spec)
|
||||
assert.NoError(t, err)
|
||||
|
||||
cmp := cluster.compareStatefulSetWith(desiredSts)
|
||||
if cmp.match {
|
||||
t.Errorf("%s: match between current and desired statefulsets albeit differences: %#v", testName, cmp)
|
||||
}
|
||||
|
||||
// now sync statefulset - the diff will trigger a replacement of the statefulset
|
||||
cluster.syncStatefulSet()
|
||||
|
||||
// compare again after the SYNC - must be identical to the desired state
|
||||
cmp = cluster.compareStatefulSetWith(desiredSts)
|
||||
if !cmp.match {
|
||||
t.Errorf("%s: current and desired statefulsets are not matching %#v", testName, cmp)
|
||||
}
|
||||
|
||||
// check if inherited annotation exists
|
||||
if _, exists := desiredSts.Annotations[inheritedAnnotation]; !exists {
|
||||
t.Errorf("%s: inherited annotation not found in desired statefulset: %#v", testName, desiredSts.Annotations)
|
||||
}
|
||||
}
|
||||
|
|
@ -227,9 +227,18 @@ func (c *Cluster) logServiceChanges(role PostgresRole, old, new *v1.Service, isU
|
|||
}
|
||||
}
|
||||
|
||||
func (c *Cluster) logVolumeChanges(old, new acidv1.Volume) {
|
||||
c.logger.Infof("volume specification has been changed")
|
||||
logNiceDiff(c.logger, old, new)
|
||||
func getPostgresContainer(podSpec *v1.PodSpec) (pgContainer v1.Container) {
|
||||
for _, container := range podSpec.Containers {
|
||||
if container.Name == constants.PostgresContainerName {
|
||||
pgContainer = container
|
||||
}
|
||||
}
|
||||
|
||||
// if no postgres container was found, take the first one in the podSpec
|
||||
if reflect.DeepEqual(pgContainer, v1.Container{}) && len(podSpec.Containers) > 0 {
|
||||
pgContainer = podSpec.Containers[0]
|
||||
}
|
||||
return pgContainer
|
||||
}
|
||||
|
||||
func (c *Cluster) getTeamMembers(teamID string) ([]string, error) {
|
||||
|
|
@ -247,13 +256,11 @@ func (c *Cluster) getTeamMembers(teamID string) ([]string, error) {
|
|||
for team, membership := range *c.Config.PgTeamMap {
|
||||
if team == teamID {
|
||||
additionalMembers = membership.AdditionalMembers
|
||||
c.logger.Debugf("found %d additional members for team %q", len(members), teamID)
|
||||
c.logger.Debugf("found %d additional members for team %q", len(additionalMembers), teamID)
|
||||
}
|
||||
}
|
||||
|
||||
for _, member := range additionalMembers {
|
||||
members = append(members, member)
|
||||
}
|
||||
members = append(members, additionalMembers...)
|
||||
}
|
||||
|
||||
if !c.OpConfig.EnableTeamsAPI {
|
||||
|
|
@ -263,14 +270,12 @@ func (c *Cluster) getTeamMembers(teamID string) ([]string, error) {
|
|||
|
||||
token, err := c.oauthTokenGetter.getOAuthToken()
|
||||
if err != nil {
|
||||
c.logger.Warnf("could not get oauth token to authenticate to team service API, only returning %d members for team %q: %v", len(members), teamID, err)
|
||||
return members, nil
|
||||
return nil, fmt.Errorf("could not get oauth token to authenticate to team service API: %v", err)
|
||||
}
|
||||
|
||||
teamInfo, err := c.teamsAPIClient.TeamInfo(teamID, token)
|
||||
if err != nil {
|
||||
c.logger.Warnf("could not get team info for team %q, only returning %d members: %v", teamID, len(members), err)
|
||||
return members, nil
|
||||
return nil, fmt.Errorf("could not get team info for team %q: %v", teamID, err)
|
||||
}
|
||||
|
||||
for _, member := range teamInfo.Members {
|
||||
|
|
@ -292,12 +297,10 @@ func (c *Cluster) annotationsSet(annotations map[string]string) map[string]strin
|
|||
pgCRDAnnotations := c.ObjectMeta.Annotations
|
||||
|
||||
// allow to inherit certain labels from the 'postgres' object
|
||||
if pgCRDAnnotations != nil {
|
||||
for k, v := range pgCRDAnnotations {
|
||||
for _, match := range c.OpConfig.InheritedAnnotations {
|
||||
if k == match {
|
||||
annotations[k] = v
|
||||
}
|
||||
for k, v := range pgCRDAnnotations {
|
||||
for _, match := range c.OpConfig.InheritedAnnotations {
|
||||
if k == match {
|
||||
annotations[k] = v
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -74,10 +74,15 @@ func (c *Cluster) syncVolumes() error {
|
|||
func (c *Cluster) syncUnderlyingEBSVolume() error {
|
||||
c.logger.Infof("starting to sync EBS volumes: type, iops, throughput, and size")
|
||||
|
||||
var err error
|
||||
var (
|
||||
err error
|
||||
newSize resource.Quantity
|
||||
)
|
||||
|
||||
targetValue := c.Spec.Volume
|
||||
newSize, err := resource.ParseQuantity(targetValue.Size)
|
||||
if newSize, err = resource.ParseQuantity(targetValue.Size); err != nil {
|
||||
return fmt.Errorf("could not parse volume size: %v", err)
|
||||
}
|
||||
targetSize := quantityToGigabyte(newSize)
|
||||
|
||||
awsGp3 := aws.String("gp3")
|
||||
|
|
|
|||
|
|
@ -24,6 +24,20 @@ import (
|
|||
"k8s.io/client-go/kubernetes/fake"
|
||||
)
|
||||
|
||||
type testVolume struct {
|
||||
size int64
|
||||
iops int64
|
||||
throughtput int64
|
||||
volType string
|
||||
}
|
||||
|
||||
var testVol = testVolume{
|
||||
size: 100,
|
||||
iops: 300,
|
||||
throughtput: 125,
|
||||
volType: "gp2",
|
||||
}
|
||||
|
||||
func newFakeK8sPVCclient() (k8sutil.KubernetesClient, *fake.Clientset) {
|
||||
clientSet := fake.NewSimpleClientset()
|
||||
|
||||
|
|
@ -189,14 +203,7 @@ func TestMigrateEBS(t *testing.T) {
|
|||
cluster.Namespace = namespace
|
||||
filterLabels := cluster.labelsSet(false)
|
||||
|
||||
testVolumes := []testVolume{
|
||||
{
|
||||
size: 100,
|
||||
},
|
||||
{
|
||||
size: 100,
|
||||
},
|
||||
}
|
||||
testVolumes := []testVolume{testVol, testVol}
|
||||
|
||||
initTestVolumesAndPods(cluster.KubeClient, namespace, clusterName, filterLabels, testVolumes)
|
||||
|
||||
|
|
@ -220,13 +227,6 @@ func TestMigrateEBS(t *testing.T) {
|
|||
cluster.executeEBSMigration()
|
||||
}
|
||||
|
||||
type testVolume struct {
|
||||
iops int64
|
||||
throughtput int64
|
||||
size int64
|
||||
volType string
|
||||
}
|
||||
|
||||
func initTestVolumesAndPods(client k8sutil.KubernetesClient, namespace, clustername string, labels labels.Set, volumes []testVolume) {
|
||||
i := 0
|
||||
for _, v := range volumes {
|
||||
|
|
@ -305,17 +305,7 @@ func TestMigrateGp3Support(t *testing.T) {
|
|||
cluster.Namespace = namespace
|
||||
filterLabels := cluster.labelsSet(false)
|
||||
|
||||
testVolumes := []testVolume{
|
||||
{
|
||||
size: 100,
|
||||
},
|
||||
{
|
||||
size: 100,
|
||||
},
|
||||
{
|
||||
size: 100,
|
||||
},
|
||||
}
|
||||
testVolumes := []testVolume{testVol, testVol, testVol}
|
||||
|
||||
initTestVolumesAndPods(cluster.KubeClient, namespace, clusterName, filterLabels, testVolumes)
|
||||
|
||||
|
|
@ -371,14 +361,7 @@ func TestManualGp2Gp3Support(t *testing.T) {
|
|||
cluster.Namespace = namespace
|
||||
filterLabels := cluster.labelsSet(false)
|
||||
|
||||
testVolumes := []testVolume{
|
||||
{
|
||||
size: 100,
|
||||
},
|
||||
{
|
||||
size: 100,
|
||||
},
|
||||
}
|
||||
testVolumes := []testVolume{testVol, testVol}
|
||||
|
||||
initTestVolumesAndPods(cluster.KubeClient, namespace, clusterName, filterLabels, testVolumes)
|
||||
|
||||
|
|
|
|||
|
|
@ -39,7 +39,7 @@ func (c *Controller) importConfigurationFromCRD(fromCRD *acidv1.OperatorConfigur
|
|||
result.EnableSpiloWalPathCompat = fromCRD.EnableSpiloWalPathCompat
|
||||
result.EtcdHost = fromCRD.EtcdHost
|
||||
result.KubernetesUseConfigMaps = fromCRD.KubernetesUseConfigMaps
|
||||
result.DockerImage = util.Coalesce(fromCRD.DockerImage, "registry.opensource.zalan.do/acid/spilo-13:2.0-p6")
|
||||
result.DockerImage = util.Coalesce(fromCRD.DockerImage, "registry.opensource.zalan.do/acid/spilo-13:2.0-p7")
|
||||
result.Workers = util.CoalesceUInt32(fromCRD.Workers, 8)
|
||||
result.MinInstances = fromCRD.MinInstances
|
||||
result.MaxInstances = fromCRD.MaxInstances
|
||||
|
|
@ -152,7 +152,7 @@ func (c *Controller) importConfigurationFromCRD(fromCRD *acidv1.OperatorConfigur
|
|||
|
||||
// logical backup config
|
||||
result.LogicalBackupSchedule = util.Coalesce(fromCRD.LogicalBackup.Schedule, "30 00 * * *")
|
||||
result.LogicalBackupDockerImage = util.Coalesce(fromCRD.LogicalBackup.DockerImage, "registry.opensource.zalan.do/acid/logical-backup:v1.6.2")
|
||||
result.LogicalBackupDockerImage = util.Coalesce(fromCRD.LogicalBackup.DockerImage, "registry.opensource.zalan.do/acid/logical-backup:v1.6.3")
|
||||
result.LogicalBackupProvider = util.Coalesce(fromCRD.LogicalBackup.BackupProvider, "s3")
|
||||
result.LogicalBackupS3Bucket = fromCRD.LogicalBackup.S3Bucket
|
||||
result.LogicalBackupS3Region = fromCRD.LogicalBackup.S3Region
|
||||
|
|
@ -180,6 +180,8 @@ func (c *Controller) importConfigurationFromCRD(fromCRD *acidv1.OperatorConfigur
|
|||
result.PostgresSuperuserTeams = fromCRD.TeamsAPI.PostgresSuperuserTeams
|
||||
result.EnablePostgresTeamCRD = fromCRD.TeamsAPI.EnablePostgresTeamCRD
|
||||
result.EnablePostgresTeamCRDSuperusers = fromCRD.TeamsAPI.EnablePostgresTeamCRDSuperusers
|
||||
result.EnableTeamMemberDeprecation = fromCRD.TeamsAPI.EnableTeamMemberDeprecation
|
||||
result.RoleDeletionSuffix = util.Coalesce(fromCRD.TeamsAPI.RoleDeletionSuffix, "_deleted")
|
||||
|
||||
// logging REST API config
|
||||
result.APIPort = util.CoalesceInt(fromCRD.LoggingRESTAPI.APIPort, 8080)
|
||||
|
|
|
|||
|
|
@ -42,6 +42,7 @@ const (
|
|||
PGSyncUserAdd = iota
|
||||
PGsyncUserAlter
|
||||
PGSyncAlterSet // handle ALTER ROLE SET parameter = value
|
||||
PGSyncUserRename
|
||||
)
|
||||
|
||||
// PgUser contains information about a single user.
|
||||
|
|
@ -53,6 +54,7 @@ type PgUser struct {
|
|||
MemberOf []string `yaml:"inrole"`
|
||||
Parameters map[string]string `yaml:"db_parameters"`
|
||||
AdminRole string `yaml:"admin_role"`
|
||||
Deleted bool `yaml:"deleted"`
|
||||
}
|
||||
|
||||
func (user *PgUser) Valid() bool {
|
||||
|
|
|
|||
|
|
@ -9,8 +9,6 @@ import (
|
|||
)
|
||||
|
||||
var (
|
||||
True = true
|
||||
False = false
|
||||
pgTeamList = acidv1.PostgresTeamList{
|
||||
TypeMeta: metav1.TypeMeta{
|
||||
Kind: "List",
|
||||
|
|
|
|||
|
|
@ -28,8 +28,8 @@ type Resources struct {
|
|||
PodLabelWaitTimeout time.Duration `name:"pod_label_wait_timeout" default:"10m"`
|
||||
PodDeletionWaitTimeout time.Duration `name:"pod_deletion_wait_timeout" default:"10m"`
|
||||
PodTerminateGracePeriod time.Duration `name:"pod_terminate_grace_period" default:"5m"`
|
||||
SpiloRunAsUser *int64 `name:"spilo_runasuser,omitempty"`
|
||||
SpiloRunAsGroup *int64 `name:"spilo_runasgroup,omitempty"`
|
||||
SpiloRunAsUser *int64 `name:"spilo_runasuser"`
|
||||
SpiloRunAsGroup *int64 `name:"spilo_runasgroup"`
|
||||
SpiloFSGroup *int64 `name:"spilo_fsgroup"`
|
||||
PodPriorityClassName string `name:"pod_priority_class_name"`
|
||||
ClusterDomain string `name:"cluster_domain" default:"cluster.local"`
|
||||
|
|
@ -114,7 +114,7 @@ type Scalyr struct {
|
|||
// LogicalBackup defines configuration for logical backup
|
||||
type LogicalBackup struct {
|
||||
LogicalBackupSchedule string `name:"logical_backup_schedule" default:"30 00 * * *"`
|
||||
LogicalBackupDockerImage string `name:"logical_backup_docker_image" default:"registry.opensource.zalan.do/acid/logical-backup:v1.6.2"`
|
||||
LogicalBackupDockerImage string `name:"logical_backup_docker_image" default:"registry.opensource.zalan.do/acid/logical-backup:v1.6.3"`
|
||||
LogicalBackupProvider string `name:"logical_backup_provider" default:"s3"`
|
||||
LogicalBackupS3Bucket string `name:"logical_backup_s3_bucket" default:""`
|
||||
LogicalBackupS3Region string `name:"logical_backup_s3_region" default:""`
|
||||
|
|
@ -152,7 +152,7 @@ type Config struct {
|
|||
WatchedNamespace string `name:"watched_namespace"` // special values: "*" means 'watch all namespaces', the empty string "" means 'watch a namespace where operator is deployed to'
|
||||
KubernetesUseConfigMaps bool `name:"kubernetes_use_configmaps" default:"false"`
|
||||
EtcdHost string `name:"etcd_host" default:""` // special values: the empty string "" means Patroni will use K8s as a DCS
|
||||
DockerImage string `name:"docker_image" default:"registry.opensource.zalan.do/acid/spilo-13:2.0-p6"`
|
||||
DockerImage string `name:"docker_image" default:"registry.opensource.zalan.do/acid/spilo-13:2.0-p7"`
|
||||
SidecarImages map[string]string `name:"sidecar_docker_images"` // deprecated in favour of SidecarContainers
|
||||
SidecarContainers []v1.Container `name:"sidecars"`
|
||||
PodServiceAccountName string `name:"pod_service_account_name" default:"postgres-pod"`
|
||||
|
|
@ -176,6 +176,8 @@ type Config struct {
|
|||
EnableTeamsAPI bool `name:"enable_teams_api" default:"true"`
|
||||
EnableTeamSuperuser bool `name:"enable_team_superuser" default:"false"`
|
||||
TeamAdminRole string `name:"team_admin_role" default:"admin"`
|
||||
RoleDeletionSuffix string `name:"role_deletion_suffix" default:"_deleted"`
|
||||
EnableTeamMemberDeprecation bool `name:"enable_team_member_deprecation" default:"false"`
|
||||
EnableAdminRoleForUsers bool `name:"enable_admin_role_for_users" default:"true"`
|
||||
EnablePostgresTeamCRD bool `name:"enable_postgres_team_crd" default:"false"`
|
||||
EnablePostgresTeamCRDSuperusers bool `name:"enable_postgres_team_crd_superusers" default:"false"`
|
||||
|
|
|
|||
|
|
@ -5,7 +5,6 @@ import "time"
|
|||
// General kubernetes-related constants
|
||||
const (
|
||||
PostgresContainerName = "postgres"
|
||||
PostgresContainerIdx = 0
|
||||
K8sAPIPath = "/apis"
|
||||
|
||||
QueueResyncPeriodPod = 5 * time.Minute
|
||||
|
|
|
|||
|
|
@ -9,11 +9,13 @@ import (
|
|||
|
||||
"github.com/zalando/postgres-operator/pkg/spec"
|
||||
"github.com/zalando/postgres-operator/pkg/util"
|
||||
"github.com/zalando/postgres-operator/pkg/util/constants"
|
||||
)
|
||||
|
||||
const (
|
||||
createUserSQL = `SET LOCAL synchronous_commit = 'local'; CREATE ROLE "%s" %s %s;`
|
||||
alterUserSQL = `ALTER ROLE "%s" %s`
|
||||
alterUserRenameSQL = `ALTER ROLE "%s" RENAME TO "%s%s"`
|
||||
alterRoleResetAllSQL = `ALTER ROLE "%s" RESET ALL`
|
||||
alterRoleSetSQL = `ALTER ROLE "%s" SET %s TO %s`
|
||||
grantToUserSQL = `GRANT %s TO "%s"`
|
||||
|
|
@ -29,6 +31,7 @@ const (
|
|||
// (except for the NOLOGIN). TODO: process other NOflags, i.e. NOSUPERUSER correctly.
|
||||
type DefaultUserSyncStrategy struct {
|
||||
PasswordEncryption string
|
||||
RoleDeletionSuffix string
|
||||
}
|
||||
|
||||
// ProduceSyncRequests figures out the types of changes that need to happen with the given users.
|
||||
|
|
@ -36,8 +39,11 @@ func (strategy DefaultUserSyncStrategy) ProduceSyncRequests(dbUsers spec.PgUserM
|
|||
newUsers spec.PgUserMap) []spec.PgSyncUserRequest {
|
||||
|
||||
var reqs []spec.PgSyncUserRequest
|
||||
// No existing roles are deleted or stripped of role memebership/flags
|
||||
for name, newUser := range newUsers {
|
||||
// do not create user that exists in DB with deletion suffix
|
||||
if newUser.Deleted {
|
||||
continue
|
||||
}
|
||||
dbUser, exists := dbUsers[name]
|
||||
if !exists {
|
||||
reqs = append(reqs, spec.PgSyncUserRequest{Kind: spec.PGSyncUserAdd, User: newUser})
|
||||
|
|
@ -70,6 +76,25 @@ func (strategy DefaultUserSyncStrategy) ProduceSyncRequests(dbUsers spec.PgUserM
|
|||
}
|
||||
}
|
||||
|
||||
// No existing roles are deleted or stripped of role membership/flags
|
||||
// but team roles will be renamed and denied from LOGIN
|
||||
for name, dbUser := range dbUsers {
|
||||
if _, exists := newUsers[name]; !exists {
|
||||
// toggle LOGIN flag based on role deletion
|
||||
userFlags := make([]string, len(dbUser.Flags))
|
||||
userFlags = append(userFlags, dbUser.Flags...)
|
||||
if dbUser.Deleted {
|
||||
dbUser.Flags = util.StringSliceReplaceElement(dbUser.Flags, constants.RoleFlagNoLogin, constants.RoleFlagLogin)
|
||||
} else {
|
||||
dbUser.Flags = util.StringSliceReplaceElement(dbUser.Flags, constants.RoleFlagLogin, constants.RoleFlagNoLogin)
|
||||
}
|
||||
if !util.IsEqualIgnoreOrder(userFlags, dbUser.Flags) {
|
||||
reqs = append(reqs, spec.PgSyncUserRequest{Kind: spec.PGsyncUserAlter, User: dbUser})
|
||||
}
|
||||
|
||||
reqs = append(reqs, spec.PgSyncUserRequest{Kind: spec.PGSyncUserRename, User: dbUser})
|
||||
}
|
||||
}
|
||||
return reqs
|
||||
}
|
||||
|
||||
|
|
@ -94,6 +119,11 @@ func (strategy DefaultUserSyncStrategy) ExecuteSyncRequests(requests []spec.PgSy
|
|||
reqretries = append(reqretries, request)
|
||||
errors = append(errors, fmt.Sprintf("could not set custom user %q parameters: %v", request.User.Name, err))
|
||||
}
|
||||
case spec.PGSyncUserRename:
|
||||
if err := strategy.alterPgUserRename(request.User, db); err != nil {
|
||||
reqretries = append(reqretries, request)
|
||||
errors = append(errors, fmt.Sprintf("could not rename custom user %q: %v", request.User.Name, err))
|
||||
}
|
||||
default:
|
||||
return fmt.Errorf("unrecognized operation: %v", request.Kind)
|
||||
}
|
||||
|
|
@ -124,6 +154,23 @@ func (strategy DefaultUserSyncStrategy) alterPgUserSet(user spec.PgUser, db *sql
|
|||
return nil
|
||||
}
|
||||
|
||||
func (strategy DefaultUserSyncStrategy) alterPgUserRename(user spec.PgUser, db *sql.DB) error {
|
||||
var query string
|
||||
|
||||
// append or trim deletion suffix depending if the user has the suffix or not
|
||||
if user.Deleted {
|
||||
newName := strings.TrimSuffix(user.Name, strategy.RoleDeletionSuffix)
|
||||
query = fmt.Sprintf(alterUserRenameSQL, user.Name, newName, "")
|
||||
} else {
|
||||
query = fmt.Sprintf(alterUserRenameSQL, user.Name, user.Name, strategy.RoleDeletionSuffix)
|
||||
}
|
||||
|
||||
if _, err := db.Exec(query); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (strategy DefaultUserSyncStrategy) createPgUser(user spec.PgUser, db *sql.DB) error {
|
||||
var userFlags []string
|
||||
var userPassword string
|
||||
|
|
|
|||
|
|
@ -151,6 +151,18 @@ func IsEqualIgnoreOrder(a, b []string) bool {
|
|||
return reflect.DeepEqual(a_copy, b_copy)
|
||||
}
|
||||
|
||||
// SliceReplaceElement
|
||||
func StringSliceReplaceElement(s []string, a, b string) (result []string) {
|
||||
tmp := make([]string, 0, len(s))
|
||||
for _, str := range s {
|
||||
if str == a {
|
||||
str = b
|
||||
}
|
||||
tmp = append(tmp, str)
|
||||
}
|
||||
return tmp
|
||||
}
|
||||
|
||||
// SubstractStringSlices finds elements in a that are not in b and return them as a result slice.
|
||||
func SubstractStringSlices(a []string, b []string) (result []string, equal bool) {
|
||||
// Slices are assumed to contain unique elements only
|
||||
|
|
|
|||
|
|
@ -166,6 +166,14 @@ func TestIsEqualIgnoreOrder(t *testing.T) {
|
|||
}
|
||||
}
|
||||
|
||||
func TestStringSliceReplaceElement(t *testing.T) {
|
||||
testSlice := []string{"a", "b", "c"}
|
||||
testSlice = StringSliceReplaceElement(testSlice, "b", "d")
|
||||
if !SliceContains(testSlice, "d") {
|
||||
t.Errorf("testSlide item not replaced: %v", testSlice)
|
||||
}
|
||||
}
|
||||
|
||||
func TestSubstractSlices(t *testing.T) {
|
||||
for _, tt := range substractTest {
|
||||
actualRes, actualEqual := SubstractStringSlices(tt.inA, tt.inB)
|
||||
|
|
|
|||
Loading…
Reference in New Issue