add images push command

Signed-off-by: 24sama <jacksama@foxmail.com>
This commit is contained in:
24sama 2022-02-25 15:14:49 +08:00
parent 5702163f78
commit 48f5f90c98
11 changed files with 256 additions and 13 deletions

View File

@ -17,6 +17,7 @@
package artifact
import (
"github.com/kubesphere/kubekey/cmd/ctl/artifact/images"
"github.com/kubesphere/kubekey/cmd/ctl/options"
"github.com/spf13/cobra"
)
@ -31,7 +32,7 @@ func NewArtifactOptions() *ArtifactOptions {
}
}
// NewCmdArtifact creates a new create command
// NewCmdArtifact creates a new cobra.Command for `kubekey artifact`
func NewCmdArtifact() *cobra.Command {
o := NewArtifactOptions()
cmd := &cobra.Command{
@ -41,6 +42,7 @@ func NewCmdArtifact() *cobra.Command {
o.CommonOptions.AddCommonFlag(cmd)
cmd.AddCommand(NewCmdCreateCluster())
cmd.AddCommand(NewCmdArtifactExport())
cmd.AddCommand(images.NewCmdArtifactImages())
return cmd
}

View File

@ -42,8 +42,8 @@ func NewArtifactExportOptions() *ArtifactExportOptions {
}
}
// NewCmdCreateCluster creates a new create cluster command
func NewCmdCreateCluster() *cobra.Command {
// NewCmdArtifactExport creates a new `kubekey artifact export` command
func NewCmdArtifactExport() *cobra.Command {
o := NewArtifactExportOptions()
cmd := &cobra.Command{
Use: "export",
@ -60,7 +60,7 @@ func NewCmdCreateCluster() *cobra.Command {
return cmd
}
func (o *ArtifactExportOptions) Complete(cmd *cobra.Command, args []string) error {
func (o *ArtifactExportOptions) Complete(_ *cobra.Command, _ []string) error {
var err error
if o.Output == "" {
o.Output = "kubekey-artifact.tar.gz"
@ -74,7 +74,7 @@ func (o *ArtifactExportOptions) Complete(cmd *cobra.Command, args []string) erro
return nil
}
func (o *ArtifactExportOptions) Validate(args []string) error {
func (o *ArtifactExportOptions) Validate(_ []string) error {
if o.ManifestFile == "" {
return fmt.Errorf("--manifest can not be an empty string")
}

View File

@ -0,0 +1,47 @@
/*
Copyright 2022 The KubeSphere Authors.
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 images
import (
"github.com/kubesphere/kubekey/cmd/ctl/options"
"github.com/spf13/cobra"
)
type ArtifactImagesOptions struct {
CommonOptions *options.CommonOptions
}
func NewArtifactImagesOptions() *ArtifactImagesOptions {
return &ArtifactImagesOptions{
CommonOptions: options.NewCommonOptions(),
}
}
// NewCmdArtifactImages creates a new `kubekey artifact image` command
func NewCmdArtifactImages() *cobra.Command {
o := NewArtifactImagesOptions()
cmd := &cobra.Command{
Use: "images",
Aliases: []string{"image", "i"},
Short: "manage KubeKey artifact image",
}
o.CommonOptions.AddCommonFlag(cmd)
cmd.AddCommand(NewCmdArtifactImagesPush())
return cmd
}

View File

@ -0,0 +1,140 @@
/*
Copyright 2022 The KubeSphere Authors.
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 images
import (
"github.com/kubesphere/kubekey/cmd/ctl/options"
"github.com/kubesphere/kubekey/cmd/ctl/util"
"github.com/kubesphere/kubekey/pkg/artifact"
"github.com/kubesphere/kubekey/pkg/bootstrap/precheck"
"github.com/kubesphere/kubekey/pkg/common"
"github.com/kubesphere/kubekey/pkg/core/module"
"github.com/kubesphere/kubekey/pkg/core/pipeline"
"github.com/kubesphere/kubekey/pkg/filesystem"
"github.com/kubesphere/kubekey/pkg/images"
"github.com/pkg/errors"
"github.com/spf13/cobra"
"os"
"path/filepath"
)
type ArtifactImagesPushOptions struct {
CommonOptions *options.CommonOptions
ImageDirPath string
Artifact string
ClusterCfgFile string
}
func NewArtifactImagesPushOptions() *ArtifactImagesPushOptions {
return &ArtifactImagesPushOptions{
CommonOptions: options.NewCommonOptions(),
}
}
// NewCmdArtifactImagesPush creates a new `kubekey artifacts images push` command
func NewCmdArtifactImagesPush() *cobra.Command {
o := NewArtifactImagesPushOptions()
cmd := &cobra.Command{
Use: "push",
Short: "push images to a registry from an artifact",
Run: func(cmd *cobra.Command, args []string) {
util.CheckErr(o.Complete(cmd, args))
util.CheckErr(o.Validate(args))
util.CheckErr(o.Run())
},
}
o.CommonOptions.AddCommonFlag(cmd)
o.AddFlags(cmd)
return cmd
}
func (o *ArtifactImagesPushOptions) Complete(_ *cobra.Command, _ []string) error {
if o.ImageDirPath == "" && o.Artifact == "" {
currentDir, err := filepath.Abs(filepath.Dir(os.Args[0]))
if err != nil {
return errors.Wrap(err, "failed to get current directory")
}
o.ImageDirPath = filepath.Join(currentDir, "kubekey", "images")
}
return nil
}
func (o *ArtifactImagesPushOptions) Validate(_ []string) error {
if o.ClusterCfgFile == "" {
return errors.New("kubekey config file is required")
}
if o.ImageDirPath != "" && o.Artifact != "" {
return errors.New("only one of --image-dir or --artifact can be specified")
}
return nil
}
func (o *ArtifactImagesPushOptions) Run() error {
arg := common.Argument{
ImagesDir: o.ImageDirPath,
Artifact: o.Artifact,
FilePath: o.ClusterCfgFile,
Debug: o.CommonOptions.Verbose,
IgnoreErr: o.CommonOptions.IgnoreErr,
}
return runPush(arg)
}
func (o *ArtifactImagesPushOptions) AddFlags(cmd *cobra.Command) {
cmd.Flags().StringVarP(&o.ImageDirPath, "images-dir", "", "", "Path to a KubeKey artifact images directory")
cmd.Flags().StringVarP(&o.Artifact, "artifact", "a", "", "Path to a KubeKey artifact")
cmd.Flags().StringVarP(&o.ClusterCfgFile, "filename", "f", "", "Path to a configuration file")
}
func runPush(arg common.Argument) error {
runtime, err := common.NewKubeRuntime(common.File, arg)
if err != nil {
return err
}
if err := newImagesPushPipeline(runtime); err != nil {
return err
}
return nil
}
func newImagesPushPipeline(runtime *common.KubeRuntime) error {
noArtifact := runtime.Arg.Artifact == ""
m := []module.Module{
&precheck.CRIPreCheckModule{},
&artifact.UnArchiveModule{Skip: noArtifact},
&images.PushModule{ImagePath: runtime.Arg.ImagesDir},
&filesystem.ChownWorkDirModule{},
}
p := pipeline.Pipeline{
Name: "ArtifactImagesPushPipeline",
Modules: m,
Runtime: runtime,
}
if err := p.Start(); err != nil {
return err
}
return nil
}

View File

@ -139,3 +139,22 @@ func (c *ClusterPreCheckModule) Init() {
getKubernetesNodesStatus,
}
}
type CRIPreCheckModule struct {
common.KubeModule
}
func (c *CRIPreCheckModule) Init() {
c.Name = "CRIPreCheckModule"
c.Desc = "Do CRI pre-check on local node"
criCheck := &task.LocalTask{
Name: "CRIPreCheck",
Desc: "Check CRI",
Action: new(CRIPreCheck),
}
c.Tasks = []task.Interface{
criCheck,
}
}

View File

@ -24,6 +24,7 @@ import (
"github.com/kubesphere/kubekey/pkg/version/kubesphere"
"github.com/pkg/errors"
versionutil "k8s.io/apimachinery/pkg/util/version"
"os/exec"
"regexp"
"strings"
)
@ -275,3 +276,14 @@ func (g *GetKubernetesNodesStatus) Execute(runtime connector.Runtime) error {
g.PipelineCache.Set(common.ClusterNodeStatus, nodeStatus)
return nil
}
type CRIPreCheck struct {
common.KubeAction
}
func (c *CRIPreCheck) Execute(_ connector.Runtime) error {
if _, err := exec.Command("/bin/bash", "-c", "which ctr").CombinedOutput(); err != nil {
return errors.New("containerd is not installed")
}
return nil
}

View File

@ -53,6 +53,7 @@ type Argument struct {
Artifact string
InstallPackages bool
CertificatesDir string
ImagesDir string
}
func NewKubeRuntime(flag string, arg Argument) (*KubeRuntime, error) {

View File

@ -44,12 +44,12 @@ func (c *ChownModule) Init() {
}
type ChownWorkDirModule struct {
common.ArtifactModule
module.BaseTaskModule
}
func (c *ChownWorkDirModule) Init() {
c.Name = "ChownWorkDirModule"
c.Desc = "Change file and dir owner"
c.Name = "ChownWorkerModule"
c.Desc = "Change kubekey work dir mode and owner"
userKubeDir := &task.LocalTask{
Name: "ChownFileAndDir",
@ -57,6 +57,19 @@ func (c *ChownWorkDirModule) Init() {
Action: &LocalTaskChown{Path: c.Runtime.GetWorkDir()},
}
c.Tasks = []task.Interface{
userKubeDir,
}
}
type ChownOutputModule struct {
common.ArtifactModule
}
func (c *ChownOutputModule) Init() {
c.Name = "ChownOutputModule"
c.Desc = "Change file and dir owner"
output := &task.LocalTask{
Name: "Chown output file",
Desc: "Chown output file",
@ -64,7 +77,6 @@ func (c *ChownWorkDirModule) Init() {
}
c.Tasks = []task.Interface{
userKubeDir,
output,
}
}

View File

@ -73,7 +73,8 @@ func (p *PullModule) Init() {
type PushModule struct {
common.KubeModule
Skip bool
Skip bool
ImagePath string
}
func (p *PushModule) IsSkip() bool {
@ -87,7 +88,7 @@ func (p *PushModule) Init() {
push := &task.LocalTask{
Name: "PushImages",
Desc: "Push images to private registry",
Action: new(PushImage),
Action: &PushImage{ImagesPath: p.ImagePath},
}
p.Tasks = []task.Interface{

View File

@ -136,10 +136,17 @@ func GetImage(runtime connector.ModuleRuntime, kubeConf *common.KubeConf, name s
type PushImage struct {
common.KubeAction
ImagesPath string
}
func (p *PushImage) Execute(runtime connector.Runtime) error {
imagesPath := filepath.Join(runtime.GetWorkDir(), "images")
var imagesPath string
if p.ImagesPath != "" {
imagesPath = p.ImagesPath
} else {
imagesPath = filepath.Join(runtime.GetWorkDir(), "images")
}
files, err := ioutil.ReadDir(imagesPath)
if err != nil {
return errors.Wrapf(errors.WithStack(err), "read %s dir faied", imagesPath)

View File

@ -35,6 +35,7 @@ func NewArtifactExportPipeline(runtime *common.ArtifactRuntime) error {
&binaries.ArtifactBinariesModule{},
&artifact.RepositoryModule{},
&artifact.ArchiveModule{},
&filesystem.ChownOutputModule{},
&filesystem.ChownWorkDirModule{},
}
@ -58,6 +59,7 @@ func NewK3sArtifactExportPipeline(runtime *common.ArtifactRuntime) error {
&binaries.K3sArtifactBinariesModule{},
&artifact.RepositoryModule{},
&artifact.ArchiveModule{},
&filesystem.ChownOutputModule{},
&filesystem.ChownWorkDirModule{},
}