Skip to content

Commit

Permalink
Sealer Application definition (sealerio#1658)
Browse files Browse the repository at this point in the history
* add kubefile translator & application definition

Signed-off-by: david.bao <[email protected]>

* taking user input as image type

Signed-off-by: David Bao <[email protected]>

* fix conflicts

Signed-off-by: david.bao <[email protected]>
Signed-off-by: David Bao <[email protected]>
  • Loading branch information
justadogistaken authored Oct 9, 2022
1 parent b15a5fd commit a20019a
Show file tree
Hide file tree
Showing 53 changed files with 3,233 additions and 169 deletions.
146 changes: 137 additions & 9 deletions build/buildimage/differ.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,14 @@ import (
"context"
"fmt"
"io/fs"
"os"
"path/filepath"
"strings"

"github.com/pkg/errors"

"github.com/sealerio/sealer/pkg/rootfs"

osi "github.com/sealerio/sealer/utils/os"

"github.com/sealerio/sealer/build/layerutils/charts"
Expand All @@ -33,17 +38,19 @@ import (
)

var (
copyToManifests = "manifests"
copyToChart = "charts"
copyToImageList = "imageList"
dispatch map[string]func(srcPath string) ([]string, error)
copyToManifests = "manifests"
copyToChart = "charts"
copyToImageList = "imageList"
copyToApplication = "application"
dispatch map[string]func(srcPath string) ([]string, error)
)

func init() {
dispatch = map[string]func(srcPath string) ([]string, error){
copyToManifests: parseYamlImages,
copyToChart: parseChartImages,
copyToImageList: parseRawImageList,
copyToManifests: parseYamlImages,
copyToChart: parseChartImages,
copyToImageList: parseRawImageList,
copyToApplication: parseApplicationImages,
}
}

Expand Down Expand Up @@ -84,6 +91,122 @@ func NewRegistryDiffer(platform v1.Platform) Differ {
}
}

func parseApplicationImages(srcPath string) ([]string, error) {
applicationPath := filepath.Clean(filepath.Join(srcPath, rootfs.GlobalManager.App().Root()))

if !osi.IsFileExist(applicationPath) {
return nil, nil
}

var (
images []string
err error
)

entries, err := os.ReadDir(applicationPath)
if err != nil {
return nil, errors.Wrap(err, "error in readdir in parseApplicationImages")
}
for _, entry := range entries {
name := entry.Name()
appPath := filepath.Join(applicationPath, name)
if entry.IsDir() {
if !isChartArtifactEnough(appPath) {
imagesTmp, err := parseKubeImages(appPath)
if err != nil {
return nil, errors.Wrap(err, fmt.Sprintf("error in parseKubeImages of %s", appPath))
}
images = append(images, imagesTmp...)
continue
}

imagesTmp, err := parseHelmImages(appPath)
if err != nil {
return nil, errors.Wrap(err, fmt.Sprintf("error in parseHelmImages of %s", appPath))
}
images = append(images, imagesTmp...)
}
}

return images, nil
}

func parseHelmImages(helmPath string) ([]string, error) {
if !osi.IsFileExist(helmPath) {
return nil, nil
}

var images []string

imageSearcher, err := charts.NewCharts()
if err != nil {
return nil, err
}

err = filepath.Walk(helmPath, func(path string, f fs.FileInfo, err error) error {
if err != nil {
return err
}

if !f.IsDir() {
return nil
}

if isChartArtifactEnough(path) {
imgs, err := imageSearcher.ListImages(path)
if err != nil {
return err
}

images = append(images, imgs...)
return filepath.SkipDir
}
return nil
})
if err != nil {
return nil, err
}
return FormatImages(images), nil
}

func parseKubeImages(kubePath string) ([]string, error) {
if !osi.IsFileExist(kubePath) {
return nil, nil
}
var images []string
imageSearcher, err := manifest.NewManifests()
if err != nil {
return nil, err
}

err = filepath.Walk(kubePath, func(path string, f fs.FileInfo, err error) error {
if err != nil {
return err
}
if f.IsDir() {
return nil
}

ext := strings.ToLower(filepath.Ext(f.Name()))
if ext != ".yaml" && ext != ".yml" && ext != ".tmpl" {
return nil
}

ima, err := imageSearcher.ListImages(path)

if err != nil {
return err
}
images = append(images, ima...)
return nil
})

if err != nil {
return nil, err
}
return FormatImages(images), nil
}

func parseChartImages(srcPath string) ([]string, error) {
chartsPath := filepath.Join(srcPath, copyToChart)
if !osi.IsFileExist(chartsPath) {
Expand All @@ -105,8 +228,7 @@ func parseChartImages(srcPath string) ([]string, error) {
return nil
}

if osi.IsFileExist(filepath.Join(path, "Chart.yaml")) && osi.IsFileExist(filepath.Join(path, "values.yaml")) &&
osi.IsFileExist(filepath.Join(path, "templates")) {
if isChartArtifactEnough(path) {
ima, err := imageSearcher.ListImages(path)
if err != nil {
return err
Expand Down Expand Up @@ -227,3 +349,9 @@ func (m metadata) loadMetadata(srcPath, rootfs string) (*runtime.Metadata, error
func NewMetadataDiffer() Differ {
return metadata{}
}

var isChartArtifactEnough = func(path string) bool {
return osi.IsFileExist(filepath.Join(path, "Chart.yaml")) &&
osi.IsFileExist(filepath.Join(path, "values.yaml")) &&
osi.IsFileExist(filepath.Join(path, "templates"))
}
20 changes: 0 additions & 20 deletions build/buildimage/image_interface.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,28 +14,8 @@

package buildimage

import (
v1 "github.com/sealerio/sealer/types/api/v1"
)

type Executor interface {
// Execute all raw layers,and merge with base layers.
Execute(ctx Context, rawLayers []v1.Layer) ([]v1.Layer, error)
Cleanup() error
}

type Differ interface {
// Process :diff changes by build-in handler and save to dst,like pull docker image from manifests or helm charts
//diff Metadata file changes save to the base layer.generally dst is the rootfs.
Process(srcPath, rootfs string) error
}

type ImageSetter interface {
// Set :fill up v1.image struct, like image annotations, platform and so on.
Set(*v1.Image) error
}

type ImageSaver interface {
// Save with image attribute,and register to image metadata.
Save(image *v1.Image) error
}
15 changes: 15 additions & 0 deletions build/buildimage/image_searcher_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
// Copyright © 2022 Alibaba Group Holding Ltd.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package buildimage
30 changes: 16 additions & 14 deletions build/buildimage/utils.go
Original file line number Diff line number Diff line change
Expand Up @@ -61,26 +61,28 @@ func readCharts(chartsPath string) string {
}

func FormatImages(images []string) (res []string) {
for _, ima := range strUtils.RemoveDuplicate(images) {
if ima == "" {
for _, img := range images {
tmpImg := strings.TrimSpace(img)
tmpImg = strings.Trim(tmpImg, `'"`)
tmpImg = strings.TrimSpace(tmpImg)
if strings.HasPrefix(tmpImg, "#") || tmpImg == "" {
continue
}
if strings.HasPrefix(ima, "#") {
continue
}
res = append(res, trimQuotes(strings.TrimSpace(ima)))
res = append(res, tmpImg)
}

res = strUtils.RemoveDuplicate(res)
return
}

func trimQuotes(s string) string {
if len(s) >= 2 {
if c := s[len(s)-1]; s[0] == c && (c == '"' || c == '\'') {
return s[1 : len(s)-1]
}
}
return s
}
//func trimQuotes(s string) string {
// if len(s) >= 2 {
// if c := s[len(s)-1]; s[0] == c && (c == '"' || c == '\'') {
// return s[1 : len(s)-1]
// }
// }
// return s
//}

func marshalJSONToFile(file string, obj interface{}) error {
data, err := json.MarshalIndent(obj, "", " ")
Expand Down
49 changes: 49 additions & 0 deletions build/kubefile/command/command.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
// Copyright © 2022 Alibaba Group Holding Ltd.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package command

const (

// the following commands are kubefile-spec commands
// we recommender users to use these commands to pack their
// demands for applications.
App = "app"
Launch = "launch"
Cmds = "cmds"

Label = "label"
Maintainer = "maintainer"

// the following commands are the intenal implementations for kube commands
Add = "add"
Arg = "arg"
Copy = "copy"
From = "from"
Run = "run"
)

// SupportedCommands is list of all Kubefile commands
var SupportedCommands = map[string]struct{}{
Add: {},
Arg: {},
Copy: {},
From: {},
Label: {},
Maintainer: {},
Run: {},
App: {},
Launch: {},
Cmds: {},
}
Loading

0 comments on commit a20019a

Please sign in to comment.