Skip to content

Commit

Permalink
remove orphans
Browse files Browse the repository at this point in the history
  • Loading branch information
davidmdm committed Feb 17, 2024
1 parent 51bab9b commit 7efdb5d
Show file tree
Hide file tree
Showing 6 changed files with 126 additions and 65 deletions.
3 changes: 2 additions & 1 deletion cmd/exp/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,10 @@ import (
"os"
"syscall"

"github.com/davidmdm/x/xcontext"
"github.com/tetratelabs/wazero"
"github.com/tetratelabs/wazero/imports/wasi_snapshot_preview1"

"github.com/davidmdm/x/xcontext"
)

func main() {
Expand Down
9 changes: 7 additions & 2 deletions cmd/halloumi/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,11 +12,12 @@ import (
"slices"
"syscall"

"github.com/davidmdm/x/xcontext"
"github.com/davidmdm/x/xerr"
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
"k8s.io/client-go/tools/clientcmd"

"github.com/davidmdm/x/xcontext"
"github.com/davidmdm/x/xerr"

"github.com/davidmdm/halloumi/internal/k8"
"github.com/davidmdm/halloumi/internal/wasi"
)
Expand Down Expand Up @@ -74,6 +75,10 @@ func run() error {
return fmt.Errorf("failed to create revision: %w", err)
}

if err := client.RemoveOrphans(ctx, cfg.ReleaseName); err != nil {
return fmt.Errorf("failed to remove orhpans: %w", err)
}

return nil
}

Expand Down
57 changes: 33 additions & 24 deletions cmd/program/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,6 @@ import (
"encoding/json"
"fmt"
"os"

v1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/runtime"
)

