From 34fd3e0bfcaf5ae8b136cc02bb98adb45be9c8e7 Mon Sep 17 00:00:00 2001 From: Ratnopam Chakrabarti Date: Thu, 18 Jun 2020 16:56:30 -0400 Subject: [PATCH] Integrate openstack provider(capo) with airshipctl * add documentation for openstack provider (capo) * add manifests for openstack provider (capo) * add cluster templates for control plane and workers * add site definition to use openstack provider (capo) with control plane and workers Change-Id: I7158aa87f2ef044d0acca448e3b1c19f58416e22 --- docs/source/img/openstack-machines.png | Bin 0 -> 144455 bytes docs/source/index.rst | 1 + .../source/providers/cluster_api_openstack.md | 827 ++++++++++++++++++ .../capo/v0.3.1/certmanager/certificate.yaml | 24 + .../v0.3.1/certmanager/kustomization.yaml | 7 + .../v0.3.1/certmanager/kustomizeconfig.yaml | 19 + ...re.cluster.x-k8s.io_openstackclusters.yaml | 558 ++++++++++++ ...re.cluster.x-k8s.io_openstackmachines.yaml | 355 ++++++++ ...er.x-k8s.io_openstackmachinetemplates.yaml | 305 +++++++ .../capo/v0.3.1/crd/kustomization.yaml | 30 + .../capo/v0.3.1/crd/kustomizeconfig.yaml | 17 + .../cainjection_in_openstackclusters.yaml | 8 + .../cainjection_in_openstackmachines.yaml | 8 + ...njection_in_openstackmachinetemplates.yaml | 8 + .../patches/webhook_in_openstackclusters.yaml | 19 + .../patches/webhook_in_openstackmachines.yaml | 19 + .../webhook_in_openstackmachinetemplates.yaml | 19 + .../capo/v0.3.1/default/kustomization.yaml | 11 + .../manager_role_aggregation_patch.yaml | 15 + .../capo/v0.3.1/default/namespace.yaml | 4 + .../function/capo/v0.3.1/kustomization.yaml | 29 + .../capo/v0.3.1/manager/kustomization.yaml | 7 + .../function/capo/v0.3.1/manager/manager.yaml | 45 + .../manager/manager_auth_proxy_patch.yaml | 25 + .../v0.3.1/manager/manager_image_patch.yaml | 12 + .../v0.3.1/manager/manager_pull_policy.yaml | 11 + .../v0.3.1/patch_crd_webhook_namespace.yaml | 3 + .../capo/v0.3.1/rbac/auth_proxy_role.yaml | 13 + .../v0.3.1/rbac/auth_proxy_role_binding.yaml | 12 + .../capo/v0.3.1/rbac/auth_proxy_service.yaml | 18 + .../capo/v0.3.1/rbac/kustomization.yaml | 10 + .../v0.3.1/rbac/leader_election_role.yaml | 26 + .../rbac/leader_election_role_binding.yaml | 12 + manifests/function/capo/v0.3.1/rbac/role.yaml | 85 ++ .../capo/v0.3.1/rbac/role_binding.yaml | 12 + .../capo/v0.3.1/webhook/kustomization.yaml | 42 + .../capo/v0.3.1/webhook/kustomizeconfig.yaml | 27 + .../v0.3.1/webhook/manager_webhook_patch.yaml | 26 + .../capo/v0.3.1/webhook/manifests.yaml | 46 + .../function/capo/v0.3.1/webhook/service.yaml | 9 + .../webhook/webhookcainjection_patch.yaml | 16 + .../function/k8scontrol-capo/cluster.yaml | 50 ++ .../k8scontrol-capo/controlplane.yaml | 85 ++ .../k8scontrol-capo/kustomization.yaml | 5 + .../function/workers-capo/kustomization.yaml | 4 + manifests/function/workers-capo/workers.yaml | 72 ++ .../shared/clusterctl/clusterctl.yaml | 43 + .../shared/clusterctl/kustomization.yaml | 2 + .../cluster_clouds_yaml_patch.yaml | 8 + .../control_plane_config_patch.yaml | 24 + .../target/controlplane/control_plane_ip.json | 3 + .../controlplane/control_plane_ip_patch.yaml | 9 + .../control_plane_machine_count_patch.yaml | 7 + .../control_plane_machine_flavor_patch.yaml | 9 + .../target/controlplane/dns_servers.json | 3 + .../controlplane/external_network_id.json | 3 + .../target/controlplane/kustomization.yaml | 35 + .../target/controlplane/ssh_key_patch.yaml | 11 + .../target/initinfra/kustomization.yaml | 4 + .../target/workers/kustomization.yaml | 10 + .../workers/workers_cloud_conf_patch.yaml | 19 + .../workers/workers_machine_count_patch.yaml | 8 + .../workers/workers_machine_flavor_patch.yaml | 9 + .../target/workers/workers_ssh_key_patch.yaml | 12 + 64 files changed, 3175 insertions(+) create mode 100644 docs/source/img/openstack-machines.png create mode 100755 docs/source/providers/cluster_api_openstack.md create mode 100644 manifests/function/capo/v0.3.1/certmanager/certificate.yaml create mode 100644 manifests/function/capo/v0.3.1/certmanager/kustomization.yaml create mode 100644 manifests/function/capo/v0.3.1/certmanager/kustomizeconfig.yaml create mode 100644 manifests/function/capo/v0.3.1/crd/bases/infrastructure.cluster.x-k8s.io_openstackclusters.yaml create mode 100644 manifests/function/capo/v0.3.1/crd/bases/infrastructure.cluster.x-k8s.io_openstackmachines.yaml create mode 100644 manifests/function/capo/v0.3.1/crd/bases/infrastructure.cluster.x-k8s.io_openstackmachinetemplates.yaml create mode 100644 manifests/function/capo/v0.3.1/crd/kustomization.yaml create mode 100644 manifests/function/capo/v0.3.1/crd/kustomizeconfig.yaml create mode 100644 manifests/function/capo/v0.3.1/crd/patches/cainjection_in_openstackclusters.yaml create mode 100644 manifests/function/capo/v0.3.1/crd/patches/cainjection_in_openstackmachines.yaml create mode 100644 manifests/function/capo/v0.3.1/crd/patches/cainjection_in_openstackmachinetemplates.yaml create mode 100644 manifests/function/capo/v0.3.1/crd/patches/webhook_in_openstackclusters.yaml create mode 100644 manifests/function/capo/v0.3.1/crd/patches/webhook_in_openstackmachines.yaml create mode 100644 manifests/function/capo/v0.3.1/crd/patches/webhook_in_openstackmachinetemplates.yaml create mode 100644 manifests/function/capo/v0.3.1/default/kustomization.yaml create mode 100644 manifests/function/capo/v0.3.1/default/manager_role_aggregation_patch.yaml create mode 100644 manifests/function/capo/v0.3.1/default/namespace.yaml create mode 100644 manifests/function/capo/v0.3.1/kustomization.yaml create mode 100644 manifests/function/capo/v0.3.1/manager/kustomization.yaml create mode 100644 manifests/function/capo/v0.3.1/manager/manager.yaml create mode 100644 manifests/function/capo/v0.3.1/manager/manager_auth_proxy_patch.yaml create mode 100644 manifests/function/capo/v0.3.1/manager/manager_image_patch.yaml create mode 100644 manifests/function/capo/v0.3.1/manager/manager_pull_policy.yaml create mode 100644 manifests/function/capo/v0.3.1/patch_crd_webhook_namespace.yaml create mode 100644 manifests/function/capo/v0.3.1/rbac/auth_proxy_role.yaml create mode 100644 manifests/function/capo/v0.3.1/rbac/auth_proxy_role_binding.yaml create mode 100644 manifests/function/capo/v0.3.1/rbac/auth_proxy_service.yaml create mode 100644 manifests/function/capo/v0.3.1/rbac/kustomization.yaml create mode 100644 manifests/function/capo/v0.3.1/rbac/leader_election_role.yaml create mode 100644 manifests/function/capo/v0.3.1/rbac/leader_election_role_binding.yaml create mode 100644 manifests/function/capo/v0.3.1/rbac/role.yaml create mode 100644 manifests/function/capo/v0.3.1/rbac/role_binding.yaml create mode 100644 manifests/function/capo/v0.3.1/webhook/kustomization.yaml create mode 100644 manifests/function/capo/v0.3.1/webhook/kustomizeconfig.yaml create mode 100644 manifests/function/capo/v0.3.1/webhook/manager_webhook_patch.yaml create mode 100644 manifests/function/capo/v0.3.1/webhook/manifests.yaml create mode 100644 manifests/function/capo/v0.3.1/webhook/service.yaml create mode 100644 manifests/function/capo/v0.3.1/webhook/webhookcainjection_patch.yaml create mode 100644 manifests/function/k8scontrol-capo/cluster.yaml create mode 100644 manifests/function/k8scontrol-capo/controlplane.yaml create mode 100644 manifests/function/k8scontrol-capo/kustomization.yaml create mode 100644 manifests/function/workers-capo/kustomization.yaml create mode 100644 manifests/function/workers-capo/workers.yaml create mode 100755 manifests/site/openstack-test-site/shared/clusterctl/clusterctl.yaml create mode 100755 manifests/site/openstack-test-site/shared/clusterctl/kustomization.yaml create mode 100644 manifests/site/openstack-test-site/target/controlplane/cluster_clouds_yaml_patch.yaml create mode 100644 manifests/site/openstack-test-site/target/controlplane/control_plane_config_patch.yaml create mode 100644 manifests/site/openstack-test-site/target/controlplane/control_plane_ip.json create mode 100644 manifests/site/openstack-test-site/target/controlplane/control_plane_ip_patch.yaml create mode 100644 manifests/site/openstack-test-site/target/controlplane/control_plane_machine_count_patch.yaml create mode 100644 manifests/site/openstack-test-site/target/controlplane/control_plane_machine_flavor_patch.yaml create mode 100644 manifests/site/openstack-test-site/target/controlplane/dns_servers.json create mode 100644 manifests/site/openstack-test-site/target/controlplane/external_network_id.json create mode 100755 manifests/site/openstack-test-site/target/controlplane/kustomization.yaml create mode 100644 manifests/site/openstack-test-site/target/controlplane/ssh_key_patch.yaml create mode 100755 manifests/site/openstack-test-site/target/initinfra/kustomization.yaml create mode 100755 manifests/site/openstack-test-site/target/workers/kustomization.yaml create mode 100644 manifests/site/openstack-test-site/target/workers/workers_cloud_conf_patch.yaml create mode 100644 manifests/site/openstack-test-site/target/workers/workers_machine_count_patch.yaml create mode 100644 manifests/site/openstack-test-site/target/workers/workers_machine_flavor_patch.yaml create mode 100644 manifests/site/openstack-test-site/target/workers/workers_ssh_key_patch.yaml diff --git a/docs/source/img/openstack-machines.png b/docs/source/img/openstack-machines.png new file mode 100644 index 0000000000000000000000000000000000000000..f6df36ff6e2236fe1807f351065fdff2501741b6 GIT binary patch literal 144455 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%0DhUfX1CAcP#OHBeNl|p0B`JG%fTKFdG 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 Yd8lII^M2oMw;VdH}Vb+-@8xw z%dnTYdvGC5xh{+-zSTjM9t)iUP^E#pqZ(JLYFuaqSzyd0>*ic*9GsZycp^EF*L=OW zK~Y+M**)WPxfA6>V?f|$-15$^=k;uwX=f3vOepN9k1?6a6XdqxjppZVh{Fplsp9tl ztLJ%v)&8_I=6$W*|MfeI6z%!ACAjn0GS@K~7U;g;^$GnW z8j{~xiFg(Rb1fVFV}$L9kjvnQFW4eZ%^(iRxcL4Gvby@cnlRZ?j0TYxjA0p~gti0h zGv?FYQfKs(-x-ruq7fu;{$+rCx$R`D0jBN`DG34BdH0Ju(&|)GeuZ%)WW+s>QA=>f z)wrD=P*dV2mqmE8NFmbY7fGMK_X~#mQ#N0%j}IQE9*Shh&~{O0e#Z+tz11rjk_;I| zLFB!Q9Fi$s732ET+z0)e^^(WiYlQjLTOD<~M1IzERPdh%#VA7-#ddK;QlI3kj=9k^qBr)-&TxM zLul2LS8OQnsjWmLDt3zcka^lmVE)&>+KCX^4py)RC4pGTyYt&1p`NV}Qnp0ks^Dpc zMQkt6iLvFcpDKC_f!iu4ab4hk3EAySrhW#Wnp*CXF;C-zNod0Zn6BJR?Wut2eQT{mmb06 zaQ9BjRAlT{oRSC~{$c_sIf(aYd|n0toT=7n)-H1%_hjfrznp)M;GK{9UEOhQ$U)pZ zNITOTOIK?IFwoa6B<#=t-P*6+)l6hI$SLB zk&^}X!_^WTMYiue@n*+mEllOLbGeV~gpPC?~$`iNt?AH%VaaFK-T&`O9l@W%1YE6Pw)u zh4Gl=?Ow%DUCY0ss^OUFl+I+}ghGdU6UoeS9TR@2b5=(7qXSyr$+ZCR_CxD#yT&A+ zY?uW1N9RPqv9aV+xz_zx`MPl0gfotB@pI$+Yu8~@TT|IBz(^{Rvuad810XIrBkG65 z%5+82nkB@a08#>RDoQ!|fGGa`$adfE?Btrxd%?5ic5K;;^FV1U>4`~y1{Qyy*JeLL zO=kcvU^Yun6?*{wi^YC;b#*`<+H3MH?yaGRYYT~#QaQFqQI;9>2qkc(f?uYY;hQcC zPqeQ|YF|)&L;BHpidcW?g_!d>i&1;D;&ls9q(f722L*P7Fi9w*it0?_znu$tllVQY zq-^80cc0&0FHSyS(iq=wwf=Np!NhgJCU3?1r-9QW$Q|6%W5~|_ zM>(5uSV30u_{&@S{PN9@R-UWp^0A|4%5;A$@@b8)E9lbak&jkhJx+CtiYjmv^j7DY ze!?5{_;X0PmJ{L`&$C*WEwvgy-<7zq(;znwo|*slS7T&qTtYf>1K{Rl;67k9b#@O0 z{^}~{^ZVC{$QNV9!O^w|OD0l; z%l#uwf2%9!nZlCqwG=Tep5*t`#kIqU6XLYhNNLLG7qf|lg99vOtZ$&l%!+E2a_u%Q zW_LH{LOA{>)QK%>z9KzU18#+kBoaMT+v+bCVpI{+X;EtD-Ts-~s}n|Pxmsa~o3?pl z@`$W^72T|N_mX@9&J!94pqTr+G{)#F^;TwTw_Heu@|;jlk*@9HZfCuFVX4eyflNVH zrA{Cd*M`7C=%b~ViWu}K4?Yd=VDYrpzX1I%-6$Yd7PogbRM(nXSjYZ3x86eV;cx!Z zlPpocOVWpI+rbMq8~1$!B;Te-@RQdPavvxzkFiMFKO_n!FmTycAxQL3v%^}=c4r2TN5NcI7+oLYAG5j~AzHhyHkscKF_4Dr{ z{r+agA+XtTBHZ4hl!a!wEhZd*IYfJf$ewL``PWYT)J}ZX7psTMfsN*e9nj_*w9xZ_ zokL+86w|DXXf|A?z!P-#`#SUW*_d6fmj$HjFPKS<%prfDKmr7t^$80LOHjhgN^<({ za>J=h`^}4OqP_)i2uGV}w85RF&e)N4V>8lC@0IbR<(Ba-A)5|80aubOD-+oCRZ zW&9sTh={E%B^wwNYHJ2IDl&$%miDi0^8A0O5RS=Fm>N+Ghqn(;WJyu`O26E8i6{$b zU}5kc#MA_z=oBA1+1QA+0PDmkgM_xr)N5<~U|!*zHdbWPG+-K!cO-13srA+BY9(?3 ztu)Po%r7PUYvO_bw#7~5grXPY;#aIf0xNG=Q*bb{zZFYAn+<0Dpb(XMC3VfR?3uh_ zYE;e^B?H`RiMFt-w2kE0^@izbextjFuAEd9hQp&@huFn+eQrT!rjI$J!{KV}E(c~c zs9~dgeLw<0U2LiZDQ#wlge;m&cHQn@n6dbJ}^PI!sip<^q$1e!cfV7bz=4 z0w=*cWW|87g!IE(F3`imNTTD=)E8x~iEp#tq+ou5@*4(43e?p8p*o3l?l>g$ z$O8ITiZGLrtgX?7DJg;aTYV9mpGt4{nw^n;Pku_f;CKRL@Px&$_P>p9(BR1h?T{{7 z{V<$wNP|Np=^V-M%qe5mZWRFJ#~(Ux<3fLk&4JH0md@*$EI0Bd|XXuyN4` zaO)lo4Q7!q-Eqnli3VrPxFD&KKzI4YZ@3TVJ_vRsf?&oDOePpW+%qC!A6+&|Pk~Ae zj1<9(+g$73NXYagZH6+m8R4N~7THP3CfB?;z-PfWHA&@Kp& z^eX$*qR(#{I*~G;-`%c)deV0@?V(LDaxsMd*d9TL)KPSfY0GU+zb@kokF`-&^`-FH zlAz7c-Bfz-B%qIicT3*i`rs&Ix1}vThuaRod|YpU|9n#>ZUm##sG90~6x0mH{0*BW zhTM3kAWT3KB4s<#M^S;X?bOC9y$hMKdN3>fS)2bibz@-1C#@xHYmdc#x*&D9e zV6K1!gsf(9Mm(7M57_*9hZv0ry52JH4D@>$nxasl5Ibm_pw;=|Uln81moADS2@Qh= zpcI{+2|by#jfAGLugr&trDa{vj!rP=Rjzj>5PX>#nwENB$o8ROJvQX+%U_~|i9*CB zA{KXZ<09%f%4bJX{yZ=Eh(4ySEV3#S7%iOFhcO?%3Jhx>b=?^d+Ihxt-F*sc;I4f{ z;=euMGdcPq*kp5EokY~A``M^R!EgrCW``AsSI zIj_!ORm$uB@6(H#lEKgc-*s8n8*(|p>-3UVK+eZu*DiDCn*{&c6~xoH<_ESEb0aB3 zeC|t@=5>>jHzJDAgM;_uA+v$Mvw`he;V-?m%Y~j!PK@~9vCYMi&hf8T!^Sbj3T;qX zSy^k)OG6tQVOd^Eh9%p@q^6UYK@9a40I9LTDZYMgWYe@ z=C6_OSw3#dhwji$$o?ZDlrsL`@-m&0IW3$fc}mi<-a1ZJ;v~l^8{;)*Wlu;NUEA8q z+j=X?AImE$zMn{U6?Oitf}qAY=A)9j+Ahi2K6l&f-OPD~;XLCD(_=gC`vXR}*#*Vi zb%!tbawXP&`yrXQ&}47CBQASB>@(UDPI>} zK;V~Tpa)T?*qsfiIG$Y@MH%vbk8&*)s1X>Sj(o6p9fMM>FtwwoMm=N4)sN%<9c!y9j2rUx`o zgBr>JeJZ693%{^%F7Q z6E_r|(_Rjw&2PKe46v1ut45vkUjSwIkU2NSWzPS}i-BegFhHHSrz-v8DGHl&oWS7c zAsAemhEH=C>~Q`*JD#L4wf#oTmPC!`fc)SLisZtfbFuCXt)M7Jd7QH-{}l%H?z6tP z8JRpt&HngkoXP|xB}KtYjXh)7qde9+und`DZv+&I5ci)vK~G#lB(oj$X3*!(nkA#z z<-_FdNUn}2X~WA9z8MBFO_NYt!KBl^ivhEaDEC)zD}mjnl1^$ECj{x!b9}mfxW074;eRH}t@$`nq-^zqC(0d{ub(QB5GK%;i(LB`{nZeQ6#5XZ_I8V>6`#EMS#+Q*4>dUg^lP7s=Qi%m+U8j)S>>HKh~ zb7YHwe99(}K!-?8VJofu$kqD|p^!f2m9>@Y8h50O0r^@ba3gF7G*yrsUQ=Y z3^b4DYTNWbtNeV2L-F!tu_N4E0ISm>I@v;maF2qz1E^;tG9bQ!}y@O_T)Z4ZAcZF-#TQF+e`Ta@Zx zRSSBlIP5$fs<6!uO8eOsia`6lhET=Di&9uEI`VD+XTE%piXL>qu z^<5ac$m%q@6CAW;6uG7K*gnPER`eB12-OT_X8}JeH#1^JR}+>yjoD6|VvNQ%=4efW zoqo{-8s*p7AEPsL+E86+x8kPF?dC0x8p0Z4@UaIcfPG(-G*$`6#G+!P6?Deu=nyUJ z2Nl%t!a%7PE6i^`q97ME6(hFtfR0X#6D%-v<1)qLMeIa%P4RA=oZ?baBG%RjFBVEZ zvXKGFTKe-SVd^1Uu?D5=7o2{kv6G^MIb^(8o1gFc*MBcJke8IX(lf@cp8sG>n{LE( zbv=`1dz~Qf5%PfaO27=~-R@#%7UwiT>5>?tM)3w^V;~l9w9c13=Ier2v);9ZpwU4y zODhar#b)fzb66Y(Y?$7X^?+wXHzOmaQ^2{-^l3= zfHkjo`dx@^CS46k&hun}Pk>{N@S>Bo`!$-)8z@tYS=>@kFE|4wH15qjVCNsCb_f=JxiNVC?LRyIUVb zg+n-b9aBLEv%AY}9?bX|r?ozF=F8rt{>~drnHvp68INik!#&kB@esrE;$8_#b`w|u7o?WeboSG@>!ThnRu7aXGv72Va}HeCjO-cxOT z2hS!*sDs=w3vt0a3rn0Ag5Socda(H!BlLM31Dm@0S?{-FIz0% z3e>|s^L5QYC@WLZ;^82a1g!1zVm%fL32H@r1L9kzp;80n*~tR5VzI+(r6DddiQ#~% zuo=>k!`~PS$3tn1Q(a^wn?fU_g&AZK$g^S)2~H4K_!g~?+kw0T^Zf>eAj_VI>F{vm z-b85%c2%&z-l$aKL#0RdEl$<1TnOaEh5KHiaer+%Fc#V)UrZD)l6lE+Q&Cmi3&m?G zeK+QCJ_czyLoB z{LtIzCd>2lhSFN5)xRGbdUMy5al8G?hqPC0X95~Y$Pky}?$n4E+jd_U+u z9@YqO=Le0=JkeFz=JJwKfBWmjxGmX+h*1RxuL8x3gG9;p^{x%rE@jgY;o;~EMdD(S zA9v&(ctjI+Nt-zhUk81cI%L0-az?a!RH4e z(){W5$Ja&rA0YnfC?+{?@5wbWb_PF#c&h3oZ!)n0!4@2N(Zjf3aGTeucXyAN`AFRC zg$|k(IkYwf_Nhk$G}%>mcS@BUg|5v^&B+TUL_W$DZ3oo4JmEio{)J0g*r#Qx2?X@} z3x7E+@z`%ZpWH|k1P-E{z^v6cwUEwCiNxmOdth;to}TrbOohj?euw^@My7u7rJw}; zMqpz#uoH9n^*vZ#f!6LcfN2`GBj?5XEqDtTF_-AMNx@|6VOw2SAd-#@7MaUF0X|bX za?6pol$j(=Bi}dPCvJyJsS8;Joi5_bN2{_$8IbS)uk(d6`)y;l<+GCy)$mG8$D4nL zB9N@8rTPJPxPyZChBEPe%%?c^z1VM=p5bySW!a^gTk1;3utL}R}| zpM8BLoX@;wgAB^S<(XIMn%yI0`t-iAuOWu#dG~CqjF!YMD7z!D?=AAl6z&>*;(JKM z()*t4n3vyRjo&rJ+f~;`;8YBj@$%#%`1*J)dQp3XMCnQ++Iv1NLpmpv8oKIL_xmlY zx+Z9`Tr!o>)mBWsTFIp1HPZ8hLZWu=$);KDS%tkaruLUas?U;WZuPei6ym{JRgk@( z0GGpYqE#*@ZeDH|!bKZGGjoQ>Zc)i)s&ETKTx6>?E}_BS7d1c0^ZMpy7@!#^nCZZD zH|cnv#&9B7XjD`{js^$W{aOAbBRv@+v>#EF7(PCZNo~d|3+;oLqbFqG8NOom0UjoBMeV1Mf}W# zC`Iwm0XW;oLhlfdN-?5dRydxFinAqqYqD&dhIt&4yH=Y|bb4=dkGX`z;!aKw4_`7! zmpAXX%UkB15vc>RX(cGUd$LUT=;5P%`4ipB>dxAKpYCZ-c#_$tBNNIw^3%+1|Abnd zEMuetNP*diIN!Mt#y2E(1Y-u1StF=m!{z%kS5`t10m`o#{?)-3V~Fdtyy(Nr(SX=I ziL3yT8cF9^WEB(4lEEjZ%e#g=I&$flVPOsz`t{+eiv!N!6C%Q3<+3emSn_v{(A<`M z2#)FR%YUUWJov#})bo0HgH&L8p?L~~*4cz7I)2q~l*Zx~hvdk@XX$}(0e^P;-dSll z5Vhlcr|YMn9OIN%RFY+U#MN8k`?oxd4Na+En&E~=6iHHPnEA5n?^_lvm5Q|iMIaKfD)jFhor%8u2WJq4W0$!z1zrh=7b zNaY7oF54i&JlXyb@dp|Xqb4MRnL8mlqLB0**znCTg$?>tXppjg`;y4B1ZM(*Bqe&* zw4(@BZxqk9B5e27E8BOO3N2o)oEgG*Vc#LZ@Q+ciI&%T^>OH9d_L?fc?+N0M& zMAK?r8$UDy=FCUSGL{TiGx3Jg(?N82*R*S02zd>f2G^Bz%4#Vi;g^ht8Liq zY2wmRNI{c4{<}@o{X>vsqTBt0Z=8kwA*3AA6LhIIQB}is4HS%=-{PS0JlkGpI4yvo zCd@U3aQ6^>^T~y^$jIF>FSf0}aXHLL`B-5c$56w6F-V6#gmjGu?-s3Jq0Dx#2*H-9 zhJEV*=lC(ft^O~jutk^_=5^)_og(bQsj(bE4MP--AU8cUF4|s6P+s3rsPkjua)%FP zQ*KuZHubmXebN0(&j|WI_xS~2ik=>XX0NyRet;J%&3CL3HM2aAF}`8ESz(G}v8h-L z*1GFy*-F|P>%z{yu!2`tQPlY8ab>I<_hAG#eE_CKOIEhTiLY5+iN~JUsU3G%Lkj0~ewCS#lMJdcvP4V`}IHELvXR zITw{fl`Cvp*Z+Jf=@cKu=R4N@{zNkr|Cshnp~MUKVC$#h~iQ7F1gUkeL*W+R|DW z$-jE24AstPOrJg#;mTfY-cy0-lwefno~51m@hZDPn0VV*aB)cH+DjrC{_dwe=hX`n0I?D=F|i0V_^~P` z*%QD&EDF)o?vm1I&`pUYg;h*)<$l$GeJUz~(i2KXu!LlWeabH|I1&kz_QbSln4T63 zjr^P(GI)_i%-DRIde!+o<`}=BP2Q%b7zsV z7$1YFGv*>IC7SX}@~1N(l@v|(WO&N#xtNw2L+w()O)xNdXE0@#Dflzz&cnQU*)Wn( z#blJpEECnh$V8;4rNF4uaAD*sHT(mN&?pt0f#(uP5EVy#O=1FcN;y|X0=W@c>FJ0L z3*uhc;h?`7wE+P}Begvx5>uukH7OoR$!WOrt`$g$Ad7kAsrS{!lXq`i)B}Y?ry)Hh z86gHWx0)&>HjU~a1i=xBxa02S$RvZ3P4Kyd)CU+0P^);yY-zRcyiFWzJaR#;RU}=!f2e1i!>m2?{=8vVTkeXLwTzZOO`Cf z!dXeEEy#gY7C>zx0xHruS<)`2|7Lk&#(#TVF-}ypW7?wIaQmVK2vl0Ql?XPemh`7^ zlu};WtV(2NB%%AvPV6e{C;3Z7b#Xlu{$a>WjYen92^3Wikc`IR_`wQ9O-Ui0CJM!S zHloHEgsCYZs4A|4UnGrD14YR1(<3uI1tG!~e7>s$@tH|5H&sGlh(>ZkJo>5+k?~)R z^l8~-{D(s@qU>HMpX{3VFnw=GSB3c*n(lyVG&bAG_@FGsxee^Fk>7mi+xrq^W4~I(xLqHJ1!a|{vh`5azna^v*x%y+c z`vjH7U4AU@OkN;hX$(e8YzzYQEI;H`AcoP;$h|&78G)F}HzYiQn{Wy;Xx(K?e)RrE zsK_v7d6y|P2n!8ITtYHJ1N}gD0GuKj_nL!>>d~D7R@N$nhKG=$&x{Tc0>UGam>ADZ zO0fx?1iFXOPs_Cj_LPt9svi;+i(r2}H+g!si;uM*tyYD|05uu@B8a4NM2xJ|V(lk6 z+<;&*?A`sK3rc2;hv?v^a?6iQA>&qQu{{GK*y~imIy(H2l@N#!tpa{je#v1v7?cty zs0?B#tbxL^uWztPfN&Zs{QWiDYOnZEBc>*VU{Pu)qKqm81nLnNtc9OWg$%ahN>62f zUL9Wn6weppny9!ZH6*>%R)rEJqGMB$m6ikz)wR3*0>;QBghoaqYf2W9Bf_90*$4=a z!OU6HkrW$&D3V{TN{<*a_~T<@kPs8eO?vwWk|C6khFLSxVbm$1P#X~#WaJ(i$mAN# zT(}6+(&Hc}8Ds5m!s?MR5*Le;eTrA>=ZAoRfb)*Pz#wXy2JRuimEYMN12ZIh+FD^u zOhsHoFvJ!U1_W}XC8uF-dL(+A%28e0fG&jKzAxW{sfiJgsdcc`)S%Chjyo66M|5Ba z;sb0ro?lAFWeuFvjucWI60*PmY!%=ib&&YVDxON(h4sR#}XMqro> z1$iaVh9_dtk~^U8t;fm3IXHFlFevUW%VXxWW^!xcr{|P(~y=J zj*3G&(I^Z-R#G5p%j)1CodC^HDT)TEA5Kd~h`1A*_mv`X`V6Fmi&0tIgMsdT6d&G% z)1?k9STqmGF~OWZz?#H`^2)Ax4$t{`5ZG+COReQG8ShPbZY*w;dS!;c#bTNG0q`0z zI?bLAc(gk+md+U@H$Im>(756In{%+T7;ia_$M2=Y=fPKfc*o(nK003SaO|4rI-68r zc)OABk%@tGaMze0`aRY?&fy7r?m7$O4(B#%&q8j#+u1pP=fW~ZyN^s%oIOAP9v(L~ z0p`XXhGQf@9=Fl?amRJ-_~QM>$Orq)U8ZX+%t*SKA?!Kz)E_q)!hDbTWqI`6$Me@a z-`;6p?(B+t!i0XYC`J@QPnff5Itv$K25@oEzh}dbT=V>97uYEa$I9HZ;>&YSPgr(+q$+tX5pVfquyZDN9$Dok zHaT}z2P3ja4s3$kZnx8!fLkphCkyG`Bc~GqMP@azPr$MXXEEK|%6-X5A(L~H z9>XT~xz%3Cb%F5rQ?ibhYyS?j877AiYHm*Tw zQCZi8!0-?R`)g2DkOQ;G4+#lz=xeIL>6}9J4LcDUnS|`DL}*lOV*i}1Un;C0WNoaw zxdO+FYRUMYf>>@vqyQ}?x!88J4AU0OL%3=f`}Q9}ORp0FIyuR{67v>kq2N>*v|-W6 zN{>TF#WCcRbz|n76ztiYkJJUzk)0Zi+|BDy?hM2H%y1Os6eBn(6WZR>IND{vf?3lL zA!@|yYmXs&@f>J|+pzm&Ar*~m4v`jflJn#D+3-15z4$!z9f*vP+BDu+aT z{v_As;K?hSd}cDizP<0cH@oG~(6DgY9jRcVH_%-*f=ora{O8;_%=@U*a}3^n||{ zEH2M6X^elycoV{NV=|fQ_hvEv8Mjiq8BYf{QQXYs%J;Q5Cf8E_uap~2#%`pt<+;9G z4OzJ!?S+?lo(plkGyfd2Qayg4rn#p8KWe|}t^ zbf25NVAt8o2sTjwhXXbT+e}l!?Qz5Q74l4mTntZqEIpIT`1df8mBusqm<;uMGa3Jk zTcypM-$`CuZl*Hk``8nZ=2%8e#tH&WU1TwAV%Y+UR1!pl3)Snzt*(i4-bzouC=`LTpG+!_cqp9EwOX&S0gUQ<<{-hGyca&5HE-~KYSfe9DF%m zdpz>%ecTA#DCy+kxfby4;nu{v-}W3lJhu{)P44+Ncy;hD*Gnzq5#!&AqSFVkVaGwV z_w;kK52NYpXvFc8xoGX~hkaz%%nQ*_oQuk)F7ERjzL;#n$#dnfoiF?Q2Vk?=xpPk) z^YwgX@a1>?@s?%2K6q|rc=_j?^$2~2UAu{~!l)w>(G2jK_X2FV0um1*L`O0JX z>zkX<-a9nn?q(u{^;U*2yUB$|o<|=%JUl!+6OXU{mK~Fw8zGH6H!e3)Tj05JCaRuA zPe1+iZ_7?>$FYKLNMMIm8Hl8)Fldxg&cn{n-^FWhtwni76IxA9q-STs+)#+TygY1J zzXrRGRUtMy6x-IkgpYUSLmLt4c^qCw1@mIZU&8B}-JFmK*WRPTNjAD-&Ql&mcDoY;pC_nk&q zY7)d9O*m56jJWtn6mNeIjjDKvI&<*Kntce5iiE<^je?Ro_=iTqU$5adHSh&595)_9 zu@tch3FxcIM|pKM&J>hF9+ZTH$Uw*?V^07uCaS(!<6y!s5{a(p@a&p-rH7|6PQ=0D zn&{(7<7N1Aztm$QnT!J>OVhPXm*;*r;=yy{Fwt$7=hoy_X!lpUt?+&4t-;Mw&-~bN zVZ7`4Vs-A(quJrn>Bobhui>cc>EFD9*cD&L@+dQ&eQq5Ve(%S)D@}(to_`J6%-eAP z@;Rv3_aWBouf=2E`zA`?|1FL(P&|0(~Z*R)Om%s5aidO#-WvZok;;}o>zW;f=QyPXJeRCBA)tm6b=cRc3`%fVM zO=kRm4YD{DK^@XoEeEIcuyV&oGh46Hb>hf#l0CE3Zqr-=*Ybtav?sM~4|tykmv+;LF`tIy`Qp z<>f+Y_7(Sd-54Hs@9X3FJyDF#>!oldVK2l)#5>VxyIOg@5+-9FCu2GBjE}3)zub!4 z>}`OTlP}__^Gm6FR*s(Il8pc7e)*)UFMJ+upOp@+MumaO&G_GsD)6%(K8XFFY(?6N z2eFi{HJ#p!w>B5ztKWSLh0OR@--ah2yPb^x7x7kED1J)Dzq67V|0Vd&51&Nt>%T?+ zyze8VtpI0CYJBIR+ad2S!HaKf#PmBKpg1$eZTx%Sg=O;NFn8kJm!HEsAMe6|%MZ7I zwP}fZx6oQ#ydg8 zxSYu(Z>}W#c-WcVCP(A>*rzJbu07^8W1|##g)yU+yg2X!i@{V=Q-HT+F}swF|{Dnz8bCDSkcf z3>q6-pPuee6)_E?U zt5N1xBB!k1Woh!fwmcpLUwQc3uCM>wkFaP;5+oE5)-L?VH@*e+?cYa|BOgawWVmlp zHVSuqhy#sc{PMqkj>0#8gHqiJ{OIwOXxaULc%w8NzkKq3SW4F8`3!Ph+x&*Xw{lQ%w0@fbZRFqSgnareIN>$kU?w~SoO zFN2+rc4J(~eKceFoyZ9p&+m(c_b}djGkp2In471ZN5{#|eT8L=H%()O_vP2)=6%hV zKgMWxc0L|A#%MQB{(YsDDaF3xU}1dqVHa}qzBb;l9>(&2De?GH@W;xZ$FFx>-oL%W zjAc0Za=(@<$k^JC3_RWM8rFh zX}cP6jU^M~!4sDKy`(4quf6k`YsK<;2=RI{d*q{kp+=mA`I!bBIerWs9RrY&U^{ie zShaE~YWIGM7F9ZKo1clEq8-@Zti#<)roqvgi_Iq*aQj`iqhiPV7*1IUeNQ#&hUHkX zU@C+|P1v&IIFe^BL~2|( zZ#>}{V@=$QH@wHq``T!K?EFGuN8>9^W4VnU8+`d=c-+1H`%0&;@GQ(&_aDtz_a7_& zzS7_eZ+FjcUtxWP_vOYIomQ4lHUZ(wKf5-%tVf@F@VI+lznEVSzQTIa!`ytu+$J|H9<11dq=(s)c`MT#==@=^?my(yU;_%@4?aLp7xwEvhzwBU!KRd)?vCkC% zqvH{@cXqopDkTLtwSFu6M&GR6wg%z%ks9 z-eCa@It`rGLG%t<;pgWEQ*S$<@Po)l<0-ss~Q4KEWsJUl!+JUl!%AH2cOGn!jfCT>~d-ve*(@r(s8 z8$3KbJUl!+JU1S^vClIWx4LZH^2Wah-q7Q@5WIZw@bK{P@bK_VUU-9_=R)xE;pW^I z|8H@aKzI%wp3z)u`Ec4DBfrMR>2QwxnjF|27fEd zt>}QsY9Dc#So(Sf(AY5u>o_JM80P)~6x8>O+kby|A8NXWV4GwU7&jXZyA2krZ9*nm zT#n0&#o=_0y1xr1(;)f>hPZ3Ka5}w1xG-!sVQ|Pq?!Nuo?e;ORjmGJ4jN9+!Kt03A zuZzRdVy8N?+327=uzWbim_&0p*!4@8VB_K8;kik<+IkqzjSnv$V8F1?@|$N2 z_$A*rCuMs#;FWcs;P~;AIGuYMr%s>3>6{##Jb4tS@+uJ=mjJCo3ZZcP^*<4^V(;$6 zvm1*rJ0lz#y1y@aYU}XMu{LBS1VSYfkGM`0E)<+DK|#9>QK34>#TTC=Y%VUtKMyuw zc49D8a>UN7m!>1J#I*jet_-Tb9N{Z(9|$ks9~~ z86gvoU*4Sdetf#^5VSfyG)g(wKI)5(WAmPaC@v_2*`-2|zXoEFTLv5!6Hf0x4u?bq zjap7^52!6YgZ)R2qaf!voZ2WDwF-#5+N8tMhm(g+!7NllM`1)P&;=+zc^J)uQW*3~ zh(r@R|J~PKhmL_^DCA?M!-cNSP7GO`kV(a`n)*;(RfVROR&Gr zP5r2^t4AC8k;oK~QXO1MzjSqQ!D4lAW#~zXX`l-o-9u0)Sl#(9+kxIr^b8I|E@geI zZ$JHgJ?QNpfL!J~9*50}p6+f8yM&OE?0Cw;ZZV^~w-0tFIGMWsWpqAl@*F|o0TiH<=u9SL#aXeiA?WuF{V62l>tT%K_~T2_wk&c$=POR%@39brLw_$kEb zY;DI|+Y9jF(JB;mnvv=+$IiV)c=vPz98wvwBK=TQQj0ftm!hDd9c48=a5;c|$BXf4 zK_^UP_)iJ*BZKUmf^0DlVb8HjY&>0uvbI6Q2W!Y!aN@*?8f?jLKwe!Bf`YZsNQ5|j zrU9+pz1Wu5fTE^;=>1d>lj8l_);yfhGsB;q*)B(4244|{C4~30AsO=bpOfH5(EJE3_LhLn5up&7a z5>n&~8@o|YetS(eXjNnsI2@>IAArSVLKTG@vN@rVOE{x%*gTA;u0gc-4+C_rAS24V zr0q64`i6!%ql78Q4!fOGnr&neI9yJcEq3m=fWor)*ppTVDcbC5GaEFw7VC=1hc>%$plZvHGnw zXtqkAh7A?P6_5mnBS^2Ny0GA#fBhZry}K8|$?1rSFk-N)7Highh}s@9ntDocpu8I? z8Hvy-WM}KhF<66F|Mo5hl@UmdCwU_Ix)2}#?KjBp4@Y)t7#WunH*wb6T!W8a|09mJ z+L4)*NOJkb$(Ej$a=iNT+o-W9kQyC=0XqMD!v-8XU4W{pB7FA28WgoiFmqZGRC0HC zt9bzX*1wL`pC7=P<2zB*CPGR=6qMA?uBV)S{_cx7+9E{~)ss{rLQCO(yz=^LY~Q#A zr(5O7N~ZFqw&_jI*7aDu`eW=pbO7bOE~LeVLv~*O>O#Sx?Rfu_%{aVu9hzksh!53K z|8=f^bJ~WmbKM$j*|{4#kK{oS9EA|-x14qtoXjtQKofuvqn7IfCIfbx z3HwgegDMspk~{AStkG0ewV;Uly&#fmALDUFC!~03E|=4h=_yLnqxA@m2*hv~DS~Y_ghcpZUc5gU|89fFX}4nQ-aH(t=|xMw1)VLO z@C(qPvAP~>57(fv-;8EbB3rC3B!y}4;U`D2v!)Z(?Sm*RYr%k6h6D`ZwIg+CGy&67 z{jhiKF>Gz>MP1i0V)SC{KT(X$Cz^1wrX7u>gocOvLriJgRcFDyvtpngdGhac*hxXp z!TJLw*iqDiLq*N#v%5%{_d|C@9g4&%ERQ#$_+&BuvZWB8pRC3H{Cb4N1R`j-7vFm2 z5T&&lf8SPuz2%*lokry$cHzMBGx*cm(|Bo530f&1X%ruu81S^n+OjJA_d6$`4mBb| zuRv{ODPG@Dh@8S29Ivj!?_N5L=l4}YtX3mASc7AS4&#OO1$b%wY5e+=d!D;~*+!L)i0nF64>92vM8ytG{l;&)1&Bu9KzMnb(Dg za0C2R*H$Ud`}9q`zO5LUX|WIuHQ_JM{|iH849hx>Q+ZY6$kxyC>U(P;h)P0yus`y) zt>fe*DlraXy9s~$-``+3Djn6UU&Ox7K78=Yr|`GU2cQaxMYO?!XMXi_Y}i`@RcJi= z3XkAOy#omm{^+SXj@2J*MMz=-G+qWdIq; zKu8+Nu0LlKF&vcNk3ZN6UHmjmO$o%-*H)utnA%fAH5vvT2-IsZ&{l<`r;1?=3C6*- zuc2%}hrW&i*btbdJII(>jb{{x|%1#@i**&~gIWVKMuz=)4Acvar>Z0@F z%5p%WhOMU=pS}7oytVFA3YNbTiOWg|#m{jTb&V3PWNx7G%XktJNVi zG6rcG*+`3#VB5AMNLz9@=4Qll1~sE8e*>O>XA5SpcnG)8O~d|AKEyy!7LvpL&X&Qo z=Jnry3%~uxCg@WZU{O{ykc5OXIUygLOOUVI7RD;6VMuY+eQX0Wpm&%XE( z^l5XjVr~%DzwkZ~Hx&sXhO_zTZZ4sA_6{VWQ?MXA2x~rAhln||sGX@G8X0pBefSFA z-JFkJ%eO;|898K1xVN9?E-V!^aDnA^*7GQSG(Ny*TWu{{}905}|dc>cW{ zD5>4V8PyPvktSiXq2)^w|d0`o7iZs ztwdQxB^sKV(Zg0esWp&OUwXOfF>k=#*w`!@uUfuOAkd2$`{=Se#DA zEh)JR;sUuR><`b0M!}gn^a@q@`Gd3Y#F9jas55bC)L546kH{c@{B%(gw6b%P6Komr zt`qf0%1Xeq-&u$sFHV5dJdDrxl*1Jggg<|KG5+VyB;*|~M^Q^ZTviLZHG$-J37*U{ z;7EQ0M3K?>c6I7A8PVB7fMRRp6R_|-XcOP4VeSi8AhRL9N{XjJahHWEv z1tP+X2$R@QP}>Kq&5rzIHLwR85o;9Vr5&w!=Z_C!|IcRNv#q(vX&!*XY{#h+XB-wfnQM z=7nca)YXahx-yg$RbZF~W{1s!oKwe8+dqWXg5!Am)tyM5y%19kLwINXMzon+NJxl4 zNMsaZ!U9lv`UH*@G*DOv`dUhGaQ_i>nN8eMWN&o-;aGIXd@`ch$`iK<*xA_yu~LuZ zgh+}n77CdKRppgjI$SO}mfyJ&i7`f!CF)q5ZVuT)9~yc2srejn>TKZx?0cI^20GkkKOkc=fO8jBC%op;uuoh>DoI#6443I`AD z#HO`xVa>YTFqx?g_HV;GZ>__J>(*iI2k&6Z=EEdc=l0!j*?aNvTmQmq_85j5-Nt{K=F$#Ka{bH8}#u z)_(}a^oQ~IJ#(N|o?A5#oVF7Gcergpyt_#Gn z8A@(xJzFv3aGXFV6m5VTA)=K>D zFaLw(Q=-W5Ki6@z)f`8Erya|e&c>W24`Q0S8(Tlg!;tA*Jw#7kh;KacZQQ+V32vwU zt+}8W-DWE?=iY}OeEmV(wsZ;ZnwJerLk(KGdN{@Ndf{|far9U*{`lTuJhQ731A`U} zI|bC|^x?TrPvZAv68G^c+CRDc#z|QZRGAVJ|ZP>ki9S-E=W7pv`+}0_e0~v+F3s!HH##ot`|u_F>7VbRzIR|m z9~i=hb?;#9j^h}jF?J%kQkiM5DZ&SDzJw3feTa`g`WS21etSvFg%r*)tIS18oBO@WiNHn1f2YZTsp&!7`}3MmBlNJN z(IvpLg()xy9BA%o!>+BNxLF*3+H zaP)W?-q=})mv)w-Yp9!)OF5zg-C<%f<1i~kfo`h+bK(NH_v`&4gApbJs=J0@qW*Zr z%n0sjy;>)R%j#b8-fbr1hKyoLJU5dc8>EATdW)i(0mP+*!k_$$6w zppjABLO9`)EAfqZJyeutgII?QBv80&rdW!8=^*YTOTRa!)Wapq+_~QVF@xiPMEcm@_RBMy(9XzmkRo%E3VQAR5d9EQvE9M5n+)x*n~OUYAal z$tpX}y|Ccoep$>Sgs0BHs+Ftom9PE)k**;eF6yMKp69V6kW8@&8Jl?s0ckUF&-Z_T zC+?bt*5-Qj+vJ#%nSijQB+N{Wfzat7qhur;#l&8v@U;?Z>6gBX`<7-yCZzVnr4EQq ziiW+j6q~nf$HAk=QD0sMtJ4IRK!)%9_&@Q;!bAutEzCEIad^N2k=#hK?0y38a#=Ar zJVe*eCIABN-R@zWKDYtzezXtMzWsfC{h_&VkSy9Lp)74qO0$(36$@n-3_}w?6VLr~ zHD3PBY;0J&1{HO6c>l$B(3iLj|MSe>@ZBskUVG&&6f}38-IP+K2*ZrnKpfncOR_YK zf>Zf$4jU00s6*=Q-^3g5{2!7+bX?!zi>Y6K2J2V<3n@kcT%$G|9BAH$HxD-8>rbwL zPJ90A8B&D`I<*?@rG@D!|?5e}97{3Z3*1`!^6dNtmA_CFA90F|k`e9hG- zQ6-8)uucn^RE`jTO7GE9lBaWqKxIxjI!g2L{9k^C`yYG+fB9e=$*beMrNTY+ja1)p zi1If;q13})B|v>+6C7R}9froIVZr=tm|Ao3%HKC3dir$uX_QFIUWkQLQ=!-D(B9sJ zE-0W@^Z@X>8VCosb8};bfT5YPb;$F<&RIGyx)xeVH*m{n^D>7HsY&F zYOtlMADIyb7}%=;l=g;(R#f#mv3yzt_3IiKloA9-2V>QOSOihuOwEgD5;E9z06FBhg~KVRE~o+XATxVf2H(Y0rwp%Oh-DH2jrku`N1 zB11%ItgYi-tGkd$dh5&=(wmQd{2}%pJcKv?`V5|XeGQ76d$~5^u=L}=rnm9@KmLw) zH?WD@VKmni;vn_M1H*0uv$?tuMWt2TCaT3pKE=E5zKi!h+KBS{j!XM05zi$cKwZIp zy!G<4`1tTCn5{M%cZZRG>KING)snt?<(pHFM{dSTW91p_I(ib_76HT(38Wz1b>D96 zJa`6XuSx$afoVP#3!B8HF@MBuvcMbv6UamfCC{~h>WVeTG4w+2{XBMg0u)DqSWE`2 z05y$++$K)WZW9?)LPV-1NJ)&wBTG`SI6Vxi-gfNBYl4Nz5qER;I)H=>boNw;jI16r zx-9MuqnN?v8Zq_y`v=j~)sLF?emI13uwB7D129{5WTTEpME(b?Y)5n#EH*RDGQ1d0r;P>#I~Okt&ED4^Xzs+pGof-@BdMX{XNxkp z@@Jc0feb)OBgMg<^lG@h0|ZFVO2W66M&ZDbGx*Vqd+?nX_Fzw)85yzuu$s&$K2(7! zGDhYFXkoQE5vW$Umk+ZtrgJkh!YDB!FF}w{+1SaCovz!-T?i}pG+$2!23xu%V*4CW zAhX>{WliZ~WkbPLIw_QtriqZ5ONR0zp#h9rS|+0UmXJYA<>#=<5E>Q(y-WhJ%z!|V z8l9bHN-p`K0%eAmNJ!VHUYQYXwb&4uo&=dpN=BT=2qoi=EsdiAkr`5KT0zW~$5A%L zA_*j9m`hxCy!qe%g;`j{z1tZ2@jy7>$OiViZ->(lxq2 zRkVbYFES?S{!B)hjI%NoQMz0<6aD5ShVDsaOqX(xY{M)6dI7Jzw*j3))D~O=s3^}z zgFua?v*RI`QN0R8+>>cm-y$juF&(UK1ZsawpE(0cg&cu%zKxLJ9u(JAq0MfB(%g(A z`*-6^e;E8DWa#eeLGJOr*t~fQ_Ma-itQB)$tH?uJuL-4vh0w&uBS^0pF<_mru}MRg z)Gi3M{W+i@J|R+?!$Dg0aBKCAF%oij9-lDNg8a~etN>6q>L9OrO}{~ zxD9g3Cs(yhDQ9vqQqNo&uzfYSGdDeK6F-+8U;EBe_|qT%0BP}dytT6!gTv>PLI-Q; zLMgZOl7(f_IM^m9UJ;476^^R(dYXRoi!a1{`%|o z^wdH9_K_3SaQGYW?+?wyPZz~df8m0d+Ddt2FZ?wM+&&{7OH)F)eNdbh6ZYrUAu2fx z^J5HD2JXJ3bD)nTO9s74#>rVzeH-={wL+&*qs?liYu=K?Gg&zD)+^|b`#K(c^d9uJ zl;cdtAgm4>);|BA_@rBfAOGUl_|;GEK+%EY$Xt0JQc_}Y*Y{Q-S~ZB`l5$8QqS3K^ zGmdrl!s6`4Cz}ePG6bMLXEQ$8R)WPVzl5)RWf9)|!s(cIjO z*49?Ews)YTy$enWwN)|6B^^N#Y&Otx-b9@Tk8XS^`tiz zkaQs%w!Z%wK3cZ{J9h5Er)yusnmuPwedZwEUcC-gt!#q8ik+XnhaHE={pc3FzveBx z`~C-b^`9@`pYLo$XFv57BlqB$NN5bu84(=cEv#668=iXRW$N<=xfp8>e}czWtiT-)eH$NB zJzH#Fl&#CfVj6;3ti|+23vuUNcVgwLdl08{;ovd45B1%<*RRFSV-*-Cowc)cH{N>d zV+;;f2itV8_ag$%~w9buAOV~>;Lyl{NJ1FNCzT0BU$X~ z?4hxd@?NwDYc}q{>ev5{KmF->oT_Nx^aZD55PLSS!C(IJJhpD#iuc!TM-S;wS6fD} z&!~8lb2%Ly&$Y)!9f?Rv#=#eqLjkvBk9%h2t-W3*LK+zFnG=t?lNI>%WEI}oU4o#b zNF*u6*ms}=M{7G{;~}O105mH}L_t*0)a@i=L=2r;2B}U4rNEBUjRTl9B?`{LLF~+} z$F`%DXdQNv5h~_3U6VL0I8oDsIdf9+8K#bI+060k* zIbG3?{E9{tbq^vtIshUv*x1B|pV1%R`_e4@;p_A9#PSpv#V#B#Y(aTzABwBmAdo4L z5<;dk`DGIeU0uD93FVlR9*ziw6xFo@+$03MA@kyS-;q5jWt;LDwSLg+BxKwNVQFRr zOx4vmQq+$XOSAEh?=8hk-(P~I(OSf%L?F=BkKcY&jG40%p_B=rk&E!zfl~AiSuoht zhYqO}F*+5cn~Z#RGj<>P!|vlgBdBw>I21?@lHzo6J@*=cxuO%N=~B2}4~58uUb}lT zq`tfp^+RlOVnW2`l3=Uq8=AYhry92Yesnerz-AGW?De9xr3%9|06QHWs2^-XaHxiU zTgkAsy7OwUKx>_gYX>fuldidqF*b?B%7aZPxVTvkZZ?JnjX`viY_KBh>1;=v#ljiu zT7v<8e)^G}>d%z`D@``pz-TNfM(dCfvlq_C%kH4gaPEopFew=wn7?8XRLU=I z%4izsK|@O`jLBK}#uMK~MxX_`$4;Vi`06VNV?(vU<%495@+vV>-8+X#MBI7OXrypx zRV07s`c@&tNK2oAr1%tMP02!r7C2K-&pn;Iwl;k zQWu6G#p8Ep!rIV_6J?Fasp*D;+D}DJ2|g?D=fUZ()%fpb9n~T9A z>fcvyL-?YfVeLns;D;*|_{VD-5Ez{aX>S`U8aiR2F)ly99Z@M+sM+%#y5gU})BpWH z`027}96opub)ADWwq4DMl3NuQ%)=tg_{tA4efSjq^sjB`A9O!NVv|Dx(we^e!~a3h zBj3VLe(@OUKl&Fw$Zvqd(u|L`A3|8>ZTQBwzKyOUo3Qg}HG0ao;OS>JWAnfjZSjXso8@rrpqvm<#!}i27^6K*uHrWD%$(d zbm%?&?X3+cCLO5w@K*e5_2=A1nWy)z$0ro`(PO8v`NNm-*T21k#_s-+5%B848~<0C zE9v}rt{$?W1Q^KB_+;G&c=OFS@%GzqbI0n{tMTqzZ{o!1a)` z4Cw7M!=lpQJ9lJ2PlKdht03jxgxa=VC?g_q*VJ&R!~Ah?b|gBlpqbd2P|Z~ zIJnIRL-aC)#YAIqq91Cz1|cCgKeZf2Qgmes8NReE4Qet-3u`)XrnVdXE+Ot;nSo$3 zg9@tJQQYpt$|cE&*DH|_6^IC>lv@PuXVfD-Ld$*1Ej2z8QZf)bEmp+F1t3%-A!7x| zT#|tY(hb<1TZc`@nqZ8H#Qm9pq=+aH8>r!wTtBT6!G0VKlc+=C+Rc>DklYX){z-0 zSQ@Ls``gaorH!YMHzdb>OQT82S0Kz^jR-mv?1{EYk7bd1)Jf&|&Vop&$?zwO6sn;v zys+sEp5Aa8GiD@WD&3E*B#=qSh@lKJn^R2T*}%Y=tfa>b4LI?@6AKW~+=f4{KZM_H zC`Taqbr@9m^{O~**jkF`KRt}K`K{2B(PPw6dD6YEB`GVG!GEX(8^4#zNr zG7%Y5YIKz6;ng=*GBPsQlX13$-t*Lz z^3N)rx-Y+gaM+uxaHOOXQ)i{1zv3X)tzVBFd-7o;#m^;@V&%8LgCG3h$9UxKWl+o9 zo87TV9%cwLJD0^Nmf28B20>XvE6R@^LXR{Ycildn6kpFf?#v@Q+{#%@#(ccd58vprk-$1CIWW*^)Y~pv2M-Zaa;;CQG#`+hYMYSRj*;C?3=G{-6Iaq&Bf80BJyD-q(Lv8+i zWs{rWpufxq!)`uXy+QP2l77UPm92#bT$z(+%g&7(6O(Zu*q2(H)F%74LGTfaKJ|L;a1C?undcF*CPwix@{AV6iuCFR9iu}hH(M} z2<}dC_oBgFOM&86ptN{#*WgmTNU%HNiB-G_XSZJ{CCi)MQOhuLoaih%T>8FRzA~ z{>oV~E3S_NI<``g`vduA2+BGog~@#6wN`T4Ez$a!Wvhh}$x~3$^7;NKTUNWi6(z)E zC6>BI`MHbgOePEZjh-@pQ}EhT!hTGY@ztSuWM&A!2+zZDH6&!hgB*7$Z2RxApp)aV z2iDIX1iz<;n|z-K^5e1(E)*|CkovQGlySrZubo`qiz#H>?P+ffziJPuPeQy%NQE_@ zhxx?+Od$hiTa+ezT>M~)EW$B%u>f!o7hugn9_sf4={LsLW9#Iz-`75r%gqE7Qf837 z=X2l>b=TFJj0(&YS9Swvk5*$Hl-238%#(-_28dh=cT)U;@-&kow4isetU}aWFbkCG zLSpK*`*v&^J28G0ypCG!ODzh#d9#GFy%F$NU;M?)v+#WX!{@*5RxtD9g4n$7`~EaBHQFIh|8YFS5}atT>Ex{nm79~NhRQq3Py+$YXVUB&7(aW5lAbf zg#79b4;(U91VUjY1bi1*=Vd@MY({a7BPZhx=J`?^SlMPQ63~W^uhWxW62>4%M>@*i zOIPA|#QLnuh8wCEejEncS8m3Q$LuF){7xT}`X&$O-31*$kfp30fT!r97Iz+MN+(Nx zXL|-Mud^4g6Gz6gZ%&BU2|ABN;K(HpO#wHI)?zVhq*>6?;w5NcgN=1is59`C?}~$& zyCOMMjA;AIw2qSSDS~(k@pZoAm(_GD0q4Q$3T7TE2*yHi2RDRkbX{+GS|{=+D<>lr z6f|Yd@L0iA7h~PT&u&@tvyzIBoRXpJ*q5^x5H;HO^Yt$tcK)~>VFc-I2cgcJl5Q}Xyup9~Bg)6-MY2z>$Tqf23{z5o;t4Jm zSq2{80bqu&A+M4*Zj=hxRfey4a%_8D)pnyXov-lEPXKgElD6w7*=+M7(_>H1P~rjD z;SKuzvO`9|%9_Dzv4i8i^`<9YpNPb4K_ZJ_!+oW)WYK%AcT17i%dXaI&&aF1f+0Ka z5WlOSzRD7C&eYbQ4L+X}P%~;mYWOm4r~Q5__&Wy6gj8tmx}y%c2@i^b#qjph{zq1Y zU&=xGr#6JT*ISi?9gq)jY{m5zgS@#g`3i;hySdU;xK$fN`Jnuhh z$3EVI#j6)Ar#a~ZCsA7iQ6v0=7W4g<>wkbF$pqnwIQbnb@sV1A6GQGx>O+&`;i7y5 zv-pKgllWhM#9Od`hvm1XX_K*vG+USvL+iY;vm;QfH8mB@4g&mYC2(K8e$cXu>(LCn zln6U`OE4pBg2M$tg*3J&Y$fg*2npizmEqW@Sd0()Cbe2|#%B_53Tv*ShL)q!oV-Sg zqa)-UKClyO!}7)5wOHAs$y-g0e(}1Lyv6XX30$;b36TL&Qic@IghIW40*O{$!s(aT z9(R(6ctq_lo-6SgwQ1<+yrHcwxY0kzUAz`c_S1{EE+8b^zh0gsJm!(!%vw$vrwmr8 zVFI!DuKAm}cI6r}-0cvW-?lp|hYyWc^yQ246RXF7{iQiYQ*=s=WduC`$Q)Jm*1jG# zkoF(U?gK%|hq?-$_lD)80O!fQYF0DBKOF6oxqulJrIkm0!y}G;C5o2Plt-gg1zVn( zj2iEPh#ISUB-n{*>E@J9w(iyYjE(Lu_BJ|E=A)gqAh?xzydtQXzepHv%mNkO^|U{*+xM@xH=-Sa?MB9aYcZ^+hBe zSCX9{9=B5@?0BAHV`OH^GvAPmWca021=wL4twPf-Z7s&N1`LK4o*czCZSPdRv-a(NhNq6!?8Ikjuo{(I!GnAt@R`#_lNFWQyVT#M{Y>+MF$%_ItA{Q-$&U zgk1GRyu^_dM8Z+B<7$)d6pI%k)LQjeuYT+{1#06L32;>| z>Bg_<+gJ`Rs~enGIME3zB@`Jj>jfG|aR>h8Lb2D?e+$`(dpQC~VK_g50R22DsL2-; zaeX`1MMXulnGad9jQ0}nRhSB7SJ5uz=!$~Z!D!?U967d|TWP9q6k(bXErv|gE+o#s z_KvAEOZr3ZaR{=l8G)F6P5w6GGeaO- z->aTNOAs|)e99jVYbM5?gxG_i3@&!z}hC(=Mz4taDlG5#TECncoW~J!W!tSW~I_=?5*9Yk@HI2L>KKM6%(e zDQ&VbBNvi1u53gpaxI20#a0K82Rw(m87=3M92xjH7-UTM=PcH*6tpt$EJoUP4fr7b zj!tv!fM9U&-7g!f=YpjV*#+%dpDMe~Nxjhiz zz=Ym12G(i9n@yHAKR6u7H04LTR|ActHig~~g2<6m=Fa$K1F8c-IQ96yhVznjR#YO- zWvxCkll!Wzw$`Ppw}a5pHWk^Sd>0r#Gosxr^P>Atf2Q7KwJtnu{VlqiV`}^3E!pt` zJ4-x9oAt_%Q27|v;>IZ{4)A-K?iZ=wLQwfJQtbpQf%>#yyyLIca`)rcc#ANL4;0BX zi<>)s9f_3yRy}2gnr!wkBm`2iY6tU>$FfXHg-0)#*3IRDt+IflXNF-~fiqZ@I^Q;H zalc%cMOlrl;QebIBnPjD`X?pRHo!YxG(xQ= zf9CO~D^+%oiqF(MTe%Sl3C`Iga4i}xpyn&8Q(K$#avB45F2XOv(l^&OM%Qzy7-YEN z*c#|?@ASnvDZ{n=&_pzdWyoXo3`99Bf_7R^?bKX>MEyty?_n2x`lrA3R0Ihr!x=fS zGqW!OcYVBN4_GP7DY~A_d$&X_=bMf691N4^=mZSdmb|&4H!E;apWul4TplH%V@3i}Y;^<&+zt~n3=(=SE~Liq=skH~YKlyVe;%VEz4~ngR|yXwgY9tKr)%!W^LcPT7?Y~vg_ z$+DA@wz3fmw0Nwt+E+>n1U`Ti1_B~49+|;xFJQUBK38_vfe`{(8gi8S9{zWpINud; zIalE1DAgO```)e!YS+R3nIH3a+E6!w_cBqK!H5Ie?->=8lo;zUZ`d&Nl_D~lM!DdS65@0G?#EL#hb@zR>DiTW5>2DMio^HQC-p z0Y=i%mBrJLr)L6ART~Dmb?)a&N`z>N#ybU7}7jnlD?7B zATiWuMbc8)6o=6c4CyiFl)pvJS}k%GWh2mgp)VtRQTAx1Pii$gn^a@Ej&ep@;*nb^ld zi1x;E@Q5UGz~$Tx=%gfqo`-Pl!84!F3pL<**SpA#6tAMRf7wKybl(n~Fp9L2NIC0h z6cnj_5@$>Ayt$vNzW=7*;%-b}AJ}~krwm`8FoXErcu$*7JU&xfl_N%Lo79m&*o$s& zXrz#o135KPJuI(7md+Oe&URPKpfDSY{>%PSNoUaalc)WkEHd)^)v>ER%G6u}LJ8^j zGqWOw^TF@g(-=amU(>z9BSIJ6GFO%&=FW(ytPK@;vw~VO8=IXYrWH;r-WE;vGMJR8 zJ`nhc_6L?nVUu=Hs`X=){~ml(v4=g_U4M%rVzob(Fo=xxzM?IKMiiz28!tA@qHl!s zH`gI&q1Jhnw&awF2KO%ZNA{GQ^V>Cpr#sXw#_AZmaWBefQW#xsl1LM!+R6A`dO)=> zFJmz>0yMwl^hD^S1=`~j? zSEtlj_bEm=TSd|FP}UG~@$ewveKx5|b4#{r=>iln4oVAOekWfb4v}HNBZCL8`*e%G z_vH$|^LcIj$&9U`R?P`WD=S5qPj~z`+dOP)W2%}51)Y?(6O-Ue5-V$D95DRLX8>oa zw2dqM4S4~tDAmD-q{Q+Nm%;SYJ<}t%MmG%n8C&y<+9klHo91Ce(S&r7bVSe;DTmn| zeVmUezH;ojc>QWt*uFqH~L86CcYP~@iPRi#~O;?0B){I>L>;^eH#QOX|5kDrAwBbAI} zLgeBO$PT7zh^pD7P(Boueh{))SS^bLUMTv0WN3Lf21Lig-RJYSvT>z9gVFG@h%dg|6)|9M;KB>Uo%1s$+?;H}{(}^BGGUK+NsM}FgGcd6| zei0*XEkh4Yl;w2ID=5N$=Djd36#QEUF2D}^9AXP_(sS&KLTIQ-ZKS+V3%JE#h8Hrz zs}PNl0|@MM%Y#$>XH98ETXAuc`LC5Fl!lt9y~8W33aMmq5Rs5p%jGFOC~h#M%5*WW z>q#AZ#qv>HCvM&IzUSi+r=v&*2b-JqWw1a=g3#27?cA4tmFs0+!`1TK=|wnD_-cK# zD9WdnZKPdokT@isrpW8}PY)qFg~2Lx;ohYr$V|+!XxLvVMDYl>8k~H^zFMT-cbDSl zw`TQ_J#JDS$~BtAnYV}3zE|*9rIC@XzkQ5bOj%<2h$6%XXv*6p4>0cg&+ds5&)Uz2UI_eL9ji2d72jOgrBS|;f3N~E6zAvHcQ zNdG9;?1M$DJMM1GXwb!f{sbDJn zC!%8J(lq#$ep#OOH{Xghqq|qH8#jpdUXGD%=>$Y2{)mo;b$0aYm9Y|i3M_HEsC_Hw z(|&y%phaGRNSBYex)T)QyQ|&TKEOitZi_W()Y{WDpsDaMtY5|Sf{@J&$LnJx}94IPu54IH;&3j zuh2YmJ;O+(dXhE$Xr%7$aFg)5uSYYXQ8;Fi)P_Q^#)=sfj<1o{Z z>7DF~EQGSQJUvphK}KZG6?67<^VD)Otdz(^Q12#S=ICkvNNRZ^aX#`f(omSJ*I6iX zMzcN9Y0DAy>TA_l+;u1*9U7e0V7iZQW4^V$0^<5Hc>44@kphO7H%rg)p6yZ4Ltt^f z!0ZrmTm+X;K?{TQbwiCJ1tCWk6sJ80ZG3=!{PR`>W6|V~4eCLWu`A~#Qjfwmufoks zJ(zR-4sk`^%}dt$gzee%8a*>XfS3O%242lRx8j=o8z zy-&kK8)JrKZ6RJyf?(G|$184bONq;==svd|vJElOX@vo^Jw+;RtaX5Rcig_%+Ra9rua$B>s$cqK>Ajat+%-4me{OqIf#O zk7qm?F~WqPK_wDwnjB|u5?gvJ5=NfFpzrM{*!KRyXP6Q9Uz@ZJr(yPHqG;n-7r*_X zNXLIU-b-9cKZ93wG8i!_w7F9wE8@J*D0&~UiO+2Dt`;ekv-ccVsGw7TM!i=@iP8hp zHe&o>8|aDk)L`%l6vdbrWn%Y(OWrqu%%hx0s1+G06WH6%S$ZZY%@{Y}a3ui!^(3-g zTTBn`KYI?WZ)(7X#x_1b%06CZx|0&yIl~i-<2oOYKWZiTZHGc2Tb#*@8baRi0(E$a zI``x4Apg6q_m{u7W!zbTsyR`0w+Mh;#M?{#)6k!t)FoJ|`O!mt$Hyp5c>}NwUzCXn z*KF|sO6+(9j&Ib6!N!oj6h>0PQzyKL0ZnOpW0n~FE0Re_TRCtXS*NdrNtT$0c?02pq_rC|Gp2+dfuFYKYPvk-CjZw??P zCiGVc!QrNJX}I3b9ub%%DXd8g`Eua}ancXx5w`mR4hjk6^OMMoG+CkQZNKgHJna=z zY;oC3*4$e97C?lVX}!aSJK5JA_&(^LVcNpeRW-zg@!Q(g{fzB%Fn{VDk;qgl`LRMZ zN(g$AO8$_%>B_-D4=b3?x^3Qc&Zs$gYIH6r#o|AEfDqo() z>C@b+i>8Nr2~kR`ItnqG1gQZ7?+c zBtLE23v`f=dp&utwpGQ=1N`sEPSSH8FwaKE#o}^BEgcJwM)gexvZMyQdd)aACeN^T zC({F+6k2QC%$`YM7o#KgZST7u<2^c4l*!IIsRxd3R37hC7_8a?GFQAVB}|2h7gNJ% z$~hETA1(*~Aun!-7WBQ$9Miuzn%$7aaSKNbu07m)_58Y;cI5Ey=z*I{c0yH65PXLS zN#Dv!jw)Tm_=i+b=^w{3YZMnINT;9tSx608Xea+CAGSvI(f0&g=2lvI^moZ=T~A?8gST_PB7O16!N;Mw^=Tng$$axTPa%noEJ(5#a5p=e6{^ znaDz=e?JN-pjcpWK}=^#txfIJ$@`f#PU% zpk>kv*7il*r`0>aY>Wn`^T_A7yOJ(tcACzY#GCeDC+@husPJI*4`ej{|Na2%ND`(F zGq|HTIemTOaRcvqG~xfcRvk{bF&hYfHFTZzl;+L_?xLg)<$HLy*=-!p_EBFuwyq@k|TfZoi{T5nYb2~jb zW#{PChh8-C`ZdR;rccB6y{^VcPbRj>oo+9RlX%z9*Bx^=NUjFW_u$Ls*ZeSY178fc zR|Nb(Ge?q`*{cVYZ7avZE0Hv*2=2~w{B>k3e(Jz~&qjXT2*Pcy<1zMnbfSIDKom+x z9Mjx+JpWO1Spo9bc|I->*XmW!-tXWlt6U>I)6;+3WF-|$5Kh%{Wa47F!GT!qEWU={ zziz={D<{AI!Bk)}0TTBhu^Xai6{e4V{RjU$N&n^_4m8Sg{4He2+?G;ZXyIZq#NB$z zd%NTmCD)^lRDCs_jCg$B=Q$n=e;G)Clj9g>lj4n{eiZ+X6V0Co;9+|&N1|IH=a0@3 zhj%S-p1)WB?Lu(XN9x?GtrZlwqp1Kot-@^`cZ121s?yfPOdqyEVT#w`zIpT&vbTMH z686tYMhIJbd2!)vXgE?ashVh#!vP^x=j%S_?i0Ok2j?dd@Zb3KP;iQir{iomI!Z7Z z!-Q>Z0kAeb6m_|1uim|cEB8B#)H@t)Jk6F^KB$7)uIunu-p?AfF`BXUx26Ibx>VUR*WI- zG7Zu;giCm_>|VO;CF~7A;EZqhP|?@HTU(hTx7VMKcr%aS%pKMYx#|!Y#aKmn$pmxl zX$}sB&qw&qyZ0QDAnZ7>P+?SkaD{u(X!{(+Z(_r@O;uW6Df7Xdprfhew}FTSdFdd9 zQ+rHXL?vEh49r!O2dWo38@|iHr5~|oBR`R=c|KE4lkYzyv_0b7ZFAILw)Vhl*H}R3 ziF>_E(z~^@GF#ENf4y@AUzO(i^LgA@Nw`gL(R4_xwX6c%CE+|5TtDO%_sqnWlIn&0 zfI1P~roE&p*t8-|?;?#4h-{nf@!p9>mX@%`T!4P46f){4`)1mu?d5s}UJ6h8lNdeQ zx>|UVB)_hJ)JWqumB88wY)v?Xvn}HsSnWVQs(2tTBF1-zbzg~Ai28=gw0Y-+I!kQ5G_+LwDDKrGQ8v~9ej&&_0Pd9;ZUZ7&YhV!|qp_9Xa$qN@V+A@31g*9r& z4ryFq7z&U4h8vgJ6TJD*dTK z3ou`0^VVuXfY6=!!0F<*-h~25JDGxN%YI9g(jo@^rN7jaORl7JgpR#g zP6aJy;RjeG(o07136ksZ=px&kuAVgB7eG!m#mYiJSlgpL-*Jp{Z60Xtq@6|7AF0{9 zBp+uoNP8i)w^gz`w@{viz4*ujwV+Uj7Vq*TaWCfli64#<>ZZVhgM&yq{MVOPhyDi2 zir>-1P<%)Wx81&&d+FZ^BBP_v2hiUiQNFw80x56O2x1NQs@qv7Be$FEA5+PxKhshE zsI@p)^W1ud(DZE|u&%aVoe0*0M)7MNuTz^odSf;`J$c%Zl+h(cH{Tq8ymB)qQMA~4 ze5aIfF<4_lq4ge5_QbxoIMmj>(MZeL3*CNsR|{tmruKoTaU`#!7Rf{d)n@V=WDZ0J z7qyD|U5VLtzaSl^nFDElH@siQ)zy)Gc=hd3jB1}%B62dp!(v{aMz;D}2xi|3)V164 zw5vni$U>VGM75nTH3UE@4>tL@F6|hKFl(b3UUUP@4Rqm;;P8hw1TbjSFDHH_gw(Em ztg#to4SQ7#p85=Q^7BG)5L7%rEGgL}NeWSt%G=+^_>=G=fstzzJAHCxi4F%n#d9}z z{>MnYH&>W(VK${N6w9|aUBU{~5sj37(!@}dASINf#RxB?V30;6Egoj`N6Q*Qx~LdD zi}Jp#^2LJET56=I>`IJ$AdbwT1AF3^ln~U$HT2G4<2jEgy5wkD!YB(M5Tb3*W#`Aqf!ADtW^V*tf1oGX3&6Uz-q<-gfTbNqBXNag@*`)! z-o!0guTeu)c_MML2-2R>vWG_%-{xS?+A=1afvfboOF^ER&)B%cKfrHeHCwzvSDpBD!!6Dmw+Bomwn_QvL|PFah$|K zqx2@BOl4fxW2OuA^0)mhXB(~yA6+&QFWIi;O*vppq+|n_uZ2LjrV9T&s0r~ncB<=f zJnTAn)KMxDZSu$4Q6%{if==y=pe;&9c4$Aei&>g-I*fr!pX6JQY-F+7L6T+1Ln}5w zgQ>C@((IPBT?G;6Ba+t9YAF??4V1wg>_Fcq&lGSj(MCwFz|Ftvh_-#X+2G+6rJVPM zIJYc}-ND@{**P^Flj_0_D;KZ)4R;y6{Nx?qHp#{-Xt9LrFV2FUpp7EBXUEE|N*s)Z zEB>d|IQeA_B+74+o0y+J=>$oH(;R-1llP|~w5RGpj@#ja#Ku}e+)1gZ)T>1tNbR`7 z1wBL`hsa5)OO8It2Tx&?=^;ynBVePJOj)@m)l6{MG1JS0OzUdLb=9#R|6U~stTE{E ze;-7)fREujp!tCjmMu}Ck5WvhycQ*kP0aT!rmgc1yMDoW;nwy>H@puvk;)FwB-9zp z<;6~_iONXD=iTnb&QeO8@`ok|@~+7;63Q~&3>N(4`7Go?%S4A$8^I^=&N?wV45T9o z4_*?+r$Xe$gm8=erkpa>q9>vY4cbotAqCq!4D47nNW3XOu9zv|hmC=R8|dfqf1Xr) zk-URu`=Y;siJ&p;;%vM^uUi~QVynv!(`WQ>ie@IPE?F9LW={Sp7fc5G6cQxy$~J

