Merge Develop to prepare V3 #77
@@ -9,11 +9,11 @@ import (
|
||||
"os"
|
||||
"strings"
|
||||
|
||||
"katenary/generator"
|
||||
"katenary/utils"
|
||||
|
||||
"github.com/compose-spec/compose-go/cli"
|
||||
"github.com/spf13/cobra"
|
||||
|
||||
"katenary/generator"
|
||||
"katenary/utils"
|
||||
)
|
||||
|
||||
const longHelp = `Katenary is a tool to convert compose files to Helm Charts.
|
||||
|
||||
@@ -1,12 +0,0 @@
|
||||
<!-- Code generated by gomarkdoc. DO NOT EDIT -->
|
||||
|
||||
# katenary
|
||||
|
||||
```go
|
||||
import "katenary/cmd/katenary"
|
||||
```
|
||||
|
||||
Katenary CLI, main package.
|
||||
|
||||
This package is not intended to be imported. It contains the main function that build the command line with \`cobra\` package.
|
||||
|
||||
@@ -35,7 +35,7 @@ var Version = "master" // changed at compile time
|
||||
```
|
||||
|
||||
<a name="Convert"></a>
|
||||
## func [Convert](<https://github.com/metal3d/katenary/blob/develop/generator/converter.go#L38>)
|
||||
## func [Convert](<https://github.com/metal3d/katenary/blob/develop/generator/converter.go#L37>)
|
||||
|
||||
```go
|
||||
func Convert(config ConvertOptions, dockerComposeFile ...string)
|
||||
@@ -116,16 +116,14 @@ func Prefix() string
|
||||
|
||||
|
||||
<a name="ChartTemplate"></a>
|
||||
## type [ChartTemplate](<https://github.com/metal3d/katenary/blob/develop/generator/chart.go#L9-L12>)
|
||||
## type [ChartTemplate](<https://github.com/metal3d/katenary/blob/develop/generator/chart.go#L25-L28>)
|
||||
|
||||
ChartTemplate is a template of a chart. It contains the content of the template and the name of the service. This is used internally to generate the templates.
|
||||
|
||||
TODO: maybe we can set it private.
|
||||
|
||||
```go
|
||||
type ChartTemplate struct {
|
||||
Content []byte
|
||||
Servicename string
|
||||
Content []byte
|
||||
}
|
||||
```
|
||||
|
||||
@@ -151,25 +149,25 @@ func NewConfigMap(service types.ServiceConfig, appName string) *ConfigMap
|
||||
NewConfigMap creates a new ConfigMap from a compose service. The appName is the name of the application taken from the project name. The ConfigMap is filled by environment variables and labels "map\-env".
|
||||
|
||||
<a name="NewConfigMapFromDirectory"></a>
|
||||
### func [NewConfigMapFromDirectory](<https://github.com/metal3d/katenary/blob/develop/generator/configMap.go#L130>)
|
||||
### func [NewConfigMapFromDirectory](<https://github.com/metal3d/katenary/blob/develop/generator/configMap.go#L128>)
|
||||
|
||||
```go
|
||||
func NewConfigMapFromDirectory(service types.ServiceConfig, appName string, path string) *ConfigMap
|
||||
func NewConfigMapFromDirectory(service types.ServiceConfig, appName, path string) *ConfigMap
|
||||
```
|
||||
|
||||
NewConfigMapFromDirectory creates a new ConfigMap from a compose service. This path is the path to the file or directory. If the path is a directory, all files in the directory are added to the ConfigMap. Each subdirectory are ignored. Note that the Generate\(\) function will create the subdirectories ConfigMaps.
|
||||
|
||||
<a name="ConfigMap.AddData"></a>
|
||||
### func \(\*ConfigMap\) [AddData](<https://github.com/metal3d/katenary/blob/develop/generator/configMap.go#L166>)
|
||||
### func \(\*ConfigMap\) [AddData](<https://github.com/metal3d/katenary/blob/develop/generator/configMap.go#L164>)
|
||||
|
||||
```go
|
||||
func (c *ConfigMap) AddData(key string, value string)
|
||||
func (c *ConfigMap) AddData(key, value string)
|
||||
```
|
||||
|
||||
AddData adds a key value pair to the configmap. Append or overwrite the value if the key already exists.
|
||||
|
||||
<a name="ConfigMap.AppendDir"></a>
|
||||
### func \(\*ConfigMap\) [AppendDir](<https://github.com/metal3d/katenary/blob/develop/generator/configMap.go#L172>)
|
||||
### func \(\*ConfigMap\) [AppendDir](<https://github.com/metal3d/katenary/blob/develop/generator/configMap.go#L170>)
|
||||
|
||||
```go
|
||||
func (c *ConfigMap) AppendDir(path string)
|
||||
@@ -178,7 +176,7 @@ func (c *ConfigMap) AppendDir(path string)
|
||||
AddFile adds files from given path to the configmap. It is not recursive, to add all files in a directory, you need to call this function for each subdirectory.
|
||||
|
||||
<a name="ConfigMap.AppendFile"></a>
|
||||
### func \(\*ConfigMap\) [AppendFile](<https://github.com/metal3d/katenary/blob/develop/generator/configMap.go#L208>)
|
||||
### func \(\*ConfigMap\) [AppendFile](<https://github.com/metal3d/katenary/blob/develop/generator/configMap.go#L206>)
|
||||
|
||||
```go
|
||||
func (c *ConfigMap) AppendFile(path string)
|
||||
@@ -187,7 +185,7 @@ func (c *ConfigMap) AppendFile(path string)
|
||||
|
||||
|
||||
<a name="ConfigMap.Filename"></a>
|
||||
### func \(\*ConfigMap\) [Filename](<https://github.com/metal3d/katenary/blob/develop/generator/configMap.go#L226>)
|
||||
### func \(\*ConfigMap\) [Filename](<https://github.com/metal3d/katenary/blob/develop/generator/configMap.go#L224>)
|
||||
|
||||
```go
|
||||
func (c *ConfigMap) Filename() string
|
||||
@@ -196,7 +194,7 @@ func (c *ConfigMap) Filename() string
|
||||
Filename returns the filename of the configmap. If the configmap is used for files, the filename contains the path.
|
||||
|
||||
<a name="ConfigMap.SetData"></a>
|
||||
### func \(\*ConfigMap\) [SetData](<https://github.com/metal3d/katenary/blob/develop/generator/configMap.go#L161>)
|
||||
### func \(\*ConfigMap\) [SetData](<https://github.com/metal3d/katenary/blob/develop/generator/configMap.go#L159>)
|
||||
|
||||
```go
|
||||
func (c *ConfigMap) SetData(data map[string]string)
|
||||
@@ -205,7 +203,7 @@ func (c *ConfigMap) SetData(data map[string]string)
|
||||
SetData sets the data of the configmap. It replaces the entire data.
|
||||
|
||||
<a name="ConfigMap.Yaml"></a>
|
||||
### func \(\*ConfigMap\) [Yaml](<https://github.com/metal3d/katenary/blob/develop/generator/configMap.go#L236>)
|
||||
### func \(\*ConfigMap\) [Yaml](<https://github.com/metal3d/katenary/blob/develop/generator/configMap.go#L234>)
|
||||
|
||||
```go
|
||||
func (c *ConfigMap) Yaml() ([]byte, error)
|
||||
@@ -225,18 +223,18 @@ type ConfigMapMount struct {
|
||||
```
|
||||
|
||||
<a name="ConvertOptions"></a>
|
||||
## type [ConvertOptions](<https://github.com/metal3d/katenary/blob/develop/generator/chart.go#L46-L53>)
|
||||
## type [ConvertOptions](<https://github.com/metal3d/katenary/blob/develop/generator/chart.go#L14-L21>)
|
||||
|
||||
ConvertOptions are the options to convert a compose project to a helm chart.
|
||||
|
||||
```go
|
||||
type ConvertOptions struct {
|
||||
Force bool // Force the chart directory deletion if it already exists.
|
||||
OutputDir string // The output directory of the chart.
|
||||
Profiles []string // Profile to use for the conversion.
|
||||
HelmUpdate bool // If true, the "helm dep update" command will be run after the chart generation.
|
||||
AppVersion *string // Set the chart "appVersion" field. If nil, the version will be set to 0.1.0.
|
||||
ChartVersion string // Set the chart "version" field.
|
||||
AppVersion *string
|
||||
OutputDir string
|
||||
ChartVersion string
|
||||
Profiles []string
|
||||
Force bool
|
||||
HelmUpdate bool
|
||||
}
|
||||
```
|
||||
|
||||
@@ -275,7 +273,7 @@ Yaml returns the yaml representation of the cronjob.
|
||||
Implements the Yaml interface.
|
||||
|
||||
<a name="CronJobValue"></a>
|
||||
## type [CronJobValue](<https://github.com/metal3d/katenary/blob/develop/generator/values.go#L50-L55>)
|
||||
## type [CronJobValue](<https://github.com/metal3d/katenary/blob/develop/generator/values.go#L47-L52>)
|
||||
|
||||
CronJobValue is a cronjob configuration that will be saved in values.yaml.
|
||||
|
||||
@@ -304,7 +302,7 @@ type DataMap interface {
|
||||
### func [NewFileMap](<https://github.com/metal3d/katenary/blob/develop/generator/configMap.go#L26>)
|
||||
|
||||
```go
|
||||
func NewFileMap(service types.ServiceConfig, appName string, kind string) DataMap
|
||||
func NewFileMap(service types.ServiceConfig, appName, kind string) DataMap
|
||||
```
|
||||
|
||||
NewFileMap creates a new DataMap from a compose service. The appName is the name of the application taken from the project name.
|
||||
@@ -340,7 +338,7 @@ func (d *Deployment) AddContainer(service types.ServiceConfig)
|
||||
AddContainer adds a container to the deployment.
|
||||
|
||||
<a name="Deployment.AddHealthCheck"></a>
|
||||
### func \(\*Deployment\) [AddHealthCheck](<https://github.com/metal3d/katenary/blob/develop/generator/deployment.go#L440>)
|
||||
### func \(\*Deployment\) [AddHealthCheck](<https://github.com/metal3d/katenary/blob/develop/generator/deployment.go#L450>)
|
||||
|
||||
```go
|
||||
func (d *Deployment) AddHealthCheck(service types.ServiceConfig, container *corev1.Container)
|
||||
@@ -367,7 +365,7 @@ func (d *Deployment) AddVolumes(service types.ServiceConfig, appName string)
|
||||
AddVolumes adds a volume to the deployment. It does not create the PVC, it only adds the volumes to the deployment. If the volume is a bind volume it will warn the user that it is not supported yet.
|
||||
|
||||
<a name="Deployment.BindFrom"></a>
|
||||
### func \(\*Deployment\) [BindFrom](<https://github.com/metal3d/katenary/blob/develop/generator/deployment.go#L320>)
|
||||
### func \(\*Deployment\) [BindFrom](<https://github.com/metal3d/katenary/blob/develop/generator/deployment.go#L330>)
|
||||
|
||||
```go
|
||||
func (d *Deployment) BindFrom(service types.ServiceConfig, binded *Deployment)
|
||||
@@ -385,7 +383,7 @@ func (d *Deployment) DependsOn(to *Deployment, servicename string) error
|
||||
DependsOn adds a initContainer to the deployment that will wait for the service to be up.
|
||||
|
||||
<a name="Deployment.Filename"></a>
|
||||
### func \(\*Deployment\) [Filename](<https://github.com/metal3d/katenary/blob/develop/generator/deployment.go#L618>)
|
||||
### func \(\*Deployment\) [Filename](<https://github.com/metal3d/katenary/blob/develop/generator/deployment.go#L628>)
|
||||
|
||||
```go
|
||||
func (d *Deployment) Filename() string
|
||||
@@ -394,7 +392,7 @@ func (d *Deployment) Filename() string
|
||||
Filename returns the filename of the deployment.
|
||||
|
||||
<a name="Deployment.SetEnvFrom"></a>
|
||||
### func \(\*Deployment\) [SetEnvFrom](<https://github.com/metal3d/katenary/blob/develop/generator/deployment.go#L348>)
|
||||
### func \(\*Deployment\) [SetEnvFrom](<https://github.com/metal3d/katenary/blob/develop/generator/deployment.go#L358>)
|
||||
|
||||
```go
|
||||
func (d *Deployment) SetEnvFrom(service types.ServiceConfig, appName string)
|
||||
@@ -403,7 +401,7 @@ func (d *Deployment) SetEnvFrom(service types.ServiceConfig, appName string)
|
||||
SetEnvFrom sets the environment variables to a configmap. The configmap is created.
|
||||
|
||||
<a name="Deployment.Yaml"></a>
|
||||
### func \(\*Deployment\) [Yaml](<https://github.com/metal3d/katenary/blob/develop/generator/deployment.go#L469>)
|
||||
### func \(\*Deployment\) [Yaml](<https://github.com/metal3d/katenary/blob/develop/generator/deployment.go#L479>)
|
||||
|
||||
```go
|
||||
func (d *Deployment) Yaml() ([]byte, error)
|
||||
@@ -430,28 +428,29 @@ const (
|
||||
```
|
||||
|
||||
<a name="HelmChart"></a>
|
||||
## type [HelmChart](<https://github.com/metal3d/katenary/blob/develop/generator/chart.go#L16-L28>)
|
||||
## type [HelmChart](<https://github.com/metal3d/katenary/blob/develop/generator/chart.go#L32-L44>)
|
||||
|
||||
HelmChart is a Helm Chart representation. It contains all the tempaltes, values, versions, helpers...
|
||||
|
||||
```go
|
||||
type HelmChart struct {
|
||||
Templates map[string]*ChartTemplate `yaml:"-"`
|
||||
Values map[string]any `yaml:"-"`
|
||||
VolumeMounts map[string]any `yaml:"-"`
|
||||
|
||||
Name string `yaml:"name"`
|
||||
ApiVersion string `yaml:"apiVersion"`
|
||||
Version string `yaml:"version"`
|
||||
AppVersion string `yaml:"appVersion"`
|
||||
Description string `yaml:"description"`
|
||||
Helper string `yaml:"-"`
|
||||
Dependencies []labelStructs.Dependency `yaml:"dependencies,omitempty"`
|
||||
Templates map[string]*ChartTemplate `yaml:"-"` // do not export to yaml
|
||||
Helper string `yaml:"-"` // do not export to yaml
|
||||
Values map[string]any `yaml:"-"` // do not export to yaml
|
||||
VolumeMounts map[string]any `yaml:"-"` // do not export to yaml
|
||||
// contains filtered or unexported fields
|
||||
}
|
||||
```
|
||||
|
||||
<a name="Generate"></a>
|
||||
### func [Generate](<https://github.com/metal3d/katenary/blob/develop/generator/generator.go#L33>)
|
||||
### func [Generate](<https://github.com/metal3d/katenary/blob/develop/generator/generator.go#L31>)
|
||||
|
||||
```go
|
||||
func Generate(project *types.Project) (*HelmChart, error)
|
||||
@@ -471,7 +470,7 @@ The Generate function will create the HelmChart object this way:
|
||||
- Merge the same\-pod services.
|
||||
|
||||
<a name="NewChart"></a>
|
||||
### func [NewChart](<https://github.com/metal3d/katenary/blob/develop/generator/chart.go#L31>)
|
||||
### func [NewChart](<https://github.com/metal3d/katenary/blob/develop/generator/chart.go#L47>)
|
||||
|
||||
```go
|
||||
func NewChart(name string) *HelmChart
|
||||
@@ -479,6 +478,15 @@ func NewChart(name string) *HelmChart
|
||||
|
||||
NewChart creates a new empty chart with the given name.
|
||||
|
||||
<a name="HelmChart.SaveTemplates"></a>
|
||||
### func \(\*HelmChart\) [SaveTemplates](<https://github.com/metal3d/katenary/blob/develop/generator/chart.go#L62>)
|
||||
|
||||
```go
|
||||
func (chart *HelmChart) SaveTemplates(templateDir string)
|
||||
```
|
||||
|
||||
SaveTemplates the templates of the chart to the given directory.
|
||||
|
||||
<a name="Help"></a>
|
||||
## type [Help](<https://github.com/metal3d/katenary/blob/develop/generator/katenaryLabels.go#L32-L37>)
|
||||
|
||||
@@ -533,17 +541,17 @@ func (ingress *Ingress) Yaml() ([]byte, error)
|
||||
|
||||
|
||||
<a name="IngressValue"></a>
|
||||
## type [IngressValue](<https://github.com/metal3d/katenary/blob/develop/generator/values.go#L27-L33>)
|
||||
## type [IngressValue](<https://github.com/metal3d/katenary/blob/develop/generator/values.go#L24-L30>)
|
||||
|
||||
IngressValue is a ingress configuration that will be saved in values.yaml.
|
||||
|
||||
```go
|
||||
type IngressValue struct {
|
||||
Enabled bool `yaml:"enabled"`
|
||||
Annotations map[string]string `yaml:"annotations"`
|
||||
Host string `yaml:"host"`
|
||||
Path string `yaml:"path"`
|
||||
Class string `yaml:"class"`
|
||||
Annotations map[string]string `yaml:"annotations"`
|
||||
Enabled bool `yaml:"enabled"`
|
||||
}
|
||||
```
|
||||
|
||||
@@ -578,16 +586,16 @@ const (
|
||||
```
|
||||
|
||||
<a name="PersistenceValue"></a>
|
||||
## type [PersistenceValue](<https://github.com/metal3d/katenary/blob/develop/generator/values.go#L19-L24>)
|
||||
## type [PersistenceValue](<https://github.com/metal3d/katenary/blob/develop/generator/values.go#L16-L21>)
|
||||
|
||||
PersistenceValue is a persistence configuration that will be saved in values.yaml.
|
||||
|
||||
```go
|
||||
type PersistenceValue struct {
|
||||
Enabled bool `yaml:"enabled"`
|
||||
StorageClass string `yaml:"storageClass"`
|
||||
Size string `yaml:"size"`
|
||||
AccessMode []string `yaml:"accessMode"`
|
||||
Enabled bool `yaml:"enabled"`
|
||||
}
|
||||
```
|
||||
|
||||
@@ -614,7 +622,7 @@ func NewRBAC(service types.ServiceConfig, appName string) *RBAC
|
||||
NewRBAC creates a new RBAC from a compose service. The appName is the name of the application taken from the project name.
|
||||
|
||||
<a name="RepositoryValue"></a>
|
||||
## type [RepositoryValue](<https://github.com/metal3d/katenary/blob/develop/generator/values.go#L13-L16>)
|
||||
## type [RepositoryValue](<https://github.com/metal3d/katenary/blob/develop/generator/values.go#L10-L13>)
|
||||
|
||||
RepositoryValue is a docker repository image and tag that will be saved in values.yaml.
|
||||
|
||||
@@ -712,7 +720,7 @@ NewSecret creates a new Secret from a compose service
|
||||
### func \(\*Secret\) [AddData](<https://github.com/metal3d/katenary/blob/develop/generator/secret.go#L87>)
|
||||
|
||||
```go
|
||||
func (s *Secret) AddData(key string, value string)
|
||||
func (s *Secret) AddData(key, value string)
|
||||
```
|
||||
|
||||
AddData adds a key value pair to the secret.
|
||||
@@ -823,7 +831,7 @@ func (r *ServiceAccount) Yaml() ([]byte, error)
|
||||
|
||||
|
||||
<a name="Value"></a>
|
||||
## type [Value](<https://github.com/metal3d/katenary/blob/develop/generator/values.go#L36-L47>)
|
||||
## type [Value](<https://github.com/metal3d/katenary/blob/develop/generator/values.go#L33-L44>)
|
||||
|
||||
Value will be saved in values.yaml. It contains configuraiton for all deployment and services.
|
||||
|
||||
@@ -832,18 +840,18 @@ type Value struct {
|
||||
Repository *RepositoryValue `yaml:"repository,omitempty"`
|
||||
Persistence map[string]*PersistenceValue `yaml:"persistence,omitempty"`
|
||||
Ingress *IngressValue `yaml:"ingress,omitempty"`
|
||||
ImagePullPolicy string `yaml:"imagePullPolicy,omitempty"`
|
||||
Environment map[string]any `yaml:"environment,omitempty"`
|
||||
Replicas *uint32 `yaml:"replicas,omitempty"`
|
||||
CronJob *CronJobValue `yaml:"cronjob,omitempty"`
|
||||
NodeSelector map[string]string `yaml:"nodeSelector"`
|
||||
ServiceAccount string `yaml:"serviceAccount"`
|
||||
Resources map[string]any `yaml:"resources"`
|
||||
ImagePullPolicy string `yaml:"imagePullPolicy,omitempty"`
|
||||
ServiceAccount string `yaml:"serviceAccount"`
|
||||
}
|
||||
```
|
||||
|
||||
<a name="NewValue"></a>
|
||||
### func [NewValue](<https://github.com/metal3d/katenary/blob/develop/generator/values.go#L62>)
|
||||
### func [NewValue](<https://github.com/metal3d/katenary/blob/develop/generator/values.go#L59>)
|
||||
|
||||
```go
|
||||
func NewValue(service types.ServiceConfig, main ...bool) *Value
|
||||
@@ -854,7 +862,7 @@ NewValue creates a new Value from a compose service. The value contains the nece
|
||||
If \`main\` is true, the tag will be empty because it will be set in the helm chart appVersion.
|
||||
|
||||
<a name="Value.AddIngress"></a>
|
||||
### func \(\*Value\) [AddIngress](<https://github.com/metal3d/katenary/blob/develop/generator/values.go#L101>)
|
||||
### func \(\*Value\) [AddIngress](<https://github.com/metal3d/katenary/blob/develop/generator/values.go#L98>)
|
||||
|
||||
```go
|
||||
func (v *Value) AddIngress(host, path string)
|
||||
@@ -863,7 +871,7 @@ func (v *Value) AddIngress(host, path string)
|
||||
|
||||
|
||||
<a name="Value.AddPersistence"></a>
|
||||
### func \(\*Value\) [AddPersistence](<https://github.com/metal3d/katenary/blob/develop/generator/values.go#L89>)
|
||||
### func \(\*Value\) [AddPersistence](<https://github.com/metal3d/katenary/blob/develop/generator/values.go#L86>)
|
||||
|
||||
```go
|
||||
func (v *Value) AddPersistence(volumeName string)
|
||||
@@ -872,7 +880,7 @@ func (v *Value) AddPersistence(volumeName string)
|
||||
AddPersistence adds persistence configuration to the Value.
|
||||
|
||||
<a name="VolumeClaim"></a>
|
||||
## type [VolumeClaim](<https://github.com/metal3d/katenary/blob/develop/generator/volume.go#L18-L23>)
|
||||
## type [VolumeClaim](<https://github.com/metal3d/katenary/blob/develop/generator/volume.go#L20-L25>)
|
||||
|
||||
VolumeClaim is a kubernetes VolumeClaim. This is a PersistentVolumeClaim.
|
||||
|
||||
@@ -884,7 +892,7 @@ type VolumeClaim struct {
|
||||
```
|
||||
|
||||
<a name="NewVolumeClaim"></a>
|
||||
### func [NewVolumeClaim](<https://github.com/metal3d/katenary/blob/develop/generator/volume.go#L26>)
|
||||
### func [NewVolumeClaim](<https://github.com/metal3d/katenary/blob/develop/generator/volume.go#L28>)
|
||||
|
||||
```go
|
||||
func NewVolumeClaim(service types.ServiceConfig, volumeName, appName string) *VolumeClaim
|
||||
@@ -893,7 +901,7 @@ func NewVolumeClaim(service types.ServiceConfig, volumeName, appName string) *Vo
|
||||
NewVolumeClaim creates a new VolumeClaim from a compose service.
|
||||
|
||||
<a name="VolumeClaim.Filename"></a>
|
||||
### func \(\*VolumeClaim\) [Filename](<https://github.com/metal3d/katenary/blob/develop/generator/volume.go#L117>)
|
||||
### func \(\*VolumeClaim\) [Filename](<https://github.com/metal3d/katenary/blob/develop/generator/volume.go#L127>)
|
||||
|
||||
```go
|
||||
func (v *VolumeClaim) Filename() string
|
||||
@@ -902,7 +910,7 @@ func (v *VolumeClaim) Filename() string
|
||||
Filename returns the suggested filename for a VolumeClaim.
|
||||
|
||||
<a name="VolumeClaim.Yaml"></a>
|
||||
### func \(\*VolumeClaim\) [Yaml](<https://github.com/metal3d/katenary/blob/develop/generator/volume.go#L56>)
|
||||
### func \(\*VolumeClaim\) [Yaml](<https://github.com/metal3d/katenary/blob/develop/generator/volume.go#L63>)
|
||||
|
||||
```go
|
||||
func (v *VolumeClaim) Yaml() ([]byte, error)
|
||||
|
||||
@@ -17,7 +17,7 @@ func NotesFile(services []string) string
|
||||
NotesFile returns the content of the note.txt file.
|
||||
|
||||
<a name="ReadMeFile"></a>
|
||||
## func [ReadMeFile](<https://github.com/metal3d/katenary/blob/develop/generator/extrafiles/readme.go#L25>)
|
||||
## func [ReadMeFile](<https://github.com/metal3d/katenary/blob/develop/generator/extrafiles/readme.go#L24>)
|
||||
|
||||
```go
|
||||
func ReadMeFile(charname, description string, values map[string]any) string
|
||||
|
||||
@@ -158,7 +158,7 @@ func PortsFrom(data string) (Ports, error)
|
||||
PortsFrom returns a Ports from the given string.
|
||||
|
||||
<a name="Probe"></a>
|
||||
## type [Probe](<https://github.com/metal3d/katenary/blob/develop/generator/labelStructs/probes.go#L8-L11>)
|
||||
## type [Probe](<https://github.com/metal3d/katenary/blob/develop/generator/labelStructs/probes.go#L11-L14>)
|
||||
|
||||
|
||||
|
||||
@@ -170,7 +170,7 @@ type Probe struct {
|
||||
```
|
||||
|
||||
<a name="ProbeFrom"></a>
|
||||
### func [ProbeFrom](<https://github.com/metal3d/katenary/blob/develop/generator/labelStructs/probes.go#L13>)
|
||||
### func [ProbeFrom](<https://github.com/metal3d/katenary/blob/develop/generator/labelStructs/probes.go#L16>)
|
||||
|
||||
```go
|
||||
func ProbeFrom(data string) (*Probe, error)
|
||||
|
||||
@@ -8,7 +8,16 @@ import "katenary/utils"
|
||||
|
||||
Utils package provides some utility functions used in katenary. It defines some constants and functions used in the whole project.
|
||||
|
||||
## func [CountStartingSpaces](<https://github.com/metal3d/katenary/blob/develop/utils/utils.go#L31>)
|
||||
## func [Confirm](<https://github.com/metal3d/katenary/blob/develop/utils/utils.go#L167>)
|
||||
|
||||
```go
|
||||
func Confirm(question string, icon ...Icon) bool
|
||||
```
|
||||
|
||||
Confirm asks a question and returns true if the answer is y.
|
||||
|
||||
<a name="CountStartingSpaces"></a>
|
||||
## func [CountStartingSpaces](<https://github.com/metal3d/katenary/blob/develop/utils/utils.go#L33>)
|
||||
|
||||
```go
|
||||
func CountStartingSpaces(line string) int
|
||||
@@ -16,8 +25,17 @@ func CountStartingSpaces(line string) int
|
||||
|
||||
CountStartingSpaces counts the number of spaces at the beginning of a string.
|
||||
|
||||
<a name="EncodeBasicYaml"></a>
|
||||
## func [EncodeBasicYaml](<https://github.com/metal3d/katenary/blob/develop/utils/utils.go#L179>)
|
||||
|
||||
```go
|
||||
func EncodeBasicYaml(data any) ([]byte, error)
|
||||
```
|
||||
|
||||
EncodeBasicYaml encodes a basic yaml from an interface.
|
||||
|
||||
<a name="GetContainerByName"></a>
|
||||
## func [GetContainerByName](<https://github.com/metal3d/katenary/blob/develop/utils/utils.go#L82>)
|
||||
## func [GetContainerByName](<https://github.com/metal3d/katenary/blob/develop/utils/utils.go#L84>)
|
||||
|
||||
```go
|
||||
func GetContainerByName(name string, containers []corev1.Container) (*corev1.Container, int)
|
||||
@@ -26,7 +44,7 @@ func GetContainerByName(name string, containers []corev1.Container) (*corev1.Con
|
||||
GetContainerByName returns a container by name and its index in the array. It returns nil, \-1 if not found.
|
||||
|
||||
<a name="GetKind"></a>
|
||||
## func [GetKind](<https://github.com/metal3d/katenary/blob/develop/utils/utils.go#L44>)
|
||||
## func [GetKind](<https://github.com/metal3d/katenary/blob/develop/utils/utils.go#L46>)
|
||||
|
||||
```go
|
||||
func GetKind(path string) (kind string)
|
||||
@@ -35,7 +53,7 @@ func GetKind(path string) (kind string)
|
||||
GetKind returns the kind of the resource from the file path.
|
||||
|
||||
<a name="GetServiceNameByPort"></a>
|
||||
## func [GetServiceNameByPort](<https://github.com/metal3d/katenary/blob/develop/utils/utils.go#L72>)
|
||||
## func [GetServiceNameByPort](<https://github.com/metal3d/katenary/blob/develop/utils/utils.go#L74>)
|
||||
|
||||
```go
|
||||
func GetServiceNameByPort(port int) string
|
||||
@@ -44,7 +62,7 @@ func GetServiceNameByPort(port int) string
|
||||
GetServiceNameByPort returns the service name for a port. It the service name is not found, it returns an empty string.
|
||||
|
||||
<a name="GetValuesFromLabel"></a>
|
||||
## func [GetValuesFromLabel](<https://github.com/metal3d/katenary/blob/develop/utils/utils.go#L122>)
|
||||
## func [GetValuesFromLabel](<https://github.com/metal3d/katenary/blob/develop/utils/utils.go#L124>)
|
||||
|
||||
```go
|
||||
func GetValuesFromLabel(service types.ServiceConfig, LabelValues string) map[string]*EnvConfig
|
||||
@@ -62,7 +80,7 @@ func HashComposefiles(files []string) (string, error)
|
||||
HashComposefiles returns a hash of the compose files.
|
||||
|
||||
<a name="Int32Ptr"></a>
|
||||
## func [Int32Ptr](<https://github.com/metal3d/katenary/blob/develop/utils/utils.go#L25>)
|
||||
## func [Int32Ptr](<https://github.com/metal3d/katenary/blob/develop/utils/utils.go#L27>)
|
||||
|
||||
```go
|
||||
func Int32Ptr(i int32) *int32
|
||||
@@ -71,7 +89,7 @@ func Int32Ptr(i int32) *int32
|
||||
Int32Ptr returns a pointer to an int32.
|
||||
|
||||
<a name="MapKeys"></a>
|
||||
## func [MapKeys](<https://github.com/metal3d/katenary/blob/develop/utils/utils.go#L156>)
|
||||
## func [MapKeys](<https://github.com/metal3d/katenary/blob/develop/utils/utils.go#L158>)
|
||||
|
||||
```go
|
||||
func MapKeys(m map[string]interface{}) []string
|
||||
@@ -80,7 +98,7 @@ func MapKeys(m map[string]interface{}) []string
|
||||
|
||||
|
||||
<a name="PathToName"></a>
|
||||
## func [PathToName](<https://github.com/metal3d/katenary/blob/develop/utils/utils.go#L101>)
|
||||
## func [PathToName](<https://github.com/metal3d/katenary/blob/develop/utils/utils.go#L103>)
|
||||
|
||||
```go
|
||||
func PathToName(path string) string
|
||||
@@ -89,7 +107,7 @@ func PathToName(path string) string
|
||||
PathToName converts a path to a kubernetes complient name.
|
||||
|
||||
<a name="StrPtr"></a>
|
||||
## func [StrPtr](<https://github.com/metal3d/katenary/blob/develop/utils/utils.go#L28>)
|
||||
## func [StrPtr](<https://github.com/metal3d/katenary/blob/develop/utils/utils.go#L30>)
|
||||
|
||||
```go
|
||||
func StrPtr(s string) *string
|
||||
@@ -98,7 +116,7 @@ func StrPtr(s string) *string
|
||||
StrPtr returns a pointer to a string.
|
||||
|
||||
<a name="TplName"></a>
|
||||
## func [TplName](<https://github.com/metal3d/katenary/blob/develop/utils/utils.go#L17>)
|
||||
## func [TplName](<https://github.com/metal3d/katenary/blob/develop/utils/utils.go#L19>)
|
||||
|
||||
```go
|
||||
func TplName(serviceName, appname string, suffix ...string) string
|
||||
@@ -107,7 +125,7 @@ func TplName(serviceName, appname string, suffix ...string) string
|
||||
TplName returns the name of the kubernetes resource as a template string. It is used in the templates and defined in \_helper.tpl file.
|
||||
|
||||
<a name="TplValue"></a>
|
||||
## func [TplValue](<https://github.com/metal3d/katenary/blob/develop/utils/utils.go#L92>)
|
||||
## func [TplValue](<https://github.com/metal3d/katenary/blob/develop/utils/utils.go#L94>)
|
||||
|
||||
```go
|
||||
func TplValue(serviceName, variable string, pipes ...string) string
|
||||
@@ -125,7 +143,7 @@ func Warn(msg ...interface{})
|
||||
Warn prints a warning message
|
||||
|
||||
<a name="WordWrap"></a>
|
||||
## func [WordWrap](<https://github.com/metal3d/katenary/blob/develop/utils/utils.go#L152>)
|
||||
## func [WordWrap](<https://github.com/metal3d/katenary/blob/develop/utils/utils.go#L154>)
|
||||
|
||||
```go
|
||||
func WordWrap(text string, lineWidth int) string
|
||||
@@ -134,7 +152,7 @@ func WordWrap(text string, lineWidth int) string
|
||||
WordWrap wraps a string to a given line width. Warning: it may break the string. You need to check the result.
|
||||
|
||||
<a name="Wrap"></a>
|
||||
## func [Wrap](<https://github.com/metal3d/katenary/blob/develop/utils/utils.go#L61>)
|
||||
## func [Wrap](<https://github.com/metal3d/katenary/blob/develop/utils/utils.go#L63>)
|
||||
|
||||
```go
|
||||
func Wrap(src, above, below string) string
|
||||
@@ -143,7 +161,7 @@ func Wrap(src, above, below string) string
|
||||
Wrap wraps a string with a string above and below. It will respect the indentation of the src string.
|
||||
|
||||
<a name="WrapBytes"></a>
|
||||
## func [WrapBytes](<https://github.com/metal3d/katenary/blob/develop/utils/utils.go#L67>)
|
||||
## func [WrapBytes](<https://github.com/metal3d/katenary/blob/develop/utils/utils.go#L69>)
|
||||
|
||||
```go
|
||||
func WrapBytes(src, above, below []byte) []byte
|
||||
@@ -152,14 +170,14 @@ func WrapBytes(src, above, below []byte) []byte
|
||||
WrapBytes wraps a byte array with a byte array above and below. It will respect the indentation of the src string.
|
||||
|
||||
<a name="EnvConfig"></a>
|
||||
## type [EnvConfig](<https://github.com/metal3d/katenary/blob/develop/utils/utils.go#L116-L119>)
|
||||
## type [EnvConfig](<https://github.com/metal3d/katenary/blob/develop/utils/utils.go#L118-L121>)
|
||||
|
||||
EnvConfig is a struct to hold the description of an environment variable.
|
||||
|
||||
```go
|
||||
type EnvConfig struct {
|
||||
Description string
|
||||
Service types.ServiceConfig
|
||||
Description string
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
@@ -77,11 +77,6 @@ h3[id*="katenaryio"] {
|
||||
}
|
||||
|
||||
/*Zoomable images*/
|
||||
|
||||
/*[data-md-color-scheme="slate"] #logo {
|
||||
background-image: url("logo-bright.svg");
|
||||
}*/
|
||||
|
||||
.zoomable svg {
|
||||
background-color: var(--md-default-bg-color);
|
||||
padding: 1rem;
|
||||
|
||||
@@ -1,30 +1,46 @@
|
||||
package generator
|
||||
|
||||
import "katenary/generator/labelStructs"
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
|
||||
"katenary/generator/labelStructs"
|
||||
"katenary/utils"
|
||||
)
|
||||
|
||||
// ConvertOptions are the options to convert a compose project to a helm chart.
|
||||
type ConvertOptions struct {
|
||||
AppVersion *string
|
||||
OutputDir string
|
||||
ChartVersion string
|
||||
Profiles []string
|
||||
Force bool
|
||||
HelmUpdate bool
|
||||
}
|
||||
|
||||
// ChartTemplate is a template of a chart. It contains the content of the template and the name of the service.
|
||||
// This is used internally to generate the templates.
|
||||
//
|
||||
// TODO: maybe we can set it private.
|
||||
type ChartTemplate struct {
|
||||
Content []byte
|
||||
Servicename string
|
||||
Content []byte
|
||||
}
|
||||
|
||||
// HelmChart is a Helm Chart representation. It contains all the
|
||||
// tempaltes, values, versions, helpers...
|
||||
type HelmChart struct {
|
||||
Templates map[string]*ChartTemplate `yaml:"-"`
|
||||
Values map[string]any `yaml:"-"`
|
||||
VolumeMounts map[string]any `yaml:"-"`
|
||||
composeHash *string `yaml:"-"`
|
||||
Name string `yaml:"name"`
|
||||
ApiVersion string `yaml:"apiVersion"`
|
||||
Version string `yaml:"version"`
|
||||
AppVersion string `yaml:"appVersion"`
|
||||
Description string `yaml:"description"`
|
||||
Helper string `yaml:"-"`
|
||||
Dependencies []labelStructs.Dependency `yaml:"dependencies,omitempty"`
|
||||
Templates map[string]*ChartTemplate `yaml:"-"` // do not export to yaml
|
||||
Helper string `yaml:"-"` // do not export to yaml
|
||||
Values map[string]any `yaml:"-"` // do not export to yaml
|
||||
VolumeMounts map[string]any `yaml:"-"` // do not export to yaml
|
||||
composeHash *string `yaml:"-"` // do not export to yaml
|
||||
}
|
||||
|
||||
// NewChart creates a new empty chart with the given name.
|
||||
@@ -42,12 +58,59 @@ func NewChart(name string) *HelmChart {
|
||||
}
|
||||
}
|
||||
|
||||
// ConvertOptions are the options to convert a compose project to a helm chart.
|
||||
type ConvertOptions struct {
|
||||
Force bool // Force the chart directory deletion if it already exists.
|
||||
OutputDir string // The output directory of the chart.
|
||||
Profiles []string // Profile to use for the conversion.
|
||||
HelmUpdate bool // If true, the "helm dep update" command will be run after the chart generation.
|
||||
AppVersion *string // Set the chart "appVersion" field. If nil, the version will be set to 0.1.0.
|
||||
ChartVersion string // Set the chart "version" field.
|
||||
// SaveTemplates the templates of the chart to the given directory.
|
||||
func (chart *HelmChart) SaveTemplates(templateDir string) {
|
||||
for name, template := range chart.Templates {
|
||||
t := template.Content
|
||||
t = removeNewlinesInsideBrackets(t)
|
||||
t = removeUnwantedLines(t)
|
||||
t = addModeline(t)
|
||||
|
||||
kind := utils.GetKind(name)
|
||||
var icon utils.Icon
|
||||
switch kind {
|
||||
case "deployment":
|
||||
icon = utils.IconPackage
|
||||
case "service":
|
||||
icon = utils.IconPlug
|
||||
case "ingress":
|
||||
icon = utils.IconWorld
|
||||
case "volumeclaim":
|
||||
icon = utils.IconCabinet
|
||||
case "configmap":
|
||||
icon = utils.IconConfig
|
||||
case "secret":
|
||||
icon = utils.IconSecret
|
||||
default:
|
||||
icon = utils.IconInfo
|
||||
}
|
||||
|
||||
servicename := template.Servicename
|
||||
if err := os.MkdirAll(filepath.Join(templateDir, servicename), 0o755); err != nil {
|
||||
fmt.Println(utils.IconFailure, err)
|
||||
os.Exit(1)
|
||||
}
|
||||
fmt.Println(icon, "Creating", kind, servicename)
|
||||
// if the name is a path, create the directory
|
||||
if strings.Contains(name, string(filepath.Separator)) {
|
||||
name = filepath.Join(templateDir, name)
|
||||
err := os.MkdirAll(filepath.Dir(name), 0o755)
|
||||
if err != nil {
|
||||
fmt.Println(utils.IconFailure, err)
|
||||
os.Exit(1)
|
||||
}
|
||||
} else {
|
||||
// remove the serivce name from the template name
|
||||
name = strings.Replace(name, servicename+".", "", 1)
|
||||
name = filepath.Join(templateDir, servicename, name)
|
||||
}
|
||||
f, err := os.Create(name)
|
||||
if err != nil {
|
||||
fmt.Println(utils.IconFailure, err)
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
f.Write(t)
|
||||
f.Close()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,13 +7,13 @@ import (
|
||||
"regexp"
|
||||
"strings"
|
||||
|
||||
"katenary/generator/labelStructs"
|
||||
"katenary/utils"
|
||||
|
||||
"github.com/compose-spec/compose-go/types"
|
||||
corev1 "k8s.io/api/core/v1"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"sigs.k8s.io/yaml"
|
||||
|
||||
"katenary/generator/labelStructs"
|
||||
"katenary/utils"
|
||||
)
|
||||
|
||||
// only used to check interface implementation
|
||||
@@ -23,7 +23,7 @@ var (
|
||||
)
|
||||
|
||||
// NewFileMap creates a new DataMap from a compose service. The appName is the name of the application taken from the project name.
|
||||
func NewFileMap(service types.ServiceConfig, appName string, kind string) DataMap {
|
||||
func NewFileMap(service types.ServiceConfig, appName, kind string) DataMap {
|
||||
switch kind {
|
||||
case "configmap":
|
||||
return NewConfigMap(service, appName)
|
||||
@@ -47,8 +47,8 @@ const (
|
||||
type ConfigMap struct {
|
||||
*corev1.ConfigMap
|
||||
service *types.ServiceConfig
|
||||
usage FileMapUsage
|
||||
path string
|
||||
usage FileMapUsage
|
||||
}
|
||||
|
||||
// NewConfigMap creates a new ConfigMap from a compose service. The appName is the name of the application taken from the project name.
|
||||
@@ -75,13 +75,13 @@ func NewConfigMap(service types.ServiceConfig, appName string) *ConfigMap {
|
||||
}
|
||||
|
||||
// get the secrets from the labels
|
||||
if secrets, err := labelStructs.SecretsFrom(service.Labels[LabelSecrets]); err != nil {
|
||||
secrets, err := labelStructs.SecretsFrom(service.Labels[LabelSecrets])
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
} else {
|
||||
// drop the secrets from the environment
|
||||
for _, secret := range secrets {
|
||||
drop[secret] = true
|
||||
}
|
||||
}
|
||||
// drop the secrets from the environment
|
||||
for _, secret := range secrets {
|
||||
drop[secret] = true
|
||||
}
|
||||
// get the label values from the labels
|
||||
varDescriptons := utils.GetValuesFromLabel(service, LabelValues)
|
||||
@@ -95,7 +95,6 @@ func NewConfigMap(service types.ServiceConfig, appName string) *ConfigMap {
|
||||
done[value] = true
|
||||
continue
|
||||
}
|
||||
// val := `{{ tpl .Values.` + service.Name + `.environment.` + value + ` $ }}`
|
||||
val := utils.TplValue(service.Name, "environment."+value)
|
||||
service.Environment[value] = &val
|
||||
}
|
||||
@@ -112,10 +111,9 @@ func NewConfigMap(service types.ServiceConfig, appName string) *ConfigMap {
|
||||
}
|
||||
}
|
||||
for key, env := range service.Environment {
|
||||
if _, ok := done[key]; ok {
|
||||
continue
|
||||
}
|
||||
if _, ok := drop[key]; ok {
|
||||
_, isDropped := drop[key]
|
||||
_, isDone := done[key]
|
||||
if isDropped || isDone {
|
||||
continue
|
||||
}
|
||||
cm.AddData(key, *env)
|
||||
@@ -127,7 +125,7 @@ func NewConfigMap(service types.ServiceConfig, appName string) *ConfigMap {
|
||||
// NewConfigMapFromDirectory creates a new ConfigMap from a compose service. This path is the path to the
|
||||
// file or directory. If the path is a directory, all files in the directory are added to the ConfigMap.
|
||||
// Each subdirectory are ignored. Note that the Generate() function will create the subdirectories ConfigMaps.
|
||||
func NewConfigMapFromDirectory(service types.ServiceConfig, appName string, path string) *ConfigMap {
|
||||
func NewConfigMapFromDirectory(service types.ServiceConfig, appName, path string) *ConfigMap {
|
||||
normalized := path
|
||||
normalized = strings.TrimLeft(normalized, ".")
|
||||
normalized = strings.TrimLeft(normalized, "/")
|
||||
@@ -163,7 +161,7 @@ func (c *ConfigMap) SetData(data map[string]string) {
|
||||
}
|
||||
|
||||
// AddData adds a key value pair to the configmap. Append or overwrite the value if the key already exists.
|
||||
func (c *ConfigMap) AddData(key string, value string) {
|
||||
func (c *ConfigMap) AddData(key, value string) {
|
||||
c.Data[key] = value
|
||||
}
|
||||
|
||||
|
||||
@@ -12,13 +12,12 @@ import (
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/compose-spec/compose-go/types"
|
||||
|
||||
"katenary/generator/extrafiles"
|
||||
"katenary/generator/labelStructs"
|
||||
"katenary/parser"
|
||||
"katenary/utils"
|
||||
|
||||
"github.com/compose-spec/compose-go/types"
|
||||
goyaml "gopkg.in/yaml.v3"
|
||||
)
|
||||
|
||||
const headerHelp = `# This file is autogenerated by katenary
|
||||
@@ -76,10 +75,11 @@ func Convert(config ConvertOptions, dockerComposeFile ...string) {
|
||||
// check if the chart directory exists
|
||||
// if yes, prevent the user from overwriting it and ask for confirmation
|
||||
if _, err := os.Stat(config.OutputDir); err == nil {
|
||||
fmt.Print(utils.IconWarning, " The chart directory "+config.OutputDir+" already exists, do you want to overwrite it? [y/N] ")
|
||||
var answer string
|
||||
fmt.Scanln(&answer)
|
||||
if strings.ToLower(answer) != "y" {
|
||||
overwrite := utils.Confirm(
|
||||
"The chart directory "+config.OutputDir+" already exists, do you want to overwrite it?",
|
||||
utils.IconWarning,
|
||||
)
|
||||
if !overwrite {
|
||||
fmt.Println("Aborting")
|
||||
os.Exit(126) // 126 is the exit code for "Command invoked cannot execute"
|
||||
}
|
||||
@@ -109,168 +109,27 @@ func Convert(config ConvertOptions, dockerComposeFile ...string) {
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
for name, template := range chart.Templates {
|
||||
t := template.Content
|
||||
t = removeNewlinesInsideBrackets(t)
|
||||
t = removeUnwantedLines(t)
|
||||
t = addModeline(t)
|
||||
// write the templates to the disk
|
||||
chart.SaveTemplates(templateDir)
|
||||
|
||||
kind := utils.GetKind(name)
|
||||
var icon utils.Icon
|
||||
switch kind {
|
||||
case "deployment":
|
||||
icon = utils.IconPackage
|
||||
case "service":
|
||||
icon = utils.IconPlug
|
||||
case "ingress":
|
||||
icon = utils.IconWorld
|
||||
case "volumeclaim":
|
||||
icon = utils.IconCabinet
|
||||
case "configmap":
|
||||
icon = utils.IconConfig
|
||||
case "secret":
|
||||
icon = utils.IconSecret
|
||||
default:
|
||||
icon = utils.IconInfo
|
||||
}
|
||||
// write the Chart.yaml file
|
||||
buildCharYamlFile(chart, project, chartPath)
|
||||
|
||||
servicename := template.Servicename
|
||||
if err := os.MkdirAll(filepath.Join(templateDir, servicename), 0o755); err != nil {
|
||||
fmt.Println(utils.IconFailure, err)
|
||||
os.Exit(1)
|
||||
}
|
||||
fmt.Println(icon, "Creating", kind, servicename)
|
||||
// if the name is a path, create the directory
|
||||
if strings.Contains(name, string(filepath.Separator)) {
|
||||
name = filepath.Join(templateDir, name)
|
||||
err := os.MkdirAll(filepath.Dir(name), 0o755)
|
||||
if err != nil {
|
||||
fmt.Println(utils.IconFailure, err)
|
||||
os.Exit(1)
|
||||
}
|
||||
} else {
|
||||
// remove the serivce name from the template name
|
||||
name = strings.Replace(name, servicename+".", "", 1)
|
||||
name = filepath.Join(templateDir, servicename, name)
|
||||
}
|
||||
f, err := os.Create(name)
|
||||
if err != nil {
|
||||
fmt.Println(utils.IconFailure, err)
|
||||
os.Exit(1)
|
||||
}
|
||||
// build and write the values.yaml file
|
||||
buildValues(chart, project, valuesPath)
|
||||
|
||||
f.Write(t)
|
||||
f.Close()
|
||||
}
|
||||
|
||||
// calculate the sha1 hash of the services
|
||||
buf := bytes.NewBuffer(nil)
|
||||
encoder := goyaml.NewEncoder(buf)
|
||||
encoder.SetIndent(2)
|
||||
if err := encoder.Encode(chart); err != nil {
|
||||
fmt.Println(err)
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
yamlChart := buf.Bytes()
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
os.Exit(1)
|
||||
}
|
||||
// concat chart adding a comment with hash of services on top
|
||||
yamlChart = append([]byte(fmt.Sprintf("# compose hash (sha1): %s\n", *chart.composeHash)), yamlChart...)
|
||||
// add the list of compose files
|
||||
files := []string{}
|
||||
for _, file := range project.ComposeFiles {
|
||||
base := filepath.Base(file)
|
||||
files = append(files, base)
|
||||
}
|
||||
yamlChart = append([]byte(fmt.Sprintf("# compose files: %s\n", strings.Join(files, ", "))), yamlChart...)
|
||||
// add generated date
|
||||
yamlChart = append([]byte(fmt.Sprintf("# generated at: %s\n", time.Now().Format(time.RFC3339))), yamlChart...)
|
||||
|
||||
// document Chart.yaml file
|
||||
yamlChart = addChartDoc(yamlChart, project)
|
||||
|
||||
f, err := os.Create(chartPath)
|
||||
if err != nil {
|
||||
fmt.Println(utils.IconFailure, err)
|
||||
os.Exit(1)
|
||||
}
|
||||
f.Write(yamlChart)
|
||||
f.Close()
|
||||
|
||||
buf.Reset()
|
||||
encoder = goyaml.NewEncoder(buf)
|
||||
encoder.SetIndent(2)
|
||||
if err = encoder.Encode(&chart.Values); err != nil {
|
||||
fmt.Println(err)
|
||||
os.Exit(1)
|
||||
}
|
||||
values := buf.Bytes()
|
||||
values = addDescriptions(values, *project)
|
||||
values = addDependencyDescription(values, chart.Dependencies)
|
||||
values = addCommentsToValues(values)
|
||||
values = addStorageClassHelp(values)
|
||||
values = addImagePullSecretsHelp(values)
|
||||
values = addImagePullPolicyHelp(values)
|
||||
values = addVariablesDoc(values, project)
|
||||
values = addMainTagAppDoc(values, project)
|
||||
values = addResourceHelp(values)
|
||||
values = addYAMLSelectorPath(values)
|
||||
values = append([]byte(headerHelp), values...)
|
||||
|
||||
f, err = os.Create(valuesPath)
|
||||
if err != nil {
|
||||
fmt.Println(utils.IconFailure, err)
|
||||
os.Exit(1)
|
||||
}
|
||||
f.Write(values)
|
||||
f.Close()
|
||||
|
||||
f, err = os.Create(helpersPath)
|
||||
if err != nil {
|
||||
fmt.Println(utils.IconFailure, err)
|
||||
os.Exit(1)
|
||||
}
|
||||
f.Write([]byte(chart.Helper))
|
||||
f.Close()
|
||||
// write the _helpers.tpl to the disk
|
||||
writeContent(helpersPath, []byte(chart.Helper))
|
||||
|
||||
// write the readme to the disk
|
||||
readme := extrafiles.ReadMeFile(chart.Name, chart.Description, chart.Values)
|
||||
f, err = os.Create(readmePath)
|
||||
if err != nil {
|
||||
fmt.Println(utils.IconFailure, err)
|
||||
os.Exit(1)
|
||||
}
|
||||
f.Write([]byte(readme))
|
||||
f.Close()
|
||||
writeContent(readmePath, []byte(readme))
|
||||
|
||||
services := make([]string, 0)
|
||||
for _, service := range project.Services {
|
||||
services = append(services, service.Name)
|
||||
}
|
||||
notes := extrafiles.NotesFile(services)
|
||||
f, err = os.Create(notesPath)
|
||||
if err != nil {
|
||||
fmt.Println(utils.IconFailure, err)
|
||||
os.Exit(1)
|
||||
}
|
||||
f.Write([]byte(notes))
|
||||
f.Close()
|
||||
// get the list of services to write in the notes
|
||||
buildNotesFile(project, notesPath)
|
||||
|
||||
executeAndHandleError := func(fn func(ConvertOptions) error, config ConvertOptions, message string) {
|
||||
if err := fn(config); err != nil {
|
||||
fmt.Println(utils.IconFailure, err)
|
||||
os.Exit(1)
|
||||
}
|
||||
fmt.Println(utils.IconSuccess, message)
|
||||
}
|
||||
|
||||
if config.HelmUpdate {
|
||||
executeAndHandleError(helmUpdate, config, "Helm dependencies updated")
|
||||
executeAndHandleError(helmLint, config, "Helm chart linted")
|
||||
fmt.Println(utils.IconSuccess, "Helm chart created successfully")
|
||||
}
|
||||
// call helm update if needed
|
||||
callHelmUpdate(config)
|
||||
}
|
||||
|
||||
const ingressClassHelp = `# Default value for ingress.class annotation
|
||||
@@ -501,31 +360,38 @@ func addResourceHelp(values []byte) []byte {
|
||||
func addVariablesDoc(values []byte, project *types.Project) []byte {
|
||||
lines := strings.Split(string(values), "\n")
|
||||
|
||||
currentService := ""
|
||||
for _, service := range project.Services {
|
||||
variables := utils.GetValuesFromLabel(service, LabelValues)
|
||||
for i, line := range lines {
|
||||
if regexp.MustCompile(`(?m)^` + service.Name + `:`).MatchString(line) {
|
||||
currentService = service.Name
|
||||
lines = addDocToVariable(service, lines)
|
||||
}
|
||||
return []byte(strings.Join(lines, "\n"))
|
||||
}
|
||||
|
||||
func addDocToVariable(service types.ServiceConfig, lines []string) []string {
|
||||
currentService := ""
|
||||
variables := utils.GetValuesFromLabel(service, LabelValues)
|
||||
for i, line := range lines {
|
||||
// if the line is a service, it is a name followed by a colon
|
||||
if regexp.MustCompile(`(?m)^` + service.Name + `:`).MatchString(line) {
|
||||
currentService = service.Name
|
||||
}
|
||||
// for each variable in the service, add the description
|
||||
for varname, variable := range variables {
|
||||
if variable == nil {
|
||||
continue
|
||||
}
|
||||
for varname, variable := range variables {
|
||||
if variable == nil {
|
||||
continue
|
||||
}
|
||||
spaces := utils.CountStartingSpaces(line)
|
||||
if regexp.MustCompile(`(?m)\s*`+varname+`:`).MatchString(line) && currentService == service.Name {
|
||||
spaces := utils.CountStartingSpaces(line)
|
||||
if regexp.MustCompile(`(?m)\s*`+varname+`:`).MatchString(line) && currentService == service.Name {
|
||||
|
||||
// add # to the beginning of the Description
|
||||
doc := strings.ReplaceAll("\n"+variable.Description, "\n", "\n"+strings.Repeat(" ", spaces)+"# ")
|
||||
doc = strings.TrimRight(doc, " ")
|
||||
doc += "\n" + line
|
||||
// add # to the beginning of the Description
|
||||
doc := strings.ReplaceAll("\n"+variable.Description, "\n", "\n"+strings.Repeat(" ", spaces)+"# ")
|
||||
doc = strings.TrimRight(doc, " ")
|
||||
doc += "\n" + line
|
||||
|
||||
lines[i] = doc
|
||||
}
|
||||
lines[i] = doc
|
||||
}
|
||||
}
|
||||
}
|
||||
return []byte(strings.Join(lines, "\n"))
|
||||
return lines
|
||||
}
|
||||
|
||||
const mainTagAppDoc = `This is the version of the main application.
|
||||
@@ -535,8 +401,6 @@ func addMainTagAppDoc(values []byte, project *types.Project) []byte {
|
||||
lines := strings.Split(string(values), "\n")
|
||||
|
||||
for _, service := range project.Services {
|
||||
inService := false
|
||||
inRegistry := false
|
||||
// read the label LabelMainApp
|
||||
if v, ok := service.Labels[LabelMainApp]; !ok {
|
||||
continue
|
||||
@@ -546,29 +410,36 @@ func addMainTagAppDoc(values []byte, project *types.Project) []byte {
|
||||
fmt.Printf("%s Adding main tag app doc %s\n", utils.IconConfig, service.Name)
|
||||
}
|
||||
|
||||
for i, line := range lines {
|
||||
if regexp.MustCompile(`^` + service.Name + `:`).MatchString(line) {
|
||||
inService = true
|
||||
}
|
||||
if inService && regexp.MustCompile(`^\s*repository:.*`).MatchString(line) {
|
||||
inRegistry = true
|
||||
}
|
||||
if inService && inRegistry {
|
||||
if regexp.MustCompile(`^\s*tag: .*`).MatchString(line) {
|
||||
spaces := utils.CountStartingSpaces(line)
|
||||
doc := strings.ReplaceAll(mainTagAppDoc, "\n", "\n"+strings.Repeat(" ", spaces)+"# ")
|
||||
doc = strings.Repeat(" ", spaces) + "# " + doc
|
||||
|
||||
lines[i] = doc + "\n" + line + "\n"
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
lines = addMainAppDoc(lines, service)
|
||||
}
|
||||
|
||||
return []byte(strings.Join(lines, "\n"))
|
||||
}
|
||||
|
||||
func addMainAppDoc(lines []string, service types.ServiceConfig) []string {
|
||||
inService := false
|
||||
inRegistry := false
|
||||
for i, line := range lines {
|
||||
if regexp.MustCompile(`^` + service.Name + `:`).MatchString(line) {
|
||||
inService = true
|
||||
}
|
||||
if inService && regexp.MustCompile(`^\s*repository:.*`).MatchString(line) {
|
||||
inRegistry = true
|
||||
}
|
||||
if inService && inRegistry {
|
||||
if regexp.MustCompile(`^\s*tag: .*`).MatchString(line) {
|
||||
spaces := utils.CountStartingSpaces(line)
|
||||
doc := strings.ReplaceAll(mainTagAppDoc, "\n", "\n"+strings.Repeat(" ", spaces)+"# ")
|
||||
doc = strings.Repeat(" ", spaces) + "# " + doc
|
||||
|
||||
lines[i] = doc + "\n" + line + "\n"
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
return lines
|
||||
}
|
||||
|
||||
func removeNewlinesInsideBrackets(values []byte) []byte {
|
||||
re, err := regexp.Compile(`(?s)\{\{(.*?)\}\}`)
|
||||
if err != nil {
|
||||
@@ -715,3 +586,89 @@ func addYAMLSelectorPath(values []byte) []byte {
|
||||
}
|
||||
return []byte(strings.Join(toReturn, "\n"))
|
||||
}
|
||||
|
||||
func writeContent(path string, content []byte) {
|
||||
f, err := os.Create(path)
|
||||
if err != nil {
|
||||
fmt.Println(utils.IconFailure, err)
|
||||
os.Exit(1)
|
||||
}
|
||||
defer f.Close()
|
||||
f.Write(content)
|
||||
}
|
||||
|
||||
func buildValues(chart *HelmChart, project *types.Project, valuesPath string) {
|
||||
values, err := utils.EncodeBasicYaml(&chart.Values)
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
os.Exit(1)
|
||||
}
|
||||
values = addDescriptions(values, *project)
|
||||
values = addDependencyDescription(values, chart.Dependencies)
|
||||
values = addCommentsToValues(values)
|
||||
values = addStorageClassHelp(values)
|
||||
values = addImagePullSecretsHelp(values)
|
||||
values = addImagePullPolicyHelp(values)
|
||||
values = addVariablesDoc(values, project)
|
||||
values = addMainTagAppDoc(values, project)
|
||||
values = addResourceHelp(values)
|
||||
values = addYAMLSelectorPath(values)
|
||||
values = append([]byte(headerHelp), values...)
|
||||
|
||||
// add vim modeline
|
||||
values = append(values, []byte("\n# vim: ft=yaml\n")...)
|
||||
|
||||
// write the values to the disk
|
||||
writeContent(valuesPath, values)
|
||||
}
|
||||
|
||||
func buildNotesFile(project *types.Project, notesPath string) {
|
||||
// get the list of services to write in the notes
|
||||
services := make([]string, 0)
|
||||
for _, service := range project.Services {
|
||||
services = append(services, service.Name)
|
||||
}
|
||||
// write the notes to the disk
|
||||
notes := extrafiles.NotesFile(services)
|
||||
writeContent(notesPath, []byte(notes))
|
||||
}
|
||||
|
||||
func buildCharYamlFile(chart *HelmChart, project *types.Project, chartPath string) {
|
||||
// calculate the sha1 hash of the services
|
||||
yamlChart, err := utils.EncodeBasicYaml(chart)
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
os.Exit(1)
|
||||
}
|
||||
// concat chart adding a comment with hash of services on top
|
||||
yamlChart = append([]byte(fmt.Sprintf("# compose hash (sha1): %s\n", *chart.composeHash)), yamlChart...)
|
||||
// add the list of compose files
|
||||
files := []string{}
|
||||
for _, file := range project.ComposeFiles {
|
||||
base := filepath.Base(file)
|
||||
files = append(files, base)
|
||||
}
|
||||
yamlChart = append([]byte(fmt.Sprintf("# compose files: %s\n", strings.Join(files, ", "))), yamlChart...)
|
||||
// add generated date
|
||||
yamlChart = append([]byte(fmt.Sprintf("# generated at: %s\n", time.Now().Format(time.RFC3339))), yamlChart...)
|
||||
|
||||
// document Chart.yaml file
|
||||
yamlChart = addChartDoc(yamlChart, project)
|
||||
|
||||
writeContent(chartPath, yamlChart)
|
||||
}
|
||||
|
||||
func callHelmUpdate(config ConvertOptions) {
|
||||
executeAndHandleError := func(fn func(ConvertOptions) error, config ConvertOptions, message string) {
|
||||
if err := fn(config); err != nil {
|
||||
fmt.Println(utils.IconFailure, err)
|
||||
os.Exit(1)
|
||||
}
|
||||
fmt.Println(utils.IconSuccess, message)
|
||||
}
|
||||
if config.HelmUpdate {
|
||||
executeAndHandleError(helmUpdate, config, "Helm dependencies updated")
|
||||
executeAndHandleError(helmLint, config, "Helm chart linted")
|
||||
fmt.Println(utils.IconSuccess, "Helm chart created successfully")
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,14 +4,14 @@ import (
|
||||
"log"
|
||||
"strings"
|
||||
|
||||
"katenary/generator/labelStructs"
|
||||
"katenary/utils"
|
||||
|
||||
"github.com/compose-spec/compose-go/types"
|
||||
batchv1 "k8s.io/api/batch/v1"
|
||||
corev1 "k8s.io/api/core/v1"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"sigs.k8s.io/yaml"
|
||||
|
||||
"katenary/generator/labelStructs"
|
||||
"katenary/utils"
|
||||
)
|
||||
|
||||
// only used to check interface implementation
|
||||
|
||||
@@ -12,7 +12,7 @@ import (
|
||||
)
|
||||
|
||||
func TestBasicCronJob(t *testing.T) {
|
||||
compose_file := `
|
||||
composeFile := `
|
||||
services:
|
||||
cron:
|
||||
image: fedora
|
||||
@@ -23,7 +23,7 @@ services:
|
||||
schedule: "*/1 * * * *"
|
||||
rbac: false
|
||||
`
|
||||
tmpDir := setup(compose_file)
|
||||
tmpDir := setup(composeFile)
|
||||
defer teardown(tmpDir)
|
||||
|
||||
currentDir, _ := os.Getwd()
|
||||
@@ -64,7 +64,7 @@ services:
|
||||
}
|
||||
|
||||
func TestCronJobbWithRBAC(t *testing.T) {
|
||||
compose_file := `
|
||||
composeFile := `
|
||||
services:
|
||||
cron:
|
||||
image: fedora
|
||||
@@ -76,7 +76,7 @@ services:
|
||||
rbac: true
|
||||
`
|
||||
|
||||
tmpDir := setup(compose_file)
|
||||
tmpDir := setup(composeFile)
|
||||
defer teardown(tmpDir)
|
||||
|
||||
currentDir, _ := os.Getwd()
|
||||
|
||||
@@ -9,14 +9,14 @@ import (
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"katenary/generator/labelStructs"
|
||||
"katenary/utils"
|
||||
|
||||
"github.com/compose-spec/compose-go/types"
|
||||
appsv1 "k8s.io/api/apps/v1"
|
||||
corev1 "k8s.io/api/core/v1"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"sigs.k8s.io/yaml"
|
||||
|
||||
"katenary/generator/labelStructs"
|
||||
"katenary/utils"
|
||||
)
|
||||
|
||||
var _ Yaml = (*Deployment)(nil)
|
||||
@@ -204,117 +204,127 @@ func (d *Deployment) AddVolumes(service types.ServiceConfig, appName string) {
|
||||
isSamePod = v != ""
|
||||
}
|
||||
|
||||
for _, volume := range service.Volumes {
|
||||
d.bindVolumes(volume, isSamePod, tobind, service, appName)
|
||||
}
|
||||
}
|
||||
|
||||
func (d *Deployment) bindVolumes(volume types.ServiceVolumeConfig, isSamePod bool, tobind map[string]bool, service types.ServiceConfig, appName string) {
|
||||
container, index := utils.GetContainerByName(service.Name, d.Spec.Template.Spec.Containers)
|
||||
defer func(d *Deployment, container *corev1.Container, index int) {
|
||||
d.Spec.Template.Spec.Containers[index] = *container
|
||||
}(d, container, index)
|
||||
if _, ok := tobind[volume.Source]; !isSamePod && volume.Type == "bind" && !ok {
|
||||
utils.Warn(
|
||||
"Bind volumes are not supported yet, " +
|
||||
"excepting for those declared as " +
|
||||
LabelConfigMapFiles +
|
||||
", skipping volume " + volume.Source +
|
||||
" from service " + service.Name,
|
||||
)
|
||||
return
|
||||
}
|
||||
|
||||
for _, volume := range service.Volumes {
|
||||
// not declared as a bind volume, skip
|
||||
if _, ok := tobind[volume.Source]; !isSamePod && volume.Type == "bind" && !ok {
|
||||
utils.Warn(
|
||||
"Bind volumes are not supported yet, " +
|
||||
"excepting for those declared as " +
|
||||
LabelConfigMapFiles +
|
||||
", skipping volume " + volume.Source +
|
||||
" from service " + service.Name,
|
||||
)
|
||||
continue
|
||||
}
|
||||
if container == nil {
|
||||
utils.Warn("Container not found for volume", volume.Source)
|
||||
return
|
||||
}
|
||||
|
||||
if container == nil {
|
||||
utils.Warn("Container not found for volume", volume.Source)
|
||||
continue
|
||||
}
|
||||
|
||||
// ensure that the volume is not already present in the container
|
||||
for _, vm := range container.VolumeMounts {
|
||||
if vm.Name == volume.Source {
|
||||
continue
|
||||
}
|
||||
}
|
||||
|
||||
switch volume.Type {
|
||||
case "volume":
|
||||
// Add volume to container
|
||||
container.VolumeMounts = append(container.VolumeMounts, corev1.VolumeMount{
|
||||
Name: volume.Source,
|
||||
MountPath: volume.Target,
|
||||
})
|
||||
// Add volume to values.yaml only if it the service is not in the same pod that another service.
|
||||
// If it is in the same pod, the volume will be added to the other service later
|
||||
if _, ok := service.Labels[LabelSamePod]; !ok {
|
||||
d.chart.Values[service.Name].(*Value).AddPersistence(volume.Source)
|
||||
}
|
||||
// Add volume to deployment
|
||||
d.Spec.Template.Spec.Volumes = append(d.Spec.Template.Spec.Volumes, corev1.Volume{
|
||||
Name: volume.Source,
|
||||
VolumeSource: corev1.VolumeSource{
|
||||
PersistentVolumeClaim: &corev1.PersistentVolumeClaimVolumeSource{
|
||||
ClaimName: utils.TplName(service.Name, appName, volume.Source),
|
||||
},
|
||||
},
|
||||
})
|
||||
case "bind":
|
||||
// Add volume to container
|
||||
stat, err := os.Stat(volume.Source)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
if stat.IsDir() {
|
||||
pathnme := utils.PathToName(volume.Source)
|
||||
if _, ok := d.configMaps[pathnme]; !ok {
|
||||
d.configMaps[pathnme] = &ConfigMapMount{
|
||||
mountPath: []mountPathConfig{},
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: make it recursive to add all files in the directory and subdirectories
|
||||
_, err := os.ReadDir(volume.Source)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
cm := NewConfigMapFromDirectory(service, appName, volume.Source)
|
||||
d.configMaps[pathnme] = &ConfigMapMount{
|
||||
configMap: cm,
|
||||
mountPath: append(d.configMaps[pathnme].mountPath, mountPathConfig{
|
||||
mountPath: volume.Target,
|
||||
}),
|
||||
}
|
||||
} else {
|
||||
// In case of a file, add it to the configmap and use "subPath" to mount it
|
||||
// Note that the volumes and volume mounts are not added to the deployment yet, they will be added later
|
||||
// in generate.go
|
||||
dirname := filepath.Dir(volume.Source)
|
||||
pathname := utils.PathToName(dirname)
|
||||
var cm *ConfigMap
|
||||
if v, ok := d.configMaps[pathname]; !ok {
|
||||
cm = NewConfigMap(*d.service, appName)
|
||||
cm.usage = FileMapUsageFiles
|
||||
cm.path = dirname
|
||||
cm.Name = utils.TplName(service.Name, appName) + "-" + pathname
|
||||
d.configMaps[pathname] = &ConfigMapMount{
|
||||
configMap: cm,
|
||||
mountPath: []mountPathConfig{{
|
||||
mountPath: volume.Target,
|
||||
subPath: filepath.Base(volume.Source),
|
||||
}},
|
||||
}
|
||||
} else {
|
||||
cm = v.configMap
|
||||
mp := d.configMaps[pathname].mountPath
|
||||
mp = append(mp, mountPathConfig{
|
||||
mountPath: volume.Target,
|
||||
subPath: filepath.Base(volume.Source),
|
||||
})
|
||||
d.configMaps[pathname].mountPath = mp
|
||||
|
||||
}
|
||||
cm.AppendFile(volume.Source)
|
||||
}
|
||||
// ensure that the volume is not already present in the container
|
||||
for _, vm := range container.VolumeMounts {
|
||||
if vm.Name == volume.Source {
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
switch volume.Type {
|
||||
case "volume":
|
||||
// Add volume to container
|
||||
container.VolumeMounts = append(container.VolumeMounts, corev1.VolumeMount{
|
||||
Name: volume.Source,
|
||||
MountPath: volume.Target,
|
||||
})
|
||||
// Add volume to values.yaml only if it the service is not in the same pod that another service.
|
||||
// If it is in the same pod, the volume will be added to the other service later
|
||||
if _, ok := service.Labels[LabelSamePod]; !ok {
|
||||
d.chart.Values[service.Name].(*Value).AddPersistence(volume.Source)
|
||||
}
|
||||
// Add volume to deployment
|
||||
d.Spec.Template.Spec.Volumes = append(d.Spec.Template.Spec.Volumes, corev1.Volume{
|
||||
Name: volume.Source,
|
||||
VolumeSource: corev1.VolumeSource{
|
||||
PersistentVolumeClaim: &corev1.PersistentVolumeClaimVolumeSource{
|
||||
ClaimName: utils.TplName(service.Name, appName, volume.Source),
|
||||
},
|
||||
},
|
||||
})
|
||||
case "bind":
|
||||
// Add volume to container
|
||||
stat, err := os.Stat(volume.Source)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
if stat.IsDir() {
|
||||
d.appendDirectoryToConfigMap(service, appName, volume)
|
||||
} else {
|
||||
d.appendFileToConfigMap(service, appName, volume)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (d *Deployment) appendDirectoryToConfigMap(service types.ServiceConfig, appName string, volume types.ServiceVolumeConfig) {
|
||||
pathnme := utils.PathToName(volume.Source)
|
||||
if _, ok := d.configMaps[pathnme]; !ok {
|
||||
d.configMaps[pathnme] = &ConfigMapMount{
|
||||
mountPath: []mountPathConfig{},
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: make it recursive to add all files in the directory and subdirectories
|
||||
_, err := os.ReadDir(volume.Source)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
cm := NewConfigMapFromDirectory(service, appName, volume.Source)
|
||||
d.configMaps[pathnme] = &ConfigMapMount{
|
||||
configMap: cm,
|
||||
mountPath: append(d.configMaps[pathnme].mountPath, mountPathConfig{
|
||||
mountPath: volume.Target,
|
||||
}),
|
||||
}
|
||||
}
|
||||
|
||||
func (d *Deployment) appendFileToConfigMap(service types.ServiceConfig, appName string, volume types.ServiceVolumeConfig) {
|
||||
// In case of a file, add it to the configmap and use "subPath" to mount it
|
||||
// Note that the volumes and volume mounts are not added to the deployment yet, they will be added later
|
||||
// in generate.go
|
||||
dirname := filepath.Dir(volume.Source)
|
||||
pathname := utils.PathToName(dirname)
|
||||
var cm *ConfigMap
|
||||
if v, ok := d.configMaps[pathname]; !ok {
|
||||
cm = NewConfigMap(*d.service, appName)
|
||||
cm.usage = FileMapUsageFiles
|
||||
cm.path = dirname
|
||||
cm.Name = utils.TplName(service.Name, appName) + "-" + pathname
|
||||
d.configMaps[pathname] = &ConfigMapMount{
|
||||
configMap: cm,
|
||||
mountPath: []mountPathConfig{{
|
||||
mountPath: volume.Target,
|
||||
subPath: filepath.Base(volume.Source),
|
||||
}},
|
||||
}
|
||||
} else {
|
||||
cm = v.configMap
|
||||
mp := d.configMaps[pathname].mountPath
|
||||
mp = append(mp, mountPathConfig{
|
||||
mountPath: volume.Target,
|
||||
subPath: filepath.Base(volume.Source),
|
||||
})
|
||||
d.configMaps[pathname].mountPath = mp
|
||||
|
||||
}
|
||||
cm.AppendFile(volume.Source)
|
||||
}
|
||||
|
||||
func (d *Deployment) BindFrom(service types.ServiceConfig, binded *Deployment) {
|
||||
|
||||
@@ -10,20 +10,22 @@ import (
|
||||
"sigs.k8s.io/yaml"
|
||||
)
|
||||
|
||||
const webTemplateOutput = `templates/web/deployment.yaml`
|
||||
|
||||
func TestGenerate(t *testing.T) {
|
||||
compose_file := `
|
||||
composeFile := `
|
||||
services:
|
||||
web:
|
||||
image: nginx:1.29
|
||||
`
|
||||
tmpDir := setup(compose_file)
|
||||
tmpDir := setup(composeFile)
|
||||
defer teardown(tmpDir)
|
||||
|
||||
currentDir, _ := os.Getwd()
|
||||
os.Chdir(tmpDir)
|
||||
defer os.Chdir(currentDir)
|
||||
|
||||
output := _compile_test(t, "-s", "templates/web/deployment.yaml")
|
||||
output := _compile_test(t, "-s", webTemplateOutput)
|
||||
|
||||
// dt := DeploymentTest{}
|
||||
dt := v1.Deployment{}
|
||||
@@ -42,7 +44,7 @@ services:
|
||||
}
|
||||
|
||||
func TestGenerateOneDeploymentWithSamePod(t *testing.T) {
|
||||
compose_file := `
|
||||
composeFile := `
|
||||
services:
|
||||
web:
|
||||
image: nginx:1.29
|
||||
@@ -57,14 +59,15 @@ services:
|
||||
katenary.v3/same-pod: web
|
||||
`
|
||||
|
||||
tmpDir := setup(compose_file)
|
||||
outDir := "./chart"
|
||||
tmpDir := setup(composeFile)
|
||||
defer teardown(tmpDir)
|
||||
|
||||
currentDir, _ := os.Getwd()
|
||||
os.Chdir(tmpDir)
|
||||
defer os.Chdir(currentDir)
|
||||
|
||||
output := _compile_test(t, "-s", "templates/web/deployment.yaml")
|
||||
output := _compile_test(t, "-s", webTemplateOutput)
|
||||
dt := v1.Deployment{}
|
||||
if err := yaml.Unmarshal([]byte(output), &dt); err != nil {
|
||||
t.Errorf(unmarshalError, err)
|
||||
@@ -76,8 +79,8 @@ services:
|
||||
// endsure that the fpm service is not created
|
||||
|
||||
var err error
|
||||
output, err = helmTemplate(ConvertOptions{
|
||||
OutputDir: "./chart",
|
||||
_, err = helmTemplate(ConvertOptions{
|
||||
OutputDir: outDir,
|
||||
}, "-s", "templates/fpm/deployment.yaml")
|
||||
if err == nil {
|
||||
t.Errorf("Expected error, got nil")
|
||||
@@ -85,7 +88,7 @@ services:
|
||||
|
||||
// ensure that the web service is created and has got 2 ports
|
||||
output, err = helmTemplate(ConvertOptions{
|
||||
OutputDir: "./chart",
|
||||
OutputDir: outDir,
|
||||
}, "-s", "templates/web/service.yaml")
|
||||
if err != nil {
|
||||
t.Errorf("Error: %s", err)
|
||||
@@ -101,7 +104,7 @@ services:
|
||||
}
|
||||
|
||||
func TestDependsOn(t *testing.T) {
|
||||
compose_file := `
|
||||
composeFile := `
|
||||
services:
|
||||
web:
|
||||
image: nginx:1.29
|
||||
@@ -115,14 +118,14 @@ services:
|
||||
ports:
|
||||
- 3306:3306
|
||||
`
|
||||
tmpDir := setup(compose_file)
|
||||
tmpDir := setup(composeFile)
|
||||
defer teardown(tmpDir)
|
||||
|
||||
currentDir, _ := os.Getwd()
|
||||
os.Chdir(tmpDir)
|
||||
defer os.Chdir(currentDir)
|
||||
|
||||
output := _compile_test(t, "-s", "templates/web/deployment.yaml")
|
||||
output := _compile_test(t, "-s", webTemplateOutput)
|
||||
dt := v1.Deployment{}
|
||||
if err := yaml.Unmarshal([]byte(output), &dt); err != nil {
|
||||
t.Errorf(unmarshalError, err)
|
||||
@@ -138,7 +141,7 @@ services:
|
||||
}
|
||||
|
||||
func TestHelmDependencies(t *testing.T) {
|
||||
compose_file := `
|
||||
composeFile := `
|
||||
services:
|
||||
web:
|
||||
image: nginx:1.29
|
||||
@@ -156,15 +159,15 @@ services:
|
||||
version: 18.x.X
|
||||
|
||||
`
|
||||
compose_file = fmt.Sprintf(compose_file, Prefix())
|
||||
tmpDir := setup(compose_file)
|
||||
composeFile = fmt.Sprintf(composeFile, Prefix())
|
||||
tmpDir := setup(composeFile)
|
||||
defer teardown(tmpDir)
|
||||
|
||||
currentDir, _ := os.Getwd()
|
||||
os.Chdir(tmpDir)
|
||||
defer os.Chdir(currentDir)
|
||||
|
||||
output := _compile_test(t, "-s", "templates/web/deployment.yaml")
|
||||
output := _compile_test(t, "-s", webTemplateOutput)
|
||||
dt := v1.Deployment{}
|
||||
if err := yaml.Unmarshal([]byte(output), &dt); err != nil {
|
||||
t.Errorf(unmarshalError, err)
|
||||
@@ -198,7 +201,7 @@ services:
|
||||
}
|
||||
|
||||
func TestLivenessProbesFromHealthCheck(t *testing.T) {
|
||||
compose_file := `
|
||||
composeFile := `
|
||||
services:
|
||||
web:
|
||||
image: nginx:1.29
|
||||
@@ -210,14 +213,14 @@ services:
|
||||
timeout: 3s
|
||||
retries: 3
|
||||
`
|
||||
tmpDir := setup(compose_file)
|
||||
tmpDir := setup(composeFile)
|
||||
defer teardown(tmpDir)
|
||||
|
||||
currentDir, _ := os.Getwd()
|
||||
os.Chdir(tmpDir)
|
||||
defer os.Chdir(currentDir)
|
||||
|
||||
output := _compile_test(t, "-s", "templates/web/deployment.yaml")
|
||||
output := _compile_test(t, "-s", webTemplateOutput)
|
||||
dt := v1.Deployment{}
|
||||
if err := yaml.Unmarshal([]byte(output), &dt); err != nil {
|
||||
t.Errorf(unmarshalError, err)
|
||||
@@ -229,7 +232,7 @@ services:
|
||||
}
|
||||
|
||||
func TestProbesFromLabels(t *testing.T) {
|
||||
compose_file := `
|
||||
composeFile := `
|
||||
services:
|
||||
web:
|
||||
image: nginx:1.29
|
||||
@@ -246,15 +249,15 @@ services:
|
||||
path: /ready
|
||||
port: 80
|
||||
`
|
||||
compose_file = fmt.Sprintf(compose_file, Prefix())
|
||||
tmpDir := setup(compose_file)
|
||||
composeFile = fmt.Sprintf(composeFile, Prefix())
|
||||
tmpDir := setup(composeFile)
|
||||
defer teardown(tmpDir)
|
||||
|
||||
currentDir, _ := os.Getwd()
|
||||
os.Chdir(tmpDir)
|
||||
defer os.Chdir(currentDir)
|
||||
|
||||
output := _compile_test(t, "-s", "templates/web/deployment.yaml")
|
||||
output := _compile_test(t, "-s", webTemplateOutput)
|
||||
dt := v1.Deployment{}
|
||||
if err := yaml.Unmarshal([]byte(output), &dt); err != nil {
|
||||
t.Errorf(unmarshalError, err)
|
||||
@@ -280,7 +283,7 @@ services:
|
||||
}
|
||||
|
||||
func TestSetValues(t *testing.T) {
|
||||
compose_file := `
|
||||
composeFile := `
|
||||
services:
|
||||
web:
|
||||
image: nginx:1.29
|
||||
@@ -292,15 +295,15 @@ services:
|
||||
- FOO
|
||||
`
|
||||
|
||||
compose_file = fmt.Sprintf(compose_file, Prefix())
|
||||
tmpDir := setup(compose_file)
|
||||
composeFile = fmt.Sprintf(composeFile, Prefix())
|
||||
tmpDir := setup(composeFile)
|
||||
defer teardown(tmpDir)
|
||||
|
||||
currentDir, _ := os.Getwd()
|
||||
os.Chdir(tmpDir)
|
||||
defer os.Chdir(currentDir)
|
||||
|
||||
output := _compile_test(t, "-s", "templates/web/deployment.yaml")
|
||||
output := _compile_test(t, "-s", webTemplateOutput)
|
||||
dt := v1.Deployment{}
|
||||
if err := yaml.Unmarshal([]byte(output), &dt); err != nil {
|
||||
t.Errorf(unmarshalError, err)
|
||||
|
||||
@@ -2,13 +2,12 @@ package extrafiles
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
_ "embed"
|
||||
"fmt"
|
||||
"sort"
|
||||
"strings"
|
||||
"text/template"
|
||||
|
||||
_ "embed"
|
||||
|
||||
"gopkg.in/yaml.v3"
|
||||
)
|
||||
|
||||
|
||||
@@ -1,7 +1,5 @@
|
||||
package generator
|
||||
|
||||
// TODO: configmap from files 20%
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
@@ -10,11 +8,11 @@ import (
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"katenary/generator/labelStructs"
|
||||
"katenary/utils"
|
||||
|
||||
"github.com/compose-spec/compose-go/types"
|
||||
corev1 "k8s.io/api/core/v1"
|
||||
|
||||
"katenary/generator/labelStructs"
|
||||
"katenary/utils"
|
||||
)
|
||||
|
||||
// Generate a chart from a compose project.
|
||||
@@ -388,7 +386,7 @@ func buildVolumes(service types.ServiceConfig, chart *HelmChart, deployments map
|
||||
y, _ := pvc.Yaml()
|
||||
chart.Templates[pvc.Filename()] = &ChartTemplate{
|
||||
Content: y,
|
||||
Servicename: service.Name, // TODO, use name
|
||||
Servicename: service.Name,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,13 +4,13 @@ import (
|
||||
"log"
|
||||
"strings"
|
||||
|
||||
"katenary/generator/labelStructs"
|
||||
"katenary/utils"
|
||||
|
||||
"github.com/compose-spec/compose-go/types"
|
||||
networkv1 "k8s.io/api/networking/v1"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"sigs.k8s.io/yaml"
|
||||
|
||||
"katenary/generator/labelStructs"
|
||||
"katenary/utils"
|
||||
)
|
||||
|
||||
var _ Yaml = (*Ingress)(nil)
|
||||
|
||||
@@ -10,9 +10,9 @@ import (
|
||||
"text/tabwriter"
|
||||
"text/template"
|
||||
|
||||
"katenary/utils"
|
||||
|
||||
"sigs.k8s.io/yaml"
|
||||
|
||||
"katenary/utils"
|
||||
)
|
||||
|
||||
var (
|
||||
|
||||
@@ -8,6 +8,8 @@ import (
|
||||
|
||||
var testingKatenaryPrefix = Prefix()
|
||||
|
||||
const mainAppLabel = "main-app"
|
||||
|
||||
func TestPrefix(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
@@ -27,7 +29,7 @@ func TestPrefix(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func Test_labelName(t *testing.T) {
|
||||
func TestLabelName(t *testing.T) {
|
||||
type args struct {
|
||||
name string
|
||||
}
|
||||
@@ -39,9 +41,9 @@ func Test_labelName(t *testing.T) {
|
||||
{
|
||||
name: "Test_labelName",
|
||||
args: args{
|
||||
name: "main-app",
|
||||
name: mainAppLabel,
|
||||
},
|
||||
want: testingKatenaryPrefix + "/main-app",
|
||||
want: testingKatenaryPrefix + "/" + mainAppLabel,
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
@@ -65,7 +67,7 @@ func TestGetLabelHelp(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestGetLabelHelpFor(t *testing.T) {
|
||||
help := GetLabelHelpFor("main-app", false)
|
||||
help := GetLabelHelpFor(mainAppLabel, false)
|
||||
if help == "" {
|
||||
t.Errorf("GetLabelHelpFor() = %v, want %v", help, "Help")
|
||||
}
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
package generator
|
||||
|
||||
import (
|
||||
"katenary/utils"
|
||||
|
||||
"github.com/compose-spec/compose-go/types"
|
||||
corev1 "k8s.io/api/core/v1"
|
||||
rbacv1 "k8s.io/api/rbac/v1"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"sigs.k8s.io/yaml"
|
||||
|
||||
"katenary/utils"
|
||||
)
|
||||
|
||||
var (
|
||||
|
||||
@@ -5,12 +5,12 @@ import (
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"katenary/utils"
|
||||
|
||||
"github.com/compose-spec/compose-go/types"
|
||||
corev1 "k8s.io/api/core/v1"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"sigs.k8s.io/yaml"
|
||||
|
||||
"katenary/utils"
|
||||
)
|
||||
|
||||
var (
|
||||
@@ -84,7 +84,7 @@ func (s *Secret) SetData(data map[string]string) {
|
||||
}
|
||||
|
||||
// AddData adds a key value pair to the secret.
|
||||
func (s *Secret) AddData(key string, value string) {
|
||||
func (s *Secret) AddData(key, value string) {
|
||||
if value == "" {
|
||||
return
|
||||
}
|
||||
|
||||
@@ -4,13 +4,13 @@ import (
|
||||
"regexp"
|
||||
"strings"
|
||||
|
||||
"katenary/utils"
|
||||
|
||||
"github.com/compose-spec/compose-go/types"
|
||||
v1 "k8s.io/api/core/v1"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/util/intstr"
|
||||
"sigs.k8s.io/yaml"
|
||||
|
||||
"katenary/utils"
|
||||
)
|
||||
|
||||
var _ Yaml = (*Service)(nil)
|
||||
|
||||
@@ -6,9 +6,6 @@ import (
|
||||
"github.com/compose-spec/compose-go/types"
|
||||
)
|
||||
|
||||
// Values is a map of all values for all services. Written to values.yaml.
|
||||
// var Values = map[string]any{}
|
||||
|
||||
// RepositoryValue is a docker repository image and tag that will be saved in values.yaml.
|
||||
type RepositoryValue struct {
|
||||
Image string `yaml:"image"`
|
||||
@@ -17,19 +14,19 @@ type RepositoryValue struct {
|
||||
|
||||
// PersistenceValue is a persistence configuration that will be saved in values.yaml.
|
||||
type PersistenceValue struct {
|
||||
Enabled bool `yaml:"enabled"`
|
||||
StorageClass string `yaml:"storageClass"`
|
||||
Size string `yaml:"size"`
|
||||
AccessMode []string `yaml:"accessMode"`
|
||||
Enabled bool `yaml:"enabled"`
|
||||
}
|
||||
|
||||
// IngressValue is a ingress configuration that will be saved in values.yaml.
|
||||
type IngressValue struct {
|
||||
Enabled bool `yaml:"enabled"`
|
||||
Annotations map[string]string `yaml:"annotations"`
|
||||
Host string `yaml:"host"`
|
||||
Path string `yaml:"path"`
|
||||
Class string `yaml:"class"`
|
||||
Annotations map[string]string `yaml:"annotations"`
|
||||
Enabled bool `yaml:"enabled"`
|
||||
}
|
||||
|
||||
// Value will be saved in values.yaml. It contains configuraiton for all deployment and services.
|
||||
@@ -37,13 +34,13 @@ type Value struct {
|
||||
Repository *RepositoryValue `yaml:"repository,omitempty"`
|
||||
Persistence map[string]*PersistenceValue `yaml:"persistence,omitempty"`
|
||||
Ingress *IngressValue `yaml:"ingress,omitempty"`
|
||||
ImagePullPolicy string `yaml:"imagePullPolicy,omitempty"`
|
||||
Environment map[string]any `yaml:"environment,omitempty"`
|
||||
Replicas *uint32 `yaml:"replicas,omitempty"`
|
||||
CronJob *CronJobValue `yaml:"cronjob,omitempty"`
|
||||
NodeSelector map[string]string `yaml:"nodeSelector"`
|
||||
ServiceAccount string `yaml:"serviceAccount"`
|
||||
Resources map[string]any `yaml:"resources"`
|
||||
ImagePullPolicy string `yaml:"imagePullPolicy,omitempty"`
|
||||
ServiceAccount string `yaml:"serviceAccount"`
|
||||
}
|
||||
|
||||
// CronJobValue is a cronjob configuration that will be saved in values.yaml.
|
||||
|
||||
@@ -3,17 +3,19 @@ package generator
|
||||
import (
|
||||
"strings"
|
||||
|
||||
"katenary/utils"
|
||||
|
||||
"github.com/compose-spec/compose-go/types"
|
||||
v1 "k8s.io/api/core/v1"
|
||||
"k8s.io/apimachinery/pkg/api/resource"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"sigs.k8s.io/yaml"
|
||||
|
||||
"katenary/utils"
|
||||
)
|
||||
|
||||
var _ Yaml = (*VolumeClaim)(nil)
|
||||
|
||||
const persistenceKey = "persistence"
|
||||
|
||||
// VolumeClaim is a kubernetes VolumeClaim. This is a PersistentVolumeClaim.
|
||||
type VolumeClaim struct {
|
||||
*v1.PersistentVolumeClaim
|
||||
@@ -41,7 +43,12 @@ func NewVolumeClaim(service types.ServiceConfig, volumeName, appName string) *Vo
|
||||
AccessModes: []v1.PersistentVolumeAccessMode{
|
||||
v1.ReadWriteOnce,
|
||||
},
|
||||
StorageClassName: utils.StrPtr(`{{ .Values.` + service.Name + `.persistence.` + volumeName + `.storageClass }}`),
|
||||
StorageClassName: utils.StrPtr(
|
||||
`{{ .Values.` +
|
||||
service.Name +
|
||||
"." + persistenceKey +
|
||||
"." + volumeName + `.storageClass }}`,
|
||||
),
|
||||
Resources: v1.VolumeResourceRequirements{
|
||||
Requests: v1.ResourceList{
|
||||
v1.ResourceStorage: resource.MustParse("1Gi"),
|
||||
@@ -69,7 +76,7 @@ func (v *VolumeClaim) Yaml() ([]byte, error) {
|
||||
strings.Replace(
|
||||
string(out),
|
||||
"1Gi",
|
||||
utils.TplValue(serviceName, "persistence."+volumeName+".size"),
|
||||
utils.TplValue(serviceName, persistenceKey+"."+volumeName+".size"),
|
||||
1,
|
||||
),
|
||||
)
|
||||
@@ -80,8 +87,8 @@ func (v *VolumeClaim) Yaml() ([]byte, error) {
|
||||
"- ReadWriteOnce",
|
||||
"{{- .Values."+
|
||||
serviceName+
|
||||
".persistence."+
|
||||
volumeName+
|
||||
"."+persistenceKey+
|
||||
"."+volumeName+
|
||||
".accessMode | toYaml | nindent __indent__ }}",
|
||||
1,
|
||||
),
|
||||
@@ -92,7 +99,10 @@ func (v *VolumeClaim) Yaml() ([]byte, error) {
|
||||
if strings.Contains(line, "storageClass") {
|
||||
lines[i] = utils.Wrap(
|
||||
line,
|
||||
"{{- if ne .Values."+serviceName+".persistence."+volumeName+".storageClass \"-\" }}",
|
||||
"{{- if ne .Values."+
|
||||
serviceName+
|
||||
"."+persistenceKey+
|
||||
"."+volumeName+".storageClass \"-\" }}",
|
||||
"{{- end }}",
|
||||
)
|
||||
}
|
||||
@@ -103,8 +113,8 @@ func (v *VolumeClaim) Yaml() ([]byte, error) {
|
||||
out = []byte(
|
||||
"{{- if .Values." +
|
||||
serviceName +
|
||||
".persistence." +
|
||||
volumeName +
|
||||
"." + persistenceKey +
|
||||
"." + volumeName +
|
||||
".enabled }}\n" +
|
||||
string(out) +
|
||||
"\n{{- end }}",
|
||||
|
||||
@@ -7,7 +7,6 @@ import (
|
||||
)
|
||||
|
||||
func TestDownloadLatestRelease(t *testing.T) {
|
||||
|
||||
// Reset the version to test the latest release
|
||||
Version = "0.0.0"
|
||||
|
||||
@@ -17,15 +16,14 @@ func TestDownloadLatestRelease(t *testing.T) {
|
||||
|
||||
// Now call the CheckLatestVersion function
|
||||
version, assets, err := CheckLatestVersion()
|
||||
|
||||
if err != nil {
|
||||
t.Errorf("Error: %s", err)
|
||||
t.Errorf("Error getting latest version: %s", err)
|
||||
}
|
||||
|
||||
fmt.Println("Version found", version)
|
||||
|
||||
// Touch exe binary
|
||||
f, _ := os.OpenFile(exe, os.O_RDONLY|os.O_CREATE, 0755)
|
||||
f, _ := os.OpenFile(exe, os.O_RDONLY|os.O_CREATE, 0o755)
|
||||
f.Write(nil)
|
||||
f.Close()
|
||||
|
||||
@@ -48,5 +46,4 @@ func TestAlreadyUpToDate(t *testing.T) {
|
||||
}
|
||||
|
||||
t.Log("Version is already the most recent", version)
|
||||
|
||||
}
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
package utils
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"log"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
@@ -114,8 +116,8 @@ func PathToName(path string) string {
|
||||
|
||||
// EnvConfig is a struct to hold the description of an environment variable.
|
||||
type EnvConfig struct {
|
||||
Description string
|
||||
Service types.ServiceConfig
|
||||
Description string
|
||||
}
|
||||
|
||||
// GetValuesFromLabel returns a map of values from a label.
|
||||
@@ -160,3 +162,27 @@ func MapKeys(m map[string]interface{}) []string {
|
||||
}
|
||||
return keys
|
||||
}
|
||||
|
||||
// Confirm asks a question and returns true if the answer is y.
|
||||
func Confirm(question string, icon ...Icon) bool {
|
||||
if len(icon) > 0 {
|
||||
fmt.Printf("%s %s [y/N] ", icon[0], question)
|
||||
} else {
|
||||
fmt.Print(question + " [y/N] ")
|
||||
}
|
||||
var response string
|
||||
fmt.Scanln(&response)
|
||||
return strings.ToLower(response) == "y"
|
||||
}
|
||||
|
||||
// EncodeBasicYaml encodes a basic yaml from an interface.
|
||||
func EncodeBasicYaml(data any) ([]byte, error) {
|
||||
buf := bytes.NewBuffer(nil)
|
||||
enc := yaml.NewEncoder(buf)
|
||||
enc.SetIndent(2)
|
||||
err := enc.Encode(data)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return buf.Bytes(), nil
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user