* Copyright (c) 2024 Huawei Technologies Co., Ltd.
* openFuyao is licensed under Mulan PSL v2.
* You can use this software according to the terms and conditions of the Mulan PSL v2.
* You may obtain a copy of Mulan PSL v2 at:
* http://license.coscl.org.cn/MulanPSL2
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
* See the Mulan PSL v2 for more details.
*/
package main
import (
"context"
"fmt"
"os"
"path/filepath"
"regexp"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/client-go/kubernetes"
"k8s.io/client-go/tools/clientcmd"
klog "k8s.io/klog/v2"
v1 "openfuyao.com/colocation-service/pkg/apis/colocation/v1"
"openfuyao.com/colocation-service/pkg/client/clientset/versioned"
)
func main() {
klog.InitFlags(nil)
kubeconfigPath := loadKubeconfigPath()
restClientConfig, err := clientcmd.BuildConfigFromFlags("", kubeconfigPath)
if err != nil {
klog.Fatalf("failed to load kubeconfig from %s: %v", kubeconfigPath, err)
}
client, err := versioned.NewForConfig(restClientConfig)
if err != nil {
klog.Fatalf("failed to create colocation client: %v", err)
}
clientset, err := kubernetes.NewForConfig(restClientConfig)
if err != nil {
klog.Fatalf("failed to create kubernetes client: %v", err)
}
createTestRule(client)
printRules(client, clientset)
}
func loadKubeconfigPath() string {
path := os.Getenv("KUBECONFIG")
if path != "" {
return path
}
home, err := os.UserHomeDir()
if err != nil {
klog.Fatalf("failed to get user home directory: %v", err)
}
return filepath.Join(home, ".kube", "config")
}
func createTestRule(client versioned.Interface) {
rule := v1.ColocationWorkloadMatchRule{}
rule.TypeMeta.APIVersion = "v1"
rule.TypeMeta.Kind = "ColocationWorkloadMatchRule"
rule.ObjectMeta.Namespace = os.Getenv("POD_NAMESPACE")
rule.ObjectMeta.Name = "ab-ce.ef_okabc"
rule.Spec.Selectors = []v1.Selector{
{
Namespace: os.Getenv("POD_NAMESPACE"),
Name: "nginx",
WorkloadTypes: []string{"Deployment"},
Selector: &metav1.LabelSelector{
MatchLabels: map[string]string{
"app": "nginx",
},
},
},
}
isValid := StringValidityCheck(rule.ObjectMeta.Name, NormalMode)
klog.Info(rule.ObjectMeta.Name, isValid)
if !isValid {
fmt.Println("rule name must consist of alphanumeric characters, '-', '_' or '.', " +
"and must start and end with an alphanumeric character")
return
}
savedRule, err := client.ColocationV1().ColocationWorkloadMatchRules(
rule.ObjectMeta.Namespace).Create(context.TODO(), &rule, metav1.CreateOptions{})
klog.Info(savedRule.ObjectMeta.Name, err)
}
func printRules(client versioned.Interface, clientset kubernetes.Interface) {
rules, _ := client.ColocationV1().ColocationWorkloadMatchRules("").List(context.TODO(), metav1.ListOptions{})
for _, rule := range rules.Items {
fmt.Println("rule.name:", rule.ObjectMeta.Name)
for _, selector := range rule.Spec.Selectors {
printSelectorPods(clientset, selector)
}
}
}
func printSelectorPods(clientset kubernetes.Interface, selector v1.Selector) {
fmt.Println(" rule.namespace:", selector.Namespace)
labelSelector, err := metav1.LabelSelectorAsSelector(selector.Selector)
if err != nil {
fmt.Printf(" couldn't convert rule selector: %v\n", err)
}
fmt.Println(" rule.labelSelector:", labelSelector.String())
pods, err := clientset.CoreV1().Pods(selector.Namespace).List(context.TODO(),
metav1.ListOptions{LabelSelector: labelSelector.String()})
if err != nil {
fmt.Printf(" couldn't list pods: %v\n", err)
}
for _, pod := range pods.Items {
fmt.Println(" rule.match.workload:", pod.Name)
}
}
type StringCheckMode string
const (
NormalMode StringCheckMode = "normal"
LabelKeyMode StringCheckMode = "label_key_mode"
)
func StringValidityCheck(input string, mode StringCheckMode) bool {
if input == "" {
return false
}
var pattern string
if mode == NormalMode {
pattern = "^([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9]$"
} else if mode == LabelKeyMode {
pattern = "[a-z0-9]([-a-z0-9]*[a-z0-9])?(\\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*"
}
re := regexp.MustCompile(pattern)
return re.MatchString(input)
}