From f74c5beef199950dc26560ef91da9d42870365a4 Mon Sep 17 00:00:00 2001 From: staffadmin Date: Sun, 26 Nov 2023 19:22:30 +0100 Subject: [PATCH] last commit before new job --- clab.log | 151 ++++++++++++++++++++++++++++++++++++++ group_vars/all.yml | 4 + group_vars/controller.yml | 1 - host_vars/ovh_master.yml | 10 +++ host_vars/ovh_worker.yml | 1 + kubernetes.yml | 73 ++++++++++++++++++ topo.clab.yml | 30 ++++++++ 7 files changed, 269 insertions(+), 1 deletion(-) create mode 100644 clab.log create mode 100644 group_vars/all.yml create mode 100644 topo.clab.yml diff --git a/clab.log b/clab.log new file mode 100644 index 0000000..f0f5151 --- /dev/null +++ b/clab.log @@ -0,0 +1,151 @@ + +2023-11-25T22:03:50.420713495Z stdout F INFO | containerlab | time="2023-11-25T22:03:49Z" level=error msg="failed deploy phase for node \"srl\": Post \"http://%2Fvar%2Frun%2Fdocker.sock/v1.43/containers/create?name=srl\": context deadline exceeded" +2023-11-25T22:03:50.420788295Z stdout F +2023-11-25T22:03:51.628933512Z stdout F INFO | containerlab | time="2023-11-25T22:03:51Z" level=error msg="failed to update node runtime information for node srl: Node: srl. containers not found" +2023-11-25T22:03:51.629011829Z stdout F +2023-11-25T22:03:53.97872517Z stdout F INFO | containerlab | time="2023-11-25T22:03:53Z" level=info msg="Running postdeploy actions for Nokia SR Linux 'srl' node" +2023-11-25T22:03:53.978815183Z stdout F +2023-11-25T22:04:00.808544249Z stdout F INFO | containerlab | time="2023-11-25T22:04:00Z" level=warning msg="Unable to locate /etc/hosts file for srl node srl: Error response from daemon: No such container: srl" +2023-11-25T22:04:00.80863376Z stdout F time="2023-11-25T22:04:00Z" level=warning msg="Unable to populate hosts for node \"srl\": Error response from daemon: No such container: srl" +2023-11-25T22:04:00.808670504Z stdout F time="2023-11-25T22:04:00Z" level=error msg="srl: failed to execute cmd: \"/opt/srlinux/bin/sr_cli -d info from state system app-management application mgmt_server state | grep running\" with error Error response from daemon: No such container: srl" +2023-11-25T22:04:00.808701938Z stdout F +2023-11-25T22:04:00.808729937Z stdout F INFO | containerlab | panic: runtime error: invalid memory address or nil pointer dereference +2023-11-25T22:04:00.808755439Z stdout F [signal SIGSEGV: segmentation violation code=0x1 addr=0x18 pc=0x24c323b] +2023-11-25T22:04:00.808776851Z stdout F +2023-11-25T22:04:00.808799942Z stdout F goroutine 68 [running]: +2023-11-25T22:04:00.808822961Z stdout F github.com/srl-labs/containerlab/clab/exec.(*ExecResult).GetReturnCode(...) +2023-11-25T22:04:00.808847792Z stdout F github.com/srl-labs/containerlab/clab/exec/exec.go:140 +2023-11-25T22:04:00.808873193Z stdout F github.com/srl-labs/containerlab/nodes/srl.(*srl).Ready(0xc000b64000, {0x352d1e8?, 0xc0005ceb40?}) +2023-11-25T22:04:00.808896667Z stdout F github.com/srl-labs/containerlab/nodes/srl/srl.go:388 +0x1db +2023-11-25T22:04:00.808919641Z stdout F github.com/srl-labs/containerlab/nodes/srl.(*srl).PostDeploy(0xc000b64000, {0x352d1e8, 0xc0005ceb40}, 0xc000da4320) +2023-11-25T22:04:00.808942725Z stdout F github.com/srl-labs/containerlab/nodes/srl/srl.go:317 +0x3d3 +2023-11-25T22:04:00.808967871Z stdout F github.com/srl-labs/containerlab/cmd.deployFn.func1({0x354fdb0, 0xc000b64000}, 0xc000b66120?) +2023-11-25T22:04:00.808991524Z stdout F github.com/srl-labs/containerlab/cmd/deploy.go:257 +0xdf +2023-11-25T22:04:00.809014233Z stdout F created by github.com/srl-labs/containerlab/cmd.deployFn +2023-11-25T22:04:00.809036975Z stdout F github.com/srl-labs/containerlab/cmd/deploy.go:254 +0x1965 +2023-11-25T22:04:00.809057625Z stdout F +2023-11-25T22:04:00.949400836Z stdout F CRITICAL | clabernetes | failed launching containerlab, err: exit status 2 +2023-11-25T22:04:00.984734741Z stdout F CRITICAL | clabernetes | received signal 'interrupt', canceling context + + + + + + +2023-11-25T19:50:55.714307172Z stdout F INFO | clabernetes | image pull through mode "auto", start image pull through attempt... +2023-11-25T19:50:55.714397331Z stdout F INFO | clabernetes | attempting containerd image pull through... +2023-11-25T19:59:20.245154095Z stdout F INFO | clabernetes | Loaded image: ghcr.io/nokia/srlinux:latest +2023-11-25T19:59:20.245272355Z stdout F +2023-11-25T19:59:22.23484068Z stdout F INFO | containerlab | time="2023-11-25T19:59:22Z" level=info msg="Containerlab v0.48.2 started" +2023-11-25T19:59:22.234881849Z stdout F +2023-11-25T19:59:22.444458147Z stdout F INFO | containerlab | time="2023-11-25T19:59:22Z" level=info msg="Parsing & checking topology file: topo.clab.yaml" +2023-11-25T19:59:22.444492911Z stdout F +2023-11-25T19:59:22.455449236Z stdout F INFO | containerlab | time="2023-11-25T19:59:22Z" level=info msg="Creating docker network: Name=\"clab\", IPv4Subnet=\"172.20.20.0/24\", IPv6Subnet=\"2001:172:20:20::/64\", MTU='ל'" +2023-11-25T19:59:22.455530224Z stdout F +2023-11-25T19:59:23.435162806Z stdout F INFO | containerlab | time="2023-11-25T19:59:23Z" level=warning msg="failed to enable LLDP on docker bridge: open /sys/class/net/br-994c18a1defc/bridge/group_fwd_mask: read-only file system" +2023-11-25T19:59:23.435256921Z stdout F +2023-11-25T19:59:23.480503179Z stdout F INFO | containerlab | time="2023-11-25T19:59:23Z" level=info msg="Creating lab directory: /clabernetes/clab-clabernetes-srl1" +2023-11-25T19:59:23.480640357Z stdout F +2023-11-25T19:59:27.974870293Z stdout F INFO | containerlab | time="2023-11-25T19:59:27Z" level=info msg="Creating container: \"srl1\"" +2023-11-25T19:59:27.974938434Z stdout F +2023-11-25T20:01:27.971503837Z stdout F INFO | containerlab | time="2023-11-25T20:01:27Z" level=error msg="failed deploy phase for node \"srl1\": Post \"http://%2Fvar%2Frun%2Fdocker.sock/v1.43/containers/create?name=srl1\": context deadline exceeded" +2023-11-25T20:01:27.971587737Z stdout F +2023-11-25T20:01:28.430297714Z stdout F INFO | containerlab | time="2023-11-25T20:01:28Z" level=error msg="failed to update node runtime information for node srl1: Node: srl1. containers not found" +2023-11-25T20:01:28.430339171Z stdout F +2023-11-25T20:01:28.602932015Z stdout F INFO | containerlab | time="2023-11-25T20:01:28Z" level=info msg="Running postdeploy actions for Nokia SR Linux 'srl1' node" +2023-11-25T20:01:28.603180654Z stdout F +2023-11-25T20:01:31.06416448Z stdout F INFO | containerlab | time="2023-11-25T20:01:31Z" level=warning msg="Unable to locate /etc/hosts file for srl node srl1: Error response from daemon: No such container: srl1" +2023-11-25T20:01:31.064257016Z stdout F +2023-11-25T20:01:31.064289639Z stdout F INFO | containerlab | time="2023-11-25T20:01:31Z" level=warning msg="Unable to populate hosts for node \"srl1\": Error response from daemon: No such container: srl1" +2023-11-25T20:01:31.06431792Z stdout F +2023-11-25T20:01:31.064352575Z stdout F INFO | containerlab | time="2023-11-25T20:01:31Z" level=error msg="srl1: failed to execute cmd: \"/opt/srlinux/bin/sr_cli -d info from state system app-management application mgmt_server state | grep running\" with error Error response from daemon: No such container: srl1" +2023-11-25T20:01:31.064380338Z stdout F +2023-11-25T20:01:31.064411739Z stdout F INFO | containerlab | panic: runtime error: invalid memory address or nil pointer dereference +2023-11-25T20:01:31.064450815Z stdout F [signal SIGSEGV: segmentation violation code=0x1 addr=0x18 pc=0x24c323b] +2023-11-25T20:01:31.064478957Z stdout F +2023-11-25T20:01:31.064507095Z stdout F goroutine 15 [running +2023-11-25T20:01:31.064542774Z stdout F INFO | containerlab | ]: +2023-11-25T20:01:31.064571797Z stdout F +2023-11-25T20:01:31.129363022Z stdout F INFO | containerlab | github.com/srl-labs/containerlab/clab/exec.(*ExecResult).GetReturnCode(...) +2023-11-25T20:01:31.129600761Z stdout F github.com/srl-labs/containerlab/clab/exec/exec.go:140 +2023-11-25T20:01:31.129636192Z stdout F github.com/srl-labs/containerlab/nodes/srl.(*srl).Ready(0xc0002102d0, {0x352d1e8?, 0xc0000c89b0?} +2023-11-25T20:01:31.129719767Z stdout F INFO | containerlab | ) +2023-11-25T20:01:31.12974786Z stdout F github.com/srl-labs/containerlab/nodes/srl/srl.go:388 +0x1db +2023-11-25T20:01:31.129775563Z stdout F github.com/srl-labs/containerlab/nodes/srl.(*srl).PostDeploy(0xc0002102d0, {0x352d1e8, 0xc0000c89b0}, 0xc0000fdb18) +2023-11-25T20:01:31.129802839Z stdout F github.com/srl-labs/containerlab/nodes/srl/srl.go:317 +0x3d3 +2023-11-25T20:01:31.129827404Z stdout F +2023-11-25T20:01:31.143964638Z stdout F INFO | containerlab | github.com/srl-labs/containerlab/cmd.deployFn.func1 +2023-11-25T20:01:31.144046567Z stdout F INFO | containerlab | ({0x354fdb0, 0xc0002102d0}, 0x0?) +2023-11-25T20:01:31.144082174Z stdout F github.com/srl-labs/containerlab/cmd/deploy.go:257 +0xdf +2023-11-25T20:01:31.144110571Z stdout F created by github.com/srl-labs/containerlab/cmd.deployFn +2023-11-25T20:01:31.144136816Z stdout F +2023-11-25T20:01:31.144166728Z stdout F INFO | containerlab | github.com/srl-labs/containerlab/cmd/deploy.go:254 +0x1965 +2023-11-25T20:01:31.144249241Z stdout F +2023-11-25T20:01:31.295197674Z stdout F CRITICAL | clabernetes | failed launching containerlab, err: exit status 2 +2023-11-25T20:01:31.410077704Z stdout F CRITICAL | clabernetes | received signal 'interrupt', canceling context +2023-11-25T20:01:43.449200999Z stdout F INFO | clabernetes | starting clabernetes... +2023-11-25T20:01:43.494512064Z stdout F INFO | clabernetes | mount: /sys/fs/cgroup mounted on /sys/fs/cgroup. + + + + + + + + + + + + +Single node + +al launch... +2023-11-25T21:40:00.112711098Z stdout F INFO | containerlab | time="2023-11-25T21:40:00Z" level=info msg="Containerlab v0.48.2 started" +2023-11-25T21:40:00.112778023Z stdout F +2023-11-25T21:40:00.13724042Z stdout F INFO | containerlab | time="2023-11-25T21:40:00Z" level=info msg="Parsing & checking topology file: topo.clab.yaml" +2023-11-25T21:40:00.137472688Z stdout F +2023-11-25T21:40:00.143557831Z stdout F INFO | containerlab | time="2023-11-25T21:40:00Z" level=info msg="Creating docker network: Name=\"clab\", IPv4Subnet=\"172.20.20.0/24\", IPv6Subnet=\"2001:172:20:20::/64\", MTU='ל'" +2023-11-25T21:40:00.143647911Z stdout F +2023-11-25T21:40:00.492185834Z stdout F INFO | containerlab | time="2023-11-25T21:40:00Z" level=warning msg="failed to enable LLDP on docker bridge: open /sys/class/net/br-376acb86d58c/bridge/group_fwd_mask: read-only file system" +2023-11-25T21:40:00.492282082Z stdout F +2023-11-25T21:40:00.521162645Z stdout F INFO | containerlab | time="2023-11-25T21:40:00Z" level=info msg="Could not read docker config: open /root/.docker/config.json: no such file or directory" +2023-11-25T21:40:00.521365379Z stdout F time="2023-11-25T21:40:00Z" level=info msg="Pulling ghcr.io/nokia/srlinux:latest Docker image" +2023-11-25T21:40:00.521394826Z stdout F +2023-11-25T21:45:35.644747445Z stdout F INFO | containerlab | time="2023-11-25T21:45:35Z" level=info msg="Done pulling ghcr.io/nokia/srlinux:latest" +2023-11-25T21:45:35.64490762Z stdout F +2023-11-25T21:45:35.651853854Z stdout F INFO | containerlab | time="2023-11-25T21:45:35Z" level=info msg="Creating lab directory: /clabernetes/clab-clabernetes-srl" +2023-11-25T21:45:35.651933847Z stdout F +2023-11-25T21:45:38.617156266Z stdout F INFO | containerlab | time="2023-11-25T21:45:38Z" level=info msg="Creating container: \"srl\"" +2023-11-25T21:45:38.617243114Z stdout F +2023-11-25T21:47:38.934919044Z stdout F INFO | containerlab | time="2023-11-25T21:47:38Z" level=error msg="failed deploy phase for node \"srl\": Post \"http://%2Fvar%2Frun%2Fdocker.sock/v1.43/containers/create?name=srl\": context deadline exceeded" +2023-11-25T21:47:38.934992495Z stdout F +2023-11-25T21:47:39.338589008Z stdout F INFO | containerlab | time="2023-11-25T21:47:39Z" level=error msg="failed to update node runtime information for node srl: Node: srl. containers not found" +2023-11-25T21:47:39.338675886Z stdout F +2023-11-25T21:47:39.63536634Z stdout F INFO | containerlab | time="2023-11-25T21:47:39Z" level=info msg="Running postdeploy actions for Nokia SR Linux 'srl' node" +2023-11-25T21:47:39.635471333Z stdout F +2023-11-25T21:47:44.137304767Z stdout F INFO | containerlab | time="2023-11-25T21:47:44Z" level=warning msg="Unable to locate /etc/hosts file for srl node srl: Error response from daemon: No such container: srl" +2023-11-25T21:47:44.137413517Z stdout F time="2023-11-25T21:47:44Z" level=warning msg="Unable to populate hosts for node \"srl\": Error response from daemon: No such container: srl" +2023-11-25T21:47:44.137452575Z stdout F +2023-11-25T21:47:44.14386319Z stdout F INFO | containerlab | time="2023-11-25T21:47:44Z" level=error msg="srl: failed to execute cmd: \"/opt/srlinux/bin/sr_cli -d info from state system app-management application mgmt_server state | grep running\" with error Error response from daemon: No such container: srl" +2023-11-25T21:47:44.143969736Z stdout F +2023-11-25T21:47:44.156895638Z stdout F INFO | containerlab | Error: could not get container for node srl: Node: srl. containers not found +2023-11-25T21:47:44.156991621Z stdout F +2023-11-25T21:47:44.178394285Z stdout F INFO | containerlab | panic: +2023-11-25T21:47:44.197911583Z stdout F INFO | containerlab | runtime error: invalid memory address or nil pointer dereference +2023-11-25T21:47:44.198000328Z stdout F [signal SIGSEGV: segmentation violation code=0x1 addr=0x18 pc=0x24c323b] +2023-11-25T21:47:44.198037998Z stdout F +2023-11-25T21:47:44.198076865Z stdout F goroutine 29 [running]: +2023-11-25T21:47:44.198111509Z stdout F +2023-11-25T21:47:44.255419442Z stdout F INFO | containerlab | github.com/srl-labs/containerlab/clab/exec.(*ExecResult).GetReturnCode(...) +2023-11-25T21:47:44.255510381Z stdout F github.com/srl-labs/containerlab/clab/exec/exec.go:140 +2023-11-25T21:47:44.25555086Z stdout F github.com/srl-labs/containerlab/nodes/srl.(*srl).Ready(0xc00050e000, {0x352d1e8?, 0xc000102e10?}) +2023-11-25T21:47:44.255582399Z stdout F github.com/srl-labs/containerlab/nodes/srl/srl.go:388 +0x1db +2023-11-25T21:47:44.255614497Z stdout F github.com/srl-labs/containerlab/nodes/srl.(*srl).PostDeploy(0xc00050e000, {0x352d1e8, 0xc000102e10}, 0xc000e282b8) +2023-11-25T21:47:44.255644277Z stdout F github.com/srl-labs/containerlab/nodes/srl/srl.go:317 +0x3d3 +2023-11-25T21:47:44.255673608Z stdout F github.com/srl-labs/containerlab/cmd.deployFn.func1({0x354fdb0, 0xc00050e000}, 0xc000e1e120?) +2023-11-25T21:47:44.255757486Z stdout F github.com/srl-labs/containerlab/cmd/deploy.go:257 +0xdf +2023-11-25T21:47:44.255783978Z stdout F created by github.com/srl-labs/containerlab/cmd.deployFn +2023-11-25T21:47:44.255809769Z stdout F github.com/srl-labs/containerlab/cmd/deploy.go:254 +0x1965 +2023-11-25T21:47:44.255833123Z stdout F +2023-11-25T21:47:44.504319871Z stdout F CRITICAL | clabernetes | failed launching containerlab, err: exit status 2 +2023-11-25T21:47:44.633490194Z stdout F CRITICAL | clabernetes | received signal 'interrupt', canceling context \ No newline at end of file diff --git a/group_vars/all.yml b/group_vars/all.yml new file mode 100644 index 0000000..9cfc334 --- /dev/null +++ b/group_vars/all.yml @@ -0,0 +1,4 @@ +github_registry_containerlab: ghcr.io +github_user: staff92 +github_token: ghp_XXXXXXXXX +github_registry_clabernetes: "oci://{{ github_registry_containerlab }}/srl-labs/clabernetes/clabernetes" \ No newline at end of file diff --git a/group_vars/controller.yml b/group_vars/controller.yml index 51cbbdb..36da195 100644 --- a/group_vars/controller.yml +++ b/group_vars/controller.yml @@ -1,6 +1,5 @@ --- -helm_version: 'v3.13.2' install_docker: true install_fail2ban: true diff --git a/host_vars/ovh_master.yml b/host_vars/ovh_master.yml index ae86a6c..2c3ace6 100644 --- a/host_vars/ovh_master.yml +++ b/host_vars/ovh_master.yml @@ -3,6 +3,16 @@ pip_executable: pip pip_install_packages: - kubernetes +package_list: + - name: python3-pip + # clabernetes + - name: jq + +install_docker: true + + +helm_version: 'v3.13.2' + management_user_list: - name: stephane shell: '/bin/bash' diff --git a/host_vars/ovh_worker.yml b/host_vars/ovh_worker.yml index db2d9e2..e3e16d7 100644 --- a/host_vars/ovh_worker.yml +++ b/host_vars/ovh_worker.yml @@ -1,5 +1,6 @@ --- +install_docker: true management_user_list: - name: stephane diff --git a/kubernetes.yml b/kubernetes.yml index 5a2a432..a355969 100644 --- a/kubernetes.yml +++ b/kubernetes.yml @@ -22,6 +22,8 @@ - kubernetes # pip install kubernetes +# install argocd + - block: - name: Download manifest on master ansible.builtin.get_url: @@ -50,3 +52,74 @@ - kubernetes_init_app tags: - kubernetes + + + +# Install clabernetes (docker on worker and master ? No, docker ok on worker but doesn't work ) ----> https://containerlab.dev/install/ + + # - name: login helm registry + # shell: "helm registry login {{ github_registry_containerlab }} -u {{ github_user }} -p {{ github_token }}" + # when: "{{ inventory_hostname in groups['kubemaster'] }}" + # tags: helm + +# helm upgrade --install --create-namespace --namespace clabernetes clabernetes oci://ghcr.io/srl-labs/clabernetes/clabernetes + +# clabverter : Converting the containerlab topology to clabernetes manifests (kubernetes style) and applying it +# docker pull ghcr.io/srl-labs/clabernetes/clabverter +# alias clabverter="mkdir -p converted && chown -R 65532:65532 converted && \ +# docker run -v $(pwd):/clabernetes/work --rm \ +# ghcr.io/srl-labs/clabernetes/clabverter" + + + +# Install loablancer with VIP (but not necessary) -> if no external access to the nodes is required, load balancer installation can be skipped altogether. + +# kubectl apply -f https://kube-vip.io/manifests/rbac.yaml +# kubectl apply -f https://raw.githubusercontent.com/kube-vip/kube-vip-cloud-provider/main/manifest/kube-vip-cloud-controller.yaml +# kubectl create configmap --namespace kube-system kubevip --from-literal range-global=172.18.1.10-172.18.1.250 + + +# CLI +#KVVERSION=$(curl -sL https://api.github.com/repos/kube-vip/kube-vip/releases | jq -r ".[0].name") +#alias kube-vip="docker run --network host --rm ghcr.io/kube-vip/kube-vip:$KVVERSION" + +# install kube-vip load balancer daemonset in ARP mode: +# I have set on public IP and listening on port kubernetes, 6443 +#kube-vip manifest daemonset --services --inCluster --arp --interface eth0 | kubectl apply -f - + + +#root@ovh-master:/tmp/srl02# mkdir -p converted && chown -R 65532:65532 converted && docker run -v $(pwd):/clabernetes/work --rm ghcr.io/srl-labs/clabernetes/clabverter --topologyFile srl02.clab.yml --stdout | kubectl apply -f - + + +# mkdir -p converted && chown -R 65532:65532 converted && docker run -v $(pwd):/clabernetes/work --rm ghcr.io/srl-labs/clabernetes/clabverter --topologyFile srl02.clab.yml --stdout | kubectl apply -f - + + +# docker run -v $(pwd):/clabernetes/work --rm ghcr.io/srl-labs/clabernetes/clabverter --topologyFile srl02.clab.yml --stdout | kubectl apply -f - + +# INFO | clabverter | starting clabversion! +# INFO | clabverter | loading and validating provided containerlab topology file... +# INFO | clabverter | handling containerlab associated file(s) if present... +# INFO | clabverter | handling containerlab topology startup config(s) if present... +# INFO | clabverter | rendering clabernetes startup config outputs... +# INFO | clabverter | handling containerlab extra file(s) if present... +# INFO | clabverter | rendering clabernetes extra file(s) outputs... +# INFO | clabverter | clabversion complete! +# configmap/srl02-srl1-startup-config created +# configmap/srl02-srl2-startup-config created +# containerlab.topology.clabernetes/srl02 created + + +# kubectl exec -n clabernetes -it srl02-srl1-646dbff599-c65gw -- bash + +# kubectl get --namespace clabernetes Containerlab +# kubectl delete --namespace clabernetes Containerlab + + + + + +# containerlab + +# echo "deb [trusted=yes] https://apt.fury.io/netdevops/ /" | \ +# sudo tee -a /etc/apt/sources.list.d/netdevops.list +# sudo apt update && sudo apt install containerlab \ No newline at end of file diff --git a/topo.clab.yml b/topo.clab.yml new file mode 100644 index 0000000..2f79856 --- /dev/null +++ b/topo.clab.yml @@ -0,0 +1,30 @@ +name: clabernetes-srl1 +prefix: "" +topology: + defaults: + ports: + - 60000:21/tcp + - 60001:22/tcp + - 60002:23/tcp + - 60003:80/tcp + - 60000:161/udp + - 60004:443/tcp + - 60005:830/tcp + - 60006:5000/tcp + - 60007:5900/tcp + - 60008:6030/tcp + - 60009:9339/tcp + - 60010:9340/tcp + - 60011:9559/tcp + - 60012:57400/tcp + nodes: + srl1: + kind: nokia_srlinux + startup-config: srl1.cfg + image: ghcr.io/nokia/srlinux + ports: [] + links: + - endpoints: + - srl1:e1-1 + - host:srl1-e1-1 +debug: false \ No newline at end of file