---
# System prepended metadata

title: OpenShift ZTP - The Hard Way

---

# OpenShift ZTP - The Hard Way

1. Install RHACM lol
2. Create Namespaces

```bash=
oc create namespace hive --dry-run=client -o yaml > 00_ns-hive.yaml
oc create namespace assisted-installer --dry-run=client -o yaml > 00_ns-assisted-installer.yaml
oc create namespace multicluster-engine --dry-run=client -o yaml > 00_ns-multicluster-engine.yaml
oc create namespace ztp-mirror --dry-run=client -o yaml > 00_ns-multicluster-engine.yaml
```

```yaml=
apiVersion: v1
kind: Namespace
metadata:
  creationTimestamp: null
  name: assisted-installer
spec: {}
---
apiVersion: v1
kind: Namespace
metadata:
  creationTimestamp: null
  name: hive
spec: {}
---
apiVersion: v1
kind: Namespace
metadata:
  creationTimestamp: null
  name: multicluster-engine
spec: {}
---
```

3. Create Root CA Bundle ConfigMap (optional)

```yaml=
kind: ConfigMap
apiVersion: v1
metadata:
  name: trusted-ca
  namespace: assisted-installer
  labels:
    config.openshift.io/inject-trusted-cabundle: 'true'
data: {}
---
kind: ConfigMap
apiVersion: v1
metadata:
  name: trusted-ca
  namespace: hive
  labels:
    config.openshift.io/inject-trusted-cabundle: 'true'
data: {}
---
kind: ConfigMap
apiVersion: v1
metadata:
  name: trusted-ca
  namespace: multicluster-engine
  labels:
    config.openshift.io/inject-trusted-cabundle: 'true'
data: {}
---
kind: ConfigMap
apiVersion: v1
metadata:
  name: trusted-ca
  namespace: open-cluster-management
  labels:
    config.openshift.io/inject-trusted-cabundle: 'true'
data: {}
---
```

4. Get just the custom certs

```bash=
# Get the proxy config for the custom certs
CA_CERT_NAME=$(oc get proxy/cluster -o jsonpath='{.spec.trustedCA.name}')

oc get cm -n openshift-config $CA_CERT_NAME -o jsonpath='{.data.ca-bundle\.crt}' > custom-ca-certs.pem
```

5. Create a CA Cert Secret for Hive/RHACM

```bash=
oc create secret generic custom-ca-certs -n hive --from-file=ca.crt=custom-ca-certs.pem

oc create secret generic custom-ca-certs -n multicluster-engine --from-file=ca.crt=custom-ca-certs.pem

oc create secret generic custom-ca-certs -n open-cluster-management --from-file=ca.crt=custom-ca-certs.pem
```

6. Point hive to use the custom ca

```bash=
oc edit hiveconfigs.hive.openshift.io -n hive
```

```yaml=
apiVersion: hive.openshift.io/v1
kind: HiveConfig
metadata:
  labels:
    installer.name: multiclusterhub
    installer.namespace: open-cluster-management
  name: hive
spec: 
  additionalCertificateAuthoritiesSecretRef: 
  - name: custom-ca-certs
```

7. Create a Pull Secret for AI/CIM/MCE/whateveritscalledthesedays

```bash=
PULL_SECRET=$(oc get secret/pull-secret -n openshift-config -o jsonpath='{.data.\.dockerconfigjson}' | base64 -d)

echo $PULL_SECRET > tmp-ps.json

oc create secret docker-registry cluster-pull-secret -n hive --from-file=.dockerconfigjson=./tmp-ps.json

oc create secret docker-registry cluster-pull-secret -n multicluster-engine --from-file=.dockerconfigjson=./tmp-ps.json

oc create secret docker-registry cluster-pull-secret -n open-cluster-management --from-file=.dockerconfigjson=./tmp-ps.json

rm ./tmp-ps.json

unset PULL_SECRET
````

8. Configure RHACM RBAC:

```yaml=
kind: ClusterRoleBinding
apiVersion: rbac.authorization.k8s.io/v1
metadata:
  name: hive-ca
