auth-proxy: reusable ingress with auth proxy object for cue configs (#113)

affects: #110

Creates reusable auth proxy object in base cue config, and migrates rpuppy, url-shortener, pihole and memberships app to it.

Memberships app always requires authentication.
url-shortener now supports non-auth based interactions.
diff --git a/core/installer/values-tmpl/memberships.cue b/core/installer/values-tmpl/memberships.cue
index 6790cfd..898cffd 100644
--- a/core/installer/values-tmpl/memberships.cue
+++ b/core/installer/values-tmpl/memberships.cue
@@ -1,6 +1,7 @@
 input: {}
 
-_domain: "memberships.\(global.privateDomain)"
+_subdomain: "memberships"
+_domain: "\(_subdomain).\(global.privateDomain)"
 
 name: "memberships"
 namespace: "core-auth-memberships"
@@ -8,22 +9,31 @@
 description: "The application is a membership management system designed to facilitate the organization and administration of groups and memberships. Can be configured to be reachable only from private network or publicly."
 icon: "<svg xmlns='http://www.w3.org/2000/svg' width='50' height='50' viewBox='0 0 24 24'><path fill='currentColor' d='M15.43 15.48c-1.1-.49-2.26-.73-3.43-.73c-1.18 0-2.33.25-3.43.73c-.23.1-.4.29-.49.52h7.85a.978.978 0 0 0-.5-.52m-2.49-6.69C12.86 8.33 12.47 8 12 8s-.86.33-.94.79l-.2 1.21h2.28z' opacity='0.3'/><path fill='currentColor' d='M10.27 12h3.46a1.5 1.5 0 0 0 1.48-1.75l-.3-1.79a2.951 2.951 0 0 0-5.82.01l-.3 1.79c-.15.91.55 1.74 1.48 1.74m.79-3.21c.08-.46.47-.79.94-.79s.86.33.94.79l.2 1.21h-2.28zm-9.4 2.32c-.13.26-.18.57-.1.88c.16.69.76 1.03 1.53 1h1.95c.83 0 1.51-.58 1.51-1.29c0-.14-.03-.27-.07-.4c-.01-.03-.01-.05.01-.08c.09-.16.14-.34.14-.53c0-.31-.14-.6-.36-.82c-.03-.03-.03-.06-.02-.1c.07-.2.07-.43.01-.65a1.12 1.12 0 0 0-.99-.74a.09.09 0 0 1-.07-.03C5.03 8.14 4.72 8 4.37 8c-.3 0-.57.1-.75.26c-.03.03-.06.03-.09.02a1.24 1.24 0 0 0-1.7 1.03c0 .02-.01.04-.03.06c-.29.26-.46.65-.41 1.05c.03.22.12.43.25.6c.03.02.03.06.02.09m14.58 2.54c-1.17-.52-2.61-.9-4.24-.9c-1.63 0-3.07.39-4.24.9A2.988 2.988 0 0 0 6 16.39V18h12v-1.61c0-1.18-.68-2.26-1.76-2.74M8.07 16a.96.96 0 0 1 .49-.52c1.1-.49 2.26-.73 3.43-.73c1.18 0 2.33.25 3.43.73c.23.1.4.29.49.52zm-6.85-1.42A2.01 2.01 0 0 0 0 16.43V18h4.5v-1.61c0-.83.23-1.61.63-2.29c-.37-.06-.74-.1-1.13-.1c-.99 0-1.93.21-2.78.58m21.56 0A6.95 6.95 0 0 0 20 14c-.39 0-.76.04-1.13.1c.4.68.63 1.46.63 2.29V18H24v-1.57c0-.81-.48-1.53-1.22-1.85M22 11v-.5c0-1.1-.9-2-2-2h-2c-.42 0-.65.48-.39.81l.7.63c-.19.31-.31.67-.31 1.06c0 1.1.9 2 2 2s2-.9 2-2'/></svg>"
 
-images: {
+_httpPortName: "http"
+
+_ingressWithAuthProxy: _IngressWithAuthProxy & {
+	inp: {
+		auth: {
+			enabled: true
+			groups: "" // TODO(gio): set admin
+		}
+		network: networks.private
+		subdomain: _subdomain
+		serviceName: "memberships"
+		port: name: _httpPortName
+	}
+}
+
+images: _ingressWithAuthProxy.out.images & {
     memberships: {
         repository: "giolekva"
         name: "memberships"
         tag: "latest"
         pullPolicy: "Always"
     }
-    authProxy: {
-        repository: "giolekva"
-        name: "auth-proxy"
-        tag: "latest"
-        pullPolicy: "Always"
-    }
 }
 
-charts: {
+charts: _ingressWithAuthProxy.out.charts & {
     memberships: {
         chart: "charts/memberships"
         sourceRef: {
@@ -32,29 +42,9 @@
             namespace: global.id
         }
     }
-    ingress: {
-        chart: "charts/ingress"
-        sourceRef: {
-            kind: "GitRepository"
-            name: "pcloud"
-            namespace: global.id
-        }
-    }
-    authProxy: {
-        chart: "charts/auth-proxy"
-        sourceRef: {
-            kind: "GitRepository"
-            name: "pcloud"
-            namespace: global.id
-        }
-    }
 }
 
-_membershipsServiceName: "memberships"
-_authProxyServiceName: "auth-proxy"
-_httpPortName: "http"
-
-helm: {
+helm: _ingressWithAuthProxy.out.helm & {
     memberships: {
         chart: charts.memberships
         values: {
@@ -69,37 +59,4 @@
             portName: _httpPortName
         }
     }
-    if input.requireAuth {
-        "auth-proxy": {
-            chart: charts.authProxy
-            values: {
-                image: {
-                    repository: images.authProxy.fullName
-                    tag: images.authProxy.tag
-                    pullPolicy: images.authProxy.pullPolicy
-                }
-                upstream: "\(_membershipsServiceName).\(release.namespace).svc.cluster.local"
-                whoAmIAddr: "https://accounts.\(global.domain)/sessions/whoami"
-                loginAddr: "https://accounts-ui.\(global.domain)/login"
-                portName: _httpPortName
-            }
-        }
-    }
-    ingress: {
-        chart: charts.ingress
-        values: {
-            domain: _domain
-            ingressClassName: input.network.ingressClass
-            certificateIssuer: input.network.certificateIssuer
-            service: {
-                if input.requireAuth {
-                    name: _authProxyServiceName
-                }
-                if !input.requireAuth {
-                    name: _membershipsServiceName
-                }
-                port: name: _httpPortName
-            }
-        }
-    }
 }
diff --git a/core/installer/values-tmpl/pihole.cue b/core/installer/values-tmpl/pihole.cue
index ff04fe2..3f33842 100644
--- a/core/installer/values-tmpl/pihole.cue
+++ b/core/installer/values-tmpl/pihole.cue
@@ -12,22 +12,28 @@
 description: "Pi-hole is a Linux network-level advertisement and Internet tracker blocking application which acts as a DNS sinkhole and optionally a DHCP server, intended for use on a private network."
 icon: "<svg xmlns='http://www.w3.org/2000/svg' width='50' height='50' viewBox='0 0 24 24'><path fill='currentColor' d='M4.344 0c.238 4.792 3.256 7.056 6.252 7.376c.165-1.692-4.319-5.6-4.319-5.6c-.008-.011.009-.025.019-.014c0 0 4.648 4.01 5.423 5.645c2.762-.15 5.196-1.947 5-4.912c0 0-4.12-.613-5 4.618C11.48 2.753 8.993 0 4.344 0zM12 7.682v.002a3.68 3.68 0 0 0-2.591 1.077L4.94 13.227a3.683 3.683 0 0 0-.86 1.356a3.31 3.31 0 0 0-.237 1.255A3.681 3.681 0 0 0 4.92 18.45l4.464 4.466a3.69 3.69 0 0 0 2.251 1.06l.002.001c.093.01.187.015.28.017l-.1-.008c.06.003.117.009.177.009l-.077-.001L12 24l-.004-.005a3.68 3.68 0 0 0 2.61-1.077l4.469-4.465a3.683 3.683 0 0 0 1.006-1.888l.012-.063a3.682 3.682 0 0 0 .057-.541l.003-.061c0-.017.003-.05.004-.06h-.002a3.683 3.683 0 0 0-1.077-2.607l-4.466-4.468a3.694 3.694 0 0 0-1.564-.927l-.07-.02a3.43 3.43 0 0 0-.946-.133L12 7.682zm3.165 3.357c.023 1.748-1.33 3.078-1.33 4.806c.164 2.227 1.733 3.207 3.266 3.146c-.035.003-.068.007-.104.009c-1.847.135-3.209-1.326-5.002-1.326c-2.23.164-3.21 1.736-3.147 3.27l-.008-.104c-.133-1.847 1.328-3.21 1.328-5.002c-.173-2.32-1.867-3.284-3.46-3.132c.1-.011.203-.021.31-.027c1.847-.133 3.209 1.328 5.002 1.328c2.082-.155 3.074-1.536 3.145-2.968zM4.344 0c.238 4.792 3.256 7.056 6.252 7.376c.165-1.692-4.319-5.6-4.319-5.6c-.008-.011.009-.025.019-.014c0 0 4.648 4.01 5.423 5.645c2.762-.15 5.196-1.947 5-4.912c0 0-4.12-.613-5 4.618C11.48 2.753 8.993 0 4.344 0zM12 7.682v.002a3.68 3.68 0 0 0-2.591 1.077L4.94 13.227a3.683 3.683 0 0 0-.86 1.356a3.31 3.31 0 0 0-.237 1.255A3.681 3.681 0 0 0 4.92 18.45l4.464 4.466a3.69 3.69 0 0 0 2.251 1.06l.002.001c.093.01.187.015.28.017l-.1-.008c.06.003.117.009.177.009l-.077-.001L12 24l-.004-.005a3.68 3.68 0 0 0 2.61-1.077l4.469-4.465a3.683 3.683 0 0 0 1.006-1.888l.012-.063a3.682 3.682 0 0 0 .057-.541l.003-.061c0-.017.003-.05.004-.06h-.002a3.683 3.683 0 0 0-1.077-2.607l-4.466-4.468a3.694 3.694 0 0 0-1.564-.927l-.07-.02a3.43 3.43 0 0 0-.946-.133L12 7.682zm3.165 3.357c.023 1.748-1.33 3.078-1.33 4.806c.164 2.227 1.733 3.207 3.266 3.146c-.035.003-.068.007-.104.009c-1.847.135-3.209-1.326-5.002-1.326c-2.23.164-3.21 1.736-3.147 3.27l-.008-.104c-.133-1.847 1.328-3.21 1.328-5.002c-.173-2.32-1.867-3.284-3.46-3.132c.1-.011.203-.021.31-.027c1.847-.133 3.209 1.328 5.002 1.328c2.082-.155 3.074-1.536 3.145-2.968z'/></svg>"
 
-images: {
+_serviceWebPort: 80
+
+_ingressWithAuthProxy: _IngressWithAuthProxy & {
+	inp: {
+		auth: input.auth
+		network: input.network
+		subdomain: input.subdomain
+		serviceName: "pihole-web"
+		port: number: _serviceWebPort
+	}
+}
+
+images: _ingressWithAuthProxy.out.images & {
 	pihole: {
 		repository: "pihole"
 		name: "pihole"
 		tag: "v5.8.1"
 		pullPolicy: "IfNotPresent"
 	}
-	authProxy: {
-		repository: "giolekva"
-		name: "auth-proxy"
-		tag: "latest"
-		pullPolicy: "Always"
-	}
 }
 
-charts: {
+charts: _ingressWithAuthProxy.out.charts & {
 	pihole: {
 		chart: "charts/pihole"
 		sourceRef: {
@@ -36,30 +42,9 @@
 			namespace: global.id
 		}
 	}
-	ingress: {
-		chart: "charts/ingress"
-		sourceRef: {
-			kind: "GitRepository"
-			name: "pcloud"
-			namespace: global.id
-		}
-	}
-	authProxy: {
-		chart: "charts/auth-proxy"
-		sourceRef: {
-			kind: "GitRepository"
-			name: "pcloud"
-			namespace: global.id
-		}
-	}
 }
 
-_piholeServiceName: "pihole-web"
-_authProxyServiceName: "auth-proxy"
-_httpPortName: "http"
-_serviceWebPort: 80
-
-helm: {
+helm: _ingressWithAuthProxy.out.helm & {
 	pihole: {
 		chart: charts.pihole
 		values: {
@@ -108,40 +93,4 @@
 			}
 		}
 	}
-	if input.auth.enabled {
-		"auth-proxy": {
-			chart: charts.authProxy
-			values: {
-				image: {
-					repository: images.authProxy.fullName
-					tag: images.authProxy.tag
-					pullPolicy: images.authProxy.pullPolicy
-				}
-				upstream: "\(_piholeServiceName).\(release.namespace).svc.cluster.local"
-				whoAmIAddr: "https://accounts.\(global.domain)/sessions/whoami"
-				loginAddr: "https://accounts-ui.\(global.domain)/login"
-				membershipAddr: "http://memberships.\(global.id)-core-auth-memberships.svc.cluster.local/api/user"
-				groups: input.auth.groups
-				portName: _httpPortName
-			}
-		}
-	}
-	ingress: {
-		chart: charts.ingress
-		values: {
-			domain: _domain
-			ingressClassName: input.network.ingressClass
-			certificateIssuer: input.network.certificateIssuer
-			service: {
-				if input.auth.enabled {
-					name: _authProxyServiceName
-					port: name: _httpPortName
-				}
-				if !input.auth.enabled {
-					name: _piholeServiceName
-					port: number: _serviceWebPort
-				}
-			}
-		}
-	}
 }
diff --git a/core/installer/values-tmpl/rpuppy.cue b/core/installer/values-tmpl/rpuppy.cue
index 4955f81..9b1d8f2 100644
--- a/core/installer/values-tmpl/rpuppy.cue
+++ b/core/installer/values-tmpl/rpuppy.cue
@@ -12,22 +12,28 @@
 description: "Delights users with randomly generate puppy pictures. Can be configured to be reachable only from private network or publicly."
 icon: "<svg xmlns='http://www.w3.org/2000/svg' width='50' height='50' viewBox='0 0 256 256'><path fill='currentColor' d='M100 140a8 8 0 1 1-8-8a8 8 0 0 1 8 8Zm64 8a8 8 0 1 0-8-8a8 8 0 0 0 8 8Zm64.94-9.11a12.12 12.12 0 0 1-5 1.11a11.83 11.83 0 0 1-9.35-4.62l-2.59-3.29V184a36 36 0 0 1-36 36H80a36 36 0 0 1-36-36v-51.91l-2.53 3.27A11.88 11.88 0 0 1 32.1 140a12.08 12.08 0 0 1-5-1.11a11.82 11.82 0 0 1-6.84-13.14l16.42-88a12 12 0 0 1 14.7-9.43h.16L104.58 44h46.84l53.08-15.6h.16a12 12 0 0 1 14.7 9.43l16.42 88a11.81 11.81 0 0 1-6.84 13.06ZM97.25 50.18L49.34 36.1a4.18 4.18 0 0 0-.92-.1a4 4 0 0 0-3.92 3.26l-16.42 88a4 4 0 0 0 7.08 3.22ZM204 121.75L150 52h-44l-54 69.75V184a28 28 0 0 0 28 28h44v-18.34l-14.83-14.83a4 4 0 0 1 5.66-5.66L128 186.34l13.17-13.17a4 4 0 0 1 5.66 5.66L132 193.66V212h44a28 28 0 0 0 28-28Zm23.92 5.48l-16.42-88a4 4 0 0 0-4.84-3.16l-47.91 14.11l62.11 80.28a4 4 0 0 0 7.06-3.23Z'/></svg>"
 
-images: {
+_httpPortName: "http"
+
+_ingressWithAuthProxy: _IngressWithAuthProxy & {
+	inp: {
+		auth: input.auth
+		network: input.network
+		subdomain: input.subdomain
+		serviceName: "rpuppy"
+		port: name: _httpPortName
+	}
+}
+
+images: _ingressWithAuthProxy.out.images & {
 	rpuppy: {
 		repository: "giolekva"
 		name: "rpuppy"
 		tag: "latest"
 		pullPolicy: "Always"
 	}
-	authProxy: {
-		repository: "giolekva"
-		name: "auth-proxy"
-		tag: "latest"
-		pullPolicy: "Always"
-	}
 }
 
-charts: {
+charts: _ingressWithAuthProxy.out.charts & {
 	rpuppy: {
 		chart: "charts/rpuppy"
 		sourceRef: {
@@ -36,29 +42,9 @@
 			namespace: global.id
 		}
 	}
-	ingress: {
-		chart: "charts/ingress"
-		sourceRef: {
-			kind: "GitRepository"
-			name: "pcloud"
-			namespace: global.id
-		}
-	}
-	authProxy: {
-		chart: "charts/auth-proxy"
-		sourceRef: {
-			kind: "GitRepository"
-			name: "pcloud"
-			namespace: global.id
-		}
-	}
 }
 
-_rpuppyServiceName: "rpuppy"
-_authProxyServiceName: "auth-proxy"
-_httpPortName: "http"
-
-helm: {
+helm: _ingressWithAuthProxy.out.helm & {
 	rpuppy: {
 		chart: charts.rpuppy
 		values: {
@@ -70,39 +56,4 @@
 			portName: _httpPortName
 		}
 	}
-	if input.auth.enabled {
-		"auth-proxy": {
-			chart: charts.authProxy
-			values: {
-				image: {
-					repository: images.authProxy.fullName
-					tag: images.authProxy.tag
-					pullPolicy: images.authProxy.pullPolicy
-				}
-				upstream: "\(_rpuppyServiceName).\(release.namespace).svc.cluster.local"
-				whoAmIAddr: "https://accounts.\(global.domain)/sessions/whoami"
-				loginAddr: "https://accounts-ui.\(global.domain)/login"
-				membershipAddr: "http://memberships.\(global.id)-core-auth-memberships.svc.cluster.local/api/user"
-				groups: input.auth.groups
-				portName: _httpPortName
-			}
-		}
-	}
-	ingress: {
-		chart: charts.ingress
-		values: {
-			domain: _domain
-			ingressClassName: input.network.ingressClass
-			certificateIssuer: input.network.certificateIssuer
-			service: {
-				if input.auth.enabled {
-					name: _authProxyServiceName
-				}
-				if !input.auth.enabled {
-					name: _rpuppyServiceName
-				}
-				port: name: _httpPortName
-			}
-		}
-	}
 }
diff --git a/core/installer/values-tmpl/url-shortener.cue b/core/installer/values-tmpl/url-shortener.cue
index 42a3ce8..a6e95ab 100644
--- a/core/installer/values-tmpl/url-shortener.cue
+++ b/core/installer/values-tmpl/url-shortener.cue
@@ -12,22 +12,28 @@
 description: "Provides URL shortening service. Can be configured to be reachable only from private network or publicly."
 icon: "<svg xmlns='http://www.w3.org/2000/svg' width='40.63' height='50' viewBox='0 0 13 16'><circle cx='2' cy='10' r='1' fill='currentColor'/><circle cx='2' cy='6' r='1' fill='currentColor'/><path fill='currentColor' d='M4.5 14c-.06 0-.11 0-.17-.03a.501.501 0 0 1-.3-.64l4-11a.501.501 0 0 1 .94.34l-4 11c-.07.2-.27.33-.47.33m3 0c-.06 0-.11 0-.17-.03a.501.501 0 0 1-.3-.64l4-11a.501.501 0 0 1 .94.34l-4 11c-.07.2-.27.33-.47.33'/></svg>"
 
-images: {
+_httpPortName: "http"
+
+_ingressWithAuthProxy: _IngressWithAuthProxy & {
+	inp: {
+		auth: input.auth
+		network: input.network
+		subdomain: input.subdomain
+		serviceName: "url-shortener"
+		port: name: _httpPortName
+	}
+}
+
+images: _ingressWithAuthProxy.out.images & {
 	urlShortener: {
 		repository: "giolekva"
 		name: "url-shortener"
 		tag: "latest"
 		pullPolicy: "Always"
 	}
-	authProxy: {
-		repository: "giolekva"
-		name: "auth-proxy"
-		tag: "latest"
-		pullPolicy: "Always"
-	}
 }
 
-charts: {
+charts: _ingressWithAuthProxy.out.charts & {
     urlShortener: {
         chart: "charts/url-shortener"
         sourceRef: {
@@ -36,29 +42,9 @@
             namespace: global.id
         }
     }
-	ingress: {
-		chart: "charts/ingress"
-		sourceRef: {
-			kind: "GitRepository"
-			name: "pcloud"
-			namespace: global.id
-		}
-	}
-	authProxy: {
-		chart: "charts/auth-proxy"
-		sourceRef: {
-			kind: "GitRepository"
-			name: "pcloud"
-			namespace: global.id
-		}
-	}
 }
 
-_urlShortenerServiceName: "url-shortener"
-_authProxyServiceName: "auth-proxy"
-_httpPortName: "http"
-
-helm: {
+helm: _ingressWithAuthProxy.out.helm & {
     "url-shortener": {
         chart: charts.urlShortener
         values: {
@@ -71,41 +57,7 @@
 				pullPolicy: images.urlShortener.pullPolicy
 			}
             portName: _httpPortName
+			requireAuth: input.auth.enabled
         }
     }
-	if input.auth.enabled {
-		"auth-proxy": {
-			chart: charts.authProxy
-			values: {
-				image: {
-					repository: images.authProxy.fullName
-					tag: images.authProxy.tag
-					pullPolicy: images.authProxy.pullPolicy
-				}
-				upstream: "\(_urlShortenerServiceName).\(release.namespace).svc.cluster.local"
-				whoAmIAddr: "https://accounts.\(global.domain)/sessions/whoami"
-				loginAddr: "https://accounts-ui.\(global.domain)/login"
-				membershipAddr: "http://memberships.\(global.id)-core-auth-memberships.svc.cluster.local/api/user"
-				groups: input.auth.groups
-				portName: _httpPortName
-			}
-		}
-	}
-	ingress: {
-		chart: charts.ingress
-		values: {
-			domain: _domain
-			ingressClassName: input.network.ingressClass
-			certificateIssuer: input.network.certificateIssuer
-			service: {
-				if input.auth.enabled {
-					name: _authProxyServiceName
-				}
-				if !input.auth.enabled {
-					name: _urlShortenerServiceName
-				}
-				port: name: _httpPortName
-			}
-		}
-	}
 }