Skip to content

Commit 5cebc14

Browse files
authored
feat: quincey (#8)
feat: quincey fix: consistent naming fix: use validate first
1 parent b94d3f6 commit 5cebc14

File tree

7 files changed

+702
-2
lines changed

7 files changed

+702
-2
lines changed

pkg/builder/builder.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ func NewBuilder(ctx *pulumi.Context, args BuilderComponentArgs, opts ...pulumi.R
3434
component := &BuilderComponent{
3535
BuilderComponentArgs: args,
3636
}
37-
err := ctx.RegisterComponentResource("the-builder:index:Builder", args.Name, component)
37+
err := ctx.RegisterComponentResource("signet:index:Builder", args.Name, component)
3838
if err != nil {
3939
return nil, fmt.Errorf("failed to register component resource: %w", err)
4040
}

pkg/quincey/helpers.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
package quincey

pkg/quincey/quincey.go

Lines changed: 339 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,339 @@
1+
package quincey
2+
3+
import (
4+
"fmt"
5+
"strconv"
6+
7+
"github.com/init4tech/signet-infra-components/pkg/utils"
8+
crd "github.com/pulumi/pulumi-kubernetes/sdk/v4/go/kubernetes/apiextensions"
9+
appsv1 "github.com/pulumi/pulumi-kubernetes/sdk/v4/go/kubernetes/apps/v1"
10+
corev1 "github.com/pulumi/pulumi-kubernetes/sdk/v4/go/kubernetes/core/v1"
11+
metav1 "github.com/pulumi/pulumi-kubernetes/sdk/v4/go/kubernetes/meta/v1"
12+
"github.com/pulumi/pulumi/sdk/v3/go/pulumi"
13+
)
14+
15+
// NewQuinceyComponent creates a new Quincey deployment in the specified namespace.
16+
// It sets up all necessary Kubernetes resources including the deployment, service,
17+
// and Istio configurations.
18+
//
19+
// Example:
20+
//
21+
// component, err := NewQuinceyComponent(ctx, "quincey", &QuinceyComponentArgs{
22+
// Namespace: pulumi.String("default"),
23+
// Image: pulumi.String("quincey:latest"),
24+
// Env: QuinceyEnv{
25+
// QuinceyPort: pulumi.String("8080"),
26+
// // ... other environment variables
27+
// },
28+
// })
29+
func NewQuinceyComponent(ctx *pulumi.Context, name string, args *QuinceyComponentArgs, opts ...pulumi.ResourceOption) (*QuinceyComponent, error) {
30+
if err := args.Validate(); err != nil {
31+
return nil, fmt.Errorf("invalid quincey component args: %w", err)
32+
}
33+
34+
component := &QuinceyComponent{
35+
ResourceState: pulumi.ResourceState{},
36+
}
37+
38+
if err := ctx.RegisterComponentResource("signet:index:Quincey", name, component); err != nil {
39+
return nil, fmt.Errorf("failed to register component resource: %w", err)
40+
}
41+
42+
// Create service account
43+
serviceAccount, err := createServiceAccount(ctx, args.Namespace, component)
44+
if err != nil {
45+
return nil, fmt.Errorf("failed to create service account: %w", err)
46+
}
47+
48+
// Create config map
49+
configMap, err := createConfigMap(ctx, args, component)
50+
if err != nil {
51+
return nil, fmt.Errorf("failed to create config map: %w", err)
52+
}
53+
54+
// Create deployment
55+
deployment, err := createDeployment(ctx, args, component)
56+
if err != nil {
57+
return nil, fmt.Errorf("failed to create deployment: %w", err)
58+
}
59+
60+
// Create service
61+
service, err := createService(ctx, args, deployment, component)
62+
if err != nil {
63+
return nil, fmt.Errorf("failed to create service: %w", err)
64+
}
65+
66+
// Create virtual service
67+
virtualService, err := createVirtualService(ctx, args, service, component)
68+
if err != nil {
69+
return nil, fmt.Errorf("failed to create virtual service: %w", err)
70+
}
71+
72+
// Create request authentication
73+
requestAuth, err := createRequestAuthentication(ctx, args, component)
74+
if err != nil {
75+
return nil, fmt.Errorf("failed to create request authentication: %w", err)
76+
}
77+
78+
// Create authorization policy
79+
authPolicy, err := createAuthorizationPolicy(ctx, component)
80+
if err != nil {
81+
return nil, fmt.Errorf("failed to create authorization policy: %w", err)
82+
}
83+
84+
component.Service = service
85+
component.ServiceAccount = serviceAccount
86+
component.ConfigMap = configMap
87+
component.Deployment = deployment
88+
component.VirtualService = virtualService
89+
component.RequestAuthentication = requestAuth
90+
component.AuthorizationPolicy = authPolicy
91+
92+
return component, nil
93+
}
94+
95+
// createServiceAccount creates a Kubernetes service account for the Quincey service
96+
func createServiceAccount(ctx *pulumi.Context, namespace pulumi.StringInput, parent *QuinceyComponent) (*corev1.ServiceAccount, error) {
97+
labels := utils.CreateResourceLabels(ComponentName, ServiceName, "signet", nil)
98+
99+
return corev1.NewServiceAccount(ctx, ServiceName, &corev1.ServiceAccountArgs{
100+
Metadata: &metav1.ObjectMetaArgs{
101+
Name: pulumi.String(ServiceName),
102+
Namespace: namespace,
103+
Labels: labels,
104+
},
105+
}, pulumi.Parent(parent))
106+
}
107+
108+
// createDeployment creates the Kubernetes deployment for the Quincey service
109+
func createDeployment(ctx *pulumi.Context, args *QuinceyComponentArgs, parent *QuinceyComponent) (*appsv1.Deployment, error) {
110+
labels := utils.CreateResourceLabels(ComponentName, ServiceName, "signet", nil)
111+
112+
containerPortInt := args.Env.QuinceyPort.ToStringOutput().ApplyT(func(s string) int {
113+
port, _ := strconv.Atoi(s)
114+
return port
115+
}).(pulumi.IntOutput)
116+
117+
return appsv1.NewDeployment(ctx, ServiceName, &appsv1.DeploymentArgs{
118+
Metadata: &metav1.ObjectMetaArgs{
119+
Name: pulumi.String(ServiceName),
120+
Namespace: args.Namespace,
121+
Labels: labels,
122+
},
123+
Spec: &appsv1.DeploymentSpecArgs{
124+
Selector: &metav1.LabelSelectorArgs{
125+
MatchLabels: labels,
126+
},
127+
Replicas: pulumi.Int(1),
128+
Template: &corev1.PodTemplateSpecArgs{
129+
Metadata: &metav1.ObjectMetaArgs{
130+
Labels: labels,
131+
},
132+
Spec: &corev1.PodSpecArgs{
133+
ServiceAccountName: pulumi.String(ServiceName),
134+
Containers: corev1.ContainerArray{
135+
createContainer(args, containerPortInt),
136+
},
137+
},
138+
},
139+
},
140+
}, pulumi.Parent(parent))
141+
}
142+
143+
// createConfigMap creates the ConfigMap for the Quincey service
144+
func createConfigMap(ctx *pulumi.Context, args *QuinceyComponentArgs, parent *QuinceyComponent) (*corev1.ConfigMap, error) {
145+
labels := utils.CreateResourceLabels(ComponentName, ServiceName, "signet", nil)
146+
147+
return utils.CreateConfigMap(ctx, ServiceName, args.Namespace, labels, args.Env)
148+
}
149+
150+
// createContainer creates the container specification for the Quincey service
151+
func createContainer(args *QuinceyComponentArgs, port pulumi.IntOutput) *corev1.ContainerArgs {
152+
return &corev1.ContainerArgs{
153+
Name: pulumi.String(ServiceName),
154+
Image: args.Image,
155+
EnvFrom: corev1.EnvFromSourceArray{
156+
&corev1.EnvFromSourceArgs{
157+
ConfigMapRef: &corev1.ConfigMapEnvSourceArgs{
158+
Name: pulumi.String(ServiceName),
159+
},
160+
},
161+
},
162+
}
163+
}
164+
165+
// createService creates the Kubernetes service for the Quincey service
166+
func createService(ctx *pulumi.Context, args *QuinceyComponentArgs, deployment *appsv1.Deployment, parent *QuinceyComponent) (*corev1.Service, error) {
167+
labels := utils.CreateResourceLabels(ComponentName, ServiceName, "signet", nil)
168+
169+
containerPortInt := args.Env.QuinceyPort.ToStringOutput().ApplyT(func(s string) int {
170+
port, err := strconv.Atoi(s)
171+
if err != nil {
172+
fmt.Printf("Error converting QuinceyPort to integer: %v. Using default port 8080.\n", err)
173+
return 8080
174+
}
175+
return port
176+
}).(pulumi.IntOutput)
177+
178+
return corev1.NewService(ctx, "quincey-server-service", &corev1.ServiceArgs{
179+
Metadata: &metav1.ObjectMetaArgs{
180+
Name: pulumi.String("quincey"),
181+
Namespace: args.Namespace,
182+
Labels: labels,
183+
},
184+
Spec: &corev1.ServiceSpecArgs{
185+
Selector: labels,
186+
Ports: corev1.ServicePortArray{
187+
&corev1.ServicePortArgs{
188+
Port: containerPortInt,
189+
TargetPort: containerPortInt,
190+
},
191+
},
192+
Type: pulumi.String("ClusterIP"),
193+
},
194+
}, pulumi.DependsOn([]pulumi.Resource{deployment}), pulumi.Parent(parent))
195+
}
196+
197+
// createVirtualService creates the Istio virtual service for the Quincey service
198+
func createVirtualService(ctx *pulumi.Context, args *QuinceyComponentArgs, service *corev1.Service, parent *QuinceyComponent) (*crd.CustomResource, error) {
199+
labels := utils.CreateResourceLabels(ComponentName, ServiceName, "signet", nil)
200+
201+
containerPortInt := args.Env.QuinceyPort.ToStringOutput().ApplyT(func(s string) int {
202+
port, err := strconv.Atoi(s)
203+
if err != nil {
204+
fmt.Printf("Error converting QuinceyPort to integer: %v. Using default port 8080.\n", err)
205+
return 8080
206+
}
207+
return port
208+
}).(pulumi.IntOutput)
209+
210+
// Get the service URL using the existing method
211+
serviceURL := parent.GetServiceURL()
212+
213+
return crd.NewCustomResource(ctx, "quincey-vservice", &crd.CustomResourceArgs{
214+
ApiVersion: pulumi.String("networking.istio.io/v1alpha3"),
215+
Kind: pulumi.String("VirtualService"),
216+
Metadata: &metav1.ObjectMetaArgs{
217+
Name: pulumi.String("quincey"),
218+
Namespace: args.Namespace,
219+
Labels: labels,
220+
},
221+
OtherFields: map[string]interface{}{
222+
"spec": map[string]interface{}{
223+
"hosts": args.VirtualServiceHosts,
224+
"gateways": []string{
225+
"default/init4-api-gateway",
226+
},
227+
"http": []map[string]interface{}{
228+
{
229+
"match": []map[string]interface{}{
230+
{
231+
"uri": map[string]interface{}{
232+
"prefix": "/signBlock",
233+
},
234+
},
235+
{
236+
"uri": map[string]interface{}{
237+
"prefix": "/healthCheck",
238+
},
239+
},
240+
},
241+
"route": []map[string]interface{}{
242+
{
243+
"destination": map[string]interface{}{
244+
"host": serviceURL,
245+
"port": map[string]interface{}{
246+
"number": containerPortInt,
247+
},
248+
},
249+
},
250+
},
251+
},
252+
},
253+
},
254+
},
255+
}, pulumi.DependsOn([]pulumi.Resource{service}), pulumi.Parent(parent))
256+
}
257+
258+
// createRequestAuthentication creates the Istio request authentication policy
259+
func createRequestAuthentication(ctx *pulumi.Context, args *QuinceyComponentArgs, parent *QuinceyComponent) (*crd.CustomResource, error) {
260+
labels := utils.CreateResourceLabels(ComponentName, ServiceName, "signet", nil)
261+
262+
return crd.NewCustomResource(ctx, "quincey-authorization-policy", &crd.CustomResourceArgs{
263+
ApiVersion: pulumi.String("security.istio.io/v1beta1"),
264+
Kind: pulumi.String("RequestAuthentication"),
265+
Metadata: &metav1.ObjectMetaArgs{
266+
Name: pulumi.String("quincey-jwt-policy"),
267+
Namespace: args.Namespace,
268+
Labels: labels,
269+
},
270+
OtherFields: map[string]interface{}{
271+
"spec": map[string]interface{}{
272+
"selector": map[string]interface{}{
273+
"matchLabels": labels,
274+
},
275+
"jwtRules": []map[string]interface{}{
276+
{
277+
"issuer": args.Env.OauthIssuer,
278+
"jwksUri": args.Env.OauthJwksUri,
279+
"outputClaimToHeaders": []map[string]interface{}{
280+
{
281+
"claim": "sub",
282+
"header": "x-jwt-claim-sub",
283+
},
284+
},
285+
},
286+
},
287+
},
288+
},
289+
}, pulumi.Parent(parent))
290+
}
291+
292+
// createAuthorizationPolicy creates the Istio authorization policy
293+
func createAuthorizationPolicy(ctx *pulumi.Context, parent *QuinceyComponent) (*crd.CustomResource, error) {
294+
labels := utils.CreateResourceLabels(ComponentName, ServiceName, "signet", nil)
295+
296+
return crd.NewCustomResource(ctx, "quincey-authorization-policy", &crd.CustomResourceArgs{
297+
ApiVersion: pulumi.String("security.istio.io/v1beta1"),
298+
Kind: pulumi.String("AuthorizationPolicy"),
299+
Metadata: &metav1.ObjectMetaArgs{
300+
Name: pulumi.String("quincey-jwt-auth-policy"),
301+
Namespace: parent.Service.Metadata.Namespace(),
302+
Labels: labels,
303+
},
304+
OtherFields: map[string]interface{}{
305+
"spec": map[string]interface{}{
306+
"selector": map[string]interface{}{
307+
"matchLabels": labels,
308+
},
309+
"action": "ALLOW",
310+
"rules": []map[string]interface{}{
311+
{
312+
"from": []map[string]interface{}{
313+
{
314+
"source": map[string]interface{}{
315+
"requestPrincipals": []string{
316+
"*",
317+
},
318+
},
319+
},
320+
},
321+
},
322+
},
323+
},
324+
},
325+
}, pulumi.Parent(parent))
326+
}
327+
328+
// GetServiceURL returns the URL of the builder service
329+
func (c *QuinceyComponent) GetServiceURL() pulumi.StringOutput {
330+
return pulumi.Sprintf("http://%s.%s.svc.cluster.local", c.Service.Metadata.Name(), c.Service.Metadata.Namespace())
331+
}
332+
333+
// GetMetricsURL returns the URL of the builder metrics endpoint
334+
func (c *QuinceyComponent) GetMetricsURL() pulumi.StringOutput {
335+
return pulumi.Sprintf("http://%s.%s.svc.cluster.local:%d/metrics",
336+
c.Service.Metadata.Name(),
337+
c.Service.Metadata.Namespace(),
338+
DefaultMetricsPort)
339+
}

0 commit comments

Comments
 (0)