subjects:
  - kind: ServiceAccount
    name: hiveadmission
    namespace: hive
  - kind: ServiceAccount
    name: hive-controllers
    namespace: hive
  - kind: ServiceAccount
    name: hive-frontend
    namespace: hive
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: ClusterRole
  name: cluster-admin
---
```

9. Configure the Assisted Installer Configuration Overrides if needed

```bash=
OC_HTTP_PROXY=$(oc get proxy/cluster -o jsonpath='{.status.httpProxy}')
OC_HTTPS_PROXY=$(oc get proxy/cluster -o jsonpath='{.status.httpsProxy}')
OC_NO_PROXY="YOUR_IP_NETWORK/24,$(oc get proxy/cluster -o jsonpath='{.status.noProxy}')"

cat > 05_cm-assisted-installer-config.yaml <<EOF
apiVersion: v1
kind: ConfigMap
metadata:
  creationTimestamp: null
  name: assisted-service-config
  namespace: multicluster-engine
  labels:
    app: assisted-service
data:
  LOG_LEVEL: "debug"
  AUTH_TYPE: "none"
  SKIP_CERT_VERIFICATION: "True"
  HTTP_PROXY: "${OC_HTTP_PROXY}"
  HTTPS_PROXY: "${OC_HTTPS_PROXY}"
  NO_PROXY: "${OC_NO_PROXY}"
  #SERVICE_IMAGE: registry.access.redhat.com/rhacm2/agent-service-rhel8@sha256:b6deaffb775887853123bac203ae1e0441014392f43ccb38e456389d20af34e4
  #SELF_VERSION: registry.access.redhat.com/rhacm2/agent-service-rhel8@sha256:b6deaffb775887853123bac203ae1e0441014392f43ccb38e456389d20af34e4
EOF

oc apply -f 05_cm-assisted-installer-config.yaml
```

10. enable console MCE

https://github.com/Red-Hat-SE-RTO/openshift-ztp/blob/main/ansible/roles/configure_rhacm_oas/templates/06_multiclusterengine.yml.j2

```bash
oc edit multiclusterengines.multicluster.openshift.io
```

```yaml=
spec:
  availabilityConfig: High
  imagePullSecret: YOUR_IMAGE_PULL_SECRET_GOES_HERE
  overrides:
    components:
    - enabled: true
      name: console-mce
```

---

# Spoke Cluster YAMLs


```bash=
export SPOKE_CLUSTER_NAME="YOUR_HOSTNAME"
export SPOKE_CLUSTER_DOMAIN="YOUR_BASE_DOMAIN"
export SPOKE_CLUSTER_TYPE="full"
export SPOKE_CLUSTER_API_VIP="YOUR_IP_GOES_HERE"
export SPOKE_CLUSTER_APP_VIP="YOUR_IP_GOES_HERE"
export SPOKE_CLUSTER_VM_SUBNET="YOUR_SUBNET_HERE/CIDR"
export SPOKE_CLUSTER_LOCATION="YOUR_LOCATION_HERE"

export NTP_SERVER1="NTP_IP_1"
export NTP_SERVER2="NTP_IP_2"
export DNS_SERVER1="NTP_IP_3"
export DNS_SERVER2="NTP_IP_4"
export GATEWAY_IP="YOUR_GATEWAY_IP_HERE"

mkdir $SPOKE_CLUSTER_NAME
cd $SPOKE_CLUSTER_NAME

## Create SSH Key pair for the cluster
ssh-keygen -t rsa -b 4096
## Tell it to save it to ./ssh-key

# Spoke Cluster Namespace
cat > 00_namespace.yaml <<EOF
apiVersion: v1
kind: Namespace
metadata:
  creationTimestamp: null
  name: $SPOKE_CLUSTER_NAME
spec: {}
EOF

# Spoke Cluster SSH Key
cat > 01_secret-ssh-key.yaml <<EOF
apiVersion: v1
kind: Secret
metadata:
  creationTimestamp: null
  name: ssh-key
  namespace: ${SPOKE_CLUSTER_NAME}
  labels:
    name: ssh-key
    cloud: baremetal
    vendor: OpenShift
    cluster-name: $SPOKE_CLUSTER_NAME
    cluster-domain: $SPOKE_CLUSTER_DOMAIN
    cluster-role: ztp-spoke
    cluster-type: $SPOKE_CLUSTER_TYPE
