github.com/Racer159/jackal@v0.32.7-0.20240401174413-0bd2339e4f2e/src/types/k8s.go (about)

     1  // SPDX-License-Identifier: Apache-2.0
     2  // SPDX-FileCopyrightText: 2021-Present The Jackal Authors
     3  
     4  // Package types contains all the types used by Jackal.
     5  package types
     6  
     7  import (
     8  	"fmt"
     9  	"time"
    10  
    11  	"github.com/Racer159/jackal/src/config/lang"
    12  	"github.com/Racer159/jackal/src/pkg/k8s"
    13  	"github.com/defenseunicorns/pkg/helpers"
    14  )
    15  
    16  // WebhookStatus defines the status of a Component Webhook operating on a Jackal package secret.
    17  type WebhookStatus string
    18  
    19  // ComponentStatus defines the deployment status of a Jackal component within a package.
    20  type ComponentStatus string
    21  
    22  // DefaultWebhookWaitDuration is the default amount of time Jackal will wait for a webhook to complete.
    23  const DefaultWebhookWaitDuration = time.Minute * 5
    24  
    25  // All the different status options for a Jackal Component or a webhook that is running for a Jackal Component deployment.
    26  const (
    27  	WebhookStatusSucceeded WebhookStatus = "Succeeded"
    28  	WebhookStatusFailed    WebhookStatus = "Failed"
    29  	WebhookStatusRunning   WebhookStatus = "Running"
    30  	WebhookStatusRemoving  WebhookStatus = "Removing"
    31  
    32  	ComponentStatusSucceeded ComponentStatus = "Succeeded"
    33  	ComponentStatusFailed    ComponentStatus = "Failed"
    34  	ComponentStatusDeploying ComponentStatus = "Deploying"
    35  	ComponentStatusRemoving  ComponentStatus = "Removing"
    36  )
    37  
    38  // Values during setup of the initial jackal state
    39  const (
    40  	JackalGeneratedPasswordLen               = 24
    41  	JackalGeneratedSecretLen                 = 48
    42  	JackalInClusterContainerRegistryNodePort = 31999
    43  	JackalRegistryPushUser                   = "jackal-push"
    44  	JackalRegistryPullUser                   = "jackal-pull"
    45  
    46  	JackalGitPushUser = "jackal-git-user"
    47  	JackalGitReadUser = "jackal-git-read-user"
    48  
    49  	JackalInClusterGitServiceURL      = "http://jackal-gitea-http.jackal.svc.cluster.local:3000"
    50  	JackalInClusterArtifactServiceURL = JackalInClusterGitServiceURL + "/api/packages/" + JackalGitPushUser
    51  )
    52  
    53  // JackalState is maintained as a secret in the Jackal namespace to track Jackal init data.
    54  type JackalState struct {
    55  	JackalAppliance bool             `json:"jackalAppliance" jsonschema:"description=Indicates if Jackal was initialized while deploying its own k8s cluster"`
    56  	Distro          string           `json:"distro" jsonschema:"description=K8s distribution of the cluster Jackal was deployed to"`
    57  	Architecture    string           `json:"architecture" jsonschema:"description=Machine architecture of the k8s node(s)"`
    58  	StorageClass    string           `json:"storageClass" jsonschema:"Default StorageClass value Jackal uses for variable templating"`
    59  	AgentTLS        k8s.GeneratedPKI `json:"agentTLS" jsonschema:"PKI certificate information for the agent pods Jackal manages"`
    60  
    61  	GitServer      GitServerInfo      `json:"gitServer" jsonschema:"description=Information about the repository Jackal is configured to use"`
    62  	RegistryInfo   RegistryInfo       `json:"registryInfo" jsonschema:"description=Information about the container registry Jackal is configured to use"`
    63  	ArtifactServer ArtifactServerInfo `json:"artifactServer" jsonschema:"description=Information about the artifact registry Jackal is configured to use"`
    64  	LoggingSecret  string             `json:"loggingSecret" jsonschema:"description=Secret value that the internal Grafana server was seeded with"`
    65  }
    66  
    67  // DeployedPackage contains information about a Jackal Package that has been deployed to a cluster
    68  // This object is saved as the data of a k8s secret within the 'Jackal' namespace (not as part of the JackalState secret).
    69  type DeployedPackage struct {
    70  	Name               string                        `json:"name"`
    71  	Data               JackalPackage                 `json:"data"`
    72  	CLIVersion         string                        `json:"cliVersion"`
    73  	Generation         int                           `json:"generation"`
    74  	DeployedComponents []DeployedComponent           `json:"deployedComponents"`
    75  	ComponentWebhooks  map[string]map[string]Webhook `json:"componentWebhooks,omitempty"`
    76  	ConnectStrings     ConnectStrings                `json:"connectStrings,omitempty"`
    77  }
    78  
    79  // DeployedComponent contains information about a Jackal Package Component that has been deployed to a cluster.
    80  type DeployedComponent struct {
    81  	Name               string           `json:"name"`
    82  	InstalledCharts    []InstalledChart `json:"installedCharts"`
    83  	Status             ComponentStatus  `json:"status"`
    84  	ObservedGeneration int              `json:"observedGeneration"`
    85  }
    86  
    87  // Webhook contains information about a Component Webhook operating on a Jackal package secret.
    88  type Webhook struct {
    89  	Name                string        `json:"name"`
    90  	WaitDurationSeconds int           `json:"waitDurationSeconds,omitempty"`
    91  	Status              WebhookStatus `json:"status"`
    92  	ObservedGeneration  int           `json:"observedGeneration"`
    93  }
    94  
    95  // InstalledChart contains information about a Helm Chart that has been deployed to a cluster.
    96  type InstalledChart struct {
    97  	Namespace string `json:"namespace"`
    98  	ChartName string `json:"chartName"`
    99  }
   100  
   101  // GitServerInfo contains information Jackal uses to communicate with a git repository to push/pull repositories to.
   102  type GitServerInfo struct {
   103  	PushUsername string `json:"pushUsername" jsonschema:"description=Username of a user with push access to the git repository"`
   104  	PushPassword string `json:"pushPassword" jsonschema:"description=Password of a user with push access to the git repository"`
   105  	PullUsername string `json:"pullUsername" jsonschema:"description=Username of a user with pull-only access to the git repository. If not provided for an external repository then the push-user is used"`
   106  	PullPassword string `json:"pullPassword" jsonschema:"description=Password of a user with pull-only access to the git repository. If not provided for an external repository then the push-user is used"`
   107  
   108  	Address        string `json:"address" jsonschema:"description=URL address of the git server"`
   109  	InternalServer bool   `json:"internalServer" jsonschema:"description=Indicates if we are using a git server that Jackal is directly managing"`
   110  }
   111  
   112  // FillInEmptyValues sets every necessary value that's currently empty to a reasonable default
   113  func (gs *GitServerInfo) FillInEmptyValues() error {
   114  	var err error
   115  	// Set default svc url if an external repository was not provided
   116  	if gs.Address == "" {
   117  		gs.Address = JackalInClusterGitServiceURL
   118  		gs.InternalServer = true
   119  	}
   120  
   121  	// Generate a push-user password if not provided by init flag
   122  	if gs.PushPassword == "" {
   123  		if gs.PushPassword, err = helpers.RandomString(JackalGeneratedPasswordLen); err != nil {
   124  			return fmt.Errorf("%s: %w", lang.ErrUnableToGenerateRandomSecret, err)
   125  		}
   126  	}
   127  
   128  	// Set read-user information if using an internal repository, otherwise copy from the push-user
   129  	if gs.PullUsername == "" {
   130  		if gs.InternalServer {
   131  			gs.PullUsername = JackalGitReadUser
   132  		} else {
   133  			gs.PullUsername = gs.PushUsername
   134  		}
   135  	}
   136  	if gs.PullPassword == "" {
   137  		if gs.InternalServer {
   138  			if gs.PullPassword, err = helpers.RandomString(JackalGeneratedPasswordLen); err != nil {
   139  				return fmt.Errorf("%s: %w", lang.ErrUnableToGenerateRandomSecret, err)
   140  			}
   141  		} else {
   142  			gs.PullPassword = gs.PushPassword
   143  		}
   144  	}
   145  
   146  	return nil
   147  }
   148  
   149  // ArtifactServerInfo contains information Jackal uses to communicate with a artifact registry to push/pull repositories to.
   150  type ArtifactServerInfo struct {
   151  	PushUsername string `json:"pushUsername" jsonschema:"description=Username of a user with push access to the artifact registry"`
   152  	PushToken    string `json:"pushPassword" jsonschema:"description=Password of a user with push access to the artifact registry"`
   153  
   154  	Address        string `json:"address" jsonschema:"description=URL address of the artifact registry"`
   155  	InternalServer bool   `json:"internalServer" jsonschema:"description=Indicates if we are using a artifact registry that Jackal is directly managing"`
   156  }
   157  
   158  // FillInEmptyValues sets every necessary value that's currently empty to a reasonable default
   159  func (as *ArtifactServerInfo) FillInEmptyValues() {
   160  	// Set default svc url if an external registry was not provided
   161  	if as.Address == "" {
   162  		as.Address = JackalInClusterArtifactServiceURL
   163  		as.InternalServer = true
   164  	}
   165  
   166  	// Set the push username to the git push user if not specified
   167  	if as.PushUsername == "" {
   168  		as.PushUsername = JackalGitPushUser
   169  	}
   170  }
   171  
   172  // RegistryInfo contains information Jackal uses to communicate with a container registry to push/pull images.
   173  type RegistryInfo struct {
   174  	PushUsername string `json:"pushUsername" jsonschema:"description=Username of a user with push access to the registry"`
   175  	PushPassword string `json:"pushPassword" jsonschema:"description=Password of a user with push access to the registry"`
   176  	PullUsername string `json:"pullUsername" jsonschema:"description=Username of a user with pull-only access to the registry. If not provided for an external registry than the push-user is used"`
   177  	PullPassword string `json:"pullPassword" jsonschema:"description=Password of a user with pull-only access to the registry. If not provided for an external registry than the push-user is used"`
   178  
   179  	Address          string `json:"address" jsonschema:"description=URL address of the registry"`
   180  	NodePort         int    `json:"nodePort" jsonschema:"description=Nodeport of the registry. Only needed if the registry is running inside the kubernetes cluster"`
   181  	InternalRegistry bool   `json:"internalRegistry" jsonschema:"description=Indicates if we are using a registry that Jackal is directly managing"`
   182  
   183  	Secret string `json:"secret" jsonschema:"description=Secret value that the registry was seeded with"`
   184  }
   185  
   186  // FillInEmptyValues sets every necessary value not already set to a reasonable default
   187  func (ri *RegistryInfo) FillInEmptyValues() error {
   188  	var err error
   189  	// Set default NodePort if none was provided
   190  	if ri.NodePort == 0 {
   191  		ri.NodePort = JackalInClusterContainerRegistryNodePort
   192  	}
   193  
   194  	// Set default url if an external registry was not provided
   195  	if ri.Address == "" {
   196  		ri.InternalRegistry = true
   197  		ri.Address = fmt.Sprintf("%s:%d", helpers.IPV4Localhost, ri.NodePort)
   198  	}
   199  
   200  	// Generate a push-user password if not provided by init flag
   201  	if ri.PushPassword == "" {
   202  		if ri.PushPassword, err = helpers.RandomString(JackalGeneratedPasswordLen); err != nil {
   203  			return fmt.Errorf("%s: %w", lang.ErrUnableToGenerateRandomSecret, err)
   204  		}
   205  	}
   206  
   207  	// Set pull-username if not provided by init flag
   208  	if ri.PullUsername == "" {
   209  		if ri.InternalRegistry {
   210  			ri.PullUsername = JackalRegistryPullUser
   211  		} else {
   212  			// If this is an external registry and a pull-user wasn't provided, use the same credentials as the push user
   213  			ri.PullUsername = ri.PushUsername
   214  		}
   215  	}
   216  	if ri.PullPassword == "" {
   217  		if ri.InternalRegistry {
   218  			if ri.PullPassword, err = helpers.RandomString(JackalGeneratedPasswordLen); err != nil {
   219  				return fmt.Errorf("%s: %w", lang.ErrUnableToGenerateRandomSecret, err)
   220  			}
   221  		} else {
   222  			// If this is an external registry and a pull-user wasn't provided, use the same credentials as the push user
   223  			ri.PullPassword = ri.PushPassword
   224  		}
   225  	}
   226  
   227  	if ri.Secret == "" {
   228  		if ri.Secret, err = helpers.RandomString(JackalGeneratedSecretLen); err != nil {
   229  			return fmt.Errorf("%s: %w", lang.ErrUnableToGenerateRandomSecret, err)
   230  		}
   231  	}
   232  
   233  	return nil
   234  }