AWSTemplateFormatVersion: "2010-09-09"
Description: "Deploys Artifactory into an existing Kubernetes cluster"
Parameters:
  KubeManifestLambdaArn:
    Type: String    
  HelmLambdaArn:
    Type: String
  KubeConfigPath:
    Type: String
  KubeConfigKmsContext:
    Type: String
  KubeGetLambdaArn:
    Type: String
  NumberOfSecondary:
    Type: Number
  AccessCIDR:
    Type: String
  ArtifactoryLicense1:
    Type: String
  ArtifactoryLicense2:
    Type: String
  ArtifactoryLicense3:
    Type: String
  ArtifactoryLicense4:
    Type: String
  ArtifactoryIAMAcessKey:
    Type: String
    NoEcho: 'true'
  SecretAccessKey:
    Type: String
    NoEcho: 'true'
  ArtifactoryS3Bucket:
    Type: String
  CertificateKey:
    Type: String
    NoEcho: 'true'
  Certificate:
    Type: String
  CertificateDomain:
    Type: String
  PrivateRepoUsername:
    NoEcho: 'true'
    Type: String
  PrivateRepoApiKey:
    NoEcho: 'true'
    Type: String
  ArtifactoryDBEndpointAddress:
    Type: String
  DatabaseName:
    Type: String
    NoEcho: 'true'
  DatabaseUser:
    Type: String
  DatabasePassword:
    Type: String
    NoEcho: 'true'
  MasterKey:
    Type: String
    NoEcho: 'true'
  ArtifactoryVersion:
    Type: String
  ArtifactoryDeploymentSize:
    Type: String
Mappings:
  DeploymentSize:
    Large:
      requestsMem: "6Gi"
      requestsCpu: "4"
      limitsMem: "10Gi"
      limitsCpu: "8"
      javaOptsXms: "6g"
      javaOptsXmx: "8g"
    Medium:
      requestsMem: "4Gi"
      requestsCpu: "2"
      limitsMem: "8Gi"
      limitsCpu: "6"
      javaOptsXms: "4g"
      javaOptsXmx: "6g"
    Small:
      requestsMem: "4Gi"
      requestsCpu: "2"
      limitsMem: "6Gi"
      limitsCpu: "4"
      javaOptsXms: "4g"
      javaOptsXmx: "4g"