stringData:
  ssh_private_key: |
$(cat ./ssh-key | awk '{printf "    %s\n", $0}')
  ssh_public_key: $(cat ./ssh-key.pub)
EOF

# Spoke Cluster Pull Secret
cat > 01_secret-pull-secret.yaml <<EOF
apiVersion: v1
kind: Secret
metadata:
  creationTimestamp: null
  name: pull-secret
  namespace: ${SPOKE_CLUSTER_NAME}
  labels:
    name: pull-secret
    cloud: baremetal
    vendor: OpenShift
    cluster-name: $SPOKE_CLUSTER_NAME
    cluster-domain: $SPOKE_CLUSTER_DOMAIN
    cluster-role: ztp-spoke
    cluster-type: $SPOKE_CLUSTER_TYPE
data:
  .dockerconfigjson: $(oc get secret/pull-secret -n openshift-config -o jsonpath='{.data.\.dockerconfigjson}')
EOF

# Custom Root CAs for the Spoke Cluster
cat > 01_cm_custom-root-ca.yaml <<EOF
kind: ConfigMap
apiVersion: v1
metadata:
  name: custom-root-ca
  namespace: ${SPOKE_CLUSTER_NAME}
  labels:
    name: custom-root-ca
    cloud: baremetal
    vendor: OpenShift
    cluster-name: $SPOKE_CLUSTER_NAME
    cluster-domain: $SPOKE_CLUSTER_DOMAIN
    cluster-role: ztp-spoke
    cluster-type: $SPOKE_CLUSTER_TYPE
    config.openshift.io/inject-trusted-cabundle: 'true'
data: {}
EOF

# Spoke Cluster AgentClusterInstall CR
cat > 02_agentclusterinstall.yaml <<EOF
apiVersion: extensions.hive.openshift.io/v1beta1
kind: AgentClusterInstall
metadata:
  name: ${SPOKE_CLUSTER_NAME}
  namespace: ${SPOKE_CLUSTER_NAME}
  labels:
    name: agentclusterinstall
    cloud: baremetal
    vendor: OpenShift
    cluster-name: $SPOKE_CLUSTER_NAME
    cluster-domain: $SPOKE_CLUSTER_DOMAIN
    cluster-role: ztp-spoke
    cluster-type: $SPOKE_CLUSTER_TYPE
spec:
  clusterDeploymentRef:
    name: ${SPOKE_CLUSTER_NAME}
  imageSetRef:
    name: img4.11.34-x86-64-appsub
  # if using UserManagedNetworking VIPs are not needed
  #apiVIP: "${SPOKE_CLUSTER_API_VIP}"
  #ingressVIP: "${SPOKE_CLUSTER_APP_VIP}"
  holdInstallation: true
  networking:
    networkType: openShiftSDN
    # userManagedNetwork == true if using an external LB
    userManagedNetworking: true
    clusterNetwork:
      - cidr: "100.80.0.0/14"
        hostPrefix: 23
    serviceNetwork:
      - "100.126.0.0/16"
    # machineNetwork defines the subnet(s) that the VMs are in
    # If using UserManagedNetworking machineNetworks cannot be defined
    #machineNetwork:
    #  - cidr: "${SPOKE_CLUSTER_VM_SUBNET}"
  provisionRequirements:
    controlPlaneAgents: 3
    workerAgents: 7
  sshPublicKey: "$(cat ./ssh-key.pub)"
  proxy:
    httpProxy: "$(oc get proxy/cluster -o jsonpath='{.status.httpProxy}')"
    httpsProxy: "$(oc get proxy/cluster -o jsonpath='{.status.httpsProxy}')"
    noProxy: "IP.ADDRESS.HERE/24,$(oc get proxy/cluster -o jsonpath='{.status.noProxy}')"
EOF