func main() {
Expand All @@ -21,24 +17,37 @@ func run() error {
encoder := json.NewEncoder(os.Stdout)
encoder.SetIndent("", " ")

return encoder.Encode([]runtime.Object{
&v1.Pod{
TypeMeta: metav1.TypeMeta{
Kind: "Pod",
APIVersion: "v1",
},
ObjectMeta: metav1.ObjectMeta{
Name: "app",
},
Spec: v1.PodSpec{
Containers: []v1.Container{
{
Name: "echo",
Image: "alpine:latest",
Command: []string{"watch", "echo", "hello", "world"},
},
},
},
},
})
fmt.Println(`[{
"apiVersion": "apps/v1",
"kind": "Deployment",
"metadata": {
"name": "sample-app-prod"
},
"spec": {
"replicas": 3,
"selector": {
"matchLabels": {
"app": "sample-app"
}
},
"template": {
"metadata": {
"labels": {
"app": "sample-app"
}
},
"spec": {
"containers": [
{
"name": "web-app",
"image": "alpine:latest",
"command": ["watch", "echo", "hello"]
}
]
}
}
}
}]`)

return nil
}
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ require (
github.com/davidmdm/x/xcontext v0.0.2
github.com/davidmdm/x/xerr v0.0.3
github.com/tetratelabs/wazero v1.6.0
gopkg.in/yaml.v3 v3.0.1
k8s.io/api v0.29.2
k8s.io/apimachinery v0.29.2
k8s.io/client-go v0.29.2
Expand Down Expand Up @@ -41,7 +42,6 @@ require (
google.golang.org/protobuf v1.32.0 // indirect
gopkg.in/inf.v0 v0.9.1 // indirect
gopkg.in/yaml.v2 v2.4.0 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
k8s.io/klog/v2 v2.120.1 // indirect
k8s.io/kube-openapi v0.0.0-20240209001042-7a0d5b415232 // indirect
k8s.io/utils v0.0.0-20240102154912-e7106e64919e // indirect
Expand Down
117 changes: 81 additions & 36 deletions internal/k8/k8.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@ import (
"k8s.io/client-go/kubernetes"
"k8s.io/client-go/rest"

"github.com/davidmdm/x/xerr"

"github.com/davidmdm/halloumi/internal"
)

Expand Down Expand Up @@ -51,38 +53,12 @@ func NewClient(cfg *rest.Config) (*Client, error) {
}

func (client Client) ApplyResource(ctx context.Context, resource *unstructured.Unstructured) error {
gvk := schema.FromAPIVersionAndKind(resource.GetAPIVersion(), resource.GetKind())

resources, err := client.discovery.ServerResourcesForGroupVersion(gvk.GroupVersion().String())
resourceInterface, err := client.getDynamicResourceInterface(resource)
if err != nil {
return fmt.Errorf("failed to discover resources for %s: %w", gvk.GroupVersion().String(), err)
}

resourceName := func() string {
for _, api := range resources.APIResources {
if api.Kind == gvk.Kind && !strings.Contains(api.Name, "/") {
return api.Name
}
}
return ""
}()

gvr := schema.GroupVersionResource{
Group: gvk.Group,
Version: gvk.Version,
Resource: resourceName,
return fmt.Errorf("failed to resolve resource: %w", err)
}

namespace := resource.GetNamespace()
if namespace == "" {
namespace = "default"
}

_, err = client.dynamic.
Resource(gvr).
Namespace(namespace).
Apply(ctx, resource.GetName(), resource, metav1.ApplyOptions{FieldManager: "halloumi"})

_, err = resourceInterface.Apply(ctx, resource.GetName(), resource, metav1.ApplyOptions{FieldManager: "halloumi"})
return err
}

Expand Down Expand Up @@ -132,7 +108,7 @@ func (client Client) MakeRevision(ctx context.Context, release string, resources
return err
}

func (client Client) GetCurrentRevision(ctx context.Context, release string) (*internal.Revision, error) {
func (client Client) RemoveOrphans(ctx context.Context, release string) error {
name := "halloumi-" + release

configmap, err := client.clientset.
Expand All @@ -141,17 +117,86 @@ func (client Client) GetCurrentRevision(ctx context.Context, release string) (*i
Get(ctx, name, metav1.GetOptions{})

if kerrors.IsNotFound(err) {
return nil, nil
return nil
}

if err != nil {
return err
}

current, _ := strconv.Atoi(configmap.Data["current"])
if current == 1 {
return nil
}

var currentRevision internal.Revision
if err := json.Unmarshal([]byte(configmap.Data[strconv.Itoa(current)]), &currentRevision); err != nil {
return err
}

canonical := func(resource *unstructured.Unstructured) string {
return resource.GetNamespace() + "/" + resource.GetKind() + "/" + resource.GetName()
}

set := map[string]struct{}{}
for _, resource := range currentRevision.Resources {
set[canonical(resource)] = struct{}{}
}

var previousRevision internal.Revision
if err := json.Unmarshal([]byte(configmap.Data[strconv.Itoa(current-1)]), &previousRevision); err != nil {
return err
}

var errs []error

for _, resource := range previousRevision.Resources {
if _, ok := set[canonical(resource)]; ok {
continue
}

resourceInterface, err := client.getDynamicResourceInterface(resource)
if err != nil {
errs = append(errs, fmt.Errorf("failed to resolve resource %s: %w", canonical(resource), err))
continue
}

if err := resourceInterface.Delete(ctx, resource.GetName(), metav1.DeleteOptions{}); err != nil {
errs = append(errs, fmt.Errorf("failed to delete %s: %w", canonical(resource), err))
continue
}
}

return xerr.MultiErrOrderedFrom("", errs...)
}

func (client Client) getDynamicResourceInterface(resource *unstructured.Unstructured) (dynamic.ResourceInterface, error) {
gvk := schema.FromAPIVersionAndKind(resource.GetAPIVersion(), resource.GetKind())

resources, err := client.discovery.ServerResourcesForGroupVersion(gvk.GroupVersion().String())
if err != nil {
return nil, err
return nil, fmt.Errorf("failed to discover resources for %s: %w", gvk.GroupVersion().String(), err)
}

var revision internal.Revision
if err := json.Unmarshal([]byte(configmap.Data[configmap.Data["current"]]), &revision); err != nil {
return nil, err
resourceName := func() string {
for _, api := range resources.APIResources {
if api.Kind == gvk.Kind && !strings.Contains(api.Name, "/") {
return api.Name
}
}
return ""
}()

gvr := schema.GroupVersionResource{
Group: gvk.Group,
Version: gvk.Version,
Resource: resourceName,
}

namespace := resource.GetNamespace()
if namespace == "" {
namespace = "default"
}

return &revision, nil
return client.dynamic.Resource(gvr).Namespace(namespace), nil
}
3 changes: 2 additions & 1 deletion internal/wasi/wasi.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,10 @@ import (
"crypto/rand"
"fmt"

"github.com/davidmdm/x/xerr"
"github.com/tetratelabs/wazero"
"github.com/tetratelabs/wazero/imports/wasi_snapshot_preview1"

"github.com/davidmdm/x/xerr"
)

func Execute(ctx context.Context, wasm []byte, release string, args ...string) (output []byte, err error) {
Expand Down

0 comments on commit 7efdb5d

Please sign in to comment.