Resources:
  NameSpace:
    Type: "Custom::KubeManifest"
    Version: '1.0'
    Properties:
      ServiceToken: !Ref KubeManifestLambdaArn
      KubeConfigPath: !Ref KubeConfigPath
      KubeConfigKmsContext: !Ref KubeConfigKmsContext
      Manifest:
        kind: Namespace
        apiVersion: v1
        metadata:
          name: jfrog-artifactory
          labels:
            app: artifactory
  CertificateStore:
    DependsOn: NameSpace
    Type: "Custom::KubeManifest"
    Version: '1.0'
    Properties:
      ServiceToken: !Ref KubeManifestLambdaArn
      KubeConfigPath: !Ref KubeConfigPath
      KubeConfigKmsContext: !Ref KubeConfigKmsContext
      Manifest:
        kind: Secret
        apiVersion: v1
        metadata:
          name: artifactory-nginx-tls
          namespace: jfrog-artifactory
          labels:
            app: artifactory
            chart: artifactory
        type: kubernetes.io/tls            
        data: 
          tls.crt: 
            Fn::Base64:
              !Sub "${Certificate}"
          tls.key:
            Fn::Base64:
              !Sub "${CertificateKey}"
  LicenseStore:
    DependsOn: NameSpace
    Type: "Custom::KubeManifest"
    Version: '1.0'
    Properties:
      ServiceToken: !Ref KubeManifestLambdaArn
      KubeConfigPath: !Ref KubeConfigPath
      KubeConfigKmsContext: !Ref KubeConfigKmsContext
      Manifest:
        kind: Secret
        apiVersion: v1
        metadata:
          name: artifactory-cluster-license
          namespace: jfrog-artifactory
          labels:
            app: artifactory
            chart: artifactory
        type: Opaque            
        stringData: 
          art.lic: !Sub 
            >-
            ${ArtifactoryLicense1}
  
  
            ${ArtifactoryLicense2}
          
          
            ${ArtifactoryLicense3}
  
  
            ${ArtifactoryLicense4}
  ArtifactoryDeployment:
    Type: "Custom::Helm"
    DependsOn: 
      - LicenseStore
      - CertificateStore
    Version: '1.0'
    Properties:
      ServiceToken: !Ref HelmLambdaArn
      KubeConfigPath: !Ref KubeConfigPath
      KubeConfigKmsContext: !Ref KubeConfigKmsContext
      Namespace: jfrog-artifactory
      Name: quickstart-artifactory-ha
      Chart: jfrog/artifactory-ha
      RepoUrl: https://charts.jfrog.io
      ValueYaml: !Sub 
        - |
          artifactory:
            name: artifactory-ha
            image:
              repository: docker.bintray.io/jfrog/artifactory-jcr
              version: ${ArtifactoryVersion}
              pullPolicy: Always
            deleteDBPropertiesOnStartup: true
            license:
              secret: artifactory-cluster-license
              dataKey: art.lic
            masterKey: ${MasterKey}
            preStartCommand: "wget -O /opt/jfrog/artifactory/tomcat/lib/mysql-connector-java-5.1.41.jar https://jcenter.bintray.com/mysql/mysql-connector-java/5.1.41/mysql-connector-java-5.1.41.jar"
            persistence:
              enabled: false
              type: aws-s3
              awsS3:
                endpoint: s3.${AWS::Region}.amazonaws.com
                region: ${AWS::Region}
                identity: ${ArtifactoryIAMAcessKey}
                credential: ${SecretAccessKey}
                bucketName: ${ArtifactoryS3Bucket}
            primary:
              resources:
                requests:
                  memory: "${requests_memory}"
                  cpu: "${requests_cpu}"
                limits:
                  memory: "${limits_memory}"
                  cpu: "${limits_cpu}"
              javaOpts:
                xms: "${java_xms}"
                xmx: "${java_xmx}"
              nodeSelector:
                partition: artifactory-primary
            node:
              replicaCount: ${NumberOfSecondary}
              resources:
                requests:
                  memory: "${requests_memory}"
                  cpu: "${requests_cpu}"
                limits:
                  memory: "${limits_memory}"
                  cpu: "${limits_cpu}"
              javaOpts:
                xms: "${java_xms}"
                xmx: "${java_xmx}"
              nodeSelector:
                partition: artifactory-secondary
              ## Only used if "affinity" is empty
              podAntiAffinity:
                ## Valid values are "soft" or "hard"; any other value indicates no anti-affinity
                type: "soft"
                topologyKey: "kubernetes.io/hostname"
          postgresql:
            enabled: false
          database:
            type: mysql
            url: jdbc:mysql://${ArtifactoryDBEndpointAddress}:3306/${DatabaseName}?characterEncoding=UTF-8&elideSetAutoCommits=true #&verifyServerCertificate=true&useSSL=true&requireSSL=true
            user: ${DatabaseUser}
            password: ${DatabasePassword}
          nginx:
            image:
              repository: docker.bintray.io/jfrog/nginx-artifactory-pro
              version: ${ArtifactoryVersion}
            tlsSecretName: artifactory-nginx-tls
            nodeSelector:
              partition: artifactory-primary
            service:
              loadBalancerSourceRanges:  [ "${AccessCIDR}" ]
            artifactoryConf: |
              ssl_protocols TLSv1 TLSv1.1 TLSv1.2 TLSv1.3;
              ssl_certificate  {{ .Values.nginx.persistence.mountPath }}/ssl/tls.crt;
              ssl_certificate_key  {{ .Values.nginx.persistence.mountPath }}/ssl/tls.key;
              ssl_session_cache shared:SSL:1m;
              ssl_prefer_server_ciphers   on;
              ## server configuration
              server {
                listen {{ .Values.nginx.internalPortHttps }} ssl;
                listen {{ .Values.nginx.internalPortHttp }} ;
                server_name ~(?<repo>.+).${CertificateDomain} ~(?<repo>.+).jfrog.team
                {{- range .Values.ingress.hosts -}}
                  {{- if contains "." . -}}
                    {{ "" | indent 0 }} ~(?<repo>.+)\.{{ . }}
                  {{- end -}}
                {{- end -}};
                if ($http_x_forwarded_proto = '') {
                  set $http_x_forwarded_proto  $scheme;
                }
                ## Application specific logs
                ## access_log /var/log/nginx/artifactory-access.log timing;
                ## error_log /var/log/nginx/artifactory-error.log;
                rewrite ^/$ /artifactory/webapp/ redirect;
                rewrite ^/artifactory/?(/webapp)?$ /artifactory/webapp/ redirect;
                rewrite ^/(v2)/(.*) /artifactory/$1/$2;
                chunked_transfer_encoding on;
                client_max_body_size 0;
                location /artifactory/ {
                  proxy_read_timeout  2400;
                  proxy_pass_header   Server;
                  proxy_cookie_path   ~*^/.* /;
                  proxy_pass          http://{{ include "artifactory-ha.fullname" . }}:{{ .Values.artifactory.externalPort }}/artifactory/;
                  proxy_set_header    X-Artifactory-Override-Base-Url $http_x_forwarded_proto://$host:$server_port/artifactory;
                  proxy_set_header    X-Forwarded-Port  $server_port;
                  proxy_set_header    X-Forwarded-Proto $http_x_forwarded_proto;
                  proxy_set_header    Host              $http_host;
                  proxy_set_header    X-Forwarded-For   $proxy_add_x_forwarded_for;
                }
              }
        - { requests_memory: !FindInMap [DeploymentSize, !Ref ArtifactoryDeploymentSize, requestsMem],
            requests_cpu: !FindInMap [DeploymentSize, !Ref ArtifactoryDeploymentSize, requestsCpu],
            limits_memory: !FindInMap [DeploymentSize, !Ref ArtifactoryDeploymentSize, limitsMem ],
            limits_cpu: !FindInMap [DeploymentSize, !Ref ArtifactoryDeploymentSize, limitsCpu ],
            java_xms: !FindInMap [DeploymentSize, !Ref ArtifactoryDeploymentSize, javaOptsXms ],
            java_xmx: !FindInMap [DeploymentSize, !Ref ArtifactoryDeploymentSize, javaOptsXmx ] }
  IngressHostName:
    DependsOn: ArtifactoryDeployment
    Type: "Custom::KubeGet"
    Version: '1.0'
    Properties:
      ServiceToken: !Ref KubeGetLambdaArn
      KubeConfigPath: !Ref KubeConfigPath
      KubeConfigKmsContext: !Ref KubeConfigKmsContext
      Namespace: jfrog-artifactory
      Name: svc/quickstart-artifactory-ha-nginx
      JsonPath: '{.status.loadBalancer.ingress[0].hostname}'        
Outputs:
  ArtifactoryUrl:
    Value: !Sub https://${IngressHostName}