# Spoke Cluster ClusterDeployment CR
cat > 03_clusterdeployment.yaml <<EOF
---
apiVersion: hive.openshift.io/v1
kind: ClusterDeployment
metadata:
  annotations:
    agentBareMetal-agentSelector/autoSelect: "true"
  name: ${SPOKE_CLUSTER_NAME}
  namespace: ${SPOKE_CLUSTER_NAME}
  labels:
    name: clusterdeployment
    cloud: baremetal
    vendor: OpenShift
    cluster-name: $SPOKE_CLUSTER_NAME
    cluster-domain: $SPOKE_CLUSTER_DOMAIN
    cluster-role: ztp-spoke
    cluster-type: $SPOKE_CLUSTER_TYPE
    cluster.open-cluster-management.io/clusterset: default
spec:
  installAttemptsLimit: 0
  baseDomain: ${SPOKE_CLUSTER_DOMAIN}
  clusterName: ${SPOKE_CLUSTER_NAME}
  installed: false
  clusterInstallRef:
    group: extensions.hive.openshift.io
    kind: AgentClusterInstall
    name: ${SPOKE_CLUSTER_NAME}
    version: v1beta1
  platform:
    agentBareMetal:
      agentSelector:
        matchLabels:
          cluster-name: ${SPOKE_CLUSTER_NAME}
          agentBareMetal-generated-infraenv-ai-flow: ${SPOKE_CLUSTER_NAME}
  pullSecretRef:
    name: pull-secret
  certificateBundles:
    - name: custom-root-ca
      certificateSecretRef:
        name: custom-root-ca
EOF

# Spoke Cluster KlusterletAddonConfig CR
cat > 04_klusterletaddonconfig.yaml <<EOF
---
apiVersion: agent.open-cluster-management.io/v1
kind: KlusterletAddonConfig
metadata:
  name: $SPOKE_CLUSTER_NAME
  namespace: $SPOKE_CLUSTER_NAME
  labels:
    name: klusterletaddonconfig
    cloud: baremetal
    vendor: OpenShift
    cluster-name: $SPOKE_CLUSTER_NAME
    cluster-domain: $SPOKE_CLUSTER_DOMAIN
    cluster-role: ztp-spoke
    cluster-type: $SPOKE_CLUSTER_TYPE
spec:
  clusterName: $SPOKE_CLUSTER_NAME
  clusterNamespace: $SPOKE_CLUSTER_NAME
  clusterLabels:
    cloud: baremetal
    vendor: OpenShift
    cluster-name: $SPOKE_CLUSTER_NAME
    cluster-domain: $SPOKE_CLUSTER_DOMAIN
    cluster-role: ztp-spoke
    cluster-type: $SPOKE_CLUSTER_TYPE
  applicationManager:
    enabled: true
  policyController:
    enabled: true
  searchCollector:
    enabled: true
  certPolicyController:
    enabled: true
  iamPolicyController:
    enabled: true
EOF

# Spoke Cluster ManagedCluster CR
cat > 05_managedcluster.yaml <<EOF
---
apiVersion: cluster.open-cluster-management.io/v1
kind: ManagedCluster
metadata:
  name: $SPOKE_CLUSTER_NAME
  namespace: $SPOKE_CLUSTER_NAME
  labels:
    name: managedcluster
    cloud: baremetal
    vendor: OpenShift
    cluster-name: $SPOKE_CLUSTER_NAME
    cluster-domain: $SPOKE_CLUSTER_DOMAIN
    cluster-role: ztp-spoke
    cluster-type: $SPOKE_CLUSTER_TYPE
spec:
  hubAcceptsClient: true
EOF

# Spoke Cluster InfraEnv CR
cat > 07_infraenv.yaml <<EOF
---
apiVersion: agent-install.openshift.io/v1beta1
kind: InfraEnv
metadata:
  name: $SPOKE_CLUSTER_NAME
  namespace: $SPOKE_CLUSTER_NAME
  labels:
    name: infraenv
    cloud: baremetal
    vendor: OpenShift
    cluster-name: $SPOKE_CLUSTER_NAME
    cluster-domain: $SPOKE_CLUSTER_DOMAIN
    cluster-role: ztp-spoke
    cluster-type: $SPOKE_CLUSTER_TYPE
    agentclusterinstalls.extensions.hive.openshift.io/location: $SPOKE_CLUSTER_LOCATION
    networkType: static
