@colisweb/rescript-toolkit 5.5.4 → 5.6.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -535,28 +535,29 @@ database_k8s() {
535
535
  HostName 127.0.0.1
536
536
  Port 2225
537
537
  LocalForward 24441 toutatis-testing-db.ca0rjdmnxf1x.eu-west-1.rds.amazonaws.com:5432
538
- LocalForward 25431 testapirds.ca0rjdmnxf1x.eu-west-1.rds.amazonaws.com:3306
538
+ LocalForward 25431 toutatis-testing-mysql-db.ca0rjdmnxf1x.eu-west-1.rds.amazonaws.com:3306
539
+ LocalForward 25531 testapirds.ca0rjdmnxf1x.eu-west-1.rds.amazonaws.com:3306
539
540
  Host bastion_staging
540
541
  HostName 127.0.0.1
541
542
  Port 2226
542
543
  LocalForward 24442 toutatis-staging-db.ca0rjdmnxf1x.eu-west-1.rds.amazonaws.com:5432
543
- LocalForward 25432 testapirds.ca0rjdmnxf1x.eu-west-1.rds.amazonaws.com:3306
544
+ LocalForward 25432 toutatis-staging-mysql-db.ca0rjdmnxf1x.eu-west-1.rds.amazonaws.com:3306
544
545
  Host bastion_recette
545
546
  HostName 127.0.0.1
546
547
  Port 2228
547
548
  LocalForward 24446 toutatis-recette-db.ca0rjdmnxf1x.eu-west-1.rds.amazonaws.com:5432
548
- LocalForward 25436 testapirds.ca0rjdmnxf1x.eu-west-1.rds.amazonaws.com:3306
549
+ LocalForward 25436 toutatis-recette-mysql-db.ca0rjdmnxf1x.eu-west-1.rds.amazonaws.com:3306
550
+ LocalForward 25536 testapirds.ca0rjdmnxf1x.eu-west-1.rds.amazonaws.com:3306
549
551
  Host bastion_production
550
552
  HostName 127.0.0.1
551
553
  Port 2227
552
554
  LocalForward 24443 toutatis-production-db-replica.ca0rjdmnxf1x.eu-west-1.rds.amazonaws.com:5432
553
- LocalForward 25433 api-production-rds-read-replica.ca0rjdmnxf1x.eu-west-1.rds.amazonaws.com:3306
554
- LocalForward 25435 archive-ca.ca0rjdmnxf1x.eu-west-1.rds.amazonaws.com:3306
555
+ LocalForward 25433 toutatis-production-mysql-db-replica.ca0rjdmnxf1x.eu-west-1.rds.amazonaws.com:3306
555
556
  EOF
556
557
  if [ "$MODE" = "production_rw" ] ; then
557
558
  cat >> "$bastion_config" <<EOF
558
559
  LocalForward 24444 toutatis-production-db.ca0rjdmnxf1x.eu-west-1.rds.amazonaws.com:5432
559
- LocalForward 25434 api-production-rds.ca0rjdmnxf1x.eu-west-1.rds.amazonaws.com:3306
560
+ LocalForward 25434 toutatis-production-mysql-db.ca0rjdmnxf1x.eu-west-1.rds.amazonaws.com:3306
560
561
  EOF
561
562
  fi
562
563
 
@@ -576,7 +577,7 @@ psql_on_k8() {
576
577
  CONNECTION=$3
577
578
  shift 3
578
579
 
579
- kubectl -n $NAMESPACE run ${SERVICE}-database-init \
580
+ kubectl -n $NAMESPACE run ${SERVICE}-postgres-init \
580
581
  --image jbergknoff/postgresql-client \
581
582
  --restart=Never \
582
583
  --attach --rm \
@@ -587,14 +588,15 @@ psql_on_k8() {
587
588
 
588
589
  mysql_on_k8() {
589
590
  local namespace=$1
590
- local db_host=$2
591
- local db_port=$3
592
- local db_init_username=$4
593
- local db_init_password=$5
594
- local query=$6
595
-
596
- kubectl -n ${namespace} run datadog-database-init \
597
- --image widdpim/mysql-client \
591
+ local service=$2
592
+ local db_host=$3
593
+ local db_port=$4
594
+ local db_init_username=$5
595
+ local db_init_password=$6
596
+ local query=$7
597
+
598
+ kubectl -n ${namespace} run ${service}-mysql-init \
599
+ --image arey/mysql-client \
598
600
  --restart=Never \
599
601
  --attach --rm \
600
602
  -- \
@@ -674,12 +676,14 @@ kube_init_datadog_in_database() {
674
676
  extract_args 8 namespace db_host db_port db_init_username db_init_password db_datadog_username db_datadog_password db_datadog_schema $*
675
677
 
676
678
  echo "======================="
677
- echo " Initializing Datadog Agent Requiement for namespace $namespace"
679
+ echo " Initializing Datadog Agent Requirement for namespace $namespace"
678
680
  echo "======================="
679
681
 
680
682
  echo "Checking if User '$db_datadog_username' exists"
683
+ local service="datadog"
684
+ found_db_users=$(mysql_on_k8 $namespace $service $db_host $db_port $db_init_username $db_init_password 'SELECT user FROM mysql.user;')
681
685
  set +e
682
- mysql_on_k8 $namespace $db_host $db_port $db_init_username $db_init_password 'SELECT user FROM mysql.user;' | grep "^$db_datadog_username$"
686
+ echo "$found_db_users" | grep "^$db_datadog_username$"
683
687
  return_code=$?
684
688
  set -e
685
689
 
@@ -690,29 +694,29 @@ kube_init_datadog_in_database() {
690
694
 
691
695
  # All the query come from this docs : https://docs.datadoghq.com/fr/database_monitoring/setup_mysql/selfhosted/?tab=mysql56
692
696
 
693
- mysql_on_k8 $namespace $db_host $db_port $db_init_username $db_init_password 'CREATE USER '"$db_datadog_username"'@"%" IDENTIFIED BY '"'$db_datadog_password'"';'
697
+ mysql_on_k8 $namespace $service $db_host $db_port $db_init_username $db_init_password 'CREATE USER '"$db_datadog_username"'@"%" IDENTIFIED BY '"'$db_datadog_password'"';'
694
698
  echo "USER created $db_datadog_username"
695
699
 
696
- mysql_on_k8 $namespace $db_host $db_port $db_init_username $db_init_password 'GRANT REPLICATION CLIENT ON *.* TO datadog@"%" WITH MAX_USER_CONNECTIONS 5;'
700
+ mysql_on_k8 $namespace $service $db_host $db_port $db_init_username $db_init_password 'GRANT REPLICATION CLIENT ON *.* TO datadog@"%" WITH MAX_USER_CONNECTIONS 5;'
697
701
  echo "ALTER USER $db_datadog_username"
698
702
 
699
- mysql_on_k8 $namespace $db_host $db_port $db_init_username $db_init_password 'GRANT PROCESS ON *.* TO '"$db_datadog_username"'@"%";'
703
+ mysql_on_k8 $namespace $service $db_host $db_port $db_init_username $db_init_password 'GRANT PROCESS ON *.* TO '"$db_datadog_username"'@"%";'
700
704
  echo "Granted PROCESS for $db_datadog_username"
701
705
 
702
- mysql_on_k8 $namespace $db_host $db_port $db_init_username $db_init_password 'GRANT SELECT ON performance_schema.* TO '"$db_datadog_username"'@"%";'
706
+ mysql_on_k8 $namespace $service $db_host $db_port $db_init_username $db_init_password 'GRANT SELECT ON performance_schema.* TO '"$db_datadog_username"'@"%";'
703
707
  echo "Granted SELECT on performance_schema for $db_datadog_username"
704
708
 
705
- mysql_on_k8 $namespace $db_host $db_port $db_init_username $db_init_password 'CREATE SCHEMA IF NOT EXISTS datadog;'
709
+ mysql_on_k8 $namespace $service $db_host $db_port $db_init_username $db_init_password 'CREATE SCHEMA IF NOT EXISTS datadog;'
706
710
  echo "CREATE SCHEMA datadog"
707
711
 
708
- mysql_on_k8 $namespace $db_host $db_port $db_init_username $db_init_password 'GRANT EXECUTE ON datadog.* to '"$db_datadog_username"'@"%";'
712
+ mysql_on_k8 $namespace $service $db_host $db_port $db_init_username $db_init_password 'GRANT EXECUTE ON datadog.* to '"$db_datadog_username"'@"%";'
709
713
  echo "Granted 'GRANT EXECUTE for $db_datadog_username on datadog"
710
714
 
711
- mysql_on_k8 $namespace $db_host $db_port $db_init_username $db_init_password 'GRANT CREATE TEMPORARY TABLES ON datadog.* TO '"$db_datadog_username"'@"%";'
715
+ mysql_on_k8 $namespace $service $db_host $db_port $db_init_username $db_init_password 'GRANT CREATE TEMPORARY TABLES ON datadog.* TO '"$db_datadog_username"'@"%";'
712
716
  echo "Granted CREATE TEMPORARY TABLES for $db_datadog_username"
713
717
 
714
718
 
715
- mysql_on_k8 $namespace $db_host $db_port $db_init_username $db_init_password 'DROP PROCEDURE IF EXISTS datadog.explain_statement;
719
+ mysql_on_k8 $namespace $service $db_host $db_port $db_init_username $db_init_password 'DROP PROCEDURE IF EXISTS datadog.explain_statement;
716
720
  DELIMITER $$
717
721
  CREATE PROCEDURE datadog.explain_statement(IN query TEXT)
718
722
  SQL SECURITY DEFINER
@@ -725,7 +729,7 @@ kube_init_datadog_in_database() {
725
729
  DELIMITER ;'
726
730
  echo "CREATE PROCEDURE PROCEDURE datadog.explain_statement"
727
731
 
728
- mysql_on_k8 $namespace $db_host $db_port $db_init_username $db_init_password 'DROP PROCEDURE IF EXISTS '"$db_datadog_username"'.explain_statement;
732
+ mysql_on_k8 $namespace $service $db_host $db_port $db_init_username $db_init_password 'DROP PROCEDURE IF EXISTS '"$db_datadog_username"'.explain_statement;
729
733
  DELIMITER $$
730
734
  CREATE PROCEDURE '"$db_datadog_username"'.explain_statement(IN query TEXT)
731
735
  SQL SECURITY DEFINER
@@ -739,7 +743,7 @@ kube_init_datadog_in_database() {
739
743
  GRANT EXECUTE ON PROCEDURE '"$db_datadog_username"'.explain_statement TO datadog@"%";'
740
744
  echo "CREATE PROCEDURE on SCHEMA $db_datadog_schema for $db_datadog_username"
741
745
 
742
- mysql_on_k8 $namespace $db_host $db_port $db_init_username $db_init_password 'DROP PROCEDURE IF EXISTS datadog.enable_events_statements_consumers;
746
+ mysql_on_k8 $namespace $service $db_host $db_port $db_init_username $db_init_password 'DROP PROCEDURE IF EXISTS datadog.enable_events_statements_consumers;
743
747
  DELIMITER $$
744
748
  CREATE PROCEDURE datadog.enable_events_statements_consumers()
745
749
  SQL SECURITY DEFINER
@@ -817,7 +821,7 @@ kube_init_datadog_in_postgres_database() {
817
821
  RETURNS NULL ON NULL INPUT
818
822
  SECURITY DEFINER;"
819
823
 
820
- kubectl -n $namespace run $service-database-init \
824
+ kubectl -n $namespace run $service-postgres-init \
821
825
  --image jbergknoff/postgresql-client \
822
826
  --restart=Never \
823
827
  --attach --rm \
@@ -869,6 +873,57 @@ kube_init_service_database() {
869
873
 
870
874
  #!/usr/bin/env bash
871
875
 
876
+ # Allow to use JMX connection to retrieve data and metrics from the pods within kubernetes
877
+ # You will need visualVM to use this tool https://visualvm.github.io/
878
+ # ex: bind_jmx testing notification
879
+ bind_jmx() {
880
+
881
+ local ENV=$1
882
+ local SERVICE_NAME=$2
883
+ local PORT=2242
884
+
885
+ start_ssh_bastion $ENV $PORT
886
+
887
+ echo "root" | ssh -f -N -oUserKnownHostsFile=/dev/null -oStrictHostKeyChecking=no -D 7777 root@127.0.0.1 -p 2242
888
+ local PODS=$(kubectl -n $ENV get pods -o wide | grep $SERVICE_NAME | grep -Eo '^[^ ]+')
889
+
890
+ echo "Choose one of the following pod to get metrics from..."
891
+ local POD_NAME=$(gum choose $PODS)
892
+ local POD_IP=$(
893
+ kubectl -n $ENV get pods -o jsonpath='{range .items[*]}{.metadata.name}{" "}{.status.podIP}{"\n"}{end}' |
894
+ grep $POD_NAME |
895
+ cut -d' ' -f2 |
896
+ head -1
897
+ )
898
+
899
+ jconsole -J-DsocksProxyHost=localhost \
900
+ -J-DsocksProxyPort=7777 \
901
+ service:jmx:rmi:///jndi/rmi://$POD_IP:7199/jmxrmi \
902
+ -J-DsocksNonProxyHosts= &
903
+
904
+ cat << EOF
905
+ Now start VisualVM
906
+ Preferences > Network > Manual Proxy Settings
907
+ SOCKS Proxy Line: Set 'localhost' and Port '7777'
908
+ File > Add JMX Connection
909
+ Set $POD_IP:7199, check 'do not require an SSL connection'
910
+ Remember to kill you bastion afterward using 'stop_ssh_bastion'
911
+ EOF
912
+ }
913
+ #!/usr/bin/env bash
914
+
915
+ k8_nodes_stats() {
916
+ kubectl get nodes -o name |
917
+ xargs kubectl describe |
918
+ grep "^Name\|workType\|cpu \|memory " |
919
+ sed -r 's/[ :=]+/\t/g' |
920
+ sed 's/\tworkType\t//g' |
921
+ sed -r 's/^Name/---\nName/g' |
922
+ grep --color "Name\|web\|workers\|cpu\|memory\|---"
923
+ }
924
+
925
+ #!/usr/bin/env bash
926
+
872
927
  # Port forward on the first matching pod
873
928
  # Ex :
874
929
  # pod_forward testing notification-http
@@ -946,12 +1001,58 @@ pick_pod() {
946
1001
 
947
1002
  #!/usr/bin/env bash
948
1003
 
1004
+ bastion_config_for_redis_ca() {
1005
+ ssh_config xufte6.0001.euw1.cache.amazonaws.com redis 2223 63789 tests testing recette-001 sandbox prod > $1
1006
+ }
1007
+
1008
+ bastion_config_for_redis_toutatis() {
1009
+ ssh_config xufte6.0001.euw1.cache.amazonaws.com toutatis 2223 63789 tests testing recette staging production > $1
1010
+ }
1011
+
1012
+ ssh_config() {
1013
+ host=$1
1014
+ host_prefix=$2
1015
+ port0=$3
1016
+ forward0=$4
1017
+ shift 4
1018
+ instance_names=("$@") # /!\ indices start at 1 with zsh
1019
+ ssh_header
1020
+
1021
+ environments=(tests testing recette staging production)
1022
+
1023
+ length=${#environments[@]}
1024
+ for (( i=1; i<=${length}; i++ ));
1025
+ do
1026
+ bastion_block bastion_${environments[$i]} $(($port0 + $i)) $(($forward0 + $i)) ${host_prefix}-${instance_names[$i]}.$host
1027
+ done
1028
+ }
1029
+
1030
+ ssh_header() {
1031
+ cat <<EOF
1032
+ UserKnownHostsFile /dev/null
1033
+ StrictHostKeyChecking no
1034
+ User root
1035
+ EOF
1036
+ }
1037
+
1038
+ bastion_block() {
1039
+ cat <<EOF
1040
+ Host $1
1041
+ HostName 127.0.0.1
1042
+ Port $2
1043
+ LocalForward $3 $4:6379
1044
+ EOF
1045
+ }
1046
+
949
1047
  redis_k8s() {
950
1048
  MODE=$1
1049
+ REDIS_INSTANCE=${2:-ca}
951
1050
  case $MODE in
1051
+ "tests") SSH_LOCAL_PORT=2224;REDIS_LOCAL_PORT=63790;ENV="tests";;
952
1052
  "testing") SSH_LOCAL_PORT=2225;REDIS_LOCAL_PORT=63791;ENV="testing";;
953
- "staging") SSH_LOCAL_PORT=2226;REDIS_LOCAL_PORT=63792;ENV="staging";;
954
- "production") SSH_LOCAL_PORT=2227;REDIS_LOCAL_PORT=63793;ENV="production";;
1053
+ "recette") SSH_LOCAL_PORT=2226;REDIS_LOCAL_PORT=63792;ENV="recette";;
1054
+ "staging") SSH_LOCAL_PORT=2227;REDIS_LOCAL_PORT=63793;ENV="staging";;
1055
+ "production") SSH_LOCAL_PORT=2228;REDIS_LOCAL_PORT=63794;ENV="production";;
955
1056
  *) echo "Unsupported ENV : $MODE"; return 1 ;;
956
1057
  esac
957
1058
 
@@ -960,23 +1061,11 @@ redis_k8s() {
960
1061
  lsof -ti tcp:$REDIS_LOCAL_PORT | xargs kill
961
1062
 
962
1063
  bastion_config=$(mktemp)
963
- cat > "$bastion_config" <<EOF
964
- UserKnownHostsFile /dev/null
965
- StrictHostKeyChecking no
966
- User root
967
- Host bastion_testing
968
- HostName 127.0.0.1
969
- Port 2225
970
- LocalForward 63791 redis-testing.xufte6.0001.euw1.cache.amazonaws.com:6379
971
- Host bastion_staging
972
- HostName 127.0.0.1
973
- Port 2226
974
- LocalForward 63792 redis-sandbox.xufte6.0001.euw1.cache.amazonaws.com:6379
975
- Host bastion_production
976
- HostName 127.0.0.1
977
- Port 2227
978
- LocalForward 63793 redis-prod.xufte6.0001.euw1.cache.amazonaws.com:6379
979
- EOF
1064
+ case $REDIS_INSTANCE in
1065
+ "ca") bastion_config_for_redis_ca "$bastion_config";;
1066
+ "toutatis") bastion_config_for_redis_toutatis "$bastion_config";;
1067
+ *) echo "Unsupported redis instance (ca or toutatis available) : $REDIS_INSTANCE"; return 1;;
1068
+ esac
980
1069
 
981
1070
  ssh -f -N \
982
1071
  -F "$bastion_config" \
@@ -1518,24 +1607,13 @@ jconsole_k8s() {
1518
1607
 
1519
1608
  #!/usr/bin/env bash
1520
1609
 
1521
- # Interactive console on an existing pod. See also run_ruby_k8s
1522
- # Ex :
1523
- # railsc_k8s_old production
1524
- # railsc_k8s_old production "User.where(email:'toni@colisweb.com')"
1525
- railsc_k8s_old() {
1526
- ENV=$1
1527
- COMMAND=$2
1528
- configure_kubectl_for $ENV
1529
- POD=$(kubectl -n $ENV get pods -o=name | grep colisweb-api-web | head -1 | sed -e 's/pod\///')
1530
- KUBERAILS="kubectl -n $ENV exec -ti $POD -- /usr/src/app/bin/rails c"
1531
- [ -z "$COMMAND" ] && eval $KUBERAILS || echo $COMMAND | eval $KUBERAILS
1532
- }
1533
-
1534
1610
  # Interactive console on an new pod. See also run_ruby_k8s
1535
1611
  # Ex :
1536
1612
  # railsc_k8s production
1613
+ # railsc_k8s production "User.where(email:'toni@colisweb.com')"
1537
1614
  railsc_k8s() {
1538
1615
  ENV=$1
1616
+ COMMAND=$2
1539
1617
  [[ $ENV = "production" || $ENV = "staging" ]] && default_tag="master-latest" || default_tag="${ENV}-latest"
1540
1618
  local image_tag=${5:-$default_tag}
1541
1619
  local IMAGE="949316342391.dkr.ecr.eu-west-1.amazonaws.com/colisweb-api:$image_tag"
@@ -1585,7 +1663,8 @@ railsc_k8s() {
1585
1663
  '
1586
1664
 
1587
1665
  sleep 5
1588
- kubectl -n $ENV exec -it $POD_NAME -- /usr/src/app/bin/rails c
1666
+ KUBERAILS="kubectl -n $ENV exec -ti $POD_NAME -- /usr/src/app/bin/rails c"
1667
+ [ -z "$COMMAND" ] && eval $KUBERAILS || echo $COMMAND | eval $KUBERAILS
1589
1668
 
1590
1669
  print "End of $POD_NAME "
1591
1670
  kubectl -n $ENV delete pods $POD_NAME
@@ -1829,11 +1908,11 @@ datadog_schedule_downtime_single() {
1829
1908
  {
1830
1909
  "active": true,
1831
1910
  "downtime_type": 0,
1832
- "start": $START,
1833
- "end": $END,
1834
- "message": "CA Deployment - performance for $SERVICE may be lower for next $DOWNTIME_MINUTES min",
1911
+ "start": '$START',
1912
+ "end": '$END',
1913
+ "message": "CA Deployment - performance for '$SERVICE' may be lower for next '$DOWNTIME_MINUTES' min",
1835
1914
  "monitor_tags": [
1836
- "service:$SERVICE",
1915
+ "service:'$SERVICE'",
1837
1916
  "performance"
1838
1917
  ],
1839
1918
  "scope": [
@@ -1843,6 +1922,7 @@ datadog_schedule_downtime_single() {
1843
1922
  }
1844
1923
  '
1845
1924
  }
1925
+
1846
1926
  #!/usr/bin/env bash
1847
1927
 
1848
1928
  docker_build_push() {
@@ -1855,11 +1935,18 @@ docker_build_push() {
1855
1935
 
1856
1936
  if ! image_exists $DOCKER_REGISTRY_ID $APPLICATION $CI_COMMIT_SHORT_SHA ; then
1857
1937
  docker pull $DOCKER_IMAGE || true
1858
- docker build $DOCKER_BUILD_ARGS -t $DOCKER_IMAGE_SHA --cache-from $DOCKER_IMAGE $DOCKER_STAGE_PATH
1938
+ SOURCE_URL=${CI_PROJECT_URL:8} # without "https://" protocol, like gitlab.com/colisweb-idl/colisweb/back/packing
1939
+ docker build $DOCKER_BUILD_ARGS \
1940
+ -t $DOCKER_IMAGE_SHA \
1941
+ --label org.opencontainers.image.revision=$(git rev-parse HEAD) \
1942
+ --label org.opencontainers.image.source=$SOURCE_URL \
1943
+ --cache-from $DOCKER_IMAGE \
1944
+ $DOCKER_STAGE_PATH
1859
1945
  docker push $DOCKER_IMAGE_SHA
1860
1946
  fi
1861
1947
  }
1862
1948
 
1949
+
1863
1950
  docker_promote() {
1864
1951
  # inspired by https://dille.name/blog/2018/09/20/how-to-tag-docker-images-without-pulling-them/
1865
1952
  OLD_TAG=${1//[^0-9a-zA-Z-.]/_}
@@ -1886,6 +1973,7 @@ docker_promote() {
1886
1973
  image_exists ${DOCKER_REGISTRY_ID} ${IMAGE_TO_CHECK} ${VERSION} || return 1
1887
1974
  done
1888
1975
  }
1976
+
1889
1977
  #!/usr/bin/env bash
1890
1978
 
1891
1979
  extract_yaml_config_variable() {
@@ -1962,7 +2050,7 @@ flyway_clean() {
1962
2050
 
1963
2051
  #!/usr/bin/env bash
1964
2052
 
1965
- FLYWAY_VERSION="5.2.4"
2053
+ FLYWAY_VERSION="7.4.0"
1966
2054
 
1967
2055
 
1968
2056
  get_yaml_variable() {
@@ -2048,7 +2136,7 @@ flyway_migrate() {
2048
2136
  "containers":[
2049
2137
  {
2050
2138
  "name":"'$POD_NAME'",
2051
- "image":"boxfuse/flyway:'$flyway_version'",
2139
+ "image":"flyway/flyway:'$flyway_version'",
2052
2140
  "command":["flyway", "-url='$db_url'", "-user='$db_user'", "-password='$db_password'", "migrate"],
2053
2141
  "volumeMounts":[
2054
2142
  {
@@ -2073,6 +2161,63 @@ flyway_migrate() {
2073
2161
  kubectl -n $namespace delete configmap $CONFIGMAP_NAME
2074
2162
  }
2075
2163
 
2164
+ #!/usr/bin/env bash
2165
+ flyway_repair() {
2166
+ set -e
2167
+ check_env_vars 4 "APPLICATION" "ENVIRONMENT" "FLYWAY_VERSION" "MIGRATION_SQL_PATH"
2168
+
2169
+ PG_YAML_PATH=".${APPLICATION}config.postgres"
2170
+
2171
+ DB_PORT="5432"
2172
+ DB_HOST=$(get_yaml_variable "${PG_YAML_PATH}.host")
2173
+ DB_DATABASE=$(get_yaml_variable "${PG_YAML_PATH}.database")
2174
+ DB_USER=$(get_yaml_variable "${PG_YAML_PATH}.user")
2175
+ DB_PASSWORD=$(get_yaml_variable "${PG_YAML_PATH}.password")
2176
+ DB_URL="jdbc:postgresql://${DB_HOST}:${DB_PORT}/${DB_DATABASE}"
2177
+
2178
+ flyway_sql_folder=$(pwd)/${MIGRATION_SQL_PATH}
2179
+
2180
+ configure_kubectl_for_ci "${ENVIRONMENT}"
2181
+ POD_NAME="${APPLICATION}-flyway-repair"
2182
+ CONFIGMAP_NAME="${APPLICATION}-flyway-repair-sql"
2183
+
2184
+ kubectl -n "${ENVIRONMENT}" delete configmap $CONFIGMAP_NAME --ignore-not-found
2185
+ kubectl -n "${ENVIRONMENT}" delete pod $POD_NAME --ignore-not-found
2186
+ kubectl -n "${ENVIRONMENT}" create configmap $CONFIGMAP_NAME --from-file="${flyway_sql_folder}"
2187
+
2188
+ kubectl -n "${ENVIRONMENT}" run --rm -it "${POD_NAME}" \
2189
+ --image=flyway/flyway \
2190
+ --restart=Never \
2191
+ --overrides='
2192
+ {
2193
+ "spec":{
2194
+ "containers":[
2195
+ {
2196
+ "name":"'$POD_NAME'",
2197
+ "image":"flyway/flyway:'${FLYWAY_VERSION}'",
2198
+ "command":["flyway", "-url='$DB_URL'", "-user='$DB_USER'", "-password='$DB_PASSWORD'", "repair"],
2199
+ "volumeMounts":[
2200
+ {
2201
+ "name":"sql",
2202
+ "mountPath":"/flyway/sql"
2203
+ }
2204
+ ]
2205
+ }
2206
+ ],
2207
+ "volumes":[
2208
+ {
2209
+ "name":"sql",
2210
+ "configMap":{
2211
+ "name":"'$CONFIGMAP_NAME'"
2212
+ }
2213
+ }
2214
+ ]
2215
+ }
2216
+ }
2217
+ '
2218
+ kubectl -n "${ENVIRONMENT}" delete configmap $CONFIGMAP_NAME
2219
+ }
2220
+
2076
2221
  #!/usr/bin/env bash
2077
2222
 
2078
2223
  record_git_commit() {
@@ -535,28 +535,29 @@ database_k8s() {
535
535
  HostName 127.0.0.1
536
536
  Port 2225
537
537
  LocalForward 24441 toutatis-testing-db.ca0rjdmnxf1x.eu-west-1.rds.amazonaws.com:5432
538
- LocalForward 25431 testapirds.ca0rjdmnxf1x.eu-west-1.rds.amazonaws.com:3306
538
+ LocalForward 25431 toutatis-testing-mysql-db.ca0rjdmnxf1x.eu-west-1.rds.amazonaws.com:3306
539
+ LocalForward 25531 testapirds.ca0rjdmnxf1x.eu-west-1.rds.amazonaws.com:3306
539
540
  Host bastion_staging
540
541
  HostName 127.0.0.1
541
542
  Port 2226
542
543
  LocalForward 24442 toutatis-staging-db.ca0rjdmnxf1x.eu-west-1.rds.amazonaws.com:5432
543
- LocalForward 25432 testapirds.ca0rjdmnxf1x.eu-west-1.rds.amazonaws.com:3306
544
+ LocalForward 25432 toutatis-staging-mysql-db.ca0rjdmnxf1x.eu-west-1.rds.amazonaws.com:3306
544
545
  Host bastion_recette
545
546
  HostName 127.0.0.1
546
547
  Port 2228
547
548
  LocalForward 24446 toutatis-recette-db.ca0rjdmnxf1x.eu-west-1.rds.amazonaws.com:5432
548
- LocalForward 25436 testapirds.ca0rjdmnxf1x.eu-west-1.rds.amazonaws.com:3306
549
+ LocalForward 25436 toutatis-recette-mysql-db.ca0rjdmnxf1x.eu-west-1.rds.amazonaws.com:3306
550
+ LocalForward 25536 testapirds.ca0rjdmnxf1x.eu-west-1.rds.amazonaws.com:3306
549
551
  Host bastion_production
550
552
  HostName 127.0.0.1
551
553
  Port 2227
552
554
  LocalForward 24443 toutatis-production-db-replica.ca0rjdmnxf1x.eu-west-1.rds.amazonaws.com:5432
553
- LocalForward 25433 api-production-rds-read-replica.ca0rjdmnxf1x.eu-west-1.rds.amazonaws.com:3306
554
- LocalForward 25435 archive-ca.ca0rjdmnxf1x.eu-west-1.rds.amazonaws.com:3306
555
+ LocalForward 25433 toutatis-production-mysql-db-replica.ca0rjdmnxf1x.eu-west-1.rds.amazonaws.com:3306
555
556
  EOF
556
557
  if [ "$MODE" = "production_rw" ] ; then
557
558
  cat >> "$bastion_config" <<EOF
558
559
  LocalForward 24444 toutatis-production-db.ca0rjdmnxf1x.eu-west-1.rds.amazonaws.com:5432
559
- LocalForward 25434 api-production-rds.ca0rjdmnxf1x.eu-west-1.rds.amazonaws.com:3306
560
+ LocalForward 25434 toutatis-production-mysql-db.ca0rjdmnxf1x.eu-west-1.rds.amazonaws.com:3306
560
561
  EOF
561
562
  fi
562
563
 
@@ -576,7 +577,7 @@ psql_on_k8() {
576
577
  CONNECTION=$3
577
578
  shift 3
578
579
 
579
- kubectl -n $NAMESPACE run ${SERVICE}-database-init \
580
+ kubectl -n $NAMESPACE run ${SERVICE}-postgres-init \
580
581
  --image jbergknoff/postgresql-client \
581
582
  --restart=Never \
582
583
  --attach --rm \
@@ -587,14 +588,15 @@ psql_on_k8() {
587
588
 
588
589
  mysql_on_k8() {
589
590
  local namespace=$1
590
- local db_host=$2
591
- local db_port=$3
592
- local db_init_username=$4
593
- local db_init_password=$5
594
- local query=$6
595
-
596
- kubectl -n ${namespace} run datadog-database-init \
597
- --image widdpim/mysql-client \
591
+ local service=$2
592
+ local db_host=$3
593
+ local db_port=$4
594
+ local db_init_username=$5
595
+ local db_init_password=$6
596
+ local query=$7
597
+
598
+ kubectl -n ${namespace} run ${service}-mysql-init \
599
+ --image arey/mysql-client \
598
600
  --restart=Never \
599
601
  --attach --rm \
600
602
  -- \
@@ -674,12 +676,14 @@ kube_init_datadog_in_database() {
674
676
  extract_args 8 namespace db_host db_port db_init_username db_init_password db_datadog_username db_datadog_password db_datadog_schema $*
675
677
 
676
678
  echo "======================="
677
- echo " Initializing Datadog Agent Requiement for namespace $namespace"
679
+ echo " Initializing Datadog Agent Requirement for namespace $namespace"
678
680
  echo "======================="
679
681
 
680
682
  echo "Checking if User '$db_datadog_username' exists"
683
+ local service="datadog"
684
+ found_db_users=$(mysql_on_k8 $namespace $service $db_host $db_port $db_init_username $db_init_password 'SELECT user FROM mysql.user;')
681
685
  set +e
682
- mysql_on_k8 $namespace $db_host $db_port $db_init_username $db_init_password 'SELECT user FROM mysql.user;' | grep "^$db_datadog_username$"
686
+ echo "$found_db_users" | grep "^$db_datadog_username$"
683
687
  return_code=$?
684
688
  set -e
685
689
 
@@ -690,29 +694,29 @@ kube_init_datadog_in_database() {
690
694
 
691
695
  # All the query come from this docs : https://docs.datadoghq.com/fr/database_monitoring/setup_mysql/selfhosted/?tab=mysql56
692
696
 
693
- mysql_on_k8 $namespace $db_host $db_port $db_init_username $db_init_password 'CREATE USER '"$db_datadog_username"'@"%" IDENTIFIED BY '"'$db_datadog_password'"';'
697
+ mysql_on_k8 $namespace $service $db_host $db_port $db_init_username $db_init_password 'CREATE USER '"$db_datadog_username"'@"%" IDENTIFIED BY '"'$db_datadog_password'"';'
694
698
  echo "USER created $db_datadog_username"
695
699
 
696
- mysql_on_k8 $namespace $db_host $db_port $db_init_username $db_init_password 'GRANT REPLICATION CLIENT ON *.* TO datadog@"%" WITH MAX_USER_CONNECTIONS 5;'
700
+ mysql_on_k8 $namespace $service $db_host $db_port $db_init_username $db_init_password 'GRANT REPLICATION CLIENT ON *.* TO datadog@"%" WITH MAX_USER_CONNECTIONS 5;'
697
701
  echo "ALTER USER $db_datadog_username"
698
702
 
699
- mysql_on_k8 $namespace $db_host $db_port $db_init_username $db_init_password 'GRANT PROCESS ON *.* TO '"$db_datadog_username"'@"%";'
703
+ mysql_on_k8 $namespace $service $db_host $db_port $db_init_username $db_init_password 'GRANT PROCESS ON *.* TO '"$db_datadog_username"'@"%";'
700
704
  echo "Granted PROCESS for $db_datadog_username"
701
705
 
702
- mysql_on_k8 $namespace $db_host $db_port $db_init_username $db_init_password 'GRANT SELECT ON performance_schema.* TO '"$db_datadog_username"'@"%";'
706
+ mysql_on_k8 $namespace $service $db_host $db_port $db_init_username $db_init_password 'GRANT SELECT ON performance_schema.* TO '"$db_datadog_username"'@"%";'
703
707
  echo "Granted SELECT on performance_schema for $db_datadog_username"
704
708
 
705
- mysql_on_k8 $namespace $db_host $db_port $db_init_username $db_init_password 'CREATE SCHEMA IF NOT EXISTS datadog;'
709
+ mysql_on_k8 $namespace $service $db_host $db_port $db_init_username $db_init_password 'CREATE SCHEMA IF NOT EXISTS datadog;'
706
710
  echo "CREATE SCHEMA datadog"
707
711
 
708
- mysql_on_k8 $namespace $db_host $db_port $db_init_username $db_init_password 'GRANT EXECUTE ON datadog.* to '"$db_datadog_username"'@"%";'
712
+ mysql_on_k8 $namespace $service $db_host $db_port $db_init_username $db_init_password 'GRANT EXECUTE ON datadog.* to '"$db_datadog_username"'@"%";'
709
713
  echo "Granted 'GRANT EXECUTE for $db_datadog_username on datadog"
710
714
 
711
- mysql_on_k8 $namespace $db_host $db_port $db_init_username $db_init_password 'GRANT CREATE TEMPORARY TABLES ON datadog.* TO '"$db_datadog_username"'@"%";'
715
+ mysql_on_k8 $namespace $service $db_host $db_port $db_init_username $db_init_password 'GRANT CREATE TEMPORARY TABLES ON datadog.* TO '"$db_datadog_username"'@"%";'
712
716
  echo "Granted CREATE TEMPORARY TABLES for $db_datadog_username"
713
717
 
714
718
 
715
- mysql_on_k8 $namespace $db_host $db_port $db_init_username $db_init_password 'DROP PROCEDURE IF EXISTS datadog.explain_statement;
719
+ mysql_on_k8 $namespace $service $db_host $db_port $db_init_username $db_init_password 'DROP PROCEDURE IF EXISTS datadog.explain_statement;
716
720
  DELIMITER $$
717
721
  CREATE PROCEDURE datadog.explain_statement(IN query TEXT)
718
722
  SQL SECURITY DEFINER
@@ -725,7 +729,7 @@ kube_init_datadog_in_database() {
725
729
  DELIMITER ;'
726
730
  echo "CREATE PROCEDURE PROCEDURE datadog.explain_statement"
727
731
 
728
- mysql_on_k8 $namespace $db_host $db_port $db_init_username $db_init_password 'DROP PROCEDURE IF EXISTS '"$db_datadog_username"'.explain_statement;
732
+ mysql_on_k8 $namespace $service $db_host $db_port $db_init_username $db_init_password 'DROP PROCEDURE IF EXISTS '"$db_datadog_username"'.explain_statement;
729
733
  DELIMITER $$
730
734
  CREATE PROCEDURE '"$db_datadog_username"'.explain_statement(IN query TEXT)
731
735
  SQL SECURITY DEFINER
@@ -739,7 +743,7 @@ kube_init_datadog_in_database() {
739
743
  GRANT EXECUTE ON PROCEDURE '"$db_datadog_username"'.explain_statement TO datadog@"%";'
740
744
  echo "CREATE PROCEDURE on SCHEMA $db_datadog_schema for $db_datadog_username"
741
745
 
742
- mysql_on_k8 $namespace $db_host $db_port $db_init_username $db_init_password 'DROP PROCEDURE IF EXISTS datadog.enable_events_statements_consumers;
746
+ mysql_on_k8 $namespace $service $db_host $db_port $db_init_username $db_init_password 'DROP PROCEDURE IF EXISTS datadog.enable_events_statements_consumers;
743
747
  DELIMITER $$
744
748
  CREATE PROCEDURE datadog.enable_events_statements_consumers()
745
749
  SQL SECURITY DEFINER
@@ -817,7 +821,7 @@ kube_init_datadog_in_postgres_database() {
817
821
  RETURNS NULL ON NULL INPUT
818
822
  SECURITY DEFINER;"
819
823
 
820
- kubectl -n $namespace run $service-database-init \
824
+ kubectl -n $namespace run $service-postgres-init \
821
825
  --image jbergknoff/postgresql-client \
822
826
  --restart=Never \
823
827
  --attach --rm \
@@ -869,6 +873,57 @@ kube_init_service_database() {
869
873
 
870
874
  #!/usr/bin/env bash
871
875
 
876
+ # Allow to use JMX connection to retrieve data and metrics from the pods within kubernetes
877
+ # You will need visualVM to use this tool https://visualvm.github.io/
878
+ # ex: bind_jmx testing notification
879
+ bind_jmx() {
880
+
881
+ local ENV=$1
882
+ local SERVICE_NAME=$2
883
+ local PORT=2242
884
+
885
+ start_ssh_bastion $ENV $PORT
886
+
887
+ echo "root" | ssh -f -N -oUserKnownHostsFile=/dev/null -oStrictHostKeyChecking=no -D 7777 root@127.0.0.1 -p 2242
888
+ local PODS=$(kubectl -n $ENV get pods -o wide | grep $SERVICE_NAME | grep -Eo '^[^ ]+')
889
+
890
+ echo "Choose one of the following pod to get metrics from..."
891
+ local POD_NAME=$(gum choose $PODS)
892
+ local POD_IP=$(
893
+ kubectl -n $ENV get pods -o jsonpath='{range .items[*]}{.metadata.name}{" "}{.status.podIP}{"\n"}{end}' |
894
+ grep $POD_NAME |
895
+ cut -d' ' -f2 |
896
+ head -1
897
+ )
898
+
899
+ jconsole -J-DsocksProxyHost=localhost \
900
+ -J-DsocksProxyPort=7777 \
901
+ service:jmx:rmi:///jndi/rmi://$POD_IP:7199/jmxrmi \
902
+ -J-DsocksNonProxyHosts= &
903
+
904
+ cat << EOF
905
+ Now start VisualVM
906
+ Preferences > Network > Manual Proxy Settings
907
+ SOCKS Proxy Line: Set 'localhost' and Port '7777'
908
+ File > Add JMX Connection
909
+ Set $POD_IP:7199, check 'do not require an SSL connection'
910
+ Remember to kill you bastion afterward using 'stop_ssh_bastion'
911
+ EOF
912
+ }
913
+ #!/usr/bin/env bash
914
+
915
+ k8_nodes_stats() {
916
+ kubectl get nodes -o name |
917
+ xargs kubectl describe |
918
+ grep "^Name\|workType\|cpu \|memory " |
919
+ sed -r 's/[ :=]+/\t/g' |
920
+ sed 's/\tworkType\t//g' |
921
+ sed -r 's/^Name/---\nName/g' |
922
+ grep --color "Name\|web\|workers\|cpu\|memory\|---"
923
+ }
924
+
925
+ #!/usr/bin/env bash
926
+
872
927
  # Port forward on the first matching pod
873
928
  # Ex :
874
929
  # pod_forward testing notification-http
@@ -946,12 +1001,58 @@ pick_pod() {
946
1001
 
947
1002
  #!/usr/bin/env bash
948
1003
 
1004
+ bastion_config_for_redis_ca() {
1005
+ ssh_config xufte6.0001.euw1.cache.amazonaws.com redis 2223 63789 tests testing recette-001 sandbox prod > $1
1006
+ }
1007
+
1008
+ bastion_config_for_redis_toutatis() {
1009
+ ssh_config xufte6.0001.euw1.cache.amazonaws.com toutatis 2223 63789 tests testing recette staging production > $1
1010
+ }
1011
+
1012
+ ssh_config() {
1013
+ host=$1
1014
+ host_prefix=$2
1015
+ port0=$3
1016
+ forward0=$4
1017
+ shift 4
1018
+ instance_names=("$@") # /!\ indices start at 1 with zsh
1019
+ ssh_header
1020
+
1021
+ environments=(tests testing recette staging production)
1022
+
1023
+ length=${#environments[@]}
1024
+ for (( i=1; i<=${length}; i++ ));
1025
+ do
1026
+ bastion_block bastion_${environments[$i]} $(($port0 + $i)) $(($forward0 + $i)) ${host_prefix}-${instance_names[$i]}.$host
1027
+ done
1028
+ }
1029
+
1030
+ ssh_header() {
1031
+ cat <<EOF
1032
+ UserKnownHostsFile /dev/null
1033
+ StrictHostKeyChecking no
1034
+ User root
1035
+ EOF
1036
+ }
1037
+
1038
+ bastion_block() {
1039
+ cat <<EOF
1040
+ Host $1
1041
+ HostName 127.0.0.1
1042
+ Port $2
1043
+ LocalForward $3 $4:6379
1044
+ EOF
1045
+ }
1046
+
949
1047
  redis_k8s() {
950
1048
  MODE=$1
1049
+ REDIS_INSTANCE=${2:-ca}
951
1050
  case $MODE in
1051
+ "tests") SSH_LOCAL_PORT=2224;REDIS_LOCAL_PORT=63790;ENV="tests";;
952
1052
  "testing") SSH_LOCAL_PORT=2225;REDIS_LOCAL_PORT=63791;ENV="testing";;
953
- "staging") SSH_LOCAL_PORT=2226;REDIS_LOCAL_PORT=63792;ENV="staging";;
954
- "production") SSH_LOCAL_PORT=2227;REDIS_LOCAL_PORT=63793;ENV="production";;
1053
+ "recette") SSH_LOCAL_PORT=2226;REDIS_LOCAL_PORT=63792;ENV="recette";;
1054
+ "staging") SSH_LOCAL_PORT=2227;REDIS_LOCAL_PORT=63793;ENV="staging";;
1055
+ "production") SSH_LOCAL_PORT=2228;REDIS_LOCAL_PORT=63794;ENV="production";;
955
1056
  *) echo "Unsupported ENV : $MODE"; return 1 ;;
956
1057
  esac
957
1058
 
@@ -960,23 +1061,11 @@ redis_k8s() {
960
1061
  lsof -ti tcp:$REDIS_LOCAL_PORT | xargs kill
961
1062
 
962
1063
  bastion_config=$(mktemp)
963
- cat > "$bastion_config" <<EOF
964
- UserKnownHostsFile /dev/null
965
- StrictHostKeyChecking no
966
- User root
967
- Host bastion_testing
968
- HostName 127.0.0.1
969
- Port 2225
970
- LocalForward 63791 redis-testing.xufte6.0001.euw1.cache.amazonaws.com:6379
971
- Host bastion_staging
972
- HostName 127.0.0.1
973
- Port 2226
974
- LocalForward 63792 redis-sandbox.xufte6.0001.euw1.cache.amazonaws.com:6379
975
- Host bastion_production
976
- HostName 127.0.0.1
977
- Port 2227
978
- LocalForward 63793 redis-prod.xufte6.0001.euw1.cache.amazonaws.com:6379
979
- EOF
1064
+ case $REDIS_INSTANCE in
1065
+ "ca") bastion_config_for_redis_ca "$bastion_config";;
1066
+ "toutatis") bastion_config_for_redis_toutatis "$bastion_config";;
1067
+ *) echo "Unsupported redis instance (ca or toutatis available) : $REDIS_INSTANCE"; return 1;;
1068
+ esac
980
1069
 
981
1070
  ssh -f -N \
982
1071
  -F "$bastion_config" \
@@ -1518,24 +1607,13 @@ jconsole_k8s() {
1518
1607
 
1519
1608
  #!/usr/bin/env bash
1520
1609
 
1521
- # Interactive console on an existing pod. See also run_ruby_k8s
1522
- # Ex :
1523
- # railsc_k8s_old production
1524
- # railsc_k8s_old production "User.where(email:'toni@colisweb.com')"
1525
- railsc_k8s_old() {
1526
- ENV=$1
1527
- COMMAND=$2
1528
- configure_kubectl_for $ENV
1529
- POD=$(kubectl -n $ENV get pods -o=name | grep colisweb-api-web | head -1 | sed -e 's/pod\///')
1530
- KUBERAILS="kubectl -n $ENV exec -ti $POD -- /usr/src/app/bin/rails c"
1531
- [ -z "$COMMAND" ] && eval $KUBERAILS || echo $COMMAND | eval $KUBERAILS
1532
- }
1533
-
1534
1610
  # Interactive console on an new pod. See also run_ruby_k8s
1535
1611
  # Ex :
1536
1612
  # railsc_k8s production
1613
+ # railsc_k8s production "User.where(email:'toni@colisweb.com')"
1537
1614
  railsc_k8s() {
1538
1615
  ENV=$1
1616
+ COMMAND=$2
1539
1617
  [[ $ENV = "production" || $ENV = "staging" ]] && default_tag="master-latest" || default_tag="${ENV}-latest"
1540
1618
  local image_tag=${5:-$default_tag}
1541
1619
  local IMAGE="949316342391.dkr.ecr.eu-west-1.amazonaws.com/colisweb-api:$image_tag"
@@ -1585,7 +1663,8 @@ railsc_k8s() {
1585
1663
  '
1586
1664
 
1587
1665
  sleep 5
1588
- kubectl -n $ENV exec -it $POD_NAME -- /usr/src/app/bin/rails c
1666
+ KUBERAILS="kubectl -n $ENV exec -ti $POD_NAME -- /usr/src/app/bin/rails c"
1667
+ [ -z "$COMMAND" ] && eval $KUBERAILS || echo $COMMAND | eval $KUBERAILS
1589
1668
 
1590
1669
  print "End of $POD_NAME "
1591
1670
  kubectl -n $ENV delete pods $POD_NAME
@@ -1829,11 +1908,11 @@ datadog_schedule_downtime_single() {
1829
1908
  {
1830
1909
  "active": true,
1831
1910
  "downtime_type": 0,
1832
- "start": $START,
1833
- "end": $END,
1834
- "message": "CA Deployment - performance for $SERVICE may be lower for next $DOWNTIME_MINUTES min",
1911
+ "start": '$START',
1912
+ "end": '$END',
1913
+ "message": "CA Deployment - performance for '$SERVICE' may be lower for next '$DOWNTIME_MINUTES' min",
1835
1914
  "monitor_tags": [
1836
- "service:$SERVICE",
1915
+ "service:'$SERVICE'",
1837
1916
  "performance"
1838
1917
  ],
1839
1918
  "scope": [
@@ -1843,6 +1922,7 @@ datadog_schedule_downtime_single() {
1843
1922
  }
1844
1923
  '
1845
1924
  }
1925
+
1846
1926
  #!/usr/bin/env bash
1847
1927
 
1848
1928
  docker_build_push() {
@@ -1855,11 +1935,18 @@ docker_build_push() {
1855
1935
 
1856
1936
  if ! image_exists $DOCKER_REGISTRY_ID $APPLICATION $CI_COMMIT_SHORT_SHA ; then
1857
1937
  docker pull $DOCKER_IMAGE || true
1858
- docker build $DOCKER_BUILD_ARGS -t $DOCKER_IMAGE_SHA --cache-from $DOCKER_IMAGE $DOCKER_STAGE_PATH
1938
+ SOURCE_URL=${CI_PROJECT_URL:8} # without "https://" protocol, like gitlab.com/colisweb-idl/colisweb/back/packing
1939
+ docker build $DOCKER_BUILD_ARGS \
1940
+ -t $DOCKER_IMAGE_SHA \
1941
+ --label org.opencontainers.image.revision=$(git rev-parse HEAD) \
1942
+ --label org.opencontainers.image.source=$SOURCE_URL \
1943
+ --cache-from $DOCKER_IMAGE \
1944
+ $DOCKER_STAGE_PATH
1859
1945
  docker push $DOCKER_IMAGE_SHA
1860
1946
  fi
1861
1947
  }
1862
1948
 
1949
+
1863
1950
  docker_promote() {
1864
1951
  # inspired by https://dille.name/blog/2018/09/20/how-to-tag-docker-images-without-pulling-them/
1865
1952
  OLD_TAG=${1//[^0-9a-zA-Z-.]/_}
@@ -1886,6 +1973,7 @@ docker_promote() {
1886
1973
  image_exists ${DOCKER_REGISTRY_ID} ${IMAGE_TO_CHECK} ${VERSION} || return 1
1887
1974
  done
1888
1975
  }
1976
+
1889
1977
  #!/usr/bin/env bash
1890
1978
 
1891
1979
  extract_yaml_config_variable() {
@@ -1962,7 +2050,7 @@ flyway_clean() {
1962
2050
 
1963
2051
  #!/usr/bin/env bash
1964
2052
 
1965
- FLYWAY_VERSION="5.2.4"
2053
+ FLYWAY_VERSION="7.4.0"
1966
2054
 
1967
2055
 
1968
2056
  get_yaml_variable() {
@@ -1990,7 +2078,7 @@ init_migrate_db() {
1990
2078
 
1991
2079
  unset KUBECONFIG
1992
2080
 
1993
- configure_kubectl_for_ci ${ENVIRONMENT}
2081
+ configure_kubectl_for ${ENVIRONMENT}
1994
2082
 
1995
2083
  kube_init_service_database \
1996
2084
  --namespace ${ENVIRONMENT} \
@@ -2036,7 +2124,7 @@ flyway_migrate() {
2036
2124
  CONFIGMAP_NAME="$service-flyway-migration-sql"
2037
2125
  POD_NAME="$service-flyway-migration"
2038
2126
 
2039
- configure_kubectl_for_ci $environment
2127
+ configure_kubectl_for $environment
2040
2128
 
2041
2129
  kubectl -n $namespace delete configmap $CONFIGMAP_NAME --ignore-not-found
2042
2130
  kubectl -n $namespace delete pod $POD_NAME --ignore-not-found
@@ -2048,7 +2136,7 @@ flyway_migrate() {
2048
2136
  "containers":[
2049
2137
  {
2050
2138
  "name":"'$POD_NAME'",
2051
- "image":"boxfuse/flyway:'$flyway_version'",
2139
+ "image":"flyway/flyway:'$flyway_version'",
2052
2140
  "command":["flyway", "-url='$db_url'", "-user='$db_user'", "-password='$db_password'", "migrate"],
2053
2141
  "volumeMounts":[
2054
2142
  {
@@ -2073,6 +2161,63 @@ flyway_migrate() {
2073
2161
  kubectl -n $namespace delete configmap $CONFIGMAP_NAME
2074
2162
  }
2075
2163
 
2164
+ #!/usr/bin/env bash
2165
+ flyway_repair() {
2166
+ set -e
2167
+ check_env_vars 4 "APPLICATION" "ENVIRONMENT" "FLYWAY_VERSION" "MIGRATION_SQL_PATH"
2168
+
2169
+ PG_YAML_PATH=".${APPLICATION}config.postgres"
2170
+
2171
+ DB_PORT="5432"
2172
+ DB_HOST=$(get_yaml_variable "${PG_YAML_PATH}.host")
2173
+ DB_DATABASE=$(get_yaml_variable "${PG_YAML_PATH}.database")
2174
+ DB_USER=$(get_yaml_variable "${PG_YAML_PATH}.user")
2175
+ DB_PASSWORD=$(get_yaml_variable "${PG_YAML_PATH}.password")
2176
+ DB_URL="jdbc:postgresql://${DB_HOST}:${DB_PORT}/${DB_DATABASE}"
2177
+
2178
+ flyway_sql_folder=$(pwd)/${MIGRATION_SQL_PATH}
2179
+
2180
+ configure_kubectl_for "${ENVIRONMENT}"
2181
+ POD_NAME="${APPLICATION}-flyway-repair"
2182
+ CONFIGMAP_NAME="${APPLICATION}-flyway-repair-sql"
2183
+
2184
+ kubectl -n "${ENVIRONMENT}" delete configmap $CONFIGMAP_NAME --ignore-not-found
2185
+ kubectl -n "${ENVIRONMENT}" delete pod $POD_NAME --ignore-not-found
2186
+ kubectl -n "${ENVIRONMENT}" create configmap $CONFIGMAP_NAME --from-file="${flyway_sql_folder}"
2187
+
2188
+ kubectl -n "${ENVIRONMENT}" run --rm -it "${POD_NAME}" \
2189
+ --image=flyway/flyway \
2190
+ --restart=Never \
2191
+ --overrides='
2192
+ {
2193
+ "spec":{
2194
+ "containers":[
2195
+ {
2196
+ "name":"'$POD_NAME'",
2197
+ "image":"flyway/flyway:'${FLYWAY_VERSION}'",
2198
+ "command":["flyway", "-url='$DB_URL'", "-user='$DB_USER'", "-password='$DB_PASSWORD'", "repair"],
2199
+ "volumeMounts":[
2200
+ {
2201
+ "name":"sql",
2202
+ "mountPath":"/flyway/sql"
2203
+ }
2204
+ ]
2205
+ }
2206
+ ],
2207
+ "volumes":[
2208
+ {
2209
+ "name":"sql",
2210
+ "configMap":{
2211
+ "name":"'$CONFIGMAP_NAME'"
2212
+ }
2213
+ }
2214
+ ]
2215
+ }
2216
+ }
2217
+ '
2218
+ kubectl -n "${ENVIRONMENT}" delete configmap $CONFIGMAP_NAME
2219
+ }
2220
+
2076
2221
  #!/usr/bin/env bash
2077
2222
 
2078
2223
  record_git_commit() {
@@ -2158,7 +2303,7 @@ deploy_chart_v3() {
2158
2303
  unset KUBECONFIG
2159
2304
 
2160
2305
  # Configure Kubectl
2161
- configure_kubectl_for_ci ${environment}
2306
+ configure_kubectl_for ${environment}
2162
2307
 
2163
2308
  # Configure helm3
2164
2309
  helm3 version --namespace ${namespace} || true
@@ -2259,40 +2404,6 @@ check_config_file() {
2259
2404
  fi
2260
2405
  }
2261
2406
 
2262
- #!/usr/bin/env bash
2263
-
2264
- configure_kubectl_for_ci() {
2265
- if [ -z ${GITLAB_PAT} ]; then
2266
- echo "Cannot configure kubectl: no GITLAB_PAT configured"
2267
- exit 1
2268
- fi
2269
-
2270
- infra_env="$1"
2271
- valid_envs="[testing][staging][production][performance][tests][recette]"
2272
- echo "$valid_envs" | grep -q "\[$infra_env\]"
2273
-
2274
- if [ $? -ne 0 ]; then
2275
- echo "Cannot configure kubectl for invalid env : $infra_env"
2276
- echo "choose one of $valid_envs"
2277
- exit 1
2278
- fi
2279
-
2280
- mkdir -p ~/.kube
2281
- curl -fsS \
2282
- --header "PRIVATE-TOKEN: $GITLAB_PAT" \
2283
- "https://gitlab.com/api/v4/projects/8141053/jobs/artifacts/$infra_env/raw/$infra_env.kubeconfig?job=4_kubernetes_config_output" \
2284
- > ~/.kube/$infra_env.kubeconfig
2285
-
2286
- curl_return_code=$?
2287
- if [ ${curl_return_code} -ne 0 ]; then
2288
- echo "Cannot configure kubectl for $infra_env, get configuration failed with code $curl_return_code"
2289
- exit ${curl_return_code}
2290
- fi
2291
-
2292
- rm -f ~/.kube/config
2293
- ln -s ~/.kube/$infra_env.kubeconfig ~/.kube/config
2294
- echo "Configured kubectl for env : $infra_env"
2295
- }
2296
2407
  notify_new_deployment() {
2297
2408
  jq --version || (apt update && apt install -y jq)
2298
2409
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@colisweb/rescript-toolkit",
3
- "version": "5.5.4",
3
+ "version": "5.6.0",
4
4
  "type": "module",
5
5
  "scripts": {
6
6
  "clean": "rescript clean",
@@ -29,7 +29,7 @@
29
29
  "dependencies": {
30
30
  "@colisweb/bs-react-intl-extractor-bin": "0.12.2",
31
31
  "@datadog/browser-rum": "5.8.0",
32
- "@dck/rescript-ky": "^2.0.0",
32
+ "@dck/rescript-ky": "2.0.1",
33
33
  "@dck/rescript-promise": "1.1.0",
34
34
  "@dck/restorative": "1.1.0",
35
35
  "@greenlabs/ppx-spice": "0.2.1",
@@ -621,6 +621,8 @@ module Make = (StateLenses: Config) => {
621
621
  ~displayTitle=?,
622
622
  ~switchClassName=?,
623
623
  ~labelClassName=?,
624
+ ~color=?,
625
+ ~className=?,
624
626
  ) =>
625
627
  <Field
626
628
  field
@@ -628,6 +630,8 @@ module Make = (StateLenses: Config) => {
628
630
  <React.Fragment>
629
631
  <Toolkit__Ui_Switch
630
632
  ?label
633
+ ?color
634
+ ?className
631
635
  onChange={value => handleChange(value)}
632
636
  name=id
633
637
  checked=value
@@ -1,15 +1,15 @@
1
1
  type error<'apiError> =
2
2
  | DecodeError(Spice.decodeError)
3
- | Unknown(Ky.error<Js.Json.t>)
3
+ | Unknown(Ky.error)
4
4
  | Custom('apiError)
5
5
 
6
6
  type requestConfig<'apiError, 'response> = {
7
7
  kyInstance: Ky.Instance.t,
8
8
  path: string,
9
- requestOptions: Ky.requestOptions<Js.Json.t, Js.Json.t, Js.Json.t, 'response>,
9
+ requestOptions: Ky.requestOptions<Js.Json.t>,
10
10
  key?: array<string>,
11
- customError?: Ky.error<Js.Json.t> => Promise.t<error<'apiError>>,
12
- mapPromise?: Js.Json.t => result<'response, error<'apiError>>,
11
+ mapCustomErrors?: Ky.error => error<'apiError>,
12
+ mapRawResponse?: (result<Js.Json.t, Ky.error>, Ky.Response.t) => result<'response, error<'apiError>>,
13
13
  }
14
14
 
15
15
  %%private(
@@ -17,44 +17,47 @@ type requestConfig<'apiError, 'response> = {
17
17
  ~instance=?,
18
18
  ~path,
19
19
  ~requestOptions,
20
- ~mapPromise=?,
21
- ~customError=?,
20
+ ~mapRawResponse=?,
21
+ ~mapCustomErrors=?,
22
22
  ~response_decode,
23
23
  ) => {
24
24
  // TODO :
25
25
  // - parseJson
26
26
  // - abort controller signal
27
27
 
28
- instance
29
- ->Option.mapWithDefault(Ky.fetch(path, requestOptions), instance => {
28
+ let kyResponse = instance->Option.mapWithDefault(Ky.fetch(path, requestOptions), instance => {
30
29
  (instance->Ky.Instance.asCallable)(path, ~options=requestOptions)
31
30
  })
31
+ kyResponse
32
32
  ->Ky.Response.json()
33
33
  ->Promise.Js.fromBsPromise
34
34
  ->Promise.Js.toResult
35
- ->Promise.flatMap(response => {
36
- switch response {
37
- | Error(err) => {
38
- let error: Ky.error<'a> = err->Obj.magic
39
- customError->Option.mapWithDefault(Promise.resolved(Error(Unknown(error))), fn =>
40
- fn(error)->Promise.map(e => Error(e))
41
- )
42
- }
43
- | Ok(response) =>
44
- switch mapPromise {
45
- | None =>
46
- Promise.resolved(
47
- switch response->response_decode {
48
- | Ok(_) as ok => ok
49
- | Error(decodeError) => Error(DecodeError(decodeError))
50
- },
51
- )
52
- | Some(fn) => Promise.resolved(fn(response))
35
+ ->Promise.flatMap(result => {
36
+ let result: result<Js.Json.t, Ky.error> = result->Obj.magic
37
+
38
+ let mapRawResponseOrDecode = switch mapRawResponse {
39
+ | Some(fn) => fn(result, kyResponse)
40
+ | None =>
41
+ switch result {
42
+ | Error(err) => Error(Unknown(err))
43
+ | Ok(response) =>
44
+ switch response->response_decode {
45
+ | Ok(response) => Ok(response)
46
+ | Error(decodeError) => Error(DecodeError(decodeError))
47
+ }
53
48
  }
54
49
  }
50
+
51
+ let mappedCustomErrors = switch mapRawResponseOrDecode {
52
+ | Error(Unknown(err)) => Error(mapCustomErrors->Option.mapWithDefault(Unknown(err), fn => fn(err)))
53
+ | _ as ok => ok
54
+ }
55
+
56
+ Promise.resolved(mappedCustomErrors)
55
57
  })
56
58
  }
57
59
  )
60
+
58
61
  module type Config = {
59
62
  type argument
60
63
  type response
@@ -80,8 +83,8 @@ let fetchAPI = (
80
83
  ~path=requestConfig.path,
81
84
  ~response_decode=C.response_decode,
82
85
  ~requestOptions=requestConfig.requestOptions,
83
- ~customError=?requestConfig.customError,
84
- ~mapPromise=?requestConfig.mapPromise,
86
+ ~mapRawResponse=?requestConfig.mapRawResponse,
87
+ ~mapCustomErrors=?requestConfig.mapCustomErrors,
85
88
  )
86
89
  }
87
90
  let useFetcher = (
@@ -1,4 +1,7 @@
1
1
  type size = [#sm | #md | #lg]
2
+ type color =
3
+ | Primary
4
+ | Black
2
5
 
3
6
  @react.component
4
7
  let make = (
@@ -16,6 +19,7 @@ let make = (
16
19
  ~disabledSwitchClassName="",
17
20
  ~switchRef: option<ReactDOM.domRef>=?,
18
21
  ~displayTitle=false,
22
+ ~color=Primary,
19
23
  ) => {
20
24
  let (isChecked, setIsChecked) = React.useState(() => checked->Option.getWithDefault(false))
21
25
  let previousChecked = Toolkit__Hooks.usePrevious(checked)
@@ -49,7 +53,10 @@ let make = (
49
53
  | #lg if displayTitle => "w-[87px] [h-32px]"
50
54
  | #lg => "w-[66px] [h-32px]"
51
55
  },
52
- isChecked ? "bg-primary-700 border-primary-700" : "bg-neutral-500",
56
+ switch color {
57
+ | Primary => isChecked ? "bg-primary-700 border-primary-700" : "bg-neutral-500"
58
+ | Black => isChecked ? "bg-black border-black" : "bg-gray-800"
59
+ },
53
60
  switchClassName,
54
61
  isChecked ? checkedSwitchClassName : "",
55
62
  disabled->Option.getWithDefault(false) ? disabledSwitchClassName : "",
@@ -1,4 +1,7 @@
1
1
  type size = [#sm | #md | #lg]
2
+ type color =
3
+ | Primary
4
+ | Black
2
5
 
3
6
  @react.component
4
7
  let make: (
@@ -16,4 +19,5 @@ let make: (
16
19
  ~disabledSwitchClassName: string=?,
17
20
  ~switchRef: ReactDOM.domRef=?,
18
21
  ~displayTitle: bool=?,
22
+ ~color: color=?,
19
23
  ) => React.element