Skip to content

Commit

Permalink
rearrange
Browse files Browse the repository at this point in the history
  • Loading branch information
nabuskey committed Mar 21, 2024
1 parent d24e809 commit 9f79b03
Show file tree
Hide file tree
Showing 22 changed files with 228 additions and 111 deletions.
57 changes: 11 additions & 46 deletions pkg/cmd/create/root.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ import (
"context"
"fmt"
"net/url"
"os"
"path/filepath"
"strings"

Expand Down Expand Up @@ -58,7 +57,7 @@ func init() {
CreateCmd.PersistentFlags().StringVar(&port, "port", "8443", "Port number under which idpBuilder tools are accessible.")
CreateCmd.PersistentFlags().BoolVar(&pathRouting, "use-path-routing", false, "When set to true, web UIs are exposed under single domain name.")
CreateCmd.Flags().StringSliceVarP(&extraPackagesDirs, "package-dir", "p", []string{}, "Paths to custom packages")
CreateCmd.Flags().StringSliceVarP(&packageCustomizationFiles, "package-custom-file", "c", []string{}, "name of the package and the path to file to customize the package with. e.g. argocd:/tmp/argocd.yaml")
CreateCmd.Flags().StringSliceVarP(&packageCustomizationFiles, "package-custom-file", "c", []string{}, "Name of the package and the path to file to customize the package with. e.g. argocd:/tmp/argocd.yaml")
// idpbuilder related flags
CreateCmd.Flags().BoolVarP(&noExit, "no-exit", "n", true, "When set, idpbuilder will not exit after all packages are synced. Useful for continuously syncing local directories.")
}
Expand Down Expand Up @@ -86,7 +85,7 @@ func create(cmd *cobra.Command, args []string) error {

var absDirPaths []string
if len(extraPackagesDirs) > 0 {
p, err := getAbsFilePaths(extraPackagesDirs, true)
p, err := helpers.GetAbsFilePaths(extraPackagesDirs, true)
if err != nil {
return err
}
Expand All @@ -95,7 +94,7 @@ func create(cmd *cobra.Command, args []string) error {

o := make(map[string]v1alpha1.PackageCustomization)
for i := range packageCustomizationFiles {
c, pErr := validatePackageCustomFile(packageCustomizationFiles[i])
c, pErr := getPackageCustomFile(packageCustomizationFiles[i])
if pErr != nil {
return pErr
}
Expand Down Expand Up @@ -141,34 +140,29 @@ func validate() error {
}

for i := range packageCustomizationFiles {
_, pErr := validatePackageCustomFile(packageCustomizationFiles[i])
_, pErr := getPackageCustomFile(packageCustomizationFiles[i])
if pErr != nil {
return pErr
}
}
return nil
}

func validatePackageCustomFile(input string) (v1alpha1.PackageCustomization, error) {
func getPackageCustomFile(input string) (v1alpha1.PackageCustomization, error) {
// the format should be `<package-name>:<path-to-file>`
s := strings.Split(input, ":")
if len(s) == 2 {
if len(s) != 2 {
return v1alpha1.PackageCustomization{}, fmt.Errorf("ensure %s is formated as <package-name>:<path-to-file>", input)
}

filePath := s[1]
f, err := filepath.Abs(filePath)
paths, err := helpers.GetAbsFilePaths([]string{s[1]}, false)
if err != nil {

return v1alpha1.PackageCustomization{}, fmt.Errorf("ensure file path (%s) is correct: %w", filePath, err)
return v1alpha1.PackageCustomization{}, err
}

info, err := os.Stat(f)
err = helpers.ValidateKubernetesYamlFile(paths[0])
if err != nil {
return v1alpha1.PackageCustomization{}, fmt.Errorf("ensure file (%s) exists and readable: %w", f, err)
}
if !info.Mode().IsRegular() {
return v1alpha1.PackageCustomization{}, fmt.Errorf("ensure specified file (%s) is a readable file", f)
return v1alpha1.PackageCustomization{}, err
}

corePkgs := map[string]struct{}{"argocd": {}, "gitea": {}, "nginx": {}}
Expand All @@ -179,35 +173,6 @@ func validatePackageCustomFile(input string) (v1alpha1.PackageCustomization, err
}
return v1alpha1.PackageCustomization{
Name: name,
FilePath: f,
FilePath: paths[0],
}, nil
}

//func validateYaml(absPath string) error {
//
//}

func getAbsFilePaths(paths []string, isDir bool) ([]string, error) {
out := make([]string, len(paths))
for i := range paths {
path := paths[i]
absPath, err := filepath.Abs(path)
if err != nil {
return nil, fmt.Errorf("failed to validate path %s : %w", path, err)
}
f, err := os.Stat(absPath)
if err != nil {
return nil, fmt.Errorf("failed to validate path %s : %w", absPath, err)
}
if isDir && !f.IsDir() {
return nil, fmt.Errorf("given path is not a directory. %s", absPath)
}
if !isDir && !f.Mode().IsRegular() {
return nil, fmt.Errorf("give path is not a file. %s", absPath)
}

out[i] = absPath
}

return out, nil
}
2 changes: 2 additions & 0 deletions pkg/cmd/helpers/test-data/notk8s.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
name: me
pluto: not a planet
3 changes: 3 additions & 0 deletions pkg/cmd/helpers/test-data/notyaml.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
not:
a
yaml
47 changes: 47 additions & 0 deletions pkg/cmd/helpers/test-data/valid.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-deployment
labels:
app: nginx
spec:
replicas: 3
selector:
matchLabels:
app: nginx
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx:1.14.2
ports:
- containerPort: 80
---
apiVersion: v1
kind: PersistentVolume
metadata:
name: my-pv
spec:
capacity:
storage: 1Gi
accessModes:
- ReadWriteOnce
storageClassName: standard
hostPath:
path: /mnt/data
---
apiVersion: v1
kind: Service
metadata:
name: nginx-service
spec:
selector:
app: nginx
ports:
- protocol: TCP
port: 80
targetPort: 80

60 changes: 60 additions & 0 deletions pkg/cmd/helpers/validation.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
package helpers

import (
"fmt"
"os"
"path/filepath"

"sigs.k8s.io/kustomize/kyaml/kio"
)

func ValidateKubernetesYamlFile(absPath string) error {
if !filepath.IsAbs(absPath) {
return fmt.Errorf("given path is not an absolute path %s", absPath)
}
b, err := os.ReadFile(absPath)
if err != nil {
return fmt.Errorf("failed reading file: %s, err: %w", absPath, err)
}
n, err := kio.FromBytes(b)
if err != nil {
return fmt.Errorf("failed parsing file as kubernetes manifests file: %s, err: %w", absPath, err)
}

for i := range n {
obj := n[i]
if obj.IsNilOrEmpty() {
return fmt.Errorf("given file %s contains an invalid kubenretes manifest", absPath)
}
if obj.GetKind() == "" || obj.GetApiVersion() == "" {
return fmt.Errorf("given file %s contains an invalid kubenretes manifest", absPath)
}
}

return nil
}

func GetAbsFilePaths(paths []string, isDir bool) ([]string, error) {
out := make([]string, len(paths))
for i := range paths {
path := paths[i]
absPath, err := filepath.Abs(path)
if err != nil {
return nil, fmt.Errorf("failed to validate path %s : %w", path, err)
}
f, err := os.Stat(absPath)
if err != nil {
return nil, fmt.Errorf("failed to validate path %s : %w", absPath, err)
}
if isDir && !f.IsDir() {
return nil, fmt.Errorf("given path is not a directory. %s", absPath)
}
if !isDir && !f.Mode().IsRegular() {
return nil, fmt.Errorf("give path is not a file. %s", absPath)
}

out[i] = absPath
}

return out, nil
}
35 changes: 35 additions & 0 deletions pkg/cmd/helpers/validation_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
package helpers

import (
"fmt"
"os"
"testing"
)

func TestValidateKubernetesYaml(t *testing.T) {
cwd, err := os.Getwd()
if err != nil {
t.Fatalf("could not get current working directory")
}

cases := map[string]struct {
expectErr bool
inputPath string
}{
//"invalidPath": {expectErr: true, inputPath: fmt.Sprintf("%s/invalid/path", cwd)},
//"notAbs": {expectErr: true, inputPath: fmt.Sprintf("invalid/path")},
//"valid": {expectErr: false, inputPath: fmt.Sprintf("%s/test-data/valid.yaml", cwd)},
//"notYaml": {expectErr: true, inputPath: fmt.Sprintf("%s/test-data/notyaml.yaml", cwd)},
"notk8s": {expectErr: true, inputPath: fmt.Sprintf("%s/test-data/notk8s.yaml", cwd)},
}

for k := range cases {
cErr := ValidateKubernetesYamlFile(cases[k].inputPath)
if cases[k].expectErr && cErr == nil {
t.Fatalf("%s expected error but did not receive error", k)
}
if !cases[k].expectErr && cErr != nil {
t.Fatalf("%s did not expect error but received error", k)
}
}
}
4 changes: 2 additions & 2 deletions pkg/controllers/localbuild/argo.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import (
"embed"

"github.com/cnoe-io/idpbuilder/api/v1alpha1"
"github.com/cnoe-io/idpbuilder/pkg/util"
"github.com/cnoe-io/idpbuilder/pkg/k8s"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/runtime/schema"
ctrl "sigs.k8s.io/controller-runtime"
Expand All @@ -19,7 +19,7 @@ const (
)

func RawArgocdInstallResources(templateData any, config v1alpha1.PackageCustomization, scheme *runtime.Scheme) ([][]byte, error) {
return util.BuildCustomizedManifests(config.FilePath, "resources/argo", installArgoFS, scheme, templateData)
return k8s.BuildCustomizedManifests(config.FilePath, "resources/argo", installArgoFS, scheme, templateData)
}

func (r *LocalbuildReconciler) ReconcileArgo(ctx context.Context, req ctrl.Request, resource *v1alpha1.Localbuild) (ctrl.Result, error) {
Expand Down
4 changes: 2 additions & 2 deletions pkg/controllers/localbuild/gitea.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import (
"fmt"

"github.com/cnoe-io/idpbuilder/api/v1alpha1"
"github.com/cnoe-io/idpbuilder/pkg/util"
"github.com/cnoe-io/idpbuilder/pkg/k8s"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/runtime/schema"
ctrl "sigs.k8s.io/controller-runtime"
Expand All @@ -27,7 +27,7 @@ const (
var installGiteaFS embed.FS

func RawGiteaInstallResources(templateData any, config v1alpha1.PackageCustomization, scheme *runtime.Scheme) ([][]byte, error) {
return util.BuildCustomizedManifests(config.FilePath, "resources/gitea/k8s", installGiteaFS, scheme, templateData)
return k8s.BuildCustomizedManifests(config.FilePath, "resources/gitea/k8s", installGiteaFS, scheme, templateData)
}

func (r *LocalbuildReconciler) ReconcileGitea(ctx context.Context, req ctrl.Request, resource *v1alpha1.Localbuild) (ctrl.Result, error) {
Expand Down
2 changes: 1 addition & 1 deletion pkg/controllers/localbuild/installer.go
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ type EmbeddedInstallation struct {
}

func (e *EmbeddedInstallation) installResources(scheme *runtime.Scheme, templateData any) ([]client.Object, error) {
return util.BuildCustomizedObjects(e.customization.FilePath, e.resourcePath, e.resourceFS, scheme, templateData)
return k8s.BuildCustomizedObjects(e.customization.FilePath, e.resourcePath, e.resourceFS, scheme, templateData)
}

func (e *EmbeddedInstallation) newNamespace(namespace string) *corev1.Namespace {
Expand Down
4 changes: 2 additions & 2 deletions pkg/controllers/localbuild/nginx.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import (
"embed"

"github.com/cnoe-io/idpbuilder/api/v1alpha1"
"github.com/cnoe-io/idpbuilder/pkg/util"
"github.com/cnoe-io/idpbuilder/pkg/k8s"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/runtime/schema"
ctrl "sigs.k8s.io/controller-runtime"
Expand All @@ -19,7 +19,7 @@ const (
var installNginxFS embed.FS

func RawNginxInstallResources(templateData any, config v1alpha1.PackageCustomization, scheme *runtime.Scheme) ([][]byte, error) {
return util.BuildCustomizedManifests(config.FilePath, "resources/nginx/k8s", installNginxFS, scheme, templateData)
return k8s.BuildCustomizedManifests(config.FilePath, "resources/nginx/k8s", installNginxFS, scheme, templateData)
}

func (r *LocalbuildReconciler) ReconcileNginx(ctx context.Context, req ctrl.Request, resource *v1alpha1.Localbuild) (ctrl.Result, error) {
Expand Down
File renamed without changes.
File renamed without changes.
59 changes: 59 additions & 0 deletions pkg/k8s/util.go
Original file line number Diff line number Diff line change
@@ -1 +1,60 @@
package k8s

import (
"embed"
"os"

"github.com/cnoe-io/idpbuilder/pkg/util"
"k8s.io/apimachinery/pkg/runtime"
"sigs.k8s.io/controller-runtime/pkg/client"
)

func BuildCustomizedManifests(filePath, fsPath string, resourceFS embed.FS, scheme *runtime.Scheme, templateData any) ([][]byte, error) {
rawResources, err := util.ConvertFSToBytes(resourceFS, fsPath, templateData)
if err != nil {
return nil, err
}

if filePath == "" {
return rawResources, nil
}

bs, _, err := applyOverrides(filePath, rawResources, scheme, templateData)
if err != nil {
return nil, err
}

return bs, nil
}

func BuildCustomizedObjects(filePath, fsPath string, resourceFS embed.FS, scheme *runtime.Scheme, templateData any) ([]client.Object, error) {
rawResources, err := util.ConvertFSToBytes(resourceFS, fsPath, templateData)
if err != nil {
return nil, err
}

if filePath == "" {
return ConvertRawResourcesToObjects(scheme, rawResources)
}

_, objs, err := applyOverrides(filePath, rawResources, scheme, templateData)
if err != nil {
return nil, err
}

return objs, nil
}

func applyOverrides(filePath string, originalFiles [][]byte, scheme *runtime.Scheme, templateData any) ([][]byte, []client.Object, error) {
customBS, err := os.ReadFile(filePath)
if err != nil {
return nil, nil, err
}

rendered, err := util.ApplyTemplate(customBS, templateData)
if err != nil {
return nil, nil, err
}

return ConvertYamlToObjectsWithOverride(scheme, originalFiles, rendered)
}
Loading

0 comments on commit 9f79b03

Please sign in to comment.