spec:
  agentLabels:
    agentclusterinstalls.extensions.hive.openshift.io/location: $SPOKE_CLUSTER_LOCATION
  clusterRef:
    name: $SPOKE_CLUSTER_NAME
    namespace: $SPOKE_CLUSTER_NAME
  sshAuthorizedKey: "$(cat ./ssh-key.pub)"
  pullSecretRef:
    name: pull-secret
  nmStateConfigLabelSelector:
    matchLabels:
      cluster-name: $SPOKE_CLUSTER_NAME
  additionalNTPSources:
    - $NTP_SERVER1
    - $NTP_SERVER2
  proxy:
    httpProxy: "$(oc get proxy/cluster -o jsonpath='{.status.httpProxy}')"
    httpsProxy: "$(oc get proxy/cluster -o jsonpath='{.status.httpsProxy}')"
    noProxy: "153.2.255.0/24,$(oc get proxy/cluster -o jsonpath='{.status.noProxy}')"
EOF

# Spoke Cluster NMStateConfig CR - Node 1
function generateNMStateConfigFile () {

NODE_NAME=$1
NODE192_ADDRESS=$2
NODE224_ADDRESS=$3
NODE192_MAC_ADDRESS=$4
NODE224_MAC_ADDRESS=$5

cat > 11_nmstate_$NODE_NAME.yaml <<EOF
---
apiVersion: agent-install.openshift.io/v1beta1
kind: NMStateConfig
metadata:
  name: $NODE_NAME
  namespace: $SPOKE_CLUSTER_NAME
  labels:
    name: nmstateconfig
    cloud: baremetal
    vendor: OpenShift
    cluster-name: $SPOKE_CLUSTER_NAME
    cluster-domain: $SPOKE_CLUSTER_DOMAIN
    cluster-role: ztp-spoke
    cluster-type: $SPOKE_CLUSTER_TYPE
spec:
  config:
    dns-resolver:
      config:
        server:
          - $DNS_SERVER1
          - $DNS_SERVER2
        search:
          - YOURZONE.COM
          - MYZONE.COM
          - OURZONE.COM
    interfaces:
      - ipv4:
          address:
            - ip: ${NODE192_ADDRESS}
              prefix-length: 20
          dhcp: false
          enabled: true
        ipv6:
          enabled: false
        mtu: 1500
        name: ens192
        state: up
        type: ethernet
      - ipv4:
          address:
            - ip: ${NODE224_ADDRESS}
              prefix-length: 20
          dhcp: false
          enabled: true
        ipv6:
          enabled: false
        mtu: 1500
        name: ens224
        state: up
        type: ethernet
    routes:
      config:
        - destination: 0.0.0.0/0
          next-hop-address: $GATEWAY_IP
          next-hop-interface: ens224
          table-id: 254
  interfaces:
    - name: ens192
      macAddress: $NODE192_MAC_ADDRESS
    - name: ens224
      macAddress: $NODE224_MAC_ADDRESS
EOF

}
# generateNMStateConfigFile HOSTNAME ENS192_IP ENS224_IP ENS192_MAC ENS224_MAC
# generateNMStateConfigFile HOSTNAME VSAN_IP PUBLIC_IP VSAN_MAC PUBLIC_MAC

# Masters
generateNMStateConfigFile your_master_node_name "interface1_IP" "interface2_IP" "interface1_MAC" "interface2_MAC"

# Infra
generateNMStateConfigFile your_infra_node_name "interface1_IP" "interface2_IP" "interface1_MAC" "interface2_MAC"

# Worker/Storage
generateNMStateConfigFile your_storage_worker_node_name "interface1_IP" "interface2_IP" "interface1_MAC" "interface2_MAC"

# Worker
generateNMStateConfigFile your_worker_node_name "interface1_IP" "interface2_IP" "interface1_MAC" "interface2_MAC"


```

---

## Bonded Networks

```bash=
export SPOKE_CLUSTER_NAME="YOUR_CLUSTER_NAME"
export SPOKE_CLUSTER_DOMAIN="YOUR_DOMAIN"
export SPOKE_CLUSTER_TYPE="full"

