diff --git a/Hackfest_Demos/OSM-11/PowerDNS/helm-cnf/README.md b/Hackfest_Demos/OSM-11/PowerDNS/helm-cnf/README.md new file mode 100644 index 0000000000000000000000000000000000000000..ba6a02283f001a66802af4e6cc13db4770f6b06c --- /dev/null +++ b/Hackfest_Demos/OSM-11/PowerDNS/helm-cnf/README.md @@ -0,0 +1,40 @@ +# K8s-At-Home PowerDNS NS + +Descriptors that installs a PowerDNS chart from K8s-At-Home repo. + +There is one VNF (powerdns\_vnf) with only one KDU. + +There is one NS that connects the VNF to a mgmt network + +## Onboarding and instantiation + +```bash +osm nfpkg-create powerdns_knf.tar.gz +osm nspkg-create powerdns_ns.tar.gz +osm ns-create --ns_name powerdns --nsd_name powerdns_ns --vim_account | --ssh_keys ${HOME}/.ssh/id_rsa.pub +``` + +### Instantiation option + +Some parameters could be passed during the instantiation. + +```bash +osm ns-create --ns_name powerdns --nsd_name powerdns_ns --vim_account | --config '{additionalParamsForVnf: [{"member-vnf-index": "openldap", "additionalParams": {"replicaCount": "2"}}]}' +osm ns-create --ns_name powerdns --nsd_name powerdns_ns --vim_account | --config_file params.yaml +``` + +## Test deployment + +```bash +helm -n list +kubectl -n get all +kubectl -n get service +``` + +## Testing PowerDNS server + +```bash +PROJECT_ID="$(osm project-list | grep "_43" | awk '{ print $4 }')" +UDP_NODE_PORT="$(k -n "${PROJECT_ID}" get svc | grep udp | awk '{ print $5 }' | sed 's#53\:\([0-9]*\)/UDP#\1#g')" +dig @ -p "${UDP_NODE_PORT}" google.com +``` diff --git a/Hackfest_Demos/OSM-11/PowerDNS/helm-cnf/powerdns_knf/powerdns_vnfd.yaml b/Hackfest_Demos/OSM-11/PowerDNS/helm-cnf/powerdns_knf/powerdns_vnfd.yaml new file mode 100644 index 0000000000000000000000000000000000000000..022b597bc8959bbabc5f5cfaa92f4534e699933d --- /dev/null +++ b/Hackfest_Demos/OSM-11/PowerDNS/helm-cnf/powerdns_knf/powerdns_vnfd.yaml @@ -0,0 +1,18 @@ +vnfd: + description: KNF with single KDU using a helm-chart for PowerDNS + df: + - id: default-df + ext-cpd: + - id: mgmt-ext + k8s-cluster-net: mgmtnet + id: powerdns_knf + k8s-cluster: + nets: + - id: mgmtnet + kdu: + - name: powerdns + helm-chart: k8s-at-home/powerdns + mgmt-cp: mgmt-ext + product-name: powerdns_knf + provider: UBITECH Ltd. + version: '1.0' diff --git a/Hackfest_Demos/OSM-11/PowerDNS/helm-cnf/powerdns_ns/params/params.yaml b/Hackfest_Demos/OSM-11/PowerDNS/helm-cnf/powerdns_ns/params/params.yaml new file mode 100644 index 0000000000000000000000000000000000000000..77e7d2c5eed79e81518df3c1291314d03101877f --- /dev/null +++ b/Hackfest_Demos/OSM-11/PowerDNS/helm-cnf/powerdns_ns/params/params.yaml @@ -0,0 +1,16 @@ +vld: +- name: mgmtnet + vim-network-name: osm-ext +additionalParamsForVnf: +- member-vnf-index: powerdns + additionalParamsForKdu: + - kdu_name: powerdns + additionalParams: + # replicaCount: 2 + # service.loadBalancerIP: '172.21.251.X' # MetalLB IP Address + # service.type: NodePort + service: + type: NodePort + # loadBalancerIP: '172.21.251.X' # MetalLB IP Address + env: + TZ: "Europe/Athens" diff --git a/Hackfest_Demos/OSM-11/PowerDNS/helm-cnf/powerdns_ns/powerdns_nsd.yaml b/Hackfest_Demos/OSM-11/PowerDNS/helm-cnf/powerdns_ns/powerdns_nsd.yaml new file mode 100644 index 0000000000000000000000000000000000000000..31204d9b69748a9a3c0fc17e78d613fea2c67348 --- /dev/null +++ b/Hackfest_Demos/OSM-11/PowerDNS/helm-cnf/powerdns_ns/powerdns_nsd.yaml @@ -0,0 +1,22 @@ +nsd: + nsd: + - description: NS consisting of a single KNF powerdns_knf connected to mgmt network + designer: OSM + df: + - id: default-df + vnf-profile: + - id: powerdns + virtual-link-connectivity: + - constituent-cpd-id: + - constituent-base-element-id: powerdns + constituent-cpd-id: mgmt-ext + virtual-link-profile-id: mgmtnet + vnfd-id: powerdns_knf + id: powerdns_ns + name: powerdns_ns + version: '1.0' + virtual-link-desc: + - id: mgmtnet + mgmt-network: 'true' + vnfd-id: + - powerdns_knf diff --git a/Hackfest_Demos/OSM-11/PowerDNS/juju-cnf/Dockerfile b/Hackfest_Demos/OSM-11/PowerDNS/juju-cnf/Dockerfile new file mode 100644 index 0000000000000000000000000000000000000000..37d1e28067e0ac7add7f998a3c4de40b9e9675f4 --- /dev/null +++ b/Hackfest_Demos/OSM-11/PowerDNS/juju-cnf/Dockerfile @@ -0,0 +1,5 @@ +FROM psitrax/powerdns:4.4.1 + +LABEL maintainer=vnapostolop@gmail.com + +RUN apk add --update python3 py3-pip \ No newline at end of file diff --git a/Hackfest_Demos/OSM-11/PowerDNS/juju-cnf/README.md b/Hackfest_Demos/OSM-11/PowerDNS/juju-cnf/README.md new file mode 100644 index 0000000000000000000000000000000000000000..ce1fec3ca5d57e4f1d45aa5612c419cc6746a912 --- /dev/null +++ b/Hackfest_Demos/OSM-11/PowerDNS/juju-cnf/README.md @@ -0,0 +1,58 @@ +# Juju bundle for PowerDNS + +Developed for the purposes of `OSM-Hackfest-11` by Christos Aslanoglou, +Vasileios Nikolaos Apostolopoulos and Georgios Katsikas. + +This Juju bundle uses a PowerDNS image from `vapostolopoulos/powerdns` +dockerhub repo. It is basically `psitrax/powerdns:4.4.1` image with python3 +and py3-pip installed. + +# Day 1-2 OSM primitives +See `initial-config-primitive` in `powerdns_vnfd.yaml` for details. +``` +add-zone +add-domain + +delete-zone +delete-domain +``` + +# Build the charm +``` +cd path/to/hackfest-11/juju-cnf/powerdns_cnf/juju-bundles +./build-charm.sh +``` + +# Deploy bundle to OSM +``` +cd path/to/hackfest-11/juju-cnf +./deploy-ns.sh your-vim-name +``` + +# Test deployment +``` +$ K8S_NAMESPACE=$(osm ns-show powerdns-cnf-ns --literal | grep kdu-instance | awk '{ print $2 }') +$ LOADBALANCER_IP=$(kubectl -n ${K8S_NAMESPACE} get svc powerdns -o json | jq ".status.loadBalancer.ingress[0].ip" -r) +$ dig @${LOADBALANCER_IP} +tcp test.example.org +; <<>> DiG 9.11.3-1ubuntu1.15-Ubuntu <<>> @172.16.0.21 +tcp test.example.org +; (1 server found) +;; global options: +cmd +;; Got answer: +;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 25399 +;; flags: qr aa rd; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 1 +;; WARNING: recursion requested but not available + +;; OPT PSEUDOSECTION: +; EDNS: version: 0, flags:; udp: 1232 +;; QUESTION SECTION: +;test.example.org. IN A + +;; ANSWER SECTION: +test.example.org. 86400 IN A 192.0.5.4 ;; <--- You should this IP + +;; Query time: 2 msec +;; SERVER: 172.16.0.21#53(172.16.0.21) +;; WHEN: Thu Jun 17 13:58:03 UTC 2021 +;; MSG SIZE rcvd: 61 + +``` \ No newline at end of file diff --git a/Hackfest_Demos/OSM-11/PowerDNS/juju-cnf/deploy-ns.sh b/Hackfest_Demos/OSM-11/PowerDNS/juju-cnf/deploy-ns.sh new file mode 100755 index 0000000000000000000000000000000000000000..4d2dc1bf583461bd8ae2e920a0feffe51d8f4f83 --- /dev/null +++ b/Hackfest_Demos/OSM-11/PowerDNS/juju-cnf/deploy-ns.sh @@ -0,0 +1,20 @@ +#!/usr/bin/env bash +set -o errexit +set -o nounset +#set -o xtrace + +if [ $# -ne 1 ]; then + echo "Usage: $0 " + echo "Declare your VIM name (can be retrieved by 'osm vim-list')" + exit 1 +fi + +VIM=$1 + +osm nfpkg-create ./powerdns_cnf +osm nspkg-create ./powerdns_cnf_ns/ +osm ns-create \ + --ns_name powerdns-cnf-ns \ + --nsd_name powerdns_cnf_ns \ + --vim_account "${VIM}" \ + --config '{vld: [ {name: mgmtnet, vim-network-name: osm-ext} ] }' diff --git a/Hackfest_Demos/OSM-11/PowerDNS/juju-cnf/powerdns_cnf/juju-bundles/build-charm.sh b/Hackfest_Demos/OSM-11/PowerDNS/juju-cnf/powerdns_cnf/juju-bundles/build-charm.sh new file mode 100755 index 0000000000000000000000000000000000000000..82866bbf4ac0e971c8e1f64a42e51c31aeb55ef3 --- /dev/null +++ b/Hackfest_Demos/OSM-11/PowerDNS/juju-cnf/powerdns_cnf/juju-bundles/build-charm.sh @@ -0,0 +1,20 @@ +#!/usr/bin/env bash +set -o errexit +set -o nounset +#set -o xtrace + +if [ ! -x "$(command -v charmcraft)" ]; then + echo >&2 "You must have the charmcraft command to use this script." + exit 1 +fi + +pushd . +rm -rf ./charms/powerdns-operator +cd ./ops/powerdns-operator +charmcraft build -v +mkdir -p ../../charms +mv build ../../charms/powerdns-operator +popd + +echo "Done" + diff --git a/Hackfest_Demos/OSM-11/PowerDNS/juju-cnf/powerdns_cnf/juju-bundles/bundle.yaml b/Hackfest_Demos/OSM-11/PowerDNS/juju-cnf/powerdns_cnf/juju-bundles/bundle.yaml new file mode 100644 index 0000000000000000000000000000000000000000..b9663123e08caa52406f06a616bb914cc981b1dc --- /dev/null +++ b/Hackfest_Demos/OSM-11/PowerDNS/juju-cnf/powerdns_cnf/juju-bundles/bundle.yaml @@ -0,0 +1,33 @@ +description: PowerDNS Bundle +bundle: kubernetes +applications: + powerdns: + charm: ./charms/powerdns-operator + scale: 1 + mariadb-k8s: + charm: cs:~charmed-osm/mariadb-k8s + scale: 1 + options: + user: youruser + password: yourpass + database: yourdatabase + root_password: yourootpassword + mysql_port: "3306" + +# Source: https://discourse.charmhub.io/t/bundle-reference/1158 +# +# relations: +# +# States the relations to add between applications. Each relation consists of a +# pair of lines, where one line begins with two dashes and the other begins +# with a single dash. Each side of a relation (each line) has the format +# ':', where 'application' must also be represented +# under the 'applications' element. Including the endpoint is not strictly +# necessary as it might be determined automatically. However, it is best +# practice to do so. +# +relations: +- - mariadb-k8s:mysql + - powerdns:db + + diff --git a/Hackfest_Demos/OSM-11/PowerDNS/juju-cnf/powerdns_cnf/juju-bundles/ops/powerdns-operator/.flake8 b/Hackfest_Demos/OSM-11/PowerDNS/juju-cnf/powerdns_cnf/juju-bundles/ops/powerdns-operator/.flake8 new file mode 100644 index 0000000000000000000000000000000000000000..8ef84fcd43f3b7a46768c31b20f36cab48ffdfe0 --- /dev/null +++ b/Hackfest_Demos/OSM-11/PowerDNS/juju-cnf/powerdns_cnf/juju-bundles/ops/powerdns-operator/.flake8 @@ -0,0 +1,9 @@ +[flake8] +max-line-length = 99 +select: E,W,F,C,N +exclude: + venv + .git + build + dist + *.egg_info diff --git a/Hackfest_Demos/OSM-11/PowerDNS/juju-cnf/powerdns_cnf/juju-bundles/ops/powerdns-operator/.gitignore b/Hackfest_Demos/OSM-11/PowerDNS/juju-cnf/powerdns_cnf/juju-bundles/ops/powerdns-operator/.gitignore new file mode 100644 index 0000000000000000000000000000000000000000..2c3f0e5ed7915b3800370e2f37f7661e29df6742 --- /dev/null +++ b/Hackfest_Demos/OSM-11/PowerDNS/juju-cnf/powerdns_cnf/juju-bundles/ops/powerdns-operator/.gitignore @@ -0,0 +1,7 @@ +venv/ +build/ +*.charm + +.coverage +__pycache__/ +*.py[cod] diff --git a/Hackfest_Demos/OSM-11/PowerDNS/juju-cnf/powerdns_cnf/juju-bundles/ops/powerdns-operator/.jujuignore b/Hackfest_Demos/OSM-11/PowerDNS/juju-cnf/powerdns_cnf/juju-bundles/ops/powerdns-operator/.jujuignore new file mode 100644 index 0000000000000000000000000000000000000000..6ccd559eabeae93e4d23215fa450130fa9b37ace --- /dev/null +++ b/Hackfest_Demos/OSM-11/PowerDNS/juju-cnf/powerdns_cnf/juju-bundles/ops/powerdns-operator/.jujuignore @@ -0,0 +1,3 @@ +/venv +*.py[cod] +*.charm diff --git a/Hackfest_Demos/OSM-11/PowerDNS/juju-cnf/powerdns_cnf/juju-bundles/ops/powerdns-operator/LICENSE b/Hackfest_Demos/OSM-11/PowerDNS/juju-cnf/powerdns_cnf/juju-bundles/ops/powerdns-operator/LICENSE new file mode 100644 index 0000000000000000000000000000000000000000..d645695673349e3947e8e5ae42332d0ac3164cd7 --- /dev/null +++ b/Hackfest_Demos/OSM-11/PowerDNS/juju-cnf/powerdns_cnf/juju-bundles/ops/powerdns-operator/LICENSE @@ -0,0 +1,202 @@ + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/Hackfest_Demos/OSM-11/PowerDNS/juju-cnf/powerdns_cnf/juju-bundles/ops/powerdns-operator/README.md b/Hackfest_Demos/OSM-11/PowerDNS/juju-cnf/powerdns_cnf/juju-bundles/ops/powerdns-operator/README.md new file mode 100644 index 0000000000000000000000000000000000000000..c23e64407a0a325d64c5288f85b078a8d4de125f --- /dev/null +++ b/Hackfest_Demos/OSM-11/PowerDNS/juju-cnf/powerdns_cnf/juju-bundles/ops/powerdns-operator/README.md @@ -0,0 +1,36 @@ +# PowerDNS + +## Overview + +This is a Kubernetes Charm to deploy [PowerDNS](https://www.powerdns.com/). + +Available actions for this charm: +* Create DNS zones + `juju run-action powerdns/0 add-zone zone-name=example.org.` +* Add DNS address record (Domain-IP mapping) + `juju run-action powerdns/0 add-domain zone-name=example.org. subdomain=test. ip=192.168.1.254` +* Delete DNS zones + `juju run-action powerdns/0 delete-zone zone-name=example.org.` +* Delete a domain-IP mapping + `juju run-action powerdns/0 delete-domain zone-name=example.org. subdomain=test.` + +## Setup Juju & MicroK8s + +If you don't have MicroK8s and Juju installed executing the following commands: + +```bash +sudo snap install juju --classic +sudo snap install microk8s --classic +juju bootstrap microk8s +``` + +# Building & deploying + +```bash +git clone https://gitlab.ubitech.eu/nsit/nfv/osm/hackfest-11-powerdns.git +cd hackfest-11-powerdns/juju-cnf/powerdns_cnf/juju-bundles +./build-charm.sh + +juju add-model powerdns +juju deploy --verbose /path/to/bundle.yaml +``` diff --git a/Hackfest_Demos/OSM-11/PowerDNS/juju-cnf/powerdns_cnf/juju-bundles/ops/powerdns-operator/actions.yaml b/Hackfest_Demos/OSM-11/PowerDNS/juju-cnf/powerdns_cnf/juju-bundles/ops/powerdns-operator/actions.yaml new file mode 100644 index 0000000000000000000000000000000000000000..a477c9186f92738ef85034476057b34b9c18a36c --- /dev/null +++ b/Hackfest_Demos/OSM-11/PowerDNS/juju-cnf/powerdns_cnf/juju-bundles/ops/powerdns-operator/actions.yaml @@ -0,0 +1,42 @@ +# Copyright 2021 UBITECH Ltd. +# See LICENSE file for licensing details. +add-zone: + description: "Creates a zone" + params: + zone-name: + description: "The DNS Zone to be created" + type: string + default: "" +delete-zone: + description: "Deletes a zone, all attached metadata and rrsets" + params: + zone-name: + description: "The DNS Zone to be deleted" + type: string + default: "" +add-domain: + description: "Add a subdomain to an existing zone" + params: + zone-name: + description: "The DNS Zone of the domain to be added" + type: string + default: "" + subdomain: + description: "The DNS subdomain to be created" + type: string + default: "" + ip: + description: "The IP of the subdomain" + type: string + default: "" +delete-domain: + description: "Delete a domain from a zone" + params: + zone-name: + description: "The DNS Zone of the domain to be deleted" + type: string + default: "" + subdomain: + description: "The DNS subdomain to be deleted" + type: string + default: "" \ No newline at end of file diff --git a/Hackfest_Demos/OSM-11/PowerDNS/juju-cnf/powerdns_cnf/juju-bundles/ops/powerdns-operator/config.yaml b/Hackfest_Demos/OSM-11/PowerDNS/juju-cnf/powerdns_cnf/juju-bundles/ops/powerdns-operator/config.yaml new file mode 100644 index 0000000000000000000000000000000000000000..3843a3a849c3cc9e00e7740d81aabcfd9caa2311 --- /dev/null +++ b/Hackfest_Demos/OSM-11/PowerDNS/juju-cnf/powerdns_cnf/juju-bundles/ops/powerdns-operator/config.yaml @@ -0,0 +1,3 @@ +# Copyright 2021 UBITECH Ltd. +# See LICENSE file for licensing details. +options: {} diff --git a/Hackfest_Demos/OSM-11/PowerDNS/juju-cnf/powerdns_cnf/juju-bundles/ops/powerdns-operator/metadata.yaml b/Hackfest_Demos/OSM-11/PowerDNS/juju-cnf/powerdns_cnf/juju-bundles/ops/powerdns-operator/metadata.yaml new file mode 100644 index 0000000000000000000000000000000000000000..3228f6ca60010e912b63d68d008c9bc5eceb4911 --- /dev/null +++ b/Hackfest_Demos/OSM-11/PowerDNS/juju-cnf/powerdns_cnf/juju-bundles/ops/powerdns-operator/metadata.yaml @@ -0,0 +1,22 @@ +# Copyright 2021 UBITECH Ltd. +# See LICENSE file for licensing details. +name: powerdns +description: | + Kubernetes operator for PowerDNS +summary: | + PowerDNS is a DNS server program, written in C++ and licensed under the GPL. + It runs on most Unix derivatives. PowerDNS features a large number of different + backends ranging from simple BIND style zonefiles to relational databases and + load balancing/failover algorithms. + +series: + - kubernetes + +deployment: + type: stateless + service: loadbalancer + +requires: + db: + interface: mysql + limit: 1 diff --git a/Hackfest_Demos/OSM-11/PowerDNS/juju-cnf/powerdns_cnf/juju-bundles/ops/powerdns-operator/requirements-dev.txt b/Hackfest_Demos/OSM-11/PowerDNS/juju-cnf/powerdns_cnf/juju-bundles/ops/powerdns-operator/requirements-dev.txt new file mode 100644 index 0000000000000000000000000000000000000000..03761a1d989a61180df6be4b247423732cf5b5bc --- /dev/null +++ b/Hackfest_Demos/OSM-11/PowerDNS/juju-cnf/powerdns_cnf/juju-bundles/ops/powerdns-operator/requirements-dev.txt @@ -0,0 +1,4 @@ +-r requirements.txt +black +coverage +flake8 diff --git a/Hackfest_Demos/OSM-11/PowerDNS/juju-cnf/powerdns_cnf/juju-bundles/ops/powerdns-operator/requirements.txt b/Hackfest_Demos/OSM-11/PowerDNS/juju-cnf/powerdns_cnf/juju-bundles/ops/powerdns-operator/requirements.txt new file mode 100644 index 0000000000000000000000000000000000000000..6deb8f54fd85b34f9b3ac61a9274c187f2670025 --- /dev/null +++ b/Hackfest_Demos/OSM-11/PowerDNS/juju-cnf/powerdns_cnf/juju-bundles/ops/powerdns-operator/requirements.txt @@ -0,0 +1,4 @@ +cryptography +ops==1.1.0 +requests +git+https://github.com/charmed-osm/ops-lib-charmed-osm/@master diff --git a/Hackfest_Demos/OSM-11/PowerDNS/juju-cnf/powerdns_cnf/juju-bundles/ops/powerdns-operator/src/charm.py b/Hackfest_Demos/OSM-11/PowerDNS/juju-cnf/powerdns_cnf/juju-bundles/ops/powerdns-operator/src/charm.py new file mode 100755 index 0000000000000000000000000000000000000000..714a0cbb63121fae3faef78ec7da48e33bf13c2d --- /dev/null +++ b/Hackfest_Demos/OSM-11/PowerDNS/juju-cnf/powerdns_cnf/juju-bundles/ops/powerdns-operator/src/charm.py @@ -0,0 +1,196 @@ +#!/usr/bin/env python3 +# Copyright 2021 UBITECH Ltd. +# See LICENSE file for licensing details. +# +# Learn more at: https://juju.is/docs/sdk + +"""Charm the service. + +Refer to the following post for a quick-start guide that will help you +develop a new k8s charm using the Operator Framework: + + https://discourse.charmhub.io/t/4208 +""" +import json +import logging + +from ops.charm import CharmBase +from ops.main import main +from ops.model import ActiveStatus, BlockedStatus +from opslib.osm.interfaces.mysql import MysqlClient +import requests + +logger = logging.getLogger(__name__) + + +class PowerDNSCharm(CharmBase): + """Charm the service.""" + + log: logging.Logger = None + + def __init__(self, *args): + super().__init__(*args) + self.log = logging.getLogger("powerdns") + + self.powerdns_api_key = "changeme" + self.headers = {"X-API-Key": self.powerdns_api_key} + self.url = "http://localhost:8081/api/v1/servers/localhost/zones" + + self.mysql_client = MysqlClient(self, "db") + self.framework.observe(self.on["db"].relation_changed, self.configure_pod) + self.framework.observe(self.on["db"].relation_broken, self.configure_pod) + + self.framework.observe(self.on["add_zone"].action, self._on_add_zone_action) + self.framework.observe( + self.on["delete_zone"].action, self._on_delete_zone_action + ) + self.framework.observe(self.on["add_domain"].action, self._on_add_domain_action) + self.framework.observe( + self.on["delete_domain"].action, self._on_delete_domain_action + ) + + self.framework.observe(self.on.config_changed, self.configure_pod) + self.framework.observe(self.on.leader_elected, self.configure_pod) + + def _on_add_zone_action(self, event): + zone = event.params["zone-name"] + + self.log.info("Running add-zone action...") + + payload = { + "name": zone, + "kind": "Native", + "masters": [], + "nameservers": ["ns1.example.org."], + } + + r = requests.post(self.url, data=json.dumps(payload), headers=self.headers) + if r.status_code != 201: + self.log.info(r.status_code, r.text) + else: + self.log.info("Added zone {zone}") + + def _on_delete_zone_action(self, event): + zone = event.params["zone-name"] + + self.log.info("Running delete-zone action...") + + r = requests.delete(self.url + "/" + zone, headers=self.headers) + if r.status_code != 204: + self.log.info(r.status_code, r.text) + else: + self.log.info(f"Deleted zone {zone}") + + def _on_add_domain_action(self, event): + zone = event.params["zone-name"] + domain = event.params["subdomain"] + ip = event.params["ip"] + + self.log.info("Running add-domain action...") + + payload = { + "rrsets": [ + { + "name": domain + zone, + "type": "A", + "ttl": 86400, + "changetype": "REPLACE", + "records": [{"content": ip}], + } + ] + } + + r = requests.patch( + self.url + "/" + zone, data=json.dumps(payload), headers=self.headers + ) + if r.status_code != 204: + self.log.info(r.status_code, r.text) + else: + self.log.info(f"Added record of {domain}{zone} in {ip}") + + def _on_delete_domain_action(self, event): + zone = event.params["zone-name"] + domain = event.params["subdomain"] + + self.log.info("Running delete-domain action...") + + payload = { + "rrsets": [{"name": domain + zone, "type": "A", "changetype": "DELETE"}] + } + + r = requests.patch( + self.url + "/" + zone, data=json.dumps(payload), headers=self.headers + ) + if r.status_code != 204: + self.log.info(r.status_code, r.text) + else: + self.log.info(f"Deleted record of {domain} in zone {zone}") + + def configure_pod(self, _): + if self.mysql_client.is_missing_data_in_unit(): + self.unit.status = BlockedStatus("missing mysql relation") + return + + mysql_host = self.mysql_client.host + mysql_port = self.mysql_client.port + mysql_root_password = self.mysql_client.root_password + mysql_root_username = "root" + mysql_database = self.mysql_client.database + + self.model.pod.set_spec( + { + "version": 3, + "containers": [ + { + "name": "powerdns", + "image": "vapostolopoulos/powerdns:latest", + "ports": [ + { + "name": "powerdns-tcp", + "containerPort": 53, + "protocol": "TCP", + }, + { + "name": "powerdns-api", + "containerPort": 8081, + "protocol": "TCP", + }, + ], + "kubernetes": { + "readinessProbe": { + "httpGet": { + "path": "/api/v1/servers", + "port": "powerdns-api", + "httpHeaders": [ + { + "name": "X-API-Key", + "value": self.powerdns_api_key, + } + ], + } + } + }, + "envConfig": { + "MYSQL_HOST": mysql_host, + "MYSQL_PORT": mysql_port, + "MYSQL_USER": mysql_root_username, + "MYSQL_PASS": mysql_root_password, + "MYSQL_DB": mysql_database, + }, + "args": [ + "--cache-ttl=120", + "--allow-axfr-ips=127.0.0.1,123.1.2.3", + "--webserver-address=0.0.0.0", + "--webserver-allow-from=0.0.0.0/0,::/0", + "--api=yes", + "--api-key=" + self.powerdns_api_key, + ], + } + ], + } + ) + self.unit.status = ActiveStatus() + + +if __name__ == "__main__": + main(PowerDNSCharm) diff --git a/Hackfest_Demos/OSM-11/PowerDNS/juju-cnf/powerdns_cnf/juju-bundles/ops/powerdns-operator/tests/__init__.py b/Hackfest_Demos/OSM-11/PowerDNS/juju-cnf/powerdns_cnf/juju-bundles/ops/powerdns-operator/tests/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/Hackfest_Demos/OSM-11/PowerDNS/juju-cnf/powerdns_cnf/powerdns_vnfd.yaml b/Hackfest_Demos/OSM-11/PowerDNS/juju-cnf/powerdns_cnf/powerdns_vnfd.yaml new file mode 100644 index 0000000000000000000000000000000000000000..2623de444945b6d31e0412dfa807085da7f4cb53 --- /dev/null +++ b/Hackfest_Demos/OSM-11/PowerDNS/juju-cnf/powerdns_cnf/powerdns_vnfd.yaml @@ -0,0 +1,90 @@ +vnfd: + product-name: powerdns_cnf + version: "1.0" + provider: UBITECH Ltd. + description: | + K8s container deployment of PowerDNS + id: powerdns_cnf + mgmt-cp: mgmtnet-ext + ext-cpd: + - id: mgmtnet-ext + k8s-cluster-net: mgmtnet + kdu: + - name: powerdns-kdu + juju-bundle: bundle.yaml + k8s-cluster: + nets: + - id: mgmtnet + df: + - id: default-df + lcm-operations-configuration: + operate-vnf-op-config: + day1-2: + - id: powerdns-kdu + initial-config-primitive: + - seq: 0 + name: add-zone + parameter: + - name: application-name + data-type: STRING + value: powerdns + - name: zone-name + data-type: STRING + value: "example.org." + - seq: 1 + name: add-domain + parameter: + - name: application-name + data-type: STRING + value: powerdns + - name: zone-name + data-type: STRING + value: "example.org." + - name: subdomain + data-type: STRING + value: "test." + - name: ip + data-type: STRING + value: "192.0.5.4" + config-primitive: + - name: add-zone + parameter: + - name: application-name + data-type: STRING + default-value: powerdns + - name: zone-name + data-type: STRING + default-value: "" + - name: delete-zone + parameter: + - name: application-name + data-type: STRING + default-value: powerdns + - name: zone-name + data-type: STRING + default-value: "" + - name: add-domain + parameter: + - name: application-name + data-type: STRING + default-value: powerdns + - name: zone-name + data-type: STRING + default-value: "" + - name: subdomain + data-type: STRING + default-value: "" + - name: ip + data-type: STRING + default-value: "" + - name: delete-domain + parameter: + - name: application-name + data-type: STRING + default-value: powerdns + - name: zone-name + data-type: STRING + default-value: "" + - name: subdomain + data-type: STRING + default-value: "" \ No newline at end of file diff --git a/Hackfest_Demos/OSM-11/PowerDNS/juju-cnf/powerdns_cnf_ns/powerdns_cnf_nsd.yaml b/Hackfest_Demos/OSM-11/PowerDNS/juju-cnf/powerdns_cnf_ns/powerdns_cnf_nsd.yaml new file mode 100644 index 0000000000000000000000000000000000000000..1979a2193627cc8c1aff62fc2ad8ba70d854f6f6 --- /dev/null +++ b/Hackfest_Demos/OSM-11/PowerDNS/juju-cnf/powerdns_cnf_ns/powerdns_cnf_nsd.yaml @@ -0,0 +1,23 @@ +nsd: + nsd: + - description: NS with 1 KDU connected to the mgmtnet VL + designer: UBITECH Ltd. + df: + - id: default-df + vnf-profile: + - id: powerdns_cnf + virtual-link-connectivity: + - constituent-cpd-id: + - constituent-base-element-id: powerdns_cnf + constituent-cpd-id: mgmtnet-ext + virtual-link-profile-id: mgmtnet + vnfd-id: powerdns_cnf + id: powerdns_cnf_ns + name: powerdns_cnf_ns + version: '1.0' + virtual-link-desc: + - id: mgmtnet + mgmt-network: true + vim-network-name: mgmt + vnfd-id: + - powerdns_cnf