-
Notifications
You must be signed in to change notification settings - Fork 48
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
* feat: add configmap resource Signed-off-by: warjiang <[email protected]> * feat: add NoDataSelect & channel for get cm list Signed-off-by: warjiang <[email protected]> * feat: implement REST api for configmap Signed-off-by: warjiang <[email protected]> * chore: rm configmap list_test Signed-off-by: dingwenjiang <[email protected]> --------- Signed-off-by: warjiang <[email protected]> Signed-off-by: dingwenjiang <[email protected]>
- Loading branch information
Showing
8 changed files
with
270 additions
and
0 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,40 @@ | ||
package service | ||
|
||
import ( | ||
"github.com/gin-gonic/gin" | ||
"github.com/karmada-io/dashboard/cmd/api/app/router" | ||
"github.com/karmada-io/dashboard/cmd/api/app/types/common" | ||
"github.com/karmada-io/dashboard/pkg/client" | ||
"github.com/karmada-io/dashboard/pkg/resource/configmap" | ||
) | ||
|
||
func handleGetConfigMap(c *gin.Context) { | ||
k8sClient := client.InClusterClientForKarmadaApiServer() | ||
dataSelect := common.ParseDataSelectPathParameter(c) | ||
nsQuery := common.ParseNamespacePathParameter(c) | ||
result, err := configmap.GetConfigMapList(k8sClient, nsQuery, dataSelect) | ||
if err != nil { | ||
common.Fail(c, err) | ||
return | ||
} | ||
common.Success(c, result) | ||
} | ||
|
||
func handleGetConfigMapDetail(c *gin.Context) { | ||
k8sClient := client.InClusterClientForKarmadaApiServer() | ||
namespace := c.Param("namespace") | ||
name := c.Param("name") | ||
result, err := configmap.GetConfigMapDetail(k8sClient, namespace, name) | ||
if err != nil { | ||
common.Fail(c, err) | ||
return | ||
} | ||
common.Success(c, result) | ||
} | ||
|
||
func init() { | ||
r := router.V1() | ||
r.GET("/configmap", handleGetConfigMap) | ||
r.GET("/configmap/:namespace", handleGetConfigMap) | ||
r.GET("/configmap/:namespace/:name", handleGetConfigMapDetail) | ||
} |
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,40 @@ | ||
package configmap | ||
|
||
import ( | ||
"github.com/karmada-io/dashboard/pkg/dataselect" | ||
api "k8s.io/api/core/v1" | ||
) | ||
|
||
// The code below allows to perform complex data section on []api.ConfigMap | ||
|
||
type ConfigMapCell api.ConfigMap | ||
|
||
func (self ConfigMapCell) GetProperty(name dataselect.PropertyName) dataselect.ComparableValue { | ||
switch name { | ||
case dataselect.NameProperty: | ||
return dataselect.StdComparableString(self.ObjectMeta.Name) | ||
case dataselect.CreationTimestampProperty: | ||
return dataselect.StdComparableTime(self.ObjectMeta.CreationTimestamp.Time) | ||
case dataselect.NamespaceProperty: | ||
return dataselect.StdComparableString(self.ObjectMeta.Namespace) | ||
default: | ||
// if name is not supported then just return a constant dummy value, sort will have no effect. | ||
return nil | ||
} | ||
} | ||
|
||
func toCells(std []api.ConfigMap) []dataselect.DataCell { | ||
cells := make([]dataselect.DataCell, len(std)) | ||
for i := range std { | ||
cells[i] = ConfigMapCell(std[i]) | ||
} | ||
return cells | ||
} | ||
|
||
func fromCells(cells []dataselect.DataCell) []api.ConfigMap { | ||
std := make([]api.ConfigMap, len(cells)) | ||
for i := range std { | ||
std[i] = api.ConfigMap(cells[i].(ConfigMapCell)) | ||
} | ||
return std | ||
} |
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,41 @@ | ||
package configmap | ||
|
||
import ( | ||
"context" | ||
"log" | ||
|
||
v1 "k8s.io/api/core/v1" | ||
metaV1 "k8s.io/apimachinery/pkg/apis/meta/v1" | ||
"k8s.io/client-go/kubernetes" | ||
) | ||
|
||
// ConfigMapDetail API resource provides mechanisms to inject containers with configuration data while keeping | ||
// containers agnostic of Kubernetes | ||
type ConfigMapDetail struct { | ||
// Extends list item structure. | ||
ConfigMap `json:",inline"` | ||
|
||
// Data contains the configuration data. | ||
// Each key must be a valid DNS_SUBDOMAIN with an optional leading dot. | ||
Data map[string]string `json:"data,omitempty"` | ||
} | ||
|
||
// GetConfigMapDetail returns detailed information about a config map | ||
func GetConfigMapDetail(client kubernetes.Interface, namespace, name string) (*ConfigMapDetail, error) { | ||
log.Printf("Getting details of %s config map in %s namespace", name, namespace) | ||
|
||
rawConfigMap, err := client.CoreV1().ConfigMaps(namespace).Get(context.TODO(), name, metaV1.GetOptions{}) | ||
|
||
if err != nil { | ||
return nil, err | ||
} | ||
|
||
return getConfigMapDetail(rawConfigMap), nil | ||
} | ||
|
||
func getConfigMapDetail(rawConfigMap *v1.ConfigMap) *ConfigMapDetail { | ||
return &ConfigMapDetail{ | ||
ConfigMap: toConfigMap(rawConfigMap.ObjectMeta), | ||
Data: rawConfigMap.Data, | ||
} | ||
} |
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,37 @@ | ||
package configmap | ||
|
||
import ( | ||
"github.com/karmada-io/dashboard/pkg/common/types" | ||
"reflect" | ||
"testing" | ||
|
||
v1 "k8s.io/api/core/v1" | ||
metaV1 "k8s.io/apimachinery/pkg/apis/meta/v1" | ||
) | ||
|
||
func TestGetConfigMapDetail(t *testing.T) { | ||
cases := []struct { | ||
configMaps *v1.ConfigMap | ||
expected *ConfigMapDetail | ||
}{ | ||
{ | ||
&v1.ConfigMap{ | ||
Data: map[string]string{"app": "my-name"}, ObjectMeta: metaV1.ObjectMeta{Name: "foo"}, | ||
}, | ||
&ConfigMapDetail{ | ||
ConfigMap: ConfigMap{ | ||
TypeMeta: types.TypeMeta{Kind: "configmap"}, | ||
ObjectMeta: types.ObjectMeta{Name: "foo"}, | ||
}, | ||
Data: map[string]string{"app": "my-name"}, | ||
}, | ||
}, | ||
} | ||
for _, c := range cases { | ||
actual := getConfigMapDetail(c.configMaps) | ||
if !reflect.DeepEqual(actual, c.expected) { | ||
t.Errorf("getConfigMapDetail(%#v) == \n%#v\nexpected \n%#v\n", | ||
c.configMaps, actual, c.expected) | ||
} | ||
} | ||
} |
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,80 @@ | ||
package configmap | ||
|
||
import ( | ||
"github.com/karmada-io/dashboard/pkg/common/errors" | ||
"github.com/karmada-io/dashboard/pkg/common/types" | ||
"github.com/karmada-io/dashboard/pkg/dataselect" | ||
"github.com/karmada-io/dashboard/pkg/resource/common" | ||
"log" | ||
|
||
v1 "k8s.io/api/core/v1" | ||
metaV1 "k8s.io/apimachinery/pkg/apis/meta/v1" | ||
"k8s.io/client-go/kubernetes" | ||
) | ||
|
||
// ConfigMapList contains a list of Config Maps in the cluster. | ||
type ConfigMapList struct { | ||
ListMeta types.ListMeta `json:"listMeta"` | ||
|
||
// Unordered list of Config Maps | ||
Items []ConfigMap `json:"items"` | ||
|
||
// List of non-critical errors, that occurred during resource retrieval. | ||
Errors []error `json:"errors"` | ||
} | ||
|
||
// ConfigMap API resource provides mechanisms to inject containers with configuration data while keeping | ||
// containers agnostic of Kubernetes | ||
type ConfigMap struct { | ||
ObjectMeta types.ObjectMeta `json:"objectMeta"` | ||
TypeMeta types.TypeMeta `json:"typeMeta"` | ||
} | ||
|
||
// GetConfigMapList returns a list of all ConfigMaps in the cluster. | ||
func GetConfigMapList(client kubernetes.Interface, nsQuery *common.NamespaceQuery, dsQuery *dataselect.DataSelectQuery) (*ConfigMapList, error) { | ||
log.Printf("Getting list config maps in the namespace %s", nsQuery.ToRequestParam()) | ||
channels := &common.ResourceChannels{ | ||
ConfigMapList: common.GetConfigMapListChannel(client, nsQuery, 1), | ||
} | ||
|
||
return GetConfigMapListFromChannels(channels, dsQuery) | ||
} | ||
|
||
// GetConfigMapListFromChannels returns a list of all Config Maps in the cluster reading required resource list once from the channels. | ||
func GetConfigMapListFromChannels(channels *common.ResourceChannels, dsQuery *dataselect.DataSelectQuery) (*ConfigMapList, error) { | ||
configMaps := <-channels.ConfigMapList.List | ||
err := <-channels.ConfigMapList.Error | ||
nonCriticalErrors, criticalError := errors.ExtractErrors(err) | ||
if criticalError != nil { | ||
return nil, criticalError | ||
} | ||
|
||
result := toConfigMapList(configMaps.Items, nonCriticalErrors, dsQuery) | ||
|
||
return result, nil | ||
} | ||
|
||
func toConfigMap(meta metaV1.ObjectMeta) ConfigMap { | ||
return ConfigMap{ | ||
ObjectMeta: types.NewObjectMeta(meta), | ||
TypeMeta: types.NewTypeMeta(types.ResourceKindConfigMap), | ||
} | ||
} | ||
|
||
func toConfigMapList(configMaps []v1.ConfigMap, nonCriticalErrors []error, dsQuery *dataselect.DataSelectQuery) *ConfigMapList { | ||
result := &ConfigMapList{ | ||
Items: make([]ConfigMap, 0), | ||
ListMeta: types.ListMeta{TotalItems: len(configMaps)}, | ||
Errors: nonCriticalErrors, | ||
} | ||
|
||
configMapCells, filteredTotal := dataselect.GenericDataSelectWithFilter(toCells(configMaps), dsQuery) | ||
configMaps = fromCells(configMapCells) | ||
result.ListMeta = types.ListMeta{TotalItems: filteredTotal} | ||
|
||
for _, item := range configMaps { | ||
result.Items = append(result.Items, toConfigMap(item.ObjectMeta)) | ||
} | ||
|
||
return result | ||
} |