export DNS_SERVER1="DNS_SERVER_1"
export DNS_SERVER2="DNS_SERVER_2"
export GATEWAY_IP="Gateway_IP"

# createBondedNMStateConfig NODE_NAME BOND0_ADDRESS BOND1_ADDRESS ENO1_MAC_ADDRESS ENO2_MAC_ADDRESS ENO3_MAC_ADDRESS ENO4_MAC_ADDRESS
function createBondedNMStateConfig () {
NODE_NAME=$1
BOND0_ADDRESS=$2
BOND1_ADDRESS=$3
ENO1_MAC_ADDRESS=$4
ENO2_MAC_ADDRESS=$5
ENO3_MAC_ADDRESS=$6
ENO4_MAC_ADDRESS=$7

cat > 11_nmstate_$NODE_NAME.yaml <<EOF
---
apiVersion: agent-install.openshift.io/v1beta1
kind: NMStateConfig
metadata:
  name: $NODE_NAME
  namespace: $SPOKE_CLUSTER_NAME
  labels:
    name: nmstateconfig
    cloud: baremetal
    vendor: OpenShift
    cluster-name: $SPOKE_CLUSTER_NAME
    cluster-domain: $SPOKE_CLUSTER_DOMAIN
    cluster-role: ztp-spoke
    cluster-type: $SPOKE_CLUSTER_TYPE
spec:
  config:
    dns-resolver:
      config:
        server:
          - $DNS_SERVER1
          - $DNS_SERVER2
        search:
          - domain1.com
          - domain2.com
    interfaces:
      - name: eno1
        type: ethernet
        state: up
      - name: eno2
        type: ethernet
        state: up
      - name: eno3
        type: ethernet
        state: up
      - name: eno4
        type: ethernet
        state: up
      - name: bond0
        type: bond
        state: down
        ipv4:
          address:
            - ip: ${BOND0_ADDRESS}
              prefix-length: 20
          dhcp: false
          enabled: true
        ipv6:
          enabled: false
        mtu: 1500
        link-aggregation:
          mode: active-backup
          options:
            primary: eno1
          port:
            - eno1
            - eno3
      - name: bond1
        type: bond
        state: up
        ipv4:
          address:
            - ip: ${BOND1_ADDRESS}
              prefix-length: 20
          dhcp: false
          enabled: true
        ipv6:
          enabled: false
        mtu: 1500
        link-aggregation:
          mode: active-backup
          options:
            primary: eno2
          port:
            - eno2
            - eno4
    routes:
      config:
        - destination: 0.0.0.0/0
          next-hop-address: $GATEWAY_IP
          next-hop-interface: bond1
          table-id: 254
  interfaces:
    - name: eno1
      macAddress: $ENO1_MAC_ADDRESS
    - name: eno2
      macAddress: $ENO2_MAC_ADDRESS
    - name: eno3
      macAddress: $ENO3_MAC_ADDRESS
    - name: eno4
      macAddress: $ENO4_MAC_ADDRESS
EOF

}

createBondedNMStateConfig your_node_name_here \
 "ip.address.1.here" \
 "ip.address.2.here" \
 "MA:CA:DD:RE:SS:01" \
 "MA:CA:DD:RE:SS:02" \
 "MA:CA:DD:RE:SS:03" \
 "MA:CA:DD:RE:SS:04"


```

---

## Optional: Deploy ZTP Mirror


> Make sure to replace the placeholder Jinja2 variables for the Proxy with proper values

```yaml=
apiVersion: v1
kind: Namespace
metadata:
  creationTimestamp: null
  name: ztp-mirror
spec: {}
---
apiVersion: v1
kind: ConfigMap
metadata:
  name: mirror-config
  namespace: ztp-mirror