jqUe()vIshJCY7X8=u(7KHF;J5PBPL3wc2+vYE XD%?Lu)Ld*3;7wUxL#|TBJmh}>CZ6PQ literal 0 HcmV?d00001 diff --git a/docs/source/index.rst b/docs/source/index.rst index 145befb39..94b1566a5 100644 --- a/docs/source/index.rst +++ b/docs/source/index.rst @@ -32,6 +32,7 @@ Welcome to airshipctl's Documentation! virtual_redfish_bmc Commands providers/cluster_api_docker + providers/cluster_api_openstack .. toctree:: :caption: Airship Project Documentation diff --git a/docs/source/providers/cluster_api_openstack.md b/docs/source/providers/cluster_api_openstack.md new file mode 100755 index 000000000..43e03b3b3 --- /dev/null +++ b/docs/source/providers/cluster_api_openstack.md @@ -0,0 +1,827 @@ +# Airshipctl integration with Cluster API Openstack + +## Overview + +This document provides instructions on the usage of airshipctl, to perform the +following operations with openstack as infrastructure provider: + +- Initialize the management cluster with cluster api, and cluster api openstack + provider components +- Create a target workload cluster with controlplane and worker machines on an openstack + cloud environment + +## Workflow + +A simple workflow that can be tested involves the following operations: + +Initialize a management cluster with cluster api and openstack provider +components: + +*`$ airshipctl cluster init`* or *`$ airshipctl cluster init --debug`* + +Create a target workload cluster with control plane and worker nodes: + +*`$ airshipctl phase apply controlplane`* + +*`$ airshipctl phase apply workers`* + +Note: `airshipctl phase apply initinfra` is not used because all the provider +components are initialized using `airshipctl cluster init`. + +## Common Prerequisite + +- Install [Docker](https://www.docker.com/) +- Install and setup [kubectl](https://kubernetes.io/docs/tasks/tools/install-kubectl/) +- Install [Kind](https://kind.sigs.k8s.io/) +- Install [Kustomize](https://kubernetes-sigs.github.io/kustomize/installation/binaries/) +- Install [Airshipctl](https://docs.airshipit.org/airshipctl/developers.html) + +## Openstack Prerequisites + +### Credentials + +In order to comunicate with openstack cloud environment, following set of credentials are +needed to be generated. + +The [env.rc]() script +sets the required environment variables related to credentials. + +`source env.rc ` + +The following variables are set. + +```bash +OPENSTACK_CLOUD: The cloud name which is used as second argument in the command above +OPENSTACK_CLOUD_YAML_B64: The secret used by capo to access OpenStack cloud +OPENSTACK_CLOUD_PROVIDER_CONF_B64: The content of cloud.conf used by OpenStack cloud +OPENSTACK_CLOUD_CACERT_B64: (Optional) The content of custom CA file which can be specified in the clouds.yaml +``` + +### SSH key pair + +An ssh key-pair must be specified by setting the `OPENSTACK_SSH_KEY_NAME` environment variable. + +A key-pair can be created by executing the following command + +`openstack keypair create [--public-key | --private-key ] ` + +### Availability zone + +The availability zone must be set as an environment variable `OPENSTACK_FAILURE_DOMAIN`. + +### DNS server + +The DNS servers must be set as an environment variable `OPENSTACK_DNS_NAMESERVERS`. + +### External network + +The openstack environment should have an external network already present. +The external network id can be specified by setting the `spec.externalNetworkId` of `OpenStackCluster` CRD of the cluster template. +The public network id can be obtained by using command + +```bash +openstack network list --external +``` + +### Floating IP + +A floating IP is automatically created and associated with the load balancer or controller node, however floating IP can also be +specified explicitly by setting the `spec.apiServerLoadBalancerFlotingIP` of `OpenStackCluster` CRD. + +Floating ip can be created using `openstack floating ip create ` command. + +Note: Only user with admin role can create a floating IP with specific IP address. + +### Operating system image + +A cluster api compatible image is required for creating workload kubernetes clusters. The kubeadm bootstrap provider that capo uses +depends on some pre-installed software like a container runtime, kubelet, kubeadm and also on an up-to-date version of cloud-init. + +The image can be referenced by setting an environment variable `OPENSTACK_IMAGE_NAME`. + +#### Install Packer + +$ mkdir packer + +$ cd packer + +$ wget + +$ unzip packer_1.6.0_linux_amd64.zip + +$ sudo mv packer /usr/local/bin/ + +#### Install Ansible + +$ sudo apt update + +$ sudo apt upgrade + +$ sudo apt install software-properties-common + +$ sudo apt-add-repository ppa:ansible/ansible + +$ sudo apt update + +$ sudo apt install ansible + +#### Build Cluster API Compliant VM Image + +```bash +$ sudo -i +# apt install qemu-kvm libvirt-bin qemu-utils +$ sudo usermod -a -G kvm `` +$ sudo chown root:kvm /dev/kvm + +``` + +Exit and log back in to make the change take place. + +```bash +git clone image-builder +cd image-builder/images/capi/ +vim packer/qemu/qemu-ubuntu-1804.json +``` + +Update the iso_url to `http://cdimage.ubuntu.com/releases/18.04/release/ubuntu-18.04.5-server-amd64.iso` + +Make sure to use the correct checksum value from +[ubuntu-releases](http://cdimage.ubuntu.com/releases/18.04.5/release/SHA256SUMS) + +$ make build-qemu-ubuntu-1804 + +#### Upload Images to Openstack + +$ openstack image create --container-format bare --disk-format qcow2 --file ubuntu-1804-kube-v1.16.14 ubuntu-1804-kube-v1.16.4 + +``` bash +$ openstack image list ++--------------------------------------+--------------------------+--------+ +| ID | Name | Status | ++--------------------------------------+--------------------------+--------+ +| 10e31af1-5414-4bae-9500-922db677e695 | amphora-x64-haproxy | active | +| 61bf8071-5e00-4806-83e0-612f8da03bf8 | cirros-0.5.1-x86_64-disk | active | +| 4fd894c7-9964-461b-bc9f-2e90fdade505 | ubuntu-1804-kube-v1.16.4 | active | ++--------------------------------------+--------------------------+--------+ +``` + +## Getting Started + +Kind is used to setup a kubernetes cluster, that will later be transformed +into a management cluster using airshipctl. The kind kubernetes cluster will be +initialized with cluster API and Cluster API openstack(CAPO) provider components. + +$ export KIND_EXPERIMENTAL_DOCKER_NETWORK=bridge + +$ kind create cluster --name capi-openstack + +```bash +Creating cluster "capi-openstack" ... +WARNING: Overriding docker network due to KIND_EXPERIMENTAL_DOCKER_NETWORK +WARNING: Here be dragons! This is not supported currently. + ✓ Ensuring node image (kindest/node:v1.18.2) 🖼 + ✓ Preparing nodes 📦 + ✓ Writing configuration 📜 + ✓ Starting control-plane 🕹️ + ✓ Installing CNI 🔌 + ✓ Installing StorageClass 💾 +Set kubectl context to "kind-capi-openstack" +You can now use your cluster with: + +kubectl cluster-info --context kind-capi-openstack +``` + +Check if all the pods are up. +$ kubectl get pods -A + +```bash +NAMESPACE NAME READY STATUS RESTARTS AGE +kube-system coredns-66bff467f8-2thc2 1/1 Running 0 2m43s +kube-system coredns-66bff467f8-4qbvk 1/1 Running 0 2m43s +kube-system etcd-capi-openstack-control-plane 1/1 Running 0 2m58s +kube-system kindnet-xwp2x 1/1 Running 0 2m43s +kube-system kube-apiserver-capi-openstack-control-plane 1/1 Running 0 2m58s +kube-system kube-controller-manager-capi-openstack-control-plane 1/1 Running 0 2m58s +kube-system kube-proxy-khhvd 1/1 Running 0 2m43s +kube-system kube-scheduler-capi-openstack-control-plane 1/1 Running 0 2m58s +local-path-storage local-path-provisioner-bd4bb6b75-qnbjk 1/1 Running 0 2m43s +``` + +## Create airshipctl configuration + +$ mkdir ~/.airship + +$ airshipctl config init + +Run the below command to configure openstack manifest, and add it to airship config + +$ airshipctl config set-manifest openstack_manifest --repo primary --url \ + --branch master --primary \ +--sub-path manifests/site/openstack-test-site --target-path /tmp/airship/ + +$ airshipctl config set-context kind-capi-openstack --manifest openstack_manifest + +```bash +Context "kind-capi-openstack" created. +``` + +$ cp ~/.kube/config ~/.airship/kubeconfig + +$ airshipctl config get-context + +```bash +Context: kind-capi-openstack +contextKubeconf: kind-capi-openstack_target +manifest: openstack_manifest + +LocationOfOrigin: /home/stack/.airship/kubeconfig +cluster: kind-capi-openstack_target +user: kind-capi-openstack +``` + +$ airshipctl config use-context kind-capi-openstack + +$ airshipctl document pull --debug + +```bash +[airshipctl] 2020/09/10 23:19:32 Reading current context manifest information from /home/stack/.airship/config +[airshipctl] 2020/09/10 23:19:32 Downloading primary repository airshipctl from https://opendev.org/airship/airshipctl into /tmp/airship/ +[airshipctl] 2020/09/10 23:19:32 Attempting to download the repository airshipctl +[airshipctl] 2020/09/10 23:19:32 Attempting to clone the repository airshipctl from https://opendev.org/airship/airshipctl +[airshipctl] 2020/09/10 23:19:32 Attempting to open repository airshipctl +[airshipctl] 2020/09/10 23:19:32 Attempting to checkout the repository airshipctl from branch refs/heads/master +``` + +$ airshipctl config set-manifest openstack_manifest --target-path /tmp/airship/airshipctl + +## Initialize Management cluster + +Execute the following command to initialize the Management cluster with CAPI and CAPO components. + +$ airshipctl cluster init --debug + +```bash +[airshipctl] 2020/09/10 23:36:23 Starting cluster-api initiation +Fetching providers +[airshipctl] 2020/09/10 23:36:23 Creating arishipctl repository implementation interface for provider cluster-api of type CoreProvider +[airshipctl] 2020/09/10 23:36:23 Setting up airshipctl provider Components client +Provider type: CoreProvider, name: cluster-api +[airshipctl] 2020/09/10 23:36:23 Getting airshipctl provider components, skipping variable substitution: true. +Provider type: CoreProvider, name: cluster-api +... +``` + +Wait for all the pods to be up. + +$ kubectl get pods -A + +```bash +NAMESPACE NAME READY STATUS RESTARTS AGE +capi-kubeadm-bootstrap-system capi-kubeadm-bootstrap-controller-manager-dfdf9877b-g44hd 2/2 Running 0 59s +capi-kubeadm-control-plane-system capi-kubeadm-control-plane-controller-manager-76c847457b-z2jtr 2/2 Running 0 58s +capi-system capi-controller-manager-7c7978f565-rk7qk 2/2 Running 0 59s +capi-webhook-system capi-controller-manager-748c57d64d-wjbnj 2/2 Running 0 60s +capi-webhook-system capi-kubeadm-bootstrap-controller-manager-65f979767f-bv6dr 2/2 Running 0 59s +capi-webhook-system capi-kubeadm-control-plane-controller-manager-7f5d88dcf9-k6kpf 2/2 Running 1 58s +capi-webhook-system capo-controller-manager-7d76dc9ddc-b9xhw 2/2 Running 0 57s +capo-system capo-controller-manager-79445d5984-k9fmc 2/2 Running 0 57s +cert-manager cert-manager-77d8f4d85f-nkg58 1/1 Running 0 71s +cert-manager cert-manager-cainjector-75f88c9f56-fcrc6 1/1 Running 0 72s +cert-manager cert-manager-webhook-56669d7fcb-cbzfn 1/1 Running 1 71s +kube-system coredns-66bff467f8-2thc2 1/1 Running 0 29m +kube-system coredns-66bff467f8-4qbvk 1/1 Running 0 29m +kube-system etcd-capi-openstack-control-plane 1/1 Running 0 29m +kube-system kindnet-xwp2x 1/1 Running 0 29m +kube-system kube-apiserver-capi-openstack-control-plane 1/1 Running 0 29m +kube-system kube-controller-manager-capi-openstack-control-plane 1/1 Running 0 29m +kube-system kube-proxy-khhvd 1/1 Running 0 29m +kube-system kube-scheduler-capi-openstack-control-plane 1/1 Running 0 29m +local-path-storage local-path-provisioner-bd4bb6b75-qnbjk 1/1 Running 0 29m +``` + +At this point, the management cluster is initialized with cluster api and cluster api openstack provider components. + +## Create control plane and worker nodes + +$ airshipctl phase apply controlplane --debug + +```bash +[airshipctl] 2020/09/11 00:11:44 building bundle from kustomize path /tmp/airship/airshipctl/manifests/site/openstack-test-site/target/controlplane +[airshipctl] 2020/09/11 00:11:44 Getting infos for bundle, inventory id is kind-capi-openstack-target-controlplane +[airshipctl] 2020/09/11 00:11:44 Inventory Object config Map not found, auto generating Invetory object +[airshipctl] 2020/09/11 00:11:44 Injecting Invetory Object: {"apiVersion":"v1","kind":"ConfigMap","metadata":{"creationTimestamp":null,"labels":{"cli-utils.sigs.k8s.io/inventory-id":"kind-capi-openstack-target-controlplane"},"name":"airshipit-kind-capi-openstack-target-controlplane","namespace":"airshipit"}}{nsfx:false,beh:unspecified} into bundle +[airshipctl] 2020/09/11 00:11:44 Making sure that inventory object namespace airshipit exists +secret/ostgt-cloud-config created +cluster.cluster.x-k8s.io/ostgt created +kubeadmcontrolplane.controlplane.cluster.x-k8s.io/ostgt-control-plane created +openstackcluster.infrastructure.cluster.x-k8s.io/ostgt created +openstackmachinetemplate.infrastructure.cluster.x-k8s.io/ostgt-control-plane created +5 resource(s) applied. 5 created, 0 unchanged, 0 configured +secret/ostgt-cloud-config is NotFound: Resource not found +cluster.cluster.x-k8s.io/ostgt is NotFound: Resource not found +kubeadmcontrolplane.controlplane.cluster.x-k8s.io/ostgt-control-plane is NotFound: Resource not found +openstackcluster.infrastructure.cluster.x-k8s.io/ostgt is NotFound: Resource not found +openstackmachinetemplate.infrastructure.cluster.x-k8s.io/ostgt-control-plane is NotFound: Resource not found +secret/ostgt-cloud-config is Current: Resource is always ready +cluster.cluster.x-k8s.io/ostgt is Current: Resource is current +kubeadmcontrolplane.controlplane.cluster.x-k8s.io/ostgt-control-plane is Current: Resource is current +openstackcluster.infrastructure.cluster.x-k8s.io/ostgt is Current: Resource is current +openstackmachinetemplate.infrastructure.cluster.x-k8s.io/ostgt-control-plane is Current: Resource is current +all resources has reached the Current status +``` + +$ airshipctl phase apply workers --debug + +```bash +[airshipctl] 2020/09/11 00:12:19 building bundle from kustomize path /tmp/airship/airshipctl/manifests/site/openstack-test-site/target/workers +[airshipctl] 2020/09/11 00:12:19 Getting infos for bundle, inventory id is kind-capi-openstack-target-workers +[airshipctl] 2020/09/11 00:12:19 Inventory Object config Map not found, auto generating Invetory object +[airshipctl] 2020/09/11 00:12:19 Injecting Invetory Object: {"apiVersion":"v1","kind":"ConfigMap","metadata":{"creationTimestamp":null,"labels":{"cli-utils.sigs.k8s.io/inventory-id":"kind-capi-openstack-target-workers"},"name":"airshipit-kind-capi-openstack-target-workers","namespace":"airshipit"}}{nsfx:false,beh:unspecified} into bundle +[airshipctl] 2020/09/11 00:12:19 Making sure that inventory object namespace airshipit exists +kubeadmconfigtemplate.bootstrap.cluster.x-k8s.io/ostgt-md-0 created +machinedeployment.cluster.x-k8s.io/ostgt-md-0 created +openstackmachinetemplate.infrastructure.cluster.x-k8s.io/ostgt-md-0 created +3 resource(s) applied. 3 created, 0 unchanged, 0 configured +kubeadmconfigtemplate.bootstrap.cluster.x-k8s.io/ostgt-md-0 is NotFound: Resource not found +machinedeployment.cluster.x-k8s.io/ostgt-md-0 is NotFound: Resource not found +openstackmachinetemplate.infrastructure.cluster.x-k8s.io/ostgt-md-0 is NotFound: Resource not found +kubeadmconfigtemplate.bootstrap.cluster.x-k8s.io/ostgt-md-0 is Current: Resource is current +machinedeployment.cluster.x-k8s.io/ostgt-md-0 is Current: Resource is current +openstackmachinetemplate.infrastructure.cluster.x-k8s.io/ostgt-md-0 is Current: Resource is current +all resources has reached the Current status +``` + +$ kubectl get po -A + +```bash +NAMESPACE NAME READY STATUS RESTARTS AGE +capi-kubeadm-bootstrap-system capi-kubeadm-bootstrap-controller-manager-dfdf9877b-g44hd 2/2 Running 0 36m +capi-kubeadm-control-plane-system capi-kubeadm-control-plane-controller-manager-76c847457b-z2jtr 2/2 Running 0 36m +capi-system capi-controller-manager-7c7978f565-rk7qk 2/2 Running 0 36m +capi-webhook-system capi-controller-manager-748c57d64d-wjbnj 2/2 Running 0 36m +capi-webhook-system capi-kubeadm-bootstrap-controller-manager-65f979767f-bv6dr 2/2 Running 0 36m +capi-webhook-system capi-kubeadm-control-plane-controller-manager-7f5d88dcf9-k6kpf 2/2 Running 1 36m +capi-webhook-system capo-controller-manager-7d76dc9ddc-b9xhw 2/2 Running 0 36m +capo-system capo-controller-manager-79445d5984-k9fmc 2/2 Running 0 36m +cert-manager cert-manager-77d8f4d85f-nkg58 1/1 Running 0 36m +cert-manager cert-manager-cainjector-75f88c9f56-fcrc6 1/1 Running 0 36m +cert-manager cert-manager-webhook-56669d7fcb-cbzfn 1/1 Running 1 36m +kube-system coredns-66bff467f8-2thc2 1/1 Running 0 64m +kube-system coredns-66bff467f8-4qbvk 1/1 Running 0 64m +kube-system etcd-capi-openstack-control-plane 1/1 Running 0 64m +kube-system kindnet-xwp2x 1/1 Running 0 64m +kube-system kube-apiserver-capi-openstack-control-plane 1/1 Running 0 64m +kube-system kube-controller-manager-capi-openstack-control-plane 1/1 Running 0 64m +kube-system kube-proxy-khhvd 1/1 Running 0 64m +kube-system kube-scheduler-capi-openstack-control-plane 1/1 Running 0 64m +local-path-storage local-path-provisioner-bd4bb6b75-qnbjk 1/1 Running 0 64m +``` + +To check logs run the below command + +$ kubectl logs capo-controller-manager-79445d5984-k9fmc -n capo-system --all-containers=true -f + +```bash +I0910 23:36:54.768316 1 listener.go:44] controller-runtime/metrics "msg"="metrics server is starting to listen" "addr"="127.0.0.1:8080" +I0910 23:36:54.768890 1 main.go:235] setup "msg"="starting manager" +I0910 23:36:54.769149 1 leaderelection.go:242] attempting to acquire leader lease capo-system/controller-leader-election-capo... +I0910 23:36:54.769199 1 internal.go:356] controller-runtime/manager "msg"="starting metrics server" "path"="/metrics" +I0910 23:36:54.853723 1 leaderelection.go:252] successfully acquired lease capo-system/controller-leader-election-capo +I0910 23:36:54.854706 1 controller.go:164] controller-runtime/controller "msg"="Starting EventSource" "controller"="openstackcluster" "source"={" Type":{"metadata":{"creationTimestamp":null},"spec":{"cloudsSecret":null,"cloudName":"","network":{},"subnet":{},"managedAPIServerLoadBalancer":false,"m anagedSecurityGroups":false,"caKeyPair":{},"etcdCAKeyPair":{},"frontProxyCAKeyPair":{},"saKeyPair":{},"controlPlaneEndpoint":{"host":"","port":0}},"stat us":{"ready":false}}} +I0910 23:36:54.854962 1 controller.go:164] controller-runtime/controller "msg"="Starting EventSource" "controller"="openstackmachine" "source"={" Type":{"metadata":{"creationTimestamp":null},"spec":{"cloudsSecret":null,"cloudName":"","flavor":"","image":""},"status":{"ready":false}}} +``` + +$ kubectl get machines + +```bash +NAME PROVIDERID PHASE +ostgt-control-plane-cggt7 openstack://a6da4363-9419-4e14-b67a-3ce86da198c4 Running +ostgt-md-0-6b564d74b8-8h8d8 openstack://23fd5b75-e3f4-4e89-b900-7a6873a146c2 Running +ostgt-md-0-6b564d74b8-pj4lm openstack://9b8323a2-757f-4905-8006-4514862fde75 Running +ostgt-md-0-6b564d74b8-wnw8l openstack://1a8f10da-5d12-4c50-a60d-f2e24a387611 Running +``` + +$ kubectl get secrets + +```bash +NAME TYPE DATA AGE +default-token-vfcm7 kubernetes.io/service-account-token 3 114m +ostgt-ca Opaque 2 47m +ostgt-cloud-config Opaque 2 51m +ostgt-control-plane-gd2gq cluster.x-k8s.io/secret 1 47m +ostgt-etcd Opaque 2 47m +ostgt-kubeconfig Opaque 1 47m +ostgt-md-0-j76jg cluster.x-k8s.io/secret 1 44m +ostgt-md-0-kdjsv cluster.x-k8s.io/secret 1 44m +ostgt-md-0-q4vmn cluster.x-k8s.io/secret 1 44m +ostgt-proxy Opaque 2 47m +ostgt-sa Opaque 2 47m +``` + +$ kubectl --namespace=default get secret/ostgt-kubeconfig -o jsonpath={.data.value} | base64 --decode > ./ostgt.kubeconfig + +$ kubectl get pods -A --kubeconfig ~/ostgt.kubeconfig + +```bash +NAMESPACE NAME READY STATUS RESTARTS AGE +kube-system calico-kube-controllers-7865ff46b6-8pbnq 1/1 Running 0 47m +kube-system calico-node-7kpjb 1/1 Running 0 44m +kube-system calico-node-d8dcc 1/1 Running 0 45m +kube-system calico-node-mdwnt 1/1 Running 0 47m +kube-system calico-node-n2qr8 1/1 Running 0 45m +kube-system coredns-6955765f44-dkvwq 1/1 Running 0 47m +kube-system coredns-6955765f44-p4mbh 1/1 Running 0 47m +kube-system etcd-ostgt-control-plane-vpmqg 1/1 Running 0 47m +kube-system kube-apiserver-ostgt-control-plane-vpmqg 1/1 Running 0 47m +kube-system kube-controller-manager-ostgt-control-plane-vpmqg 1/1 Running 0 47m +kube-system kube-proxy-j6msn 1/1 Running 0 44m +kube-system kube-proxy-kgxvq 1/1 Running 0 45m +kube-system kube-proxy-lfmlf 1/1 Running 0 45m +kube-system kube-proxy-zq26j 1/1 Running 0 47m +kube-system kube-scheduler-ostgt-control-plane-vpmqg 1/1 Running 0 47m +``` + +$ kubectl get nodes --kubeconfig ~/ostgt.kubeconfig + +```bash +NAME STATUS ROLES AGE VERSION +ostgt-control-plane-vpmqg Ready master 49m v1.17.3 +ostgt-md-0-6p2f9 Ready 46m v1.17.3 +ostgt-md-0-h8hn9 Ready 47m v1.17.3 +ostgt-md-0-k9k66 Ready 46m v1.17.3 +``` + +$ kubectl get cs --kubeconfig ~/ostgt.kubeconfig + +```bash +NAME STATUS MESSAGE ERROR +controller-manager Healthy ok +scheduler Healthy ok +etcd-0 Healthy {"health":"true"} +``` + +Now, the control plane and worker node are created on openstack. + +![Machines](../img/openstack-machines.png) + +## Tear Down Clusters + +In order to delete the cluster run the below command. This will delete +the control plane, workers and all other resources +associated with the cluster on openstack. + +```bash +$ airshipctl phase render controlplane -k Cluster | kubectl delete -f - +cluster.cluster.x-k8s.io "ostgt" deleted +``` + +$ kind delete cluster --name capi-openstack + +## Reference + +### Installation Using Devstack + +- Install [Devstack](https://docs.openstack.org/devstack/latest/guides/devstack-with-lbaas-v2.html) + +- Create `ubuntu-1910-kube-v1.17.3.qcow2` image in the devstack. + +Download a capi compatible image for ubuntu OS. + +```bash +wget https://github.com/sbueringer/image-builder/releases/download/v1.17.3-04/ubuntu-1910-kube-v1.17.3.qcow2 + +openstack image create --container-format bare --disk-format qcow2 --file ubuntu-1910-kube-v1.17.3.qcow2 ubuntu-1910-kube-v1.17.3 +``` + +Check if the image status is `active` + +```bash +stack@stackdev-ev:/opt/stack/devstack$ openstack image list ++--------------------------------------+--------------------------+--------+ +| ID | Name | Status | ++--------------------------------------+--------------------------+--------+ +| 83002c1d-436d-4007-bea1-3ffc94fa193b | amphora-x64-haproxy | active | +| a801c914-a0b9-485a-ba5f-246e912cb656 | cirros-0.5.1-x86_64-disk | active | +| 8e8fc7a8-cfe0-4251-bdde-8600838f2ed8 | ubuntu-1910-kube-v1.17.3 | active | +``` + +- Generate credentials + +In devstack environment, normally the `clouds.yaml` file is found at `etc/openstack/` location. + +Execute the following command to generate the cloud credentials for devstack + +```bash +wget https://raw.githubusercontent.com/kubernetes-sigs/cluster-api-provider-openstack/master/templates/env.rc -O /tmp/env.rc +source /tmp/env.rc /etc/openstack/clouds.yaml devstack +``` + +A snippet of sample clouds.yaml file can be seen below for cloud `devstack`. + +```bash +clouds: + devstack: + auth: + auth_url: http://10.0.4.4/identity + project_id: f3deb6e94bee4addaed3ba42d6ffaeba + user_domain_name: Default + username: demo + password: pass + region_name: RegionOne +``` + +The list of project_id-s can be retrieved by `openstack project list` in the devstack environment. + +- Ensure that `demo` user has `admin` rights so that floating ip-s can be created at the time of +workload cluster deployment. + +```bash +cd /opt/stack/devstack +export OS_USERNAME=admin +$ . ./openrc +$ openstack role add --project demo --user demo admin +``` + +- Create Floating IP + +To create floating ip, following command can be used + +`openstack floating ip create public --floating-ip-address $FLOATING_IP_ADDRESS` + +where `FLOATING_IP_ADDRESS` is the specified ip address and `public` is the name of +the external network in devstack. + +`openstack floating ip list` command shows the list of all floating ip-s. + +- Allow ssh access to controlplane and worker nodes + +Cluster api creates following security groups if `spec.managedSecurityGroups` of +`OpenStackCluster` CRD is set to true. + +- k8s-cluster-default-``-secgroup-controlplane (for control plane) +- k8s-cluster-default-``-secgroup-worker (for worker nodes) + +These security group rules include the kubeadm's +[Check required ports](https://kubernetes.io/docs/setup/production-environment/tools/kubeadm/install-kubeadm/#check-required-ports) +so that each node can not be logged in through ssh by default. + +If ssh access to the nodes is required then follow the below steps - + +Create a security group allowing ssh access + +```bash +openstack security group create --project demo --project-domain Default allow-ssh +openstack security group rule create allow-ssh --protocol tcp --dst-port 22:22 --remote-ip 0.0.0.0/0 +``` + +Add the security group to `OpenStackMachineTemplate` CRD as below + +```bash +apiVersion: infrastructure.cluster.x-k8s.io/v1alpha3 +kind: OpenStackMachineTemplate +metadata: + name: ${CLUSTER_NAME}-control-plane +spec: + template: + spec: + securityGroups: + - name: allow-ssh +``` + +### Provider Manifests + +Provider Configuration for Capo is referenced from +[Config](https://github.com/kubernetes-sigs/cluster-api-provider-openstack/tree/master/config) + +$ tree airshipctl/manifests/function/capo + +```bash +└── v0.3.1 + ├── certmanager + │ ├── certificate.yaml + │ ├── kustomization.yaml + │ └── kustomizeconfig.yaml + ├── crd + │ ├── bases + │ │ ├── infrastructure.cluster.x-k8s.io_openstackclusters.yaml + │ │ ├── infrastructure.cluster.x-k8s.io_openstackmachines.yaml + │ │ └── infrastructure.cluster.x-k8s.io_openstackmachinetemplates.yaml + │ ├── kustomization.yaml + │ ├── kustomizeconfig.yaml + │ └── patches + │ ├── cainjection_in_openstackclusters.yaml + │ ├── cainjection_in_openstackmachines.yaml + │ ├── cainjection_in_openstackmachinetemplates.yaml + │ ├── webhook_in_openstackclusters.yaml + │ ├── webhook_in_openstackmachines.yaml + │ └── webhook_in_openstackmachinetemplates.yaml + ├── default + │ ├── kustomization.yaml + │ ├── manager_role_aggregation_patch.yaml + │ └── namespace.yaml + ├── kustomization.yaml + ├── manager + │ ├── kustomization.yaml + │ ├── manager.yaml + │ ├── manager_auth_proxy_patch.yaml + │ ├── manager_image_patch.yaml + │ └── manager_pull_policy.yaml + ├── patch_crd_webhook_namespace.yaml + ├── rbac + │ ├── auth_proxy_role.yaml + │ ├── auth_proxy_role_binding.yaml + │ ├── auth_proxy_service.yaml + │ ├── kustomization.yaml + │ ├── leader_election_role.yaml + │ ├── leader_election_role_binding.yaml + │ ├── role.yaml + │ └── role_binding.yaml + └── webhook + ├── kustomization.yaml + ├── kustomizeconfig.yaml + ├── manager_webhook_patch.yaml + ├── manifests.yaml + ├── service.yaml + └── webhookcainjection_patch.yaml +``` + +### Cluster Templates + +airshipctl/manifests/function/k8scontrol-capo contains cluster.yaml, controlplane.yaml templates. + +```bash +cluster.yaml: Contains CRDs Cluster, OpenstackCluster, Secret +controlplane.yaml: Contains CRDs KubeadmControlPlane, OpenstackMachineTemplate +``` + +$ tree airshipctl/manifests/function/k8scontrol-capo + +```bash +airshipctl/manifests/function/k8scontrol-capo +├── cluster.yaml +├── controlplane.yaml +└── kustomization.yaml +``` + +airshipctl/manifests/function/workers-capo contains workers.yaml + +```bash +workers.yaml: Contains CRDs Cluster, OpenstackCluster, Secret +``` + +$ tree airshipctl/manifests/function/workers-capo + +```bash +airshipctl/manifests/function/workers-capo +. +├── kustomization.yaml +└── workers.yaml +``` + +### Test Site Manifests + +#### openstack-test-site/shared + +airshipctl cluster init uses +airshipctl/manifests/site/openstack-test-site/shared/clusterctl to initialize +management cluster with defined provider components and version. + +$ tree airshipctl/manifests/site/openstack-test-site/shared + +```bash +└── clusterctl + ├── clusterctl.yaml + └── kustomization.yaml +``` + +#### openstack-test-site/target + +There are 3 phases currently available in openstack-test-site/target + +```bash +controlplane - Patches templates in manifests/function/k8scontrol-capo +workers - Patches template in manifests/function/workers-capo +initinfra - Simply calls `openstack-test-site/shared/clusterctl +``` + +Note: `airshipctl cluster init` initializes all the provider components +including the openstack infrastructure provider component. As a result, `airshipctl +phase apply initinfra` is not used. + +#### Patch Merge Strategy + +Json and strategic merge patches are applied on templates in `manifests/function/k8scontrol-capo` +from `airshipctl/manifests/site/openstack-test-site/target/controlplane` when +`airshipctl phase apply controlplane` command is executed + +Json and strategic merge patches are applied on templates in `manifests/function/workers-capo` +from `airshipctl/manifests/site/openstack-test-site/target/workers` when +`airshipctl phase apply workers` command is executed + +```bash +controlplane/control_plane_ip.json: patches control plane ip in template function/k8scontrol-capo/cluster.yaml +controlplane/dns_servers.json: patches dns servers in template function/k8scontrol-capo/cluster.yaml +controlplane/external_network_id.json: patches external network id in template function/k8scontrol-capo/cluster.yaml +cluster_clouds_yaml_patch.yaml: patches clouds.yaml configuration in template function/k8scontrol-capo/cluster.yaml +controlplane/control_plane_ip_patch.yaml: patches controlplane ip in template function/k8scontrol-capo/controlplane.yaml +controlplane/control_plane_config_patch.yaml: patches cloud configuration in template function/k8scontrol-capo/controlplane.yaml +controlplane/ssh_key_patch.yaml: patches ssh key in template function/k8scontrol-capo/controlplane.yaml +controlplane/control_plane_machine_count_patch.yaml: patches controlplane replica count in template function/k8scontrol-capo/controlplane.yaml +controlplane/control_plane_machine_flavor_patch.yaml: patches controlplane machine flavor in template function/k8scontrol-capo/controlplane.yaml +workers/workers_cloud_conf_patch.yaml: patches cloud configuration in template function/workers-capo/workers.yaml +workers/workers_machine_count_patch.yaml: patches worker replica count in template function/workers-capo/workers.yaml +workers/workers_machine_flavor_patch.yaml: patches worker machine flavor in template function/workers-capo/workers.yaml +workers/workers_ssh_key_patch.yaml: patches ssh key in template function/workers-capo/workers.yaml + +``` + +## Software Version Information + +All the instructions provided in the document have been tested using the software and +version, provided in this section. + +### Docker + +```bash +$ docker version +Client: Docker Engine - Community + Version: 19.03.12 + API version: 1.40 + Go version: go1.13.10 + Git commit: 48a66213fe + Built: Mon Jun 22 15:45:36 2020 + OS/Arch: linux/amd64 + Experimental: false + +Server: Docker Engine - Community + Engine: + Version: 19.03.12 + API version: 1.40 (minimum version 1.12) + Go version: go1.13.10 + Git commit: 48a66213fe + Built: Mon Jun 22 15:44:07 2020 + OS/Arch: linux/amd64 + Experimental: false + containerd: + Version: 1.2.13 + GitCommit: 7ad184331fa3e55e52b890ea95e65ba581ae3429 + runc: + Version: 1.0.0-rc10 + GitCommit: dc9208a3303feef5b3839f4323d9beb36df0a9dd + docker-init: + Version: 0.18.0 + GitCommit: fec3683 + +``` + +### Kind + +```bash +$ kind version +kind v0.8.1 go1.14.2 linux/amd64 +``` + +### Kubectl + +```bash +$ kubectl version --short +Client Version: v1.17.4 +Server Version: v1.18.2 +``` + +### Go + +```bash +$ go version +go version go1.10.4 linux/amd64 +``` + +### Kustomize + +```bash +$ kustomize version +{Version:kustomize/v3.8.0 GitCommit:6a50372dd5686df22750b0c729adaf369fbf193c BuildDate:2020-07-05T14:08:42Z GoOs:linux GoArch:amd64} +``` + +### OS + +```bash +$ cat /etc/os-release +NAME="Ubuntu" +VERSION="18.04.4 LTS (Bionic Beaver)" +ID=ubuntu +ID_LIKE=debian +PRETTY_NAME="Ubuntu 18.04.4 LTS" +VERSION_ID="18.04" +HOME_URL="https://www.ubuntu.com/" +SUPPORT_URL="https://help.ubuntu.com/" +BUG_REPORT_URL="https://bugs.launchpad.net/ubuntu/" +PRIVACY_POLICY_URL="https://www.ubuntu.com/legal/terms-and-policies/privacy-policy" +VERSION_CODENAME=bionic +UBUNTU_CODENAME=bionic +``` + +## Virtual Machine Specification + +All the instructions in the document were perfomed on VM(with nested virtualization enabled) +with 16 vCPUs, 64 GB RAM. diff --git a/manifests/function/capo/v0.3.1/certmanager/certificate.yaml b/manifests/function/capo/v0.3.1/certmanager/certificate.yaml new file mode 100644 index 000000000..af4e13ffe --- /dev/null +++ b/manifests/function/capo/v0.3.1/certmanager/certificate.yaml @@ -0,0 +1,24 @@ +# The following manifests contain a self-signed issuer CR and a certificate CR. +# More document can be found at https://docs.cert-manager.io +apiVersion: cert-manager.io/v1alpha2 +kind: Issuer +metadata: + name: selfsigned-issuer + namespace: system +spec: + selfSigned: {} +--- +apiVersion: cert-manager.io/v1alpha2 +kind: Certificate +metadata: + name: serving-cert # this name should match the one appeared in kustomizeconfig.yaml + namespace: system +spec: + # $(SERVICE_NAME) and $(SERVICE_NAMESPACE) will be substituted by kustomize + dnsNames: + - $(SERVICE_NAME).$(SERVICE_NAMESPACE).svc + - $(SERVICE_NAME).$(SERVICE_NAMESPACE).svc.cluster.local + issuerRef: + kind: Issuer + name: selfsigned-issuer + secretName: $(SERVICE_NAME)-cert # this secret will not be prefixed, since it's not managed by kustomize diff --git a/manifests/function/capo/v0.3.1/certmanager/kustomization.yaml b/manifests/function/capo/v0.3.1/certmanager/kustomization.yaml new file mode 100644 index 000000000..e0182475f --- /dev/null +++ b/manifests/function/capo/v0.3.1/certmanager/kustomization.yaml @@ -0,0 +1,7 @@ +apiVersion: kustomize.config.k8s.io/v1beta1 +kind: Kustomization +resources: +- certificate.yaml + +configurations: +- kustomizeconfig.yaml diff --git a/manifests/function/capo/v0.3.1/certmanager/kustomizeconfig.yaml b/manifests/function/capo/v0.3.1/certmanager/kustomizeconfig.yaml new file mode 100644 index 000000000..28a895a40 --- /dev/null +++ b/manifests/function/capo/v0.3.1/certmanager/kustomizeconfig.yaml @@ -0,0 +1,19 @@ +# This configuration is for teaching kustomize how to update name ref and var substitution +nameReference: +- kind: Issuer + group: cert-manager.io + fieldSpecs: + - kind: Certificate + group: cert-manager.io + path: spec/issuerRef/name + +varReference: +- kind: Certificate + group: cert-manager.io + path: spec/commonName +- kind: Certificate + group: cert-manager.io + path: spec/dnsNames +- kind: Certificate + group: cert-manager.io + path: spec/secretName diff --git a/manifests/function/capo/v0.3.1/crd/bases/infrastructure.cluster.x-k8s.io_openstackclusters.yaml b/manifests/function/capo/v0.3.1/crd/bases/infrastructure.cluster.x-k8s.io_openstackclusters.yaml new file mode 100644 index 000000000..a6ed05229 --- /dev/null +++ b/manifests/function/capo/v0.3.1/crd/bases/infrastructure.cluster.x-k8s.io_openstackclusters.yaml @@ -0,0 +1,558 @@ + +--- +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + controller-gen.kubebuilder.io/version: v0.2.9 + creationTimestamp: null + name: openstackclusters.infrastructure.cluster.x-k8s.io +spec: + group: infrastructure.cluster.x-k8s.io + names: + categories: + - cluster-api + kind: OpenStackCluster + listKind: OpenStackClusterList + plural: openstackclusters + singular: openstackcluster + scope: Namespaced + versions: + - additionalPrinterColumns: + - description: Cluster to which this OpenStackCluster belongs + jsonPath: .metadata.labels.cluster\.x-k8s\.io/cluster-name + name: Cluster + type: string + - description: Cluster infrastructure is ready for OpenStack instances + jsonPath: .status.ready + name: Ready + type: string + - description: Network the cluster is using + jsonPath: .status.network.id + name: Network + type: string + - description: Subnet the cluster is using + jsonPath: .status.network.subnet.id + name: Subnet + type: string + - description: API Endpoint + jsonPath: .status.network.apiServerLoadBalancer.ip + name: Endpoint + priority: 1 + type: string + name: v1alpha3 + schema: + openAPIV3Schema: + description: OpenStackCluster is the Schema for the openstackclusters API + properties: + apiVersion: + description: 'APIVersion defines the versioned schema of this representation + of an object. Servers should convert recognized schemas to the latest + internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources' + type: string + kind: + description: 'Kind is a string value representing the REST resource this + object represents. Servers may infer this from the endpoint the client + submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds' + type: string + metadata: + type: object + spec: + description: OpenStackClusterSpec defines the desired state of OpenStackCluster + properties: + apiServerLoadBalancerAdditionalPorts: + description: APIServerLoadBalancerAdditionalPorts adds additional + ports to the APIServerLoadBalancer + items: + type: integer + type: array + apiServerLoadBalancerFloatingIP: + description: APIServerLoadBalancerFloatingIP is the floatingIP which + will be associated to the APIServer loadbalancer. The floatingIP + will be created if it not already exists. + type: string + apiServerLoadBalancerPort: + description: APIServerLoadBalancerPort is the port on which the listener + on the APIServer loadbalancer will be created + type: integer + caKeyPair: + description: CAKeyPair is the key pair for ca certs. + properties: + cert: + description: base64 encoded cert and key + format: byte + type: string + key: + format: byte + type: string + type: object + cloudName: + description: The name of the cloud to use from the clouds secret + type: string + cloudsSecret: + description: The name of the secret containing the openstack credentials + properties: + name: + description: Name is unique within a namespace to reference a + secret resource. + type: string + namespace: + description: Namespace defines the space within which the secret + name must be unique. + type: string + type: object + controlPlaneAvailabilityZones: + description: ControlPlaneAvailabilityZones is the az to deploy control + plane to + items: + type: string + type: array + controlPlaneEndpoint: + description: ControlPlaneEndpoint represents the endpoint used to + communicate with the control plane. + properties: + host: + description: The hostname on which the API server is serving. + type: string + port: + description: The port on which the API server is serving. + format: int32 + type: integer + required: + - host + - port + type: object + disablePortSecurity: + description: DisablePortSecurity disables the port security of the + network created for the Kubernetes cluster, which also disables + SecurityGroups + type: boolean + disableServerTags: + description: 'Default: True. In case of server tag errors, set to + False' + type: boolean + dnsNameservers: + description: DNSNameservers is the list of nameservers for OpenStack + Subnet being created. Set this value when you need create a new + network/subnet while the access through DNS is required. + items: + type: string + type: array + etcdCAKeyPair: + description: EtcdCAKeyPair is the key pair for etcd. + properties: + cert: + description: base64 encoded cert and key + format: byte + type: string + key: + format: byte + type: string + type: object + externalNetworkId: + description: ExternalNetworkID is the ID of an external OpenStack + Network. This is necessary to get public internet to the VMs. + type: string + externalRouterIPs: + description: ExternalRouterIPs is an array of externalIPs on the respective + subnets. This is necessary if the router needs a fixed ip in a specific + subnet. + items: + properties: + fixedIP: + description: The FixedIP in the corresponding subnet + type: string + subnet: + description: The subnet in which the FixedIP is used for the + Gateway of this router + properties: + filter: + description: Filters for optional network query + properties: + cidr: + type: string + description: + type: string + enableDhcp: + type: boolean + gateway_ip: + type: string + id: + type: string + ipVersion: + type: integer + ipv6AddressMode: + type: string + ipv6RaMode: + type: string + limit: + type: integer + marker: + type: string + name: + type: string + networkId: + type: string + notTags: + type: string + notTagsAny: + type: string + projectId: + type: string + sortDir: + type: string + sortKey: + type: string + subnetpoolId: + type: string + tags: + type: string + tagsAny: + type: string + tenantId: + type: string + type: object + uuid: + description: The UUID of the network. Required if you omit + the port attribute. + type: string + type: object + required: + - subnet + type: object + type: array + frontProxyCAKeyPair: + description: FrontProxyCAKeyPair is the key pair for FrontProxyKeyPair. + properties: + cert: + description: base64 encoded cert and key + format: byte + type: string + key: + format: byte + type: string + type: object + managedAPIServerLoadBalancer: + description: 'ManagedAPIServerLoadBalancer defines whether a LoadBalancer + for the APIServer should be created. If set to true the following + properties are mandatory: APIServerLoadBalancerFloatingIP, APIServerLoadBalancerPort' + type: boolean + managedSecurityGroups: + description: 'ManagedSecurityGroups defines that kubernetes manages + the OpenStack security groups for now, that means that we''ll create + security group allows traffic to/from machines belonging to that + group based on Calico CNI plugin default network requirements: BGP + and IP-in-IP for master node(s) and worker node(s) respectively. + In the future, we could make this more flexible.' + type: boolean + network: + description: If NodeCIDR cannot be set this can be used to detect + an existing network. + properties: + adminStateUp: + type: boolean + description: + type: string + id: + type: string + limit: + type: integer + marker: + type: string + name: + type: string + notTags: + type: string + notTagsAny: + type: string + projectId: + type: string + shared: + type: boolean + sortDir: + type: string + sortKey: + type: string + status: + type: string + tags: + type: string + tagsAny: + type: string + tenantId: + type: string + type: object + nodeCidr: + description: NodeCIDR is the OpenStack Subnet to be created. Cluster + actuator will create a network, a subnet with NodeCIDR, and a router + connected to this subnet. If you leave this empty, no network will + be created. + type: string + saKeyPair: + description: SAKeyPair is the service account key pair. + properties: + cert: + description: base64 encoded cert and key + format: byte + type: string + key: + format: byte + type: string + type: object + subnet: + description: If NodeCIDR cannot be set this can be used to detect + an existing subnet. + properties: + cidr: + type: string + description: + type: string + enableDhcp: + type: boolean + gateway_ip: + type: string + id: + type: string + ipVersion: + type: integer + ipv6AddressMode: + type: string + ipv6RaMode: + type: string + limit: + type: integer + marker: + type: string + name: + type: string + networkId: + type: string + notTags: + type: string + notTagsAny: + type: string + projectId: + type: string + sortDir: + type: string + sortKey: + type: string + subnetpoolId: + type: string + tags: + type: string + tagsAny: + type: string + tenantId: + type: string + type: object + tags: + description: Tags for all resources in cluster + items: + type: string + type: array + useOctavia: + description: UseOctavia is weather LoadBalancer Service is Octavia + or not + type: boolean + type: object + status: + description: OpenStackClusterStatus defines the observed state of OpenStackCluster + properties: + controlPlaneSecurityGroup: + description: 'ControlPlaneSecurityGroups contains all the information + about the OpenStack Security Group that needs to be applied to control + plane nodes. TODO: Maybe instead of two properties, we add a property + to the group?' + properties: + id: + type: string + name: + type: string + rules: + items: + description: SecurityGroupRule represent the basic information + of the associated OpenStack Security Group Role. + properties: + description: + type: string + direction: + type: string + etherType: + type: string + name: + type: string + portRangeMax: + type: integer + portRangeMin: + type: integer + protocol: + type: string + remoteGroupID: + type: string + remoteIPPrefix: + type: string + securityGroupID: + type: string + required: + - description + - direction + - etherType + - name + - portRangeMax + - portRangeMin + - protocol + - remoteGroupID + - remoteIPPrefix + - securityGroupID + type: object + type: array + required: + - id + - name + - rules + type: object + failureDomains: + additionalProperties: + description: FailureDomainSpec is the Schema for Cluster API failure + domains. It allows controllers to understand how many failure + domains a cluster can optionally span across. + properties: + attributes: + additionalProperties: + type: string + description: Attributes is a free form map of attributes an + infrastructure provider might use or require. + type: object + controlPlane: + description: ControlPlane determines if this failure domain + is suitable for use by control plane machines. + type: boolean + type: object + description: FailureDomains represent OpenStack availability zones + type: object + network: + description: Network contains all information about the created OpenStack + Network. It includes Subnets and Router. + properties: + apiServerLoadBalancer: + description: Be careful when using APIServerLoadBalancer, because + this field is optional and therefore not set in all cases + properties: + id: + type: string + internalIP: + type: string + ip: + type: string + name: + type: string + required: + - id + - internalIP + - ip + - name + type: object + id: + type: string + name: + type: string + router: + description: Router represents basic information about the associated + OpenStack Neutron Router + properties: + id: + type: string + name: + type: string + required: + - id + - name + type: object + subnet: + description: Subnet represents basic information about the associated + OpenStack Neutron Subnet + properties: + cidr: + type: string + id: + type: string + name: + type: string + required: + - cidr + - id + - name + type: object + required: + - id + - name + type: object + ready: + type: boolean + workerSecurityGroup: + description: WorkerSecurityGroup contains all the information about + the OpenStack Security Group that needs to be applied to worker + nodes. + properties: + id: + type: string + name: + type: string + rules: + items: + description: SecurityGroupRule represent the basic information + of the associated OpenStack Security Group Role. + properties: + description: + type: string + direction: + type: string + etherType: + type: string + name: + type: string + portRangeMax: + type: integer + portRangeMin: + type: integer + protocol: + type: string + remoteGroupID: + type: string + remoteIPPrefix: + type: string + securityGroupID: + type: string + required: + - description + - direction + - etherType + - name + - portRangeMax + - portRangeMin + - protocol + - remoteGroupID + - remoteIPPrefix + - securityGroupID + type: object + type: array + required: + - id + - name + - rules + type: object + required: + - ready + type: object + type: object + served: true + storage: true + subresources: + status: {} +status: + acceptedNames: + kind: "" + plural: "" + conditions: [] + storedVersions: [] diff --git a/manifests/function/capo/v0.3.1/crd/bases/infrastructure.cluster.x-k8s.io_openstackmachines.yaml b/manifests/function/capo/v0.3.1/crd/bases/infrastructure.cluster.x-k8s.io_openstackmachines.yaml new file mode 100644 index 000000000..d5ff4f1b6 --- /dev/null +++ b/manifests/function/capo/v0.3.1/crd/bases/infrastructure.cluster.x-k8s.io_openstackmachines.yaml @@ -0,0 +1,355 @@ + +--- +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + controller-gen.kubebuilder.io/version: v0.2.9 + creationTimestamp: null + name: openstackmachines.infrastructure.cluster.x-k8s.io +spec: + group: infrastructure.cluster.x-k8s.io + names: + categories: + - cluster-api + kind: OpenStackMachine + listKind: OpenStackMachineList + plural: openstackmachines + singular: openstackmachine + scope: Namespaced + versions: + - additionalPrinterColumns: + - description: Cluster to which this OpenStackMachine belongs + jsonPath: .metadata.labels.cluster\.x-k8s\.io/cluster-name + name: Cluster + type: string + - description: OpenStack instance state + jsonPath: .status.instanceState + name: State + type: string + - description: Machine ready status + jsonPath: .status.ready + name: Ready + type: string + - description: OpenStack instance ID + jsonPath: .spec.providerID + name: InstanceID + type: string + - description: Machine object which owns with this OpenStackMachine + jsonPath: .metadata.ownerReferences[?(@.kind=="Machine")].name + name: Machine + type: string + name: v1alpha3 + schema: + openAPIV3Schema: + description: OpenStackMachine is the Schema for the openstackmachines API + properties: + apiVersion: + description: 'APIVersion defines the versioned schema of this representation + of an object. Servers should convert recognized schemas to the latest + internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources' + type: string + kind: + description: 'Kind is a string value representing the REST resource this + object represents. Servers may infer this from the endpoint the client + submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds' + type: string + metadata: + type: object + spec: + description: OpenStackMachineSpec defines the desired state of OpenStackMachine + properties: + cloudName: + description: The name of the cloud to use from the clouds secret + type: string + cloudsSecret: + description: The name of the secret containing the openstack credentials + properties: + name: + description: Name is unique within a namespace to reference a + secret resource. + type: string + namespace: + description: Namespace defines the space within which the secret + name must be unique. + type: string + type: object + configDrive: + description: Config Drive support + type: boolean + flavor: + description: The flavor reference for the flavor for your server instance. + type: string + floatingIP: + description: The floatingIP which will be associated to the machine, + only used for master. The floatingIP should have been created and + haven't been associated. + type: string + image: + description: The name of the image to use for your server instance. + If the RootVolume is specified, this will be ignored and use rootVolume + directly. + type: string + networks: + description: A networks object. Required parameter when there are + multiple networks defined for the tenant. When you do not specify + the networks parameter, the server attaches to the only network + created for the current tenant. + items: + properties: + filter: + description: Filters for optional network query + properties: + adminStateUp: + type: boolean + description: + type: string + id: + type: string + limit: + type: integer + marker: + type: string + name: + type: string + notTags: + type: string + notTagsAny: + type: string + projectId: + type: string + shared: + type: boolean + sortDir: + type: string + sortKey: + type: string + status: + type: string + tags: + type: string + tagsAny: + type: string + tenantId: + type: string + type: object + fixedIp: + description: A fixed IPv4 address for the NIC. + type: string + subnets: + description: Subnet within a network to use + items: + properties: + filter: + description: Filters for optional network query + properties: + cidr: + type: string + description: + type: string + enableDhcp: + type: boolean + gateway_ip: + type: string + id: + type: string + ipVersion: + type: integer + ipv6AddressMode: + type: string + ipv6RaMode: + type: string + limit: + type: integer + marker: + type: string + name: + type: string + networkId: + type: string + notTags: + type: string + notTagsAny: + type: string + projectId: + type: string + sortDir: + type: string + sortKey: + type: string + subnetpoolId: + type: string + tags: + type: string + tagsAny: + type: string + tenantId: + type: string + type: object + uuid: + description: The UUID of the network. Required if you + omit the port attribute. + type: string + type: object + type: array + uuid: + description: The UUID of the network. Required if you omit the + port attribute. + type: string + type: object + type: array + providerID: + description: ProviderID is the unique identifier as specified by the + cloud provider. + type: string + rootVolume: + description: The volume metadata to boot from + properties: + deviceType: + type: string + diskSize: + type: integer + sourceType: + type: string + sourceUUID: + type: string + type: object + securityGroups: + description: The names of the security groups to assign to the instance + items: + properties: + filter: + description: Filters used to query security groups in openstack + properties: + description: + type: string + id: + type: string + limit: + type: integer + marker: + type: string + name: + type: string + notTags: + type: string + notTagsAny: + type: string + projectId: + type: string + sortDir: + type: string + sortKey: + type: string + tags: + type: string + tagsAny: + type: string + tenantId: + type: string + type: object + name: + description: Security Group name + type: string + uuid: + description: Security Group UID + type: string + type: object + type: array + serverGroupID: + description: The server group to assign the machine to + type: string + serverMetadata: + additionalProperties: + type: string + description: Metadata mapping. Allows you to create a map of key value + pairs to add to the server instance. + type: object + sshKeyName: + description: The ssh key to inject in the instance + type: string + tags: + description: Machine tags Requires Nova api 2.52 minimum! + items: + type: string + type: array + trunk: + description: Whether the server instance is created on a trunk port + or not. + type: boolean + userDataSecret: + description: The name of the secret containing the user data (startup + script in most cases) + properties: + name: + description: Name is unique within a namespace to reference a + secret resource. + type: string + namespace: + description: Namespace defines the space within which the secret + name must be unique. + type: string + type: object + required: + - flavor + - image + type: object + status: + description: OpenStackMachineStatus defines the observed state of OpenStackMachine + properties: + addresses: + description: Addresses contains the OpenStack instance associated + addresses. + items: + description: NodeAddress contains information for the node's address. + properties: + address: + description: The node address. + type: string + type: + description: Node address type, one of Hostname, ExternalIP + or InternalIP. + type: string + required: + - address + - type + type: object + type: array + errorMessage: + description: "FailureMessage will be set in the event that there is + a terminal problem reconciling the Machine and will contain a more + verbose string suitable for logging and human consumption. \n This + field should not be set for transitive errors that a controller + faces that are expected to be fixed automatically over time (like + service outages), but instead indicate that something is fundamentally + wrong with the Machine's spec or the configuration of the controller, + and that manual intervention is required. Examples of terminal errors + would be invalid combinations of settings in the spec, values that + are unsupported by the controller, or the responsible controller + itself being critically misconfigured. \n Any transient errors that + occur during the reconciliation of Machines can be added as events + to the Machine object and/or logged in the controller's output." + type: string + errorReason: + description: Constants aren't automatically generated for unversioned + packages. Instead share the same constant for all versioned packages + type: string + instanceState: + description: InstanceState is the state of the OpenStack instance + for this machine. + type: string + ready: + description: Ready is true when the provider resource is ready. + type: boolean + type: object + type: object + served: true + storage: true + subresources: + status: {} +status: + acceptedNames: + kind: "" + plural: "" + conditions: [] + storedVersions: [] diff --git a/manifests/function/capo/v0.3.1/crd/bases/infrastructure.cluster.x-k8s.io_openstackmachinetemplates.yaml b/manifests/function/capo/v0.3.1/crd/bases/infrastructure.cluster.x-k8s.io_openstackmachinetemplates.yaml new file mode 100644 index 000000000..540bb8688 --- /dev/null +++ b/manifests/function/capo/v0.3.1/crd/bases/infrastructure.cluster.x-k8s.io_openstackmachinetemplates.yaml @@ -0,0 +1,305 @@ + +--- +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + controller-gen.kubebuilder.io/version: v0.2.9 + creationTimestamp: null + name: openstackmachinetemplates.infrastructure.cluster.x-k8s.io +spec: + group: infrastructure.cluster.x-k8s.io + names: + categories: + - cluster-api + kind: OpenStackMachineTemplate + listKind: OpenStackMachineTemplateList + plural: openstackmachinetemplates + singular: openstackmachinetemplate + scope: Namespaced + versions: + - name: v1alpha3 + schema: + openAPIV3Schema: + description: OpenStackMachineTemplate is the Schema for the openstackmachinetemplates + API + properties: + apiVersion: + description: 'APIVersion defines the versioned schema of this representation + of an object. Servers should convert recognized schemas to the latest + internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources' + type: string + kind: + description: 'Kind is a string value representing the REST resource this + object represents. Servers may infer this from the endpoint the client + submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds' + type: string + metadata: + type: object + spec: + description: OpenStackMachineTemplateSpec defines the desired state of + OpenStackMachineTemplate + properties: + template: + description: OpenStackMachineTemplateResource describes the data needed + to create a OpenStackMachine from a template + properties: + spec: + description: Spec is the specification of the desired behavior + of the machine. + properties: + cloudName: + description: The name of the cloud to use from the clouds + secret + type: string + cloudsSecret: + description: The name of the secret containing the openstack + credentials + properties: + name: + description: Name is unique within a namespace to reference + a secret resource. + type: string + namespace: + description: Namespace defines the space within which + the secret name must be unique. + type: string + type: object + configDrive: + description: Config Drive support + type: boolean + flavor: + description: The flavor reference for the flavor for your + server instance. + type: string + floatingIP: + description: The floatingIP which will be associated to the + machine, only used for master. The floatingIP should have + been created and haven't been associated. + type: string + image: + description: The name of the image to use for your server + instance. If the RootVolume is specified, this will be ignored + and use rootVolume directly. + type: string + networks: + description: A networks object. Required parameter when there + are multiple networks defined for the tenant. When you do + not specify the networks parameter, the server attaches + to the only network created for the current tenant. + items: + properties: + filter: + description: Filters for optional network query + properties: + adminStateUp: + type: boolean + description: + type: string + id: + type: string + limit: + type: integer + marker: + type: string + name: + type: string + notTags: + type: string + notTagsAny: + type: string + projectId: + type: string + shared: + type: boolean + sortDir: + type: string + sortKey: + type: string + status: + type: string + tags: + type: string + tagsAny: + type: string + tenantId: + type: string + type: object + fixedIp: + description: A fixed IPv4 address for the NIC. + type: string + subnets: + description: Subnet within a network to use + items: + properties: + filter: + description: Filters for optional network query + properties: + cidr: + type: string + description: + type: string + enableDhcp: + type: boolean + gateway_ip: + type: string + id: + type: string + ipVersion: + type: integer + ipv6AddressMode: + type: string + ipv6RaMode: + type: string + limit: + type: integer + marker: + type: string + name: + type: string + networkId: + type: string + notTags: + type: string + notTagsAny: + type: string + projectId: + type: string + sortDir: + type: string + sortKey: + type: string + subnetpoolId: + type: string + tags: + type: string + tagsAny: + type: string + tenantId: + type: string + type: object + uuid: + description: The UUID of the network. Required + if you omit the port attribute. + type: string + type: object + type: array + uuid: + description: The UUID of the network. Required if you + omit the port attribute. + type: string + type: object + type: array + providerID: + description: ProviderID is the unique identifier as specified + by the cloud provider. + type: string + rootVolume: + description: The volume metadata to boot from + properties: + deviceType: + type: string + diskSize: + type: integer + sourceType: + type: string + sourceUUID: + type: string + type: object + securityGroups: + description: The names of the security groups to assign to + the instance + items: + properties: + filter: + description: Filters used to query security groups in + openstack + properties: + description: + type: string + id: + type: string + limit: + type: integer + marker: + type: string + name: + type: string + notTags: + type: string + notTagsAny: + type: string + projectId: + type: string + sortDir: + type: string + sortKey: + type: string + tags: + type: string + tagsAny: + type: string + tenantId: + type: string + type: object + name: + description: Security Group name + type: string + uuid: + description: Security Group UID + type: string + type: object + type: array + serverGroupID: + description: The server group to assign the machine to + type: string + serverMetadata: + additionalProperties: + type: string + description: Metadata mapping. Allows you to create a map + of key value pairs to add to the server instance. + type: object + sshKeyName: + description: The ssh key to inject in the instance + type: string + tags: + description: Machine tags Requires Nova api 2.52 minimum! + items: + type: string + type: array + trunk: + description: Whether the server instance is created on a trunk + port or not. + type: boolean + userDataSecret: + description: The name of the secret containing the user data + (startup script in most cases) + properties: + name: + description: Name is unique within a namespace to reference + a secret resource. + type: string + namespace: + description: Namespace defines the space within which + the secret name must be unique. + type: string + type: object + required: + - flavor + - image + type: object + required: + - spec + type: object + required: + - template + type: object + type: object + served: true + storage: true +status: + acceptedNames: + kind: "" + plural: "" + conditions: [] + storedVersions: [] diff --git a/manifests/function/capo/v0.3.1/crd/kustomization.yaml b/manifests/function/capo/v0.3.1/crd/kustomization.yaml new file mode 100644 index 000000000..f73e14544 --- /dev/null +++ b/manifests/function/capo/v0.3.1/crd/kustomization.yaml @@ -0,0 +1,30 @@ +commonLabels: + cluster.x-k8s.io/v1alpha3: v1alpha3 + +# This kustomization.yaml is not intended to be run by itself, +# since it depends on service name and namespace that are out of this kustomize package. +# It should be run by config/ +resources: +- bases/infrastructure.cluster.x-k8s.io_openstackclusters.yaml +- bases/infrastructure.cluster.x-k8s.io_openstackmachines.yaml +- bases/infrastructure.cluster.x-k8s.io_openstackmachinetemplates.yaml +# +kubebuilder:scaffold:crdkustomizeresource + +patchesStrategicMerge: +# [WEBHOOK] To enable webhook, uncomment all the sections with [WEBHOOK] prefix. +# patches here are for enabling the conversion webhook for each CRD +- patches/webhook_in_openstackclusters.yaml +- patches/webhook_in_openstackmachines.yaml +- patches/webhook_in_openstackmachinetemplates.yaml +# +kubebuilder:scaffold:crdkustomizewebhookpatch + +# [CERTMANAGER] To enable webhook, uncomment all the sections with [CERTMANAGER] prefix. +# patches here are for enabling the CA injection for each CRD +- patches/cainjection_in_openstackclusters.yaml +- patches/cainjection_in_openstackmachines.yaml +- patches/cainjection_in_openstackmachinetemplates.yaml +# +kubebuilder:scaffold:crdkustomizecainjectionpatch + +# the following config is for teaching kustomize how to do kustomization for CRDs. +configurations: +- kustomizeconfig.yaml diff --git a/manifests/function/capo/v0.3.1/crd/kustomizeconfig.yaml b/manifests/function/capo/v0.3.1/crd/kustomizeconfig.yaml new file mode 100644 index 000000000..8e2d8d6b1 --- /dev/null +++ b/manifests/function/capo/v0.3.1/crd/kustomizeconfig.yaml @@ -0,0 +1,17 @@ +# This file is for teaching kustomize how to substitute name and namespace reference in CRD +nameReference: +- kind: Service + version: v1 + fieldSpecs: + - kind: CustomResourceDefinition + group: apiextensions.k8s.io + path: spec/conversion/webhook/clientConfig/service/name + +namespace: +- kind: CustomResourceDefinition + group: apiextensions.k8s.io + path: spec/conversion/webhook/clientConfig/service/namespace + create: false + +varReference: +- path: metadata/annotations diff --git a/manifests/function/capo/v0.3.1/crd/patches/cainjection_in_openstackclusters.yaml b/manifests/function/capo/v0.3.1/crd/patches/cainjection_in_openstackclusters.yaml new file mode 100644 index 000000000..fc4d7b75c --- /dev/null +++ b/manifests/function/capo/v0.3.1/crd/patches/cainjection_in_openstackclusters.yaml @@ -0,0 +1,8 @@ +# The following patch adds a directive for certmanager to inject CA into the CRD +# CRD conversion requires k8s 1.13 or later. +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + cert-manager.io/inject-ca-from: $(CERTIFICATE_NAMESPACE)/$(CERTIFICATE_NAME) + name: openstackclusters.infrastructure.cluster.x-k8s.io diff --git a/manifests/function/capo/v0.3.1/crd/patches/cainjection_in_openstackmachines.yaml b/manifests/function/capo/v0.3.1/crd/patches/cainjection_in_openstackmachines.yaml new file mode 100644 index 000000000..48c5a6c24 --- /dev/null +++ b/manifests/function/capo/v0.3.1/crd/patches/cainjection_in_openstackmachines.yaml @@ -0,0 +1,8 @@ +# The following patch adds a directive for certmanager to inject CA into the CRD +# CRD conversion requires k8s 1.13 or later. +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + cert-manager.io/inject-ca-from: $(CERTIFICATE_NAMESPACE)/$(CERTIFICATE_NAME) + name: openstackmachines.infrastructure.cluster.x-k8s.io diff --git a/manifests/function/capo/v0.3.1/crd/patches/cainjection_in_openstackmachinetemplates.yaml b/manifests/function/capo/v0.3.1/crd/patches/cainjection_in_openstackmachinetemplates.yaml new file mode 100644 index 000000000..e48fbbb23 --- /dev/null +++ b/manifests/function/capo/v0.3.1/crd/patches/cainjection_in_openstackmachinetemplates.yaml @@ -0,0 +1,8 @@ +# The following patch adds a directive for certmanager to inject CA into the CRD +# CRD conversion requires k8s 1.13 or later. +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + cert-manager.io/inject-ca-from: $(CERTIFICATE_NAMESPACE)/$(CERTIFICATE_NAME) + name: openstackmachinetemplates.infrastructure.cluster.x-k8s.io diff --git a/manifests/function/capo/v0.3.1/crd/patches/webhook_in_openstackclusters.yaml b/manifests/function/capo/v0.3.1/crd/patches/webhook_in_openstackclusters.yaml new file mode 100644 index 000000000..e78332980 --- /dev/null +++ b/manifests/function/capo/v0.3.1/crd/patches/webhook_in_openstackclusters.yaml @@ -0,0 +1,19 @@ +# The following patch enables conversion webhook for CRD +# CRD conversion requires k8s 1.13 or later. +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + name: openstackclusters.infrastructure.cluster.x-k8s.io +spec: + conversion: + strategy: Webhook + webhook: + conversionReviewVersions: ["v1", "v1beta1"] + clientConfig: + # this is "\n" used as a placeholder, otherwise it will be rejected by the apiserver for being blank, + # but we're going to set it later using the cert-manager (or potentially a patch if not using cert-manager) + caBundle: Cg== + service: + namespace: system + name: webhook-service + path: /convert diff --git a/manifests/function/capo/v0.3.1/crd/patches/webhook_in_openstackmachines.yaml b/manifests/function/capo/v0.3.1/crd/patches/webhook_in_openstackmachines.yaml new file mode 100644 index 000000000..37e5bf24a --- /dev/null +++ b/manifests/function/capo/v0.3.1/crd/patches/webhook_in_openstackmachines.yaml @@ -0,0 +1,19 @@ +# The following patch enables conversion webhook for CRD +# CRD conversion requires k8s 1.13 or later. +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + name: openstackmachines.infrastructure.cluster.x-k8s.io +spec: + conversion: + strategy: Webhook + webhook: + conversionReviewVersions: ["v1", "v1beta1"] + clientConfig: + # this is "\n" used as a placeholder, otherwise it will be rejected by the apiserver for being blank, + # but we're going to set it later using the cert-manager (or potentially a patch if not using cert-manager) + caBundle: Cg== + service: + namespace: system + name: webhook-service + path: /convert diff --git a/manifests/function/capo/v0.3.1/crd/patches/webhook_in_openstackmachinetemplates.yaml b/manifests/function/capo/v0.3.1/crd/patches/webhook_in_openstackmachinetemplates.yaml new file mode 100644 index 000000000..ed620b7fd --- /dev/null +++ b/manifests/function/capo/v0.3.1/crd/patches/webhook_in_openstackmachinetemplates.yaml @@ -0,0 +1,19 @@ +# The following patch enables conversion webhook for CRD +# CRD conversion requires k8s 1.13 or later. +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + name: openstackmachinetemplates.infrastructure.cluster.x-k8s.io +spec: + conversion: + strategy: Webhook + webhook: + conversionReviewVersions: ["v1", "v1beta1"] + clientConfig: + # this is "\n" used as a placeholder, otherwise it will be rejected by the apiserver for being blank, + # but we're going to set it later using the cert-manager (or potentially a patch if not using cert-manager) + caBundle: Cg== + service: + namespace: system + name: webhook-service + path: /convert diff --git a/manifests/function/capo/v0.3.1/default/kustomization.yaml b/manifests/function/capo/v0.3.1/default/kustomization.yaml new file mode 100644 index 000000000..c49148291 --- /dev/null +++ b/manifests/function/capo/v0.3.1/default/kustomization.yaml @@ -0,0 +1,11 @@ +namespace: capo-system + +resources: +- namespace.yaml + +bases: +- ../rbac +- ../manager + +patchesStrategicMerge: +- manager_role_aggregation_patch.yaml diff --git a/manifests/function/capo/v0.3.1/default/manager_role_aggregation_patch.yaml b/manifests/function/capo/v0.3.1/default/manager_role_aggregation_patch.yaml new file mode 100644 index 000000000..8e335f493 --- /dev/null +++ b/manifests/function/capo/v0.3.1/default/manager_role_aggregation_patch.yaml @@ -0,0 +1,15 @@ +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + name: manager-role + labels: + cluster.x-k8s.io/aggregate-to-manager: "true" +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRoleBinding +metadata: + name: manager-rolebinding +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: ClusterRole + name: capi-system-capi-aggregated-manager-role diff --git a/manifests/function/capo/v0.3.1/default/namespace.yaml b/manifests/function/capo/v0.3.1/default/namespace.yaml new file mode 100644 index 000000000..1ab3a7255 --- /dev/null +++ b/manifests/function/capo/v0.3.1/default/namespace.yaml @@ -0,0 +1,4 @@ +apiVersion: v1 +kind: Namespace +metadata: + name: system diff --git a/manifests/function/capo/v0.3.1/kustomization.yaml b/manifests/function/capo/v0.3.1/kustomization.yaml new file mode 100644 index 000000000..6c425b597 --- /dev/null +++ b/manifests/function/capo/v0.3.1/kustomization.yaml @@ -0,0 +1,29 @@ +namePrefix: capo- + +commonLabels: + cluster.x-k8s.io/provider: "infrastructure-openstack" + +bases: +- crd +- webhook # Disable this if you're not using the webhook functionality. +- default + +patchesJson6902: +- target: + group: apiextensions.k8s.io + version: v1 + kind: CustomResourceDefinition + name: openstackclusters.infrastructure.cluster.x-k8s.io + path: patch_crd_webhook_namespace.yaml +- target: + group: apiextensions.k8s.io + version: v1 + kind: CustomResourceDefinition + name: openstackmachines.infrastructure.cluster.x-k8s.io + path: patch_crd_webhook_namespace.yaml +- target: + group: apiextensions.k8s.io + version: v1 + kind: CustomResourceDefinition + name: openstackmachinetemplates.infrastructure.cluster.x-k8s.io + path: patch_crd_webhook_namespace.yaml diff --git a/manifests/function/capo/v0.3.1/manager/kustomization.yaml b/manifests/function/capo/v0.3.1/manager/kustomization.yaml new file mode 100644 index 000000000..4691c98f5 --- /dev/null +++ b/manifests/function/capo/v0.3.1/manager/kustomization.yaml @@ -0,0 +1,7 @@ +resources: +- manager.yaml + +patchesStrategicMerge: +- manager_image_patch.yaml +- manager_pull_policy.yaml +- manager_auth_proxy_patch.yaml diff --git a/manifests/function/capo/v0.3.1/manager/manager.yaml b/manifests/function/capo/v0.3.1/manager/manager.yaml new file mode 100644 index 000000000..8efaac677 --- /dev/null +++ b/manifests/function/capo/v0.3.1/manager/manager.yaml @@ -0,0 +1,45 @@ +--- +apiVersion: apps/v1 +kind: Deployment +metadata: + name: controller-manager + namespace: system + labels: + control-plane: capo-controller-manager +spec: + selector: + matchLabels: + control-plane: capo-controller-manager + replicas: 1 + template: + metadata: + labels: + control-plane: capo-controller-manager + annotations: + prometheus.io/scrape: 'true' + spec: + containers: + - args: + - --enable-leader-election + image: controller:latest + imagePullPolicy: IfNotPresent + name: manager + ports: + - containerPort: 9440 + name: healthz + protocol: TCP + - containerPort: 8080 + name: metrics + protocol: TCP + readinessProbe: + httpGet: + path: /readyz + port: healthz + livenessProbe: + httpGet: + path: /healthz + port: healthz + terminationGracePeriodSeconds: 10 + tolerations: + - effect: NoSchedule + key: node-role.kubernetes.io/master diff --git a/manifests/function/capo/v0.3.1/manager/manager_auth_proxy_patch.yaml b/manifests/function/capo/v0.3.1/manager/manager_auth_proxy_patch.yaml new file mode 100644 index 000000000..61cb5e7cb --- /dev/null +++ b/manifests/function/capo/v0.3.1/manager/manager_auth_proxy_patch.yaml @@ -0,0 +1,25 @@ +# This patch inject a sidecar container which is a HTTP proxy for the controller manager, +# it performs RBAC authorization against the Kubernetes API using SubjectAccessReviews. +apiVersion: apps/v1 +kind: Deployment +metadata: + name: controller-manager + namespace: system +spec: + template: + spec: + containers: + - name: kube-rbac-proxy + image: gcr.io/kubebuilder/kube-rbac-proxy:v0.4.1 + args: + - "--secure-listen-address=0.0.0.0:8443" + - "--upstream=http://127.0.0.1:8080/" + - "--logtostderr=true" + - "--v=10" + ports: + - containerPort: 8443 + name: https + - name: manager + args: + - "--metrics-addr=127.0.0.1:8080" + - "--enable-leader-election" diff --git a/manifests/function/capo/v0.3.1/manager/manager_image_patch.yaml b/manifests/function/capo/v0.3.1/manager/manager_image_patch.yaml new file mode 100644 index 000000000..3c8063a30 --- /dev/null +++ b/manifests/function/capo/v0.3.1/manager/manager_image_patch.yaml @@ -0,0 +1,12 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: controller-manager + namespace: system +spec: + template: + spec: + containers: + # Change the value of image field below to your controller image URL + - image: gcr.io/k8s-staging-capi-openstack/capi-openstack-controller-amd64:v20200707-v0.3.1 + name: manager diff --git a/manifests/function/capo/v0.3.1/manager/manager_pull_policy.yaml b/manifests/function/capo/v0.3.1/manager/manager_pull_policy.yaml new file mode 100644 index 000000000..cd7ae12c0 --- /dev/null +++ b/manifests/function/capo/v0.3.1/manager/manager_pull_policy.yaml @@ -0,0 +1,11 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: controller-manager + namespace: system +spec: + template: + spec: + containers: + - name: manager + imagePullPolicy: IfNotPresent diff --git a/manifests/function/capo/v0.3.1/patch_crd_webhook_namespace.yaml b/manifests/function/capo/v0.3.1/patch_crd_webhook_namespace.yaml new file mode 100644 index 000000000..110f3a494 --- /dev/null +++ b/manifests/function/capo/v0.3.1/patch_crd_webhook_namespace.yaml @@ -0,0 +1,3 @@ +- op: replace + path: "/spec/conversion/webhook/clientConfig/service/namespace" + value: capi-webhook-system diff --git a/manifests/function/capo/v0.3.1/rbac/auth_proxy_role.yaml b/manifests/function/capo/v0.3.1/rbac/auth_proxy_role.yaml new file mode 100644 index 000000000..618f5e417 --- /dev/null +++ b/manifests/function/capo/v0.3.1/rbac/auth_proxy_role.yaml @@ -0,0 +1,13 @@ +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + name: proxy-role +rules: +- apiGroups: ["authentication.k8s.io"] + resources: + - tokenreviews + verbs: ["create"] +- apiGroups: ["authorization.k8s.io"] + resources: + - subjectaccessreviews + verbs: ["create"] diff --git a/manifests/function/capo/v0.3.1/rbac/auth_proxy_role_binding.yaml b/manifests/function/capo/v0.3.1/rbac/auth_proxy_role_binding.yaml new file mode 100644 index 000000000..48ed1e4b8 --- /dev/null +++ b/manifests/function/capo/v0.3.1/rbac/auth_proxy_role_binding.yaml @@ -0,0 +1,12 @@ +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRoleBinding +metadata: + name: proxy-rolebinding +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: ClusterRole + name: proxy-role +subjects: +- kind: ServiceAccount + name: default + namespace: system diff --git a/manifests/function/capo/v0.3.1/rbac/auth_proxy_service.yaml b/manifests/function/capo/v0.3.1/rbac/auth_proxy_service.yaml new file mode 100644 index 000000000..0277d13dd --- /dev/null +++ b/manifests/function/capo/v0.3.1/rbac/auth_proxy_service.yaml @@ -0,0 +1,18 @@ +apiVersion: v1 +kind: Service +metadata: + annotations: + prometheus.io/port: "8443" + prometheus.io/scheme: https + prometheus.io/scrape: "true" + labels: + control-plane: capo-controller-manager + name: controller-manager-metrics-service + namespace: system +spec: + ports: + - name: https + port: 8443 + targetPort: https + selector: + control-plane: capo-controller-manager diff --git a/manifests/function/capo/v0.3.1/rbac/kustomization.yaml b/manifests/function/capo/v0.3.1/rbac/kustomization.yaml new file mode 100644 index 000000000..ac51278be --- /dev/null +++ b/manifests/function/capo/v0.3.1/rbac/kustomization.yaml @@ -0,0 +1,10 @@ +apiVersion: kustomize.config.k8s.io/v1beta1 +kind: Kustomization +resources: +- role.yaml +- role_binding.yaml +- leader_election_role.yaml +- leader_election_role_binding.yaml +- auth_proxy_service.yaml +- auth_proxy_role.yaml +- auth_proxy_role_binding.yaml diff --git a/manifests/function/capo/v0.3.1/rbac/leader_election_role.yaml b/manifests/function/capo/v0.3.1/rbac/leader_election_role.yaml new file mode 100644 index 000000000..85093a8c2 --- /dev/null +++ b/manifests/function/capo/v0.3.1/rbac/leader_election_role.yaml @@ -0,0 +1,26 @@ +# permissions to do leader election. +apiVersion: rbac.authorization.k8s.io/v1 +kind: Role +metadata: + name: leader-election-role +rules: +- apiGroups: + - "" + resources: + - configmaps + verbs: + - get + - list + - watch + - create + - update + - patch + - delete +- apiGroups: + - "" + resources: + - configmaps/status + verbs: + - get + - update + - patch diff --git a/manifests/function/capo/v0.3.1/rbac/leader_election_role_binding.yaml b/manifests/function/capo/v0.3.1/rbac/leader_election_role_binding.yaml new file mode 100644 index 000000000..eed16906f --- /dev/null +++ b/manifests/function/capo/v0.3.1/rbac/leader_election_role_binding.yaml @@ -0,0 +1,12 @@ +apiVersion: rbac.authorization.k8s.io/v1 +kind: RoleBinding +metadata: + name: leader-election-rolebinding +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: Role + name: leader-election-role +subjects: +- kind: ServiceAccount + name: default + namespace: system diff --git a/manifests/function/capo/v0.3.1/rbac/role.yaml b/manifests/function/capo/v0.3.1/rbac/role.yaml new file mode 100644 index 000000000..db8659421 --- /dev/null +++ b/manifests/function/capo/v0.3.1/rbac/role.yaml @@ -0,0 +1,85 @@ + +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + creationTimestamp: null + name: manager-role +rules: +- apiGroups: + - "" + resources: + - events + verbs: + - create + - get + - list + - patch + - update + - watch +- apiGroups: + - "" + resources: + - secrets + verbs: + - get + - list + - watch +- apiGroups: + - cluster.x-k8s.io + resources: + - clusters + - clusters/status + verbs: + - get + - list + - watch +- apiGroups: + - cluster.x-k8s.io + resources: + - machines + - machines/status + verbs: + - get + - list + - watch +- apiGroups: + - infrastructure.cluster.x-k8s.io + resources: + - openstackclusters + verbs: + - create + - delete + - get + - list + - patch + - update + - watch +- apiGroups: + - infrastructure.cluster.x-k8s.io + resources: + - openstackclusters/status + verbs: + - get + - patch + - update +- apiGroups: + - infrastructure.cluster.x-k8s.io + resources: + - openstackmachines + verbs: + - create + - delete + - get + - list + - patch + - update + - watch +- apiGroups: + - infrastructure.cluster.x-k8s.io + resources: + - openstackmachines/status + verbs: + - get + - patch + - update diff --git a/manifests/function/capo/v0.3.1/rbac/role_binding.yaml b/manifests/function/capo/v0.3.1/rbac/role_binding.yaml new file mode 100644 index 000000000..8f2658702 --- /dev/null +++ b/manifests/function/capo/v0.3.1/rbac/role_binding.yaml @@ -0,0 +1,12 @@ +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRoleBinding +metadata: + name: manager-rolebinding +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: ClusterRole + name: manager-role +subjects: +- kind: ServiceAccount + name: default + namespace: system diff --git a/manifests/function/capo/v0.3.1/webhook/kustomization.yaml b/manifests/function/capo/v0.3.1/webhook/kustomization.yaml new file mode 100644 index 000000000..edd5cc7ac --- /dev/null +++ b/manifests/function/capo/v0.3.1/webhook/kustomization.yaml @@ -0,0 +1,42 @@ +namespace: capi-webhook-system + +resources: +- manifests.yaml +- service.yaml +- ../certmanager +- ../manager + +configurations: +- kustomizeconfig.yaml + +patchesStrategicMerge: +- manager_webhook_patch.yaml +- webhookcainjection_patch.yaml # Disable this value if you don't have any defaulting or validation webhook. If you don't know, you can check if the manifests.yaml file in the same directory has any contents. + +vars: +- name: CERTIFICATE_NAMESPACE # namespace of the certificate CR + objref: + kind: Certificate + group: cert-manager.io + version: v1alpha2 + name: serving-cert # this name should match the one in certificate.yaml + fieldref: + fieldpath: metadata.namespace +- name: CERTIFICATE_NAME + objref: + kind: Certificate + group: cert-manager.io + version: v1alpha2 + name: serving-cert # this name should match the one in certificate.yaml +- name: SERVICE_NAMESPACE # namespace of the service + objref: + kind: Service + version: v1 + name: webhook-service + fieldref: + fieldpath: metadata.namespace +- name: SERVICE_NAME + objref: + kind: Service + version: v1 + name: webhook-service diff --git a/manifests/function/capo/v0.3.1/webhook/kustomizeconfig.yaml b/manifests/function/capo/v0.3.1/webhook/kustomizeconfig.yaml new file mode 100644 index 000000000..fddf04146 --- /dev/null +++ b/manifests/function/capo/v0.3.1/webhook/kustomizeconfig.yaml @@ -0,0 +1,27 @@ +# the following config is for teaching kustomize where to look at when substituting vars. +# It requires kustomize v2.1.0 or newer to work properly. +nameReference: +- kind: Service + version: v1 + fieldSpecs: + - kind: MutatingWebhookConfiguration + group: admissionregistration.k8s.io + path: webhooks/clientConfig/service/name + - kind: ValidatingWebhookConfiguration + group: admissionregistration.k8s.io + path: webhooks/clientConfig/service/name + +namespace: +- kind: MutatingWebhookConfiguration + group: admissionregistration.k8s.io + path: webhooks/clientConfig/service/namespace + create: true +- kind: ValidatingWebhookConfiguration + group: admissionregistration.k8s.io + path: webhooks/clientConfig/service/namespace + create: true + +varReference: +- path: metadata/annotations +- kind: Deployment + path: spec/template/spec/volumes/secret/secretName diff --git a/manifests/function/capo/v0.3.1/webhook/manager_webhook_patch.yaml b/manifests/function/capo/v0.3.1/webhook/manager_webhook_patch.yaml new file mode 100644 index 000000000..671fb1f8e --- /dev/null +++ b/manifests/function/capo/v0.3.1/webhook/manager_webhook_patch.yaml @@ -0,0 +1,26 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: controller-manager + namespace: system +spec: + template: + spec: + containers: + - name: manager + args: + - "--metrics-addr=127.0.0.1:8080" + - "--webhook-port=9443" + ports: + - containerPort: 9443 + name: webhook-server + protocol: TCP + volumeMounts: + - mountPath: /tmp/k8s-webhook-server/serving-certs + name: cert + readOnly: true + volumes: + - name: cert + secret: + defaultMode: 420 + secretName: $(SERVICE_NAME)-cert diff --git a/manifests/function/capo/v0.3.1/webhook/manifests.yaml b/manifests/function/capo/v0.3.1/webhook/manifests.yaml new file mode 100644 index 000000000..32e41bf19 --- /dev/null +++ b/manifests/function/capo/v0.3.1/webhook/manifests.yaml @@ -0,0 +1,46 @@ + +--- +apiVersion: admissionregistration.k8s.io/v1beta1 +kind: ValidatingWebhookConfiguration +metadata: + creationTimestamp: null + name: validating-webhook-configuration +webhooks: +- clientConfig: + caBundle: Cg== + service: + name: webhook-service + namespace: system + path: /validate-infrastructure-cluster-x-k8s-io-v1alpha3-openstackmachine + failurePolicy: Fail + matchPolicy: Equivalent + name: validation.openstackmachine.infrastructure.cluster.x-k8s.io + rules: + - apiGroups: + - infrastructure.cluster.x-k8s.io + apiVersions: + - v1alpha3 + operations: + - CREATE + - UPDATE + resources: + - openstackmachines +- clientConfig: + caBundle: Cg== + service: + name: webhook-service + namespace: system + path: /validate-infrastructure-cluster-x-k8s-io-v1alpha3-openstackmachinetemplate + failurePolicy: Fail + matchPolicy: Equivalent + name: validation.openstackmachinetemplate.infrastructure.x-k8s.io + rules: + - apiGroups: + - infrastructure.cluster.x-k8s.io + apiVersions: + - v1alpha3 + operations: + - CREATE + - UPDATE + resources: + - openstackmachinetemplates diff --git a/manifests/function/capo/v0.3.1/webhook/service.yaml b/manifests/function/capo/v0.3.1/webhook/service.yaml new file mode 100644 index 000000000..711977f54 --- /dev/null +++ b/manifests/function/capo/v0.3.1/webhook/service.yaml @@ -0,0 +1,9 @@ +apiVersion: v1 +kind: Service +metadata: + name: webhook-service + namespace: system +spec: + ports: + - port: 443 + targetPort: webhook-server diff --git a/manifests/function/capo/v0.3.1/webhook/webhookcainjection_patch.yaml b/manifests/function/capo/v0.3.1/webhook/webhookcainjection_patch.yaml new file mode 100644 index 000000000..dde991537 --- /dev/null +++ b/manifests/function/capo/v0.3.1/webhook/webhookcainjection_patch.yaml @@ -0,0 +1,16 @@ +# This patch add annotation to admission webhook config and +# the variables $(CERTIFICATE_NAMESPACE) and $(CERTIFICATE_NAME) will be substituted by kustomize. +# uncomment the following lines to enable mutating webhook +#apiVersion: admissionregistration.k8s.io/v1beta1 +#kind: MutatingWebhookConfiguration +#metadata: +# name: mutating-webhook-configuration +# annotations: +# cert-manager.k8s.io/inject-ca-from: $(CERTIFICATE_NAMESPACE)/$(CERTIFICATE_NAME) +--- +apiVersion: admissionregistration.k8s.io/v1beta1 +kind: ValidatingWebhookConfiguration +metadata: + name: validating-webhook-configuration + annotations: + cert-manager.io/inject-ca-from: $(CERTIFICATE_NAMESPACE)/$(CERTIFICATE_NAME) diff --git a/manifests/function/k8scontrol-capo/cluster.yaml b/manifests/function/k8scontrol-capo/cluster.yaml new file mode 100644 index 000000000..22c72dc71 --- /dev/null +++ b/manifests/function/k8scontrol-capo/cluster.yaml @@ -0,0 +1,50 @@ +apiVersion: cluster.x-k8s.io/v1alpha3 +kind: Cluster +metadata: + name: ostgt + namespace: default +spec: + clusterNetwork: + pods: + cidrBlocks: + - 192.168.0.0/16 + serviceDomain: cluster.local + controlPlaneRef: + apiVersion: controlplane.cluster.x-k8s.io/v1alpha3 + kind: KubeadmControlPlane + name: ostgt-control-plane + infrastructureRef: + apiVersion: infrastructure.cluster.x-k8s.io/v1alpha3 + kind: OpenStackCluster + name: ostgt +--- +apiVersion: infrastructure.cluster.x-k8s.io/v1alpha3 +kind: OpenStackCluster +metadata: + name: ostgt + namespace: default +spec: + apiServerLoadBalancerFloatingIP: ${OPENSTACK_CONTROLPLANE_IP} + apiServerLoadBalancerPort: 6443 + cloudName: devstack + cloudsSecret: + name: ostgt-cloud-config + namespace: default + disablePortSecurity: false + disableServerTags: true + dnsNameservers: + - "${OPENSTACK_DNS_NAMESERVERS}" + externalNetworkId: "{OPENSTACK_EXTERNAL_NETWORK_ID}" + managedAPIServerLoadBalancer: true + managedSecurityGroups: true + nodeCidr: 10.6.0.0/24 + useOctavia: true +--- +apiVersion: v1 +kind: Secret +metadata: + name: ostgt-cloud-config + namespace: default +data: + cacert: ${CLOUD_CERT_B64} + clouds.yaml: ${CLOUDS_YAML_B64} diff --git a/manifests/function/k8scontrol-capo/controlplane.yaml b/manifests/function/k8scontrol-capo/controlplane.yaml new file mode 100644 index 000000000..c947d11c8 --- /dev/null +++ b/manifests/function/k8scontrol-capo/controlplane.yaml @@ -0,0 +1,85 @@ +apiVersion: controlplane.cluster.x-k8s.io/v1alpha3 +kind: KubeadmControlPlane +metadata: + name: ostgt-control-plane + namespace: default +spec: + infrastructureTemplate: + apiVersion: infrastructure.cluster.x-k8s.io/v1alpha3 + kind: OpenStackMachineTemplate + name: ostgt-control-plane + kubeadmConfigSpec: + clusterConfiguration: + apiServer: + extraArgs: + cloud-config: /etc/kubernetes/cloud.conf + cloud-provider: openstack + extraVolumes: + - hostPath: /etc/kubernetes/cloud.conf + mountPath: /etc/kubernetes/cloud.conf + name: cloud + readOnly: true + controlPlaneEndpoint: ${OPENSTACK_CONTROL_PLANE_IP}:6443 + controllerManager: + extraArgs: + cloud-config: /etc/kubernetes/cloud.conf + cloud-provider: openstack + extraVolumes: + - hostPath: /etc/kubernetes/cloud.conf + mountPath: /etc/kubernetes/cloud.conf + name: cloud + readOnly: true + - hostPath: /etc/certs/cacert + mountPath: /etc/certs/cacert + name: cacerts + readOnly: true + imageRepository: k8s.gcr.io + files: + - content: ${CLOUD_CONF_B64} + encoding: base64 + owner: root + path: /etc/kubernetes/cloud.conf + permissions: "0600" + - content: ${CLOUD_CERT_B64} + encoding: base64 + owner: root + path: /etc/certs/cacert + permissions: "0600" + initConfiguration: + nodeRegistration: + kubeletExtraArgs: + cloud-config: /etc/kubernetes/cloud.conf + cloud-provider: openstack + name: '{{ local_hostname }}' + joinConfiguration: + nodeRegistration: + kubeletExtraArgs: + cloud-config: /etc/kubernetes/cloud.conf + cloud-provider: openstack + name: '{{ local_hostname }}' + postKubeadmCommands: + - sudo kubectl --kubeconfig /etc/kubernetes/admin.conf apply -f https://docs.projectcalico.org/v3.15/manifests/calico.yaml + ntp: + servers: [] + users: + - name: capo + sshAuthorizedKeys: + - ${OPENSTACK_SSH_KEY} + sudo: ALL=(ALL) NOPASSWD:ALL + replicas: 1 + version: v1.17.3 +--- +apiVersion: infrastructure.cluster.x-k8s.io/v1alpha3 +kind: OpenStackMachineTemplate +metadata: + name: ostgt-control-plane + namespace: default +spec: + template: + spec: + cloudName: devstack + cloudsSecret: + name: ostgt-cloud-config + namespace: default + flavor: ${CONTROLPLANE_MACHINE_FLAVOR} + image: ubuntu-1910-kube-v1.17.3 diff --git a/manifests/function/k8scontrol-capo/kustomization.yaml b/manifests/function/k8scontrol-capo/kustomization.yaml new file mode 100644 index 000000000..09fa7c547 --- /dev/null +++ b/manifests/function/k8scontrol-capo/kustomization.yaml @@ -0,0 +1,5 @@ +apiVersion: kustomize.config.k8s.io/v1beta1 +kind: Kustomization +resources: + - cluster.yaml + - controlplane.yaml diff --git a/manifests/function/workers-capo/kustomization.yaml b/manifests/function/workers-capo/kustomization.yaml new file mode 100644 index 000000000..730dd82e7 --- /dev/null +++ b/manifests/function/workers-capo/kustomization.yaml @@ -0,0 +1,4 @@ +apiVersion: kustomize.config.k8s.io/v1beta1 +kind: Kustomization +resources: + - workers.yaml diff --git a/manifests/function/workers-capo/workers.yaml b/manifests/function/workers-capo/workers.yaml new file mode 100644 index 000000000..83a65c7f8 --- /dev/null +++ b/manifests/function/workers-capo/workers.yaml @@ -0,0 +1,72 @@ +apiVersion: cluster.x-k8s.io/v1alpha3 +kind: MachineDeployment +metadata: + name: ostgt-md-0 + namespace: default +spec: + clusterName: ostgt + replicas: 0 + selector: + matchLabels: null + template: + spec: + bootstrap: + configRef: + apiVersion: bootstrap.cluster.x-k8s.io/v1alpha3 + kind: KubeadmConfigTemplate + name: ostgt-md-0 + clusterName: ostgt + failureDomain: nova + infrastructureRef: + apiVersion: infrastructure.cluster.x-k8s.io/v1alpha3 + kind: OpenStackMachineTemplate + name: ostgt-md-0 + version: v1.17.3 +--- +apiVersion: infrastructure.cluster.x-k8s.io/v1alpha3 +kind: OpenStackMachineTemplate +metadata: + name: ostgt-md-0 + namespace: default +spec: + template: + spec: + cloudName: devstack + cloudsSecret: + name: ostgt-cloud-config + namespace: default + flavor: ${WORKER_MACHINE_FLAVOR} + image: ubuntu-1910-kube-v1.17.3 +--- +apiVersion: bootstrap.cluster.x-k8s.io/v1alpha3 +kind: KubeadmConfigTemplate +metadata: + name: ostgt-md-0 + namespace: default +spec: + template: + spec: + files: + - content: ${CLOUD_CONF_B64} + encoding: base64 + owner: root + path: /etc/kubernetes/cloud.conf + permissions: "0600" + - content: ${CLOUD_CERT_B64} + encoding: base64 + owner: root + path: /etc/certs/cacert + permissions: "0600" + joinConfiguration: + nodeRegistration: + kubeletExtraArgs: + cloud-config: /etc/kubernetes/cloud.conf + cloud-provider: openstack + name: '{{ local_hostname }}' + ntp: + servers: [] + users: + - name: capo + sshAuthorizedKeys: + - ${OPENSTACK_SSH_KEY} + sudo: ALL=(ALL) NOPASSWD:ALL diff --git a/manifests/site/openstack-test-site/shared/clusterctl/clusterctl.yaml b/manifests/site/openstack-test-site/shared/clusterctl/clusterctl.yaml new file mode 100755 index 000000000..a05a0366b --- /dev/null +++ b/manifests/site/openstack-test-site/shared/clusterctl/clusterctl.yaml @@ -0,0 +1,43 @@ +apiVersion: airshipit.org/v1alpha1 +kind: Clusterctl +metadata: + labels: + airshipit.org/deploy-k8s: "false" + name: clusterctl-v1 +init-options: + core-provider: "cluster-api:v0.3.7" + bootstrap-providers: + - "kubeadm:v0.3.7" + infrastructure-providers: + - "openstack:v0.3.1" + control-plane-providers: + - "kubeadm:v0.3.7" +providers: + - name: "openstack" + type: "InfrastructureProvider" + versions: + v0.3.1: manifests/function/capo/v0.3.1 + - name: "kubeadm" + type: "BootstrapProvider" + variable-substitution: true + versions: + v0.3.7: manifests/function/cabpk/v0.3.7 + - name: "cluster-api" + type: "CoreProvider" + variable-substitution: true + versions: + v0.3.7: manifests/function/capi/v0.3.7 + - name: "kubeadm" + type: "ControlPlaneProvider" + variable-substitution: true + versions: + v0.3.7: manifests/function/cacpk/v0.3.7 +additional-vars: + CONTAINER_CAPM3_MANAGER: quay.io/metal3-io/cluster-api-provider-metal3:v0.3.2 + CONTAINER_CACPK_MANAGER: us.gcr.io/k8s-artifacts-prod/cluster-api/kubeadm-control-plane-controller:v0.3.7 + CONTAINER_CABPK_MANAGER: us.gcr.io/k8s-artifacts-prod/cluster-api/kubeadm-bootstrap-controller:v0.3.7 + CONTAINER_CAPI_MANAGER: us.gcr.io/k8s-artifacts-prod/cluster-api/cluster-api-controller:v0.3.7 + CONTAINER_CAPM3_AUTH_PROXY: gcr.io/kubebuilder/kube-rbac-proxy:v0.4.0 + CONTAINER_CACPK_AUTH_PROXY: gcr.io/kubebuilder/kube-rbac-proxy:v0.4.1 + CONTAINER_CABPK_AUTH_PROXY: gcr.io/kubebuilder/kube-rbac-proxy:v0.4.1 + CONTAINER_CAPI_AUTH_PROXY: gcr.io/kubebuilder/kube-rbac-proxy:v0.4.1 \ No newline at end of file diff --git a/manifests/site/openstack-test-site/shared/clusterctl/kustomization.yaml b/manifests/site/openstack-test-site/shared/clusterctl/kustomization.yaml new file mode 100755 index 000000000..4bc44013e --- /dev/null +++ b/manifests/site/openstack-test-site/shared/clusterctl/kustomization.yaml @@ -0,0 +1,2 @@ +resources: + - clusterctl.yaml diff --git a/manifests/site/openstack-test-site/target/controlplane/cluster_clouds_yaml_patch.yaml b/manifests/site/openstack-test-site/target/controlplane/cluster_clouds_yaml_patch.yaml new file mode 100644 index 000000000..26a3da7ed --- /dev/null +++ b/manifests/site/openstack-test-site/target/controlplane/cluster_clouds_yaml_patch.yaml @@ -0,0 +1,8 @@ +apiVersion: v1 +kind: Secret +metadata: + name: ostgt-cloud-config + namespace: default +data: + cacert: Cg== + clouds.yaml: Y2xvdWRzOgogIGRldnN0YWNrOgogICAgYXV0aDoKICAgICAgYXV0aF91cmw6IGh0dHA6Ly8xMC4wLjEuNC9pZGVudGl0eQogICAgICBwcm9qZWN0X2lkOiAyMThkMWNiYzMyOWM0YWUzYWNjODhjYTU5NTAwMTUwMQogICAgICB1c2VyX2RvbWFpbl9uYW1lOiBEZWZhdWx0CiAgICAgIHVzZXJuYW1lOiBkZW1vCiAgICAgIHBhc3N3b3JkOiBwYXNzCiAgICByZWdpb25fbmFtZTogUmVnaW9uT25lCg== diff --git a/manifests/site/openstack-test-site/target/controlplane/control_plane_config_patch.yaml b/manifests/site/openstack-test-site/target/controlplane/control_plane_config_patch.yaml new file mode 100644 index 000000000..ec19aeadb --- /dev/null +++ b/manifests/site/openstack-test-site/target/controlplane/control_plane_config_patch.yaml @@ -0,0 +1,24 @@ +apiVersion: controlplane.cluster.x-k8s.io/v1alpha3 +kind: KubeadmControlPlane +metadata: + name: ostgt-control-plane + namespace: default +spec: + infrastructureTemplate: + apiVersion: infrastructure.cluster.x-k8s.io/v1alpha3 + kind: OpenStackMachineTemplate + name: ostgt-control-plane + kubeadmConfigSpec: + files: + - path: /etc/kubernetes/cloud.conf + content: W0dsb2JhbF0KYXV0aC11cmw9aHR0cDovLzEwLjAuMS40L2lkZW50aXR5CnVzZXJuYW1lPSJkZW1vIgpwYXNzd29yZD0icGFzcyIKdGVuYW50LWlkPSIyMThkMWNiYzMyOWM0YWUzYWNjODhjYTU5NTAwMTUwMSIKZG9tYWluLW5hbWU9IkRlZmF1bHQiCnJlZ2lvbj0iUmVnaW9uT25lIgo= + encoding: base64 + owner: root + permissions: "0600" + - path: /etc/certs/cacert + content: Cg== + encoding: base64 + owner: root + permissions: "0600" + postKubeadmCommands: + - sudo kubectl --kubeconfig /etc/kubernetes/admin.conf apply -f https://docs.projectcalico.org/v3.15/manifests/calico.yaml \ No newline at end of file diff --git a/manifests/site/openstack-test-site/target/controlplane/control_plane_ip.json b/manifests/site/openstack-test-site/target/controlplane/control_plane_ip.json new file mode 100644 index 000000000..6a341952a --- /dev/null +++ b/manifests/site/openstack-test-site/target/controlplane/control_plane_ip.json @@ -0,0 +1,3 @@ +[ + { "op": "replace","path": "/spec/apiServerLoadBalancerFloatingIP","value": "172.24.4.120" } +] diff --git a/manifests/site/openstack-test-site/target/controlplane/control_plane_ip_patch.yaml b/manifests/site/openstack-test-site/target/controlplane/control_plane_ip_patch.yaml new file mode 100644 index 000000000..636b52856 --- /dev/null +++ b/manifests/site/openstack-test-site/target/controlplane/control_plane_ip_patch.yaml @@ -0,0 +1,9 @@ +apiVersion: controlplane.cluster.x-k8s.io/v1alpha3 +kind: KubeadmControlPlane +metadata: + name: ostgt-control-plane + namespace: default +spec: + kubeadmConfigSpec: + clusterConfiguration: + controlPlaneEndpoint: 172.24.4.120:6443 diff --git a/manifests/site/openstack-test-site/target/controlplane/control_plane_machine_count_patch.yaml b/manifests/site/openstack-test-site/target/controlplane/control_plane_machine_count_patch.yaml new file mode 100644 index 000000000..c0f7b128c --- /dev/null +++ b/manifests/site/openstack-test-site/target/controlplane/control_plane_machine_count_patch.yaml @@ -0,0 +1,7 @@ +apiVersion: controlplane.cluster.x-k8s.io/v1alpha3 +kind: KubeadmControlPlane +metadata: + name: ostgt-control-plane + namespace: default +spec: + replicas: 1 diff --git a/manifests/site/openstack-test-site/target/controlplane/control_plane_machine_flavor_patch.yaml b/manifests/site/openstack-test-site/target/controlplane/control_plane_machine_flavor_patch.yaml new file mode 100644 index 000000000..b524b4a29 --- /dev/null +++ b/manifests/site/openstack-test-site/target/controlplane/control_plane_machine_flavor_patch.yaml @@ -0,0 +1,9 @@ +apiVersion: infrastructure.cluster.x-k8s.io/v1alpha3 +kind: OpenStackMachineTemplate +metadata: + name: ostgt-control-plane + namespace: default +spec: + template: + spec: + flavor: ds4G diff --git a/manifests/site/openstack-test-site/target/controlplane/dns_servers.json b/manifests/site/openstack-test-site/target/controlplane/dns_servers.json new file mode 100644 index 000000000..7775dbab1 --- /dev/null +++ b/manifests/site/openstack-test-site/target/controlplane/dns_servers.json @@ -0,0 +1,3 @@ +[ + { "op": "replace","path": "/spec/dnsNameservers/0","value": "8.8.8.8" } +] diff --git a/manifests/site/openstack-test-site/target/controlplane/external_network_id.json b/manifests/site/openstack-test-site/target/controlplane/external_network_id.json new file mode 100644 index 000000000..1603e579f --- /dev/null +++ b/manifests/site/openstack-test-site/target/controlplane/external_network_id.json @@ -0,0 +1,3 @@ +[ + { "op": "replace","path": "/spec/externalNetworkId","value": "da57dbbe-c923-4641-b00a-0060d52f6f95" } +] diff --git a/manifests/site/openstack-test-site/target/controlplane/kustomization.yaml b/manifests/site/openstack-test-site/target/controlplane/kustomization.yaml new file mode 100755 index 000000000..656960058 --- /dev/null +++ b/manifests/site/openstack-test-site/target/controlplane/kustomization.yaml @@ -0,0 +1,35 @@ +apiVersion: kustomize.config.k8s.io/v1beta1 +kind: Kustomization +resources: + - ../../../../function/k8scontrol-capo + +patchesJson6902: + + - target: + group: infrastructure.cluster.x-k8s.io + version: v1alpha3 + kind: OpenStackCluster + name: "ostgt" + path: control_plane_ip.json + + - target: + group: infrastructure.cluster.x-k8s.io + version: v1alpha3 + kind: OpenStackCluster + name: "ostgt" + path: dns_servers.json + + - target: + group: infrastructure.cluster.x-k8s.io + version: v1alpha3 + kind: OpenStackCluster + name: "ostgt" + path: external_network_id.json + +patchesStrategicMerge: + - cluster_clouds_yaml_patch.yaml + - control_plane_ip_patch.yaml + - control_plane_config_patch.yaml + - ssh_key_patch.yaml + - control_plane_machine_count_patch.yaml + - control_plane_machine_flavor_patch.yaml diff --git a/manifests/site/openstack-test-site/target/controlplane/ssh_key_patch.yaml b/manifests/site/openstack-test-site/target/controlplane/ssh_key_patch.yaml new file mode 100644 index 000000000..975a2c0bc --- /dev/null +++ b/manifests/site/openstack-test-site/target/controlplane/ssh_key_patch.yaml @@ -0,0 +1,11 @@ +apiVersion: controlplane.cluster.x-k8s.io/v1alpha3 +kind: KubeadmControlPlane +metadata: + name: ostgt-control-plane + namespace: default +spec: + kubeadmConfigSpec: + users: + - name: capo + sshAuthorizedKeys: + - ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQC5CeROtz81ZJ/2wCUBnK0X67dL01s5KgOQhqlvn2PG1onGoEwKuwVgnUH3CtGJj1wjq4GqWduBoLvPrSt6qGL/tX8ZiVp2XS8SkDcxo69zo4QMoBdjTwfXwASalcEjQr7nRW8eMlgeI8+bRkhDuCBQLTYHoe6jQh/sWKhj25cgeAkU8eqe+bB9C8d7C/DeWBN6AJaBGjX7F2Azm8Fg6ArtxabuEDw3DYvdm+Y4GvLDfJ3MQR/S2etk8lwWaxlDWIfTwVeCDlG098rRRKKtiaF9LFq08+wEPPEBsyX1q9aNNfdcoCZnuSoWZ5ceBMxZSobA3vBy2jHUGz+slR4ADM7P stack@devstack-magnum diff --git a/manifests/site/openstack-test-site/target/initinfra/kustomization.yaml b/manifests/site/openstack-test-site/target/initinfra/kustomization.yaml new file mode 100755 index 000000000..c2942afaa --- /dev/null +++ b/manifests/site/openstack-test-site/target/initinfra/kustomization.yaml @@ -0,0 +1,4 @@ +resources: + - ../../shared/clusterctl +commonLabels: + airshipit.org/stage: initinfra diff --git a/manifests/site/openstack-test-site/target/workers/kustomization.yaml b/manifests/site/openstack-test-site/target/workers/kustomization.yaml new file mode 100755 index 000000000..a5eb70db8 --- /dev/null +++ b/manifests/site/openstack-test-site/target/workers/kustomization.yaml @@ -0,0 +1,10 @@ +apiVersion: kustomize.config.k8s.io/v1beta1 +kind: Kustomization +resources: + - ../../../../function/workers-capo + +patchesStrategicMerge: + - workers_machine_count_patch.yaml + - workers_machine_flavor_patch.yaml + - workers_cloud_conf_patch.yaml + - workers_ssh_key_patch.yaml diff --git a/manifests/site/openstack-test-site/target/workers/workers_cloud_conf_patch.yaml b/manifests/site/openstack-test-site/target/workers/workers_cloud_conf_patch.yaml new file mode 100644 index 000000000..f39385763 --- /dev/null +++ b/manifests/site/openstack-test-site/target/workers/workers_cloud_conf_patch.yaml @@ -0,0 +1,19 @@ +apiVersion: bootstrap.cluster.x-k8s.io/v1alpha3 +kind: KubeadmConfigTemplate +metadata: + name: ostgt-md-0 + namespace: default +spec: + template: + spec: + files: + - content: W0dsb2JhbF0KYXV0aC11cmw9aHR0cDovLzEwLjAuMS40L2lkZW50aXR5CnVzZXJuYW1lPSJkZW1vIgpwYXNzd29yZD0icGFzcyIKdGVuYW50LWlkPSIyMThkMWNiYzMyOWM0YWUzYWNjODhjYTU5NTAwMTUwMSIKZG9tYWluLW5hbWU9IkRlZmF1bHQiCnJlZ2lvbj0iUmVnaW9uT25lIgo= + encoding: base64 + owner: root + path: /etc/kubernetes/cloud.conf + permissions: "0600" + - content: Cg== + encoding: base64 + owner: root + path: /etc/certs/cacert + permissions: "0600" diff --git a/manifests/site/openstack-test-site/target/workers/workers_machine_count_patch.yaml b/manifests/site/openstack-test-site/target/workers/workers_machine_count_patch.yaml new file mode 100644 index 000000000..e0343ff50 --- /dev/null +++ b/manifests/site/openstack-test-site/target/workers/workers_machine_count_patch.yaml @@ -0,0 +1,8 @@ +apiVersion: cluster.x-k8s.io/v1alpha3 +kind: MachineDeployment +metadata: + name: ostgt-md-0 + namespace: default +spec: + clusterName: ostgt + replicas: 3 diff --git a/manifests/site/openstack-test-site/target/workers/workers_machine_flavor_patch.yaml b/manifests/site/openstack-test-site/target/workers/workers_machine_flavor_patch.yaml new file mode 100644 index 000000000..86592e5f5 --- /dev/null +++ b/manifests/site/openstack-test-site/target/workers/workers_machine_flavor_patch.yaml @@ -0,0 +1,9 @@ +apiVersion: infrastructure.cluster.x-k8s.io/v1alpha3 +kind: OpenStackMachineTemplate +metadata: + name: ostgt-md-0 + namespace: default +spec: + template: + spec: + flavor: m1.small diff --git a/manifests/site/openstack-test-site/target/workers/workers_ssh_key_patch.yaml b/manifests/site/openstack-test-site/target/workers/workers_ssh_key_patch.yaml new file mode 100644 index 000000000..26b623e74 --- /dev/null +++ b/manifests/site/openstack-test-site/target/workers/workers_ssh_key_patch.yaml @@ -0,0 +1,12 @@ +apiVersion: bootstrap.cluster.x-k8s.io/v1alpha3 +kind: KubeadmConfigTemplate +metadata: + name: ostgt-md-0 + namespace: default +spec: + template: + spec: + users: + - name: capo + sshAuthorizedKeys: + - ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQC5CeROtz81ZJ/2wCUBnK0X67dL01s5KgOQhqlvn2PG1onGoEwKuwVgnUH3CtGJj1wjq4GqWduBoLvPrSt6qGL/tX8ZiVp2XS8SkDcxo69zo4QMoBdjTwfXwASalcEjQr7nRW8eMlgeI8+bRkhDuCBQLTYHoe6jQh/sWKhj25cgeAkU8eqe+bB9C8d7C/DeWBN6AJaBGjX7F2Azm8Fg6ArtxabuEDw3DYvdm+Y4GvLDfJ3MQR/S2etk8lwWaxlDWIfTwVeCDlG098rRRKKtiaF9LFq08+wEPPEBsyX1q9aNNfdcoCZnuSoWZ5ceBMxZSobA3vBy2jHUGz+slR4ADM7P stack@devstack-magnum