-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #1 from DescartesResearch/general_refactoring
General package refactoring, api restructuring, klog logging
- Loading branch information
Showing
86 changed files
with
2,891 additions
and
1,952 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
# Package Descriptions | ||
|
||
## cmd | ||
|
||
Contains main file and command line flag parsing | ||
|
||
## internal | ||
|
||
Contains generic helper structs and functions: | ||
|
||
- broadcast: A utility packages for broadcasting channels | ||
- infrastructure: Definition and handling of REST endpoint handlers | ||
|
||
## pkg | ||
|
||
Contains the core functionality and interfaces of this adapter: | ||
|
||
- control: The core logic regarding essential resource types, e.g., pods and nodes | ||
- interfaces: The REST interfaces for communication with MiSim and Kubernetes components | ||
- misim: Misim specific data types and logic | ||
- storage: Interfaces and structs for storing data in the adapter |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,48 @@ | ||
package infrastructure | ||
|
||
import ( | ||
apps "k8s.io/api/apps/v1" | ||
batch "k8s.io/api/batch/v1" | ||
core "k8s.io/api/core/v1" | ||
policy "k8s.io/api/policy/v1" | ||
storage "k8s.io/api/storage/v1" | ||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" | ||
"k8s.io/apimachinery/pkg/runtime" | ||
cluster "sigs.k8s.io/cluster-api/api/v1beta1" | ||
exp "sigs.k8s.io/cluster-api/exp/api/v1beta1" | ||
) | ||
|
||
func GetEmptyResourceList(resourceType string) runtime.Object { | ||
switch resourceType { | ||
case "replicasets": | ||
return &apps.ReplicaSetList{TypeMeta: metav1.TypeMeta{Kind: "ReplicaSetList", APIVersion: "apps/v1"}, Items: nil} | ||
case "persistentvolumes": | ||
return &core.PersistentVolumeList{TypeMeta: metav1.TypeMeta{Kind: "PersistentVolumeList", APIVersion: "v1"}, Items: nil} | ||
case "statefulsets": | ||
return &apps.StatefulSetList{TypeMeta: metav1.TypeMeta{Kind: "StatefulSetList", APIVersion: "apps/v1"}, Items: nil} | ||
case "storageclasses": | ||
return &storage.StorageClassList{TypeMeta: metav1.TypeMeta{Kind: "StorageClassList", APIVersion: "storage.k8s.io/v1"}, Items: nil} | ||
case "csidrivers": | ||
return &storage.CSIDriverList{TypeMeta: metav1.TypeMeta{Kind: "CSIDriverList", APIVersion: "storage.k8s.io/v1"}, Items: nil} | ||
case "poddisruptionbudgets": | ||
return &policy.PodDisruptionBudgetList{TypeMeta: metav1.TypeMeta{Kind: "PodDisruptionBudgetList", APIVersion: "policy/v1"}, Items: nil} | ||
case "csinodes": | ||
return &storage.CSINodeList{TypeMeta: metav1.TypeMeta{Kind: "CSINodeList", APIVersion: "storage.k8s.io/v1"}, Items: nil} | ||
case "persistentvolumeclaims": | ||
return &core.PersistentVolumeClaimList{TypeMeta: metav1.TypeMeta{Kind: "PersistentVolumeClaimList", APIVersion: "v1"}, Items: nil} | ||
case "csistoragecapacities": | ||
return &storage.CSIStorageCapacityList{TypeMeta: metav1.TypeMeta{Kind: "CSIStorageCapacityList", APIVersion: "storage.k8s.io/v1beta1"}, Items: nil} | ||
case "services": | ||
return &core.ServiceList{TypeMeta: metav1.TypeMeta{Kind: "ServiceList", APIVersion: "v1"}, Items: nil} | ||
case "replicationcontrollers": | ||
return &core.ReplicationControllerList{TypeMeta: metav1.TypeMeta{Kind: "ReplicationControllerList", APIVersion: "v1"}, Items: nil} | ||
case "jobs": | ||
return &batch.JobList{TypeMeta: metav1.TypeMeta{Kind: "JobList", APIVersion: "batch/v1"}, Items: nil} | ||
case "machinedeployments": | ||
return &cluster.MachineDeploymentList{TypeMeta: metav1.TypeMeta{Kind: "MachineDeploymentList", APIVersion: "cluster.x-k8s.io/v1beta1"}, Items: nil} | ||
case "machinepools": | ||
return &exp.MachinePoolList{TypeMeta: metav1.TypeMeta{Kind: "MachinePoolList", APIVersion: "cluster.x-k8s.io/v1beta1"}, Items: nil} | ||
default: | ||
return nil | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
package infrastructure | ||
|
||
import ( | ||
"net/http" | ||
) | ||
|
||
type Endpoint func(w http.ResponseWriter, r *http.Request) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,61 @@ | ||
package infrastructure | ||
|
||
import ( | ||
"encoding/json" | ||
"github.com/gorilla/mux" | ||
"io" | ||
"k8s.io/klog/v2" | ||
"net/http" | ||
) | ||
|
||
func HandleRequest[T any](supplier func() T) Endpoint { | ||
return func(w http.ResponseWriter, r *http.Request) { | ||
klog.V(7).Infof("Req: %s%s?%s", r.Host, r.URL.Path, r.URL.RawQuery) | ||
w.Header().Set("Content-Type", "application/json") | ||
resourceList := supplier() | ||
json.NewEncoder(w).Encode(resourceList) | ||
} | ||
} | ||
|
||
func HandleRequestWithBody[B any, T any](supplier func(B) T) Endpoint { | ||
return func(w http.ResponseWriter, r *http.Request) { | ||
klog.V(7).Infof("Req: %s%s?%s", r.Host, r.URL.Path, r.URL.RawQuery) | ||
w.Header().Set("Content-Type", "application/json") | ||
reqBody, _ := io.ReadAll(r.Body) | ||
var payload B | ||
err := json.Unmarshal(reqBody, &payload) | ||
if err != nil { | ||
klog.V(1).ErrorS(err, "There was an error decoding the json. err = %s", err) | ||
w.WriteHeader(500) | ||
return | ||
} | ||
resourceList := supplier(payload) | ||
json.NewEncoder(w).Encode(resourceList) | ||
} | ||
} | ||
|
||
func HandleRequestWithParamsAndBody[B any, T any](supplier func(map[string]string, B) T) Endpoint { | ||
return func(w http.ResponseWriter, r *http.Request) { | ||
klog.V(7).Infof("Req: %s%s?%s", r.Host, r.URL.Path, r.URL.RawQuery) | ||
w.Header().Set("Content-Type", "application/json") | ||
reqBody, _ := io.ReadAll(r.Body) | ||
var payload B | ||
err := json.Unmarshal(reqBody, &payload) | ||
if err != nil { | ||
klog.V(1).ErrorS(err, "There was an error decoding the json. err = %s", err) | ||
w.WriteHeader(500) | ||
return | ||
} | ||
resourceList := supplier(mux.Vars(r), payload) | ||
json.NewEncoder(w).Encode(resourceList) | ||
} | ||
} | ||
|
||
func HandleRequestWithParams[T any](supplier func(map[string]string) T) Endpoint { | ||
return func(w http.ResponseWriter, r *http.Request) { | ||
klog.V(7).Infof("Req: %s%s?%s", r.Host, r.URL.Path, r.URL.RawQuery) | ||
w.Header().Set("Content-Type", "application/json") | ||
resourceList := supplier(mux.Vars(r)) | ||
json.NewEncoder(w).Encode(resourceList) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,57 @@ | ||
package infrastructure | ||
|
||
import ( | ||
"encoding/json" | ||
"k8s.io/klog/v2" | ||
"net/http" | ||
"strings" | ||
) | ||
|
||
// If query parameter "watch" is added writes empty | ||
// Writes {"metadata": null, "items": null} to the response | ||
func UnsupportedResource() Endpoint { | ||
return func(w http.ResponseWriter, r *http.Request) { | ||
klog.V(7).Infof("Req: %s%s?%s", r.Host, r.URL.Path, r.URL.RawQuery) | ||
w.Header().Set("Content-Type", "application/json") | ||
if r.URL.Query().Get("watch") != "" { | ||
ctx := r.Context() | ||
flusher, ok := w.(http.Flusher) | ||
if !ok { | ||
http.NotFound(w, r) | ||
return | ||
} | ||
|
||
// Send the initial headers saying we're gonna stream the response. | ||
w.Header().Set("Transfer-Encoding", "chunked") | ||
w.WriteHeader(http.StatusOK) | ||
flusher.Flush() | ||
|
||
for { | ||
select { | ||
case <-ctx.Done(): | ||
klog.V(6).Info("Client stopped listening") | ||
return | ||
} | ||
} | ||
} else { | ||
// if no watch we just list the resource | ||
// just return nothing here, to *string datatype enables us to use nil | ||
// y := map[string]*string{"metadata": nil, "items": nil} | ||
resourceType := strings.Split(r.URL.Path, "/") | ||
|
||
y := GetEmptyResourceList(resourceType[len(resourceType)-1]) | ||
var err error | ||
if y == nil { | ||
z := map[string]*string{"metadata": nil, "items": nil} | ||
err = json.NewEncoder(w).Encode(z) | ||
klog.V(6).ErrorS(err, "unseen type %s\n", resourceType[len(resourceType)-1]) | ||
} else { | ||
err = json.NewEncoder(w).Encode(y) | ||
} | ||
if err != nil { | ||
klog.V(1).ErrorS(err, "unable to encode empty resource list, error is: %v", err) | ||
return | ||
} | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,67 @@ | ||
package infrastructure | ||
|
||
import ( | ||
"encoding/json" | ||
"go-kube/internal/broadcast" | ||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" | ||
"k8s.io/klog/v2" | ||
"net/http" | ||
) | ||
|
||
func HandleWatchableRequest[T any](supplier func() (T, *broadcast.BroadcastServer[metav1.WatchEvent])) Endpoint { | ||
return func(w http.ResponseWriter, r *http.Request) { | ||
klog.V(7).Infof("Req: %s%s?%s", r.Host, r.URL.Path, r.URL.RawQuery) | ||
w.Header().Set("Content-Type", "application/json") | ||
resourceList, broadcastServer := supplier() | ||
if r.URL.Query().Get("watch") != "" { | ||
// watch initiated HTTP streaming answers | ||
// Sources: https://gist.github.com/vmarmol/b967b29917a34d9307ce | ||
// https://github.com/kubernetes/kubernetes/blob/828495bcc013b77bb63bcb64111e094e455715bb/staging/src/k8s.io/apiserver/pkg/endpoints/handlers/watch.go#L181 | ||
// https://stackoverflow.com/questions/54890809/how-to-use-request-context-instead-of-closenotifier | ||
ctx := r.Context() | ||
flusher, ok := w.(http.Flusher) | ||
if !ok { | ||
http.NotFound(w, r) | ||
return | ||
} | ||
// Send the initial headers saying we're gonna stream the response. | ||
w.Header().Set("Transfer-Encoding", "chunked") | ||
w.WriteHeader(http.StatusOK) | ||
flusher.Flush() | ||
|
||
enc := json.NewEncoder(w) | ||
|
||
eventChannel := broadcastServer.Subscribe() | ||
defer broadcastServer.CancelSubscription(eventChannel) | ||
|
||
klog.V(6).Infof("Client started listening (%s)...", r.URL.Path) | ||
for { | ||
klog.V(6).Infof("Client waits for result (%s)...", r.URL.Path) | ||
select { | ||
case <-ctx.Done(): | ||
klog.V(6).Infof("Client stopped listening (%s)", r.URL.Path) | ||
return | ||
case event := <-eventChannel: | ||
klog.V(6).Infof("Received event for client (%s) of type %s", r.URL.Path, event.Type) | ||
if err := enc.Encode(event); err != nil { | ||
klog.V(1).ErrorS(err, "unable to encode watch object %T: %v", event, err) | ||
// client disconnect. | ||
return | ||
} | ||
if len(eventChannel) == 0 { | ||
flusher.Flush() | ||
klog.V(6).Infof("Client flushed (%s)!", r.URL.Path) | ||
//return | ||
} | ||
} | ||
} | ||
} else { | ||
// if no watch we just list the resource | ||
err := json.NewEncoder(w).Encode(resourceList) | ||
if err != nil { | ||
klog.V(1).ErrorS(err, "unable to encode resource list, error is: %v", err) | ||
return | ||
} | ||
} | ||
} | ||
} |
Oops, something went wrong.