data:
  config.yml: |-
    app:
      assets:
        - source: https://mirror.openshift.com/pub/openshift-v4/x86_64/dependencies/rhcos/4.11/latest/rhcos-live.x86_64.iso
          destination: "/tmp/server/pub/openshift-v4/x86_64/dependencies/rhcos/4.11/latest/rhcos-live.x86_64.iso"

        - source: https://mirror.openshift.com/pub/openshift-v4/x86_64/dependencies/rhcos/4.11/latest/rhcos-live-rootfs.x86_64.img
          destination: "/tmp/server/pub/openshift-v4/x86_64/dependencies/rhcos/4.11/latest/rhcos-live-rootfs.x86_64.img"

        - source: https://mirror.openshift.com/pub/openshift-v4/x86_64/dependencies/rhcos/4.12/latest/rhcos-live.x86_64.iso
          destination: "/tmp/server/pub/openshift-v4/x86_64/dependencies/rhcos/4.12/latest/rhcos-live.x86_64.iso"

        - source: https://mirror.openshift.com/pub/openshift-v4/x86_64/dependencies/rhcos/4.12/latest/rhcos-live-rootfs.x86_64.img
          destination: "/tmp/server/pub/openshift-v4/x86_64/dependencies/rhcos/4.12/latest/rhcos-live-rootfs.x86_64.img"
          #overwrite: true
      server:
        host: 0.0.0.0
        base_path: "/pub/"
        fs_path: "/tmp/server/pub"
        skip_tls_verify: true
        port: 8080
        timeouts:
          server: 0
          read: 0
          write: 0
          idle: 0
---
kind: ConfigMap
apiVersion: v1
metadata:
  name: trusted-ca
  namespace: ztp-mirror
  labels:
    config.openshift.io/inject-trusted-cabundle: 'true'
data: {}
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: ztp-mirror
  namespace: ztp-mirror
spec:
  accessModes:
    - ReadWriteOnce
  volumeMode: Filesystem
  resources:
    requests:
      storage: 20Gi
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: mirror-server
  namespace: ztp-mirror
spec:
  selector:
    matchLabels:
      app: mirror-server
  replicas: 1
  strategy:
    type: Recreate
  template:
    metadata:
      labels:
        app: mirror-server
    spec:
      volumes:
        - name: ztp-mirror
          persistentVolumeClaim:
            claimName: ztp-mirror
        - name: mirror-config
          configMap:
            name: mirror-config
        - name: trusted-ca
          configMap:
            name: trusted-ca
            items:
              - key: ca-bundle.crt
                path: tls-ca-bundle.pem
      containers:
        - name: mirror-server
          image: quay.io/kenmoini/go-http-mirror:latest
          imagePullPolicy: Always
          env:
            - name: HTTP_PROXY
              value: "{{ cluster_wide_http_proxy }}"
            - name: http_proxy
              value: "{{ cluster_wide_http_proxy }}"
            - name: HTTPS_PROXY
              value: "{{ cluster_wide_https_proxy }}"
            - name: https_proxy
              value: "{{ cluster_wide_https_proxy }}"
            - name: NO_PROXY
              value: "{{ cluster_wide_no_proxy }}"
            - name: no_proxy
              value: "{{ cluster_wide_no_proxy }}"
          ports:
            - containerPort: 8080
          resources:
            requests:
              cpu: "100m"
              memory: "100Mi"
            limits:
              cpu: "500m"
              memory: "500Mi"
          volumeMounts:
            - name: mirror-config
              mountPath: /etc/ztp-mirror
            - name: ztp-mirror
              mountPath: /tmp/server/pub
            - mountPath: /etc/pki/ca-trust/extracted/pem
              name: trusted-ca
              readOnly: true
---
apiVersion: v1
kind: Service
metadata:
  name: ztp-mirror
  namespace: ztp-mirror
spec:
  selector:
    app: mirror-server
  ports:
    - protocol: TCP
      port: 8080
      targetPort: 8080
---
apiVersion: route.openshift.io/v1
kind: Route
metadata:
  name: ztp-mirror
  namespace: ztp-mirror
  annotations:
    haproxy.router.openshift.io/timeout: "600s"
spec:
  # No need to specify the host unless you want it on a specific FQDN
  #host: ztp-mirror-ztp-mirror.apps.core-ocp.lab.kemo.network
  path: /
  to:
    kind: Service
    name: ztp-mirror
  port:
    targetPort: 8080
  tls:
    termination: edge
    insecureEdgeTerminationPolicy: Allow
  wildcardPolicy: None
```
