mirror of
https://github.com/onepanelio/onepanel.git
synced 2025-09-26 17:51:13 +08:00
feat: add create namespace code
This commit is contained in:
438
pkg/namespace.go
438
pkg/namespace.go
@@ -1,11 +1,20 @@
|
||||
package v1
|
||||
|
||||
import (
|
||||
"encoding/base64"
|
||||
"fmt"
|
||||
"github.com/onepanelio/core/pkg/util"
|
||||
"github.com/onepanelio/core/pkg/util/data"
|
||||
"google.golang.org/grpc/codes"
|
||||
"io/ioutil"
|
||||
vapps "k8s.io/api/apps/v1"
|
||||
v1 "k8s.io/api/core/v1"
|
||||
vnet "k8s.io/api/networking/v1"
|
||||
v1rbac "k8s.io/api/rbac/v1"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/util/json"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
)
|
||||
|
||||
@@ -77,7 +86,432 @@ func (c *Client) ListNamespaces() (namespaces []*Namespace, err error) {
|
||||
return
|
||||
}
|
||||
|
||||
// CreateNamespace creates a new namespace in the system
|
||||
func (c *Client) CreateNamespace(sourceNamespace, name string) (namespace *Namespace, err error) {
|
||||
return nil, util.NewUserError(codes.FailedPrecondition, "Creating namespaces is not supported in the community edition")
|
||||
newNamespace := name
|
||||
domain := *c.systemConfig.Domain()
|
||||
artifactRepositorySource, err := c.GetArtifactRepositorySource(sourceNamespace)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
config, err := c.GetNamespaceConfig(sourceNamespace)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if config.ArtifactRepository.S3 == nil {
|
||||
return nil, util.NewUserError(codes.Internal, "S3 compatible artifact repository not set")
|
||||
}
|
||||
|
||||
accessKey := config.ArtifactRepository.S3.AccessKey
|
||||
secretKey := config.ArtifactRepository.S3.Secretkey
|
||||
|
||||
if err := c.createK8sNamespace(name); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if err := c.createNetworkPolicy(newNamespace); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if err := c.createIstioVirtualService(newNamespace, domain); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if err := c.createRole(newNamespace); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if err := c.createDefaultSecret(newNamespace); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if err := c.createSecretOnepanelDefaultNamespace(newNamespace, accessKey, secretKey); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if err := c.createProviderDependentMinioDeployment(newNamespace, artifactRepositorySource); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if err := c.createProviderDependentMinioService(newNamespace, artifactRepositorySource); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if err := c.createNamespaceConfigMap(sourceNamespace, newNamespace); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if err := c.createNamespaceClusterRoleBinding(newNamespace); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if err := c.createNamespaceRoleBinding(newNamespace); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if err := c.createNamespaceServiceAccount(newNamespace); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if err := c.createNamespaceModelClusterRoleBinding(newNamespace); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if err := c.createNamespaceTemplates(newNamespace); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
namespace = &Namespace{
|
||||
Name: name,
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
func (c *Client) createK8sNamespace(name string) error {
|
||||
createNamespace := &v1.Namespace{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: name,
|
||||
Labels: map[string]string{
|
||||
"istio-injection": "enabled",
|
||||
onepanelEnabledLabelKey: "true",
|
||||
"app.kubernetes.io/component": "onepanel",
|
||||
"app.kubernetes.io/instance": "onepanel-v0.5.0",
|
||||
"app.kubernetes.io/managed-by": "onepanel-cli",
|
||||
"app.kubernetes.io/name": "onepanel",
|
||||
"app.kubernetes.io/part-of": "onepanel",
|
||||
"app.kubernetes.io/version": "v0.5.0",
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
_, err := c.CoreV1().Namespaces().Create(createNamespace)
|
||||
if err != nil && strings.Contains(err.Error(), "already exists") {
|
||||
return util.NewUserError(codes.AlreadyExists, "Namespace '"+name+"' already exists")
|
||||
}
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
func (c *Client) createNetworkPolicy(namespace string) error {
|
||||
replacements := map[string]string{
|
||||
"$(applicationDefaultNamespace)": namespace,
|
||||
}
|
||||
|
||||
dataStr, err := replaceVariables(filepath.Join("manifest", "networkpolicy-onepanel-defaultnamespace.json"), replacements)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
data := []byte(dataStr)
|
||||
|
||||
networkPolicy := &vnet.NetworkPolicy{}
|
||||
if err := json.Unmarshal(data, networkPolicy); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
_, err = c.NetworkingV1().NetworkPolicies(namespace).Create(networkPolicy)
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
func (c *Client) createIstioVirtualService(namespace, domain string) error {
|
||||
replacements := map[string]string{
|
||||
"$(applicationDefaultNamespace)": namespace,
|
||||
"$(applicationDomain)": domain,
|
||||
}
|
||||
|
||||
dataStr, err := replaceVariables(filepath.Join("manifest", "service-minio-onepanel.json"), replacements)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
data := []byte(dataStr)
|
||||
|
||||
return c.CreateVirtualService(namespace, data)
|
||||
}
|
||||
|
||||
func (c *Client) createRole(namespace string) error {
|
||||
replacements := map[string]string{
|
||||
"$(applicationDefaultNamespace)": namespace,
|
||||
}
|
||||
|
||||
dataStr, err := replaceVariables(filepath.Join("manifest", "role-onepanel-defaultnamespace.json"), replacements)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
data := []byte(dataStr)
|
||||
|
||||
role := &v1rbac.Role{}
|
||||
if err := json.Unmarshal(data, role); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
_, err = c.RbacV1().Roles(namespace).Create(role)
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
func (c *Client) createDefaultSecret(namespace string) error {
|
||||
replacements := map[string]string{
|
||||
"$(applicationDefaultNamespace)": namespace,
|
||||
}
|
||||
|
||||
dataStr, err := replaceVariables(filepath.Join("manifest", "secret-onepanel-default-env-defaultnamespace.json"), replacements)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
data := []byte(dataStr)
|
||||
|
||||
secret := &v1.Secret{}
|
||||
if err := json.Unmarshal(data, secret); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
_, err = c.CoreV1().Secrets(namespace).Create(secret)
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
func (c *Client) createSecretOnepanelDefaultNamespace(namespace, accessKey, secretKey string) error {
|
||||
replacements := map[string]string{
|
||||
"$(applicationDefaultNamespace)": namespace,
|
||||
"$(artifactRepositoryS3AccessKey)": base64.StdEncoding.EncodeToString([]byte(accessKey)),
|
||||
"$(artifactRepositoryS3SecretKey)": base64.StdEncoding.EncodeToString([]byte(secretKey)),
|
||||
}
|
||||
|
||||
dataStr, err := replaceVariables(filepath.Join("manifest", "secret-onepanel-defaultnamespace.json"), replacements)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
data := []byte(dataStr)
|
||||
|
||||
secret := &v1.Secret{}
|
||||
if err := json.Unmarshal(data, secret); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
_, err = c.CoreV1().Secrets(namespace).Create(secret)
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
func (c *Client) createProviderDependentMinioDeployment(namespace, artifactRepositoryProvider string) error {
|
||||
replacements := map[string]string{
|
||||
"$(applicationDefaultNamespace)": namespace,
|
||||
}
|
||||
|
||||
//// AWS S3 doesn't require a specific artifactRepositoryProvider
|
||||
if artifactRepositoryProvider == "s3" {
|
||||
return nil
|
||||
}
|
||||
|
||||
dataStr, err := replaceVariables(filepath.Join("manifest", artifactRepositoryProvider, "deployment.json"), replacements)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
data := []byte(dataStr)
|
||||
|
||||
deployment := &vapps.Deployment{}
|
||||
if err := json.Unmarshal(data, deployment); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
_, err = c.AppsV1().Deployments(namespace).Create(deployment)
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
func (c *Client) createProviderDependentMinioService(namespace, artifactRepositoryProvider string) error {
|
||||
replacements := map[string]string{
|
||||
"$(applicationDefaultNamespace)": namespace,
|
||||
}
|
||||
|
||||
// AWS S3 doesn't require a specific artifactRepositoryProvider
|
||||
if artifactRepositoryProvider == "s3" {
|
||||
return nil
|
||||
}
|
||||
|
||||
dataStr, err := replaceVariables(filepath.Join("manifest", artifactRepositoryProvider, "service.json"), replacements)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
data := []byte(dataStr)
|
||||
|
||||
service := &v1.Service{}
|
||||
if err := json.Unmarshal(data, service); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
_, err = c.CoreV1().Services(namespace).Create(service)
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
func (c *Client) createNamespaceClusterRoleBinding(namespace string) error {
|
||||
replacements := map[string]string{
|
||||
"$(applicationDefaultNamespace)": namespace,
|
||||
}
|
||||
|
||||
dataStr, err := replaceVariables(filepath.Join("manifest", "clusterrolebinding-onepanel-namespaces-defaultnamespace.json"), replacements)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
data := []byte(dataStr)
|
||||
|
||||
resource := &v1rbac.ClusterRoleBinding{}
|
||||
if err := json.Unmarshal(data, resource); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
resource.Name += "-" + namespace
|
||||
|
||||
_, err = c.RbacV1().ClusterRoleBindings().Create(resource)
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
func (c *Client) createNamespaceRoleBinding(namespace string) error {
|
||||
replacements := map[string]string{
|
||||
"$(applicationDefaultNamespace)": namespace,
|
||||
}
|
||||
|
||||
dataStr, err := replaceVariables(filepath.Join("manifest", "rolebinding-onepanel-defaultnamespace.json"), replacements)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
data := []byte(dataStr)
|
||||
|
||||
resource := &v1rbac.RoleBinding{}
|
||||
if err := json.Unmarshal(data, resource); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
_, err = c.RbacV1().RoleBindings(namespace).Create(resource)
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
func (c *Client) createNamespaceServiceAccount(namespace string) error {
|
||||
replacements := map[string]string{
|
||||
"$(applicationDefaultNamespace)": namespace,
|
||||
}
|
||||
|
||||
dataStr, err := replaceVariables(filepath.Join("manifest", "service-account.json"), replacements)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
data := []byte(dataStr)
|
||||
|
||||
resource := &v1.ServiceAccount{}
|
||||
if err := json.Unmarshal(data, resource); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
_, err = c.CoreV1().ServiceAccounts(namespace).Create(resource)
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
func (c *Client) createNamespaceConfigMap(sourceNamespace, namespace string) error {
|
||||
sourceConfigMap, err := c.CoreV1().ConfigMaps(sourceNamespace).Get("onepanel", metav1.GetOptions{})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
data := sourceConfigMap.Data["artifactRepository"]
|
||||
sourceKey := "minio-gateway." + sourceNamespace + ".svc.cluster.local:9000"
|
||||
replaceKey := "minio-gateway." + namespace + ".svc.cluster.local:9000"
|
||||
data = strings.ReplaceAll(data, sourceKey, replaceKey)
|
||||
sourceConfigMap.Data["artifactRepository"] = data
|
||||
|
||||
configMap := &v1.ConfigMap{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: "onepanel",
|
||||
Namespace: namespace,
|
||||
},
|
||||
Data: sourceConfigMap.Data,
|
||||
}
|
||||
|
||||
configMap.Namespace = namespace
|
||||
|
||||
_, err = c.CoreV1().ConfigMaps(namespace).Create(configMap)
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
func (c *Client) createNamespaceModelClusterRoleBinding(namespace string) error {
|
||||
replacements := map[string]string{
|
||||
"$(applicationDefaultNamespace)": namespace,
|
||||
}
|
||||
|
||||
dataStr, err := replaceVariables(filepath.Join("manifest", "clusterrolebinding-models.json"), replacements)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
data := []byte(dataStr)
|
||||
|
||||
resource := &v1rbac.ClusterRoleBinding{}
|
||||
if err := json.Unmarshal(data, resource); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
_, err = c.RbacV1().ClusterRoleBindings().Create(resource)
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
func (c *Client) createNamespaceTemplates(namespace string) error {
|
||||
wd, err := os.Getwd()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
workflowDir := filepath.Join(wd, "db", "yaml")
|
||||
|
||||
filepaths := make([]string, 0)
|
||||
|
||||
err = filepath.Walk(workflowDir,
|
||||
func(path string, info os.FileInfo, err error) error {
|
||||
if !info.IsDir() {
|
||||
filepaths = append(filepaths, path)
|
||||
}
|
||||
|
||||
return nil
|
||||
},
|
||||
)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
for _, filename := range filepaths {
|
||||
manifest, err := data.ManifestFileFromFile(filename)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if manifest.Metadata.Kind == "Workflow" {
|
||||
if manifest.Metadata.Action == "create" {
|
||||
if err := c.createWorkflowTemplateFromGenericManifest(namespace, manifest); err != nil {
|
||||
return err
|
||||
}
|
||||
} else {
|
||||
if err := c.updateWorkflowTemplateManifest(namespace, manifest); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
} else if manifest.Metadata.Kind == "Workspace" {
|
||||
if manifest.Metadata.Action == "create" {
|
||||
if err := c.createWorkspaceTemplateFromGenericManifest(namespace, manifest); err != nil {
|
||||
return err
|
||||
}
|
||||
} else {
|
||||
if err := c.updateWorkspaceTemplateManifest(namespace, manifest); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
} else {
|
||||
return fmt.Errorf("unknown manifest type for file %v", filename)
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
Reference in New Issue
Block a user