feat: support to modify the download url and checksum of the components

Signed-off-by: 24sama <jacksama@foxmail.com>
This commit is contained in:
24sama 2022-08-29 16:50:36 +08:00
parent e0849b22a5
commit 94e4d58cf9
22 changed files with 725 additions and 176 deletions

View File

@ -0,0 +1,51 @@
/*
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 v1beta1
// Component is optional configuration for modifying the FTP server.
type Component struct {
// ZONE is the zone of the KKCluster where can get the binaries.
// If you have problem to access https://storage.googleapis.com, you can set "zone: cn".
ZONE string `json:"zone,omitempty"`
// Host is the host to download the binaries.
Host string `json:"host,omitempty"`
// Overrides is a list of components download information that need to be overridden.
Overrides []Override `json:"overrides,omitempty"`
}
// Override is a component download information that need to be overridden.
type Override struct {
// ID is the component id name. e.g. kubeadm, kubelet, containerd, etc.
ID string `json:"id,omitempty"`
// Arch is the component arch. e.g. amd64, arm64, etc.
Arch string `json:"arch,omitempty"`
// Version is the component version. e.g. v1.21.1, v1.22.0, etc.
Version string `json:"version,omitempty"`
// URL is the download url of the binaries.
URL string `json:"url,omitempty"`
// Path defines the URL path, which is the string of information that comes after the top level domain name.
Path string `json:"path,omitempty"`
// Checksum is the SHA256 checksum of the binary.
Checksum string `json:"checksum,omitempty"`
}

View File

@ -30,9 +30,6 @@ const (
// KKClusterSpec defines the desired state of KKCluster
type KKClusterSpec struct {
// ZONE is the zone of the KKCluster where can get the binaries.
// If you have problem to access https://storage.googleapis.com, you can set "zone: cn".
ZONE string `json:"zone,omitempty"`
// Nodes represents the information about the nodes available to the cluster
Nodes Nodes `json:"nodes"`
@ -45,6 +42,11 @@ type KKClusterSpec struct {
// +optional
ControlPlaneLoadBalancer *KKLoadBalancerSpec `json:"controlPlaneLoadBalancer,omitempty"`
// Component is optional configuration for modifying the FTP server
// that gets the necessary components for the cluster.
// +optional
Component *Component `json:"component,omitempty"`
// Registry represents the cluster image registry used to pull the images.
// +optional
Registry Registry `json:"registry"`

View File

@ -53,6 +53,26 @@ func (in *Auth) DeepCopy() *Auth {
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *Component) DeepCopyInto(out *Component) {
*out = *in
if in.Overrides != nil {
in, out := &in.Overrides, &out.Overrides
*out = make([]Override, len(*in))
copy(*out, *in)
}
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Component.
func (in *Component) DeepCopy() *Component {
if in == nil {
return nil
}
out := new(Component)
in.DeepCopyInto(out)
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *ContainerManager) DeepCopyInto(out *ContainerManager) {
*out = *in
@ -137,6 +157,11 @@ func (in *KKClusterSpec) DeepCopyInto(out *KKClusterSpec) {
*out = new(KKLoadBalancerSpec)
**out = **in
}
if in.Component != nil {
in, out := &in.Component, &out.Component
*out = new(Component)
(*in).DeepCopyInto(*out)
}
in.Registry.DeepCopyInto(&out.Registry)
}
@ -648,6 +673,21 @@ func (in *Nodes) DeepCopy() *Nodes {
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *Override) DeepCopyInto(out *Override) {
*out = *in
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Override.
func (in *Override) DeepCopy() *Override {
if in == nil {
return nil
}
out := new(Override)
in.DeepCopyInto(out)
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *Registry) DeepCopyInto(out *Registry) {
*out = *in

View File

@ -53,6 +53,50 @@ spec:
spec:
description: KKClusterSpec defines the desired state of KKCluster
properties:
component:
description: Component is optional configuration for modifying the
FTP server that gets the necessary components for the cluster.
properties:
host:
description: Host is the host to download the binaries.
type: string
overrides:
description: Overrides is a list of components download information
that need to be overridden.
items:
description: Override is a component download information that
need to be overridden.
properties:
arch:
description: Arch is the component arch. e.g. amd64, arm64,
etc.
type: string
checksum:
description: Checksum is the SHA256 checksum of the binary.
type: string
id:
description: ID is the component id name. e.g. kubeadm,
kubelet, containerd, etc.
type: string
path:
description: Path defines the URL path, which is the string
of information that comes after the top level domain name.
type: string
url:
description: URL is the download url of the binaries.
type: string
version:
description: Version is the component version. e.g. v1.21.1,
v1.22.0, etc.
type: string
type: object
type: array
zone:
description: 'ZONE is the zone of the KKCluster where can get
the binaries. If you have problem to access https://storage.googleapis.com,
you can set "zone: cn".'
type: string
type: object
controlPlaneEndpoint:
description: ControlPlaneEndpoint represents the endpoint used to
communicate with the control plane.
@ -276,11 +320,6 @@ spec:
- namespaceOverride
- privateRegistry
type: object
zone:
description: 'ZONE is the zone of the KKCluster where can get the
binaries. If you have problem to access https://storage.googleapis.com,
you can set "zone: cn".'
type: string
required:
- nodes
type: object

View File

@ -71,6 +71,53 @@ spec:
spec:
description: KKClusterSpec defines the desired state of KKCluster
properties:
component:
description: Component is optional configuration for modifying
the FTP server that gets the necessary components for the
cluster.
properties:
host:
description: Host is the host to download the binaries.
type: string
overrides:
description: Overrides is a list of components download
information that need to be overridden.
items:
description: Override is a component download information
that need to be overridden.
properties:
arch:
description: Arch is the component arch. e.g. amd64,
arm64, etc.
type: string
checksum:
description: Checksum is the SHA256 checksum of
the binary.
type: string
id:
description: ID is the component id name. e.g. kubeadm,
kubelet, containerd, etc.
type: string
path:
description: Path defines the URL path, which is
the string of information that comes after the
top level domain name.
type: string
url:
description: URL is the download url of the binaries.
type: string
version:
description: Version is the component version. e.g.
v1.21.1, v1.22.0, etc.
type: string
type: object
type: array
zone:
description: 'ZONE is the zone of the KKCluster where
can get the binaries. If you have problem to access
https://storage.googleapis.com, you can set "zone: cn".'
type: string
type: object
controlPlaneEndpoint:
description: ControlPlaneEndpoint represents the endpoint
used to communicate with the control plane.
@ -304,11 +351,6 @@ spec:
- namespaceOverride
- privateRegistry
type: object
zone:
description: 'ZONE is the zone of the KKCluster where can
get the binaries. If you have problem to access https://storage.googleapis.com,
you can set "zone: cn".'
type: string
required:
- nodes
type: object

View File

@ -87,8 +87,6 @@ type ClusterScoper interface {
KubernetesClusterName() string
// RootFs is the cluster scope rootfs
RootFs() rootfs.Interface
// Zone returns the cluster zone.
Zone() string
// PatchObject persists the cluster configuration and status.
PatchObject() error
// Close closes the current scope persisting the cluster configuration and status.

View File

@ -226,9 +226,28 @@ func (s *ClusterScope) RootFs() rootfs.Interface {
return s.rootFs
}
// Zone returns the KKCluster binaries zone.
func (s *ClusterScope) Zone() string {
return s.KKCluster.Spec.ZONE
// ComponentZone returns the KKCluster binaries zone.
func (s *ClusterScope) ComponentZone() string {
if s.KKCluster.Spec.Component == nil {
return ""
}
return s.KKCluster.Spec.Component.ZONE
}
// ComponentHost returns the KKCluster binaries host.
func (s *ClusterScope) ComponentHost() string {
if s.KKCluster.Spec.Component == nil {
return ""
}
return s.KKCluster.Spec.Component.Host
}
// ComponentOverrides returns the KKCluster binaries overrides.
func (s *ClusterScope) ComponentOverrides() []infrav1.Override {
if s.KKCluster.Spec.Component == nil {
return []infrav1.Override{}
}
return s.KKCluster.Spec.Component.Overrides
}
// ControlPlaneLoadBalancer returns the KKLoadBalancerSpec.

View File

@ -24,10 +24,17 @@ import (
// KKInstanceScope is a scope for global KKInstance.
type KKInstanceScope interface {
pkg.ClusterScoper
// ComponentZone returns the cluster zone.
ComponentZone() string
// ComponentHost returns the host to download the binaries.
ComponentHost() string
// ComponentOverrides returns the component overrides.
ComponentOverrides() []infrav1.Override
// GlobalAuth returns the global auth configuration of all instances.
GlobalAuth() *infrav1.Auth
// GlobalContainerManager returns the global container manager configuration of all instances.
GlobalContainerManager() *infrav1.ContainerManager
// GlobalRegistry returns the global registry configuration of all instances.
GlobalRegistry() *infrav1.Registry
// AllInstancesSpec returns the KKInstanceSpec
AllInstancesSpec() []infrav1.KKInstanceSpec

View File

@ -22,8 +22,10 @@ import (
"text/template"
"time"
infrav1 "github.com/kubesphere/kubekey/exp/cluster-api-provider-kubekey/api/v1beta1"
"github.com/kubesphere/kubekey/exp/cluster-api-provider-kubekey/pkg/service/operation"
"github.com/kubesphere/kubekey/exp/cluster-api-provider-kubekey/pkg/service/operation/file"
"github.com/kubesphere/kubekey/exp/cluster-api-provider-kubekey/pkg/service/operation/file/checksum"
)
//go:embed templates
@ -55,15 +57,44 @@ func (s *Service) DownloadAll(timeout time.Duration) error {
kubectl,
}
zone := s.scope.ComponentZone()
host := s.scope.ComponentHost()
overrideMap := make(map[string]infrav1.Override)
for _, o := range s.scope.ComponentOverrides() {
overrideMap[o.ID+o.Version+o.Arch] = o
}
for _, b := range binaries {
b.SetZone(s.scope.Zone())
needGet := true
if b.LocalExist() && b.CompareChecksum() == nil {
needGet = false
if b.RemoteExist() {
if err := b.Chmod("+x"); err != nil {
return err
}
continue
}
if needGet {
if !(b.LocalExist() && b.CompareChecksum() == nil) {
// Only the host is an empty string, we can set ip the zone.
// Because the URL path which in the QingStor is not the same as the default.
if host == "" {
b.SetZone(zone)
}
var path, url, checksumStr string
// If the override is match, we will use the override to replace the default.
if override, ok := overrideMap[b.ID()+b.Version()+b.Arch()]; ok {
path = override.Path
url = override.URL
checksumStr = override.Checksum
}
// Always try to set the "host, path, url, checksum".
// If the these vars are empty strings, it will not make any changes.
b.SetHost(host)
b.SetPath(path)
b.SetURL(url)
b.SetChecksum(checksum.NewStringChecksum(checksumStr))
s.instanceScope.V(4).Info("download binary", "binary", b.Name(),
"version", b.Version(), "url", b.URL())
"version", b.Version(), "url", b.URL().String())
if err := b.Get(timeout); err != nil {
return err
}
@ -71,6 +102,7 @@ func (s *Service) DownloadAll(timeout time.Duration) error {
return err
}
}
if err := b.Copy(true); err != nil {
return err
}

View File

@ -32,6 +32,7 @@ import (
"github.com/kubesphere/kubekey/exp/cluster-api-provider-kubekey/pkg/scope"
"github.com/kubesphere/kubekey/exp/cluster-api-provider-kubekey/pkg/service/operation"
"github.com/kubesphere/kubekey/exp/cluster-api-provider-kubekey/pkg/service/operation/file"
"github.com/kubesphere/kubekey/exp/cluster-api-provider-kubekey/pkg/service/operation/file/checksum"
)
// ContainerdService is a ContainerManager service implementation for containerd.
@ -129,15 +130,41 @@ func (s *ContainerdService) Get(timeout time.Duration) error {
crictl,
}
zone := s.scope.ComponentZone()
host := s.scope.ComponentHost()
overrideMap := make(map[string]infrav1.Override)
for _, o := range s.scope.ComponentOverrides() {
overrideMap[o.ID+o.Version+o.Arch] = o
}
for _, b := range binaries {
b.SetZone(s.scope.Zone())
needGet := true
if b.LocalExist() && b.CompareChecksum() == nil {
needGet = false
if b.RemoteExist() {
continue
}
if needGet {
if !(b.LocalExist() && b.CompareChecksum() == nil) {
// Only the host is an empty string, we can set ip the zone.
// Because the URL path which in the QingStor is not the same as the default.
if host == "" {
b.SetZone(zone)
}
var path, url, checksumStr string
// If the override is match, we will use the override to replace the default.
if override, ok := overrideMap[b.ID()+b.Version()+b.Arch()]; ok {
path = override.Path
url = override.URL
checksumStr = override.Checksum
}
// Always try to set the "host, path, url, checksum".
// If the these vars are empty strings, it will not make any changes.
b.SetHost(host)
b.SetPath(path)
b.SetURL(url)
b.SetChecksum(checksum.NewStringChecksum(checksumStr))
s.instanceScope.V(4).Info("download binary", "binary", b.Name(),
"version", b.Version(), "url", b.URL())
"version", b.Version(), "url", b.URL().String())
if err := b.Get(timeout); err != nil {
return err
}
@ -145,6 +172,7 @@ func (s *ContainerdService) Get(timeout time.Duration) error {
return err
}
}
if err := b.Copy(true); err != nil {
return err
}

View File

@ -20,27 +20,122 @@ import (
"crypto/sha256"
"fmt"
"io"
"net/url"
"os"
"path"
"reflect"
"strings"
"time"
"github.com/hashicorp/go-getter"
urlhelper "github.com/hashicorp/go-getter/helper/url"
"github.com/pkg/errors"
"github.com/kubesphere/kubekey/exp/cluster-api-provider-kubekey/pkg/service/operation/file/checksum"
)
// Default
const (
ZONE = "cn"
DefaultDownloadHost = "https://github.com"
DefaultDownloadHostGoogle = "https://storage.googleapis.com"
DefaultDownloadHostQingStor = "https://kubernetes-release.pek3b.qingstor.com"
)
// BinaryParams represents the parameters of a Binary.
type BinaryParams struct {
File *File
ID string
Version string
Arch string
URL *url.URL
Checksum checksum.Interface
}
// NewBinary returns a new Binary.
func NewBinary(params BinaryParams) *Binary {
b := &Binary{
file: params.File,
id: params.ID,
version: params.Version,
arch: params.Arch,
url: params.URL,
checksum: params.Checksum,
}
return b
}
// Binary is a binary implementation of Binary interface.
type Binary struct {
*File
file *File
id string
version string
arch string
url string
cnURL string
url *url.URL
checksum checksum.Interface
}
// Name returns the name of the Binary file.
func (b *Binary) Name() string {
return b.file.Name()
}
// Type returns the type of the Binary file.
func (b *Binary) Type() Type {
return b.file.Type()
}
// LocalPath returns the local path of the Binary file.
func (b *Binary) LocalPath() string {
return b.file.LocalPath()
}
// RemotePath returns the remote path of the Binary file.
func (b *Binary) RemotePath() string {
return b.file.RemotePath()
}
// LocalExist returns true if the Binary file is existed in the local path.
func (b *Binary) LocalExist() bool {
return b.file.LocalExist()
}
// RemoteExist returns true if the Binary file is existed (and the SHA256 check passes) in the remote path.
func (b *Binary) RemoteExist() bool {
if !b.file.RemoteExist() {
return false
}
cmd := fmt.Sprintf("sha256sum %s | cut -d\" \" -f1", b.file.RemotePath())
remoteSHA256, err := b.file.sshClient.SudoCmd(cmd)
if err != nil {
return false
}
if err := b.checksum.Get(); err != nil {
return false
}
if remoteSHA256 != b.checksum.Value() {
return false
}
return true
}
// Copy copies the Binary file from the local path to the remote path.
func (b *Binary) Copy(override bool) error {
return b.file.Copy(override)
}
// Fetch copies the Binary file from the remote path to the local path.
func (b *Binary) Fetch(override bool) error {
return b.file.Fetch(override)
}
// Chmod changes the mode of the Binary file.
func (b *Binary) Chmod(option string) error {
return b.file.Chmod(option)
}
// ID returns the id of the binary.
func (b *Binary) ID() string {
return b.id
@ -57,29 +152,69 @@ func (b *Binary) Version() string {
}
// URL returns the download url of the binary.
func (b *Binary) URL() string {
func (b *Binary) URL() *url.URL {
return b.url
}
// SetURL sets the download url of the binary.
func (b *Binary) SetURL(urlStr string) {
if urlStr == "" {
return
}
u, err := url.Parse(urlStr)
if err != nil {
return
}
b.url = u
}
// SetHost sets the host to download the binaries.
func (b *Binary) SetHost(host string) {
if host == "" {
return
}
u, err := url.Parse(host)
if err != nil {
return
}
u.Path = b.url.Path
b.url = u
}
// SetPath sets the URL path of the binary.
func (b *Binary) SetPath(pathStr string) {
if pathStr == "" {
return
}
ref, err := url.Parse(pathStr)
if err != nil {
return
}
b.url = b.url.ResolveReference(ref)
}
// SetZone sets the zone of the binary.
func (b *Binary) SetZone(zone string) {
if zone == "cn" {
b.url = b.cnURL
if strings.EqualFold(zone, ZONE) {
b.SetHost(DefaultDownloadHostQingStor)
}
}
// SetChecksum sets the checksum of the binary.
func (b *Binary) SetChecksum(c checksum.Interface) {
if reflect.ValueOf(c).IsNil() {
return
}
b.checksum = c
}
// Get downloads the binary from remote.
func (b *Binary) Get(timeout time.Duration) error {
client := &getter.HttpGetter{
ReadTimeout: timeout,
}
url, err := urlhelper.Parse(b.url)
if err != nil {
return errors.Wrapf(err, "failed to parse url: %s", b.url)
}
if err := client.GetFile(b.LocalPath(), url); err != nil {
if err := client.GetFile(b.LocalPath(), b.URL()); err != nil {
return errors.Wrapf(err, "failed to http get file: %s", b.LocalPath())
}
@ -117,3 +252,9 @@ func (b *Binary) CompareChecksum() error {
}
return nil
}
func parseURL(host, pathStr string) *url.URL {
u, _ := url.Parse(host)
u.Path = path.Join(u.Path, pathStr)
return u
}

View File

@ -0,0 +1,40 @@
/*
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 checksum
// StringChecksum is a simple checksum implementation for given strings.
type StringChecksum struct {
value string
}
// NewStringChecksum returns a new StringChecksum for the given string.
func NewStringChecksum(value string) *StringChecksum {
if value == "" {
return nil
}
return &StringChecksum{value: value}
}
// Get the StringChecksum Get() method will do nothing.
func (s *StringChecksum) Get() error {
return nil
}
// Value returns the value of the StringChecksum.
func (s *StringChecksum) Value() string {
return s.value
}

View File

@ -27,16 +27,18 @@ import (
// Containerd info
const (
ContainerdName = "containerd-%s-linux-%s.tar.gz"
ContainerdID = "containerd"
ContainerdDownloadURLTmpl = "https://github.com/containerd/containerd/releases/download/v%s/containerd-%s-linux-%s.tar.gz"
ContainerdDownloadURLTmplCN = "https://kubernetes-release.pek3b.qingstor.com/containerd/containerd/releases/download/v%s/containerd-%s-linux-%s.tar.gz"
ContainerdName = "containerd-%s-linux-%s.tar.gz"
ContainerdID = "containerd"
ContainerdURLPathTmpl = "/containerd/containerd/releases/download/v%s/containerd-%s-linux-%s.tar.gz"
)
// NewContainerd returns a new Binary for containerd
func NewContainerd(sshClient ssh.Interface, rootFs rootfs.Interface, version, arch string) (*Binary, error) {
internal := checksum.NewChecksum(ContainerdID, version, arch)
// Containerd is a Binary for containerd.
type Containerd struct {
*Binary
}
// NewContainerd returns a new Containerd.
func NewContainerd(sshClient ssh.Interface, rootFs rootfs.Interface, version, arch string) (*Containerd, error) {
fileName := fmt.Sprintf(ContainerdName, version, arch)
file, err := NewFile(Params{
SSHClient: sshClient,
@ -50,13 +52,16 @@ func NewContainerd(sshClient ssh.Interface, rootFs rootfs.Interface, version, ar
return nil, err
}
return &Binary{
file,
ContainerdID,
version,
arch,
fmt.Sprintf(ContainerdDownloadURLTmpl, version, version, arch),
fmt.Sprintf(ContainerdDownloadURLTmplCN, version, version, arch),
internal,
}, nil
u := parseURL(DefaultDownloadHost, fmt.Sprintf(ContainerdURLPathTmpl, version, version, arch))
internal := checksum.NewChecksum(ContainerdID, version, arch)
binary := NewBinary(BinaryParams{
File: file,
ID: ContainerdID,
Version: version,
Arch: arch,
URL: u,
Checksum: internal,
})
return &Containerd{binary}, nil
}

View File

@ -19,6 +19,7 @@ package file
import (
"fmt"
"path/filepath"
"strings"
"github.com/kubesphere/kubekey/exp/cluster-api-provider-kubekey/pkg/clients/ssh"
"github.com/kubesphere/kubekey/exp/cluster-api-provider-kubekey/pkg/rootfs"
@ -27,16 +28,19 @@ import (
// Crictl info
const (
CrictlName = "crictl-%s-linux-%s.tar.gz"
CrictlID = "crictl"
CrictlDownloadURLTmpl = "https://github.com/kubernetes-sigs/cri-tools/releases/download/%s/crictl-%s-linux-%s.tar.gz"
CrictlDownloadURLTmplCN = "https://kubernetes-release.pek3b.qingstor.com/cri-tools/releases/download/%s/crictl-%s-linux-%s.tar.gz"
CrictlName = "crictl-%s-linux-%s.tar.gz"
CrictlID = "crictl"
CrictlURLPathTmpl = "/kubernetes-sigs/cri-tools/releases/download/%s/crictl-%s-linux-%s.tar.gz"
CrictlURLPathTmplCN = "/cri-tools/releases/download/%s/crictl-%s-linux-%s.tar.gz"
)
// NewCrictl returns a new Binary for crictl
func NewCrictl(sshClient ssh.Interface, rootFs rootfs.Interface, version, arch string) (*Binary, error) {
internal := checksum.NewChecksum(CrictlID, version, arch)
// Crictl is a Binary for crictl.
type Crictl struct {
*Binary
}
// NewCrictl returns a new Crictl.
func NewCrictl(sshClient ssh.Interface, rootFs rootfs.Interface, version, arch string) (*Crictl, error) {
fileName := fmt.Sprintf(CrictlName, version, arch)
file, err := NewFile(Params{
SSHClient: sshClient,
@ -50,13 +54,24 @@ func NewCrictl(sshClient ssh.Interface, rootFs rootfs.Interface, version, arch s
return nil, err
}
return &Binary{
file,
CrictlID,
version,
arch,
fmt.Sprintf(CrictlDownloadURLTmpl, version, version, arch),
fmt.Sprintf(CrictlDownloadURLTmplCN, version, version, arch),
internal,
}, nil
u := parseURL(DefaultDownloadHost, fmt.Sprintf(CrictlURLPathTmpl, version, version, arch))
internal := checksum.NewChecksum(CrictlID, version, arch)
binary := NewBinary(BinaryParams{
File: file,
ID: CrictlID,
Version: version,
Arch: arch,
URL: u,
Checksum: internal,
})
return &Crictl{binary}, nil
}
// SetZone override Binary's SetZone method.
func (c *Crictl) SetZone(zone string) {
if strings.EqualFold(zone, ZONE) {
c.SetHost(DefaultDownloadHostQingStor)
c.SetPath(fmt.Sprintf(CrictlURLPathTmplCN, c.version, c.version, c.arch))
}
}

View File

@ -19,6 +19,7 @@ package file
import (
"fmt"
"path/filepath"
"strings"
"github.com/kubesphere/kubekey/exp/cluster-api-provider-kubekey/pkg/clients/ssh"
"github.com/kubesphere/kubekey/exp/cluster-api-provider-kubekey/pkg/rootfs"
@ -28,17 +29,22 @@ import (
// Docker info
const (
DockerName = "docker-%s.tgz"
DockerID = "docker"
DockerDownloadURLTmpl = "https://download.docker.com/linux/static/stable/%s/docker-%s.tgz"
DockerDownloadURLTmplCN = "https://mirrors.aliyun.com/docker-ce/linux/static/stable/%s/docker-%s.tgz"
DockerDefaultVersion = "20.10.8"
DockerName = "docker-%s.tgz"
DockerID = "docker"
DockerURL = "https://download.docker.com"
DockerURLPathTmpl = "/linux/static/stable/%s/docker-%s.tgz"
DockerURLCN = "https://mirrors.aliyun.com"
DockerURLPathTmplCN = "/docker-ce/linux/static/stable/%s/docker-%s.tgz"
DockerDefaultVersion = "20.10.8"
)
// NewDocker returns a new Binary for docker.
func NewDocker(sshClient ssh.Interface, rootFs rootfs.Interface, version, arch string) (*Binary, error) {
internal := checksum.NewChecksum(DockerID, version, arch)
// Docker is a Binary for docker.
type Docker struct {
*Binary
}
// NewDocker returns a new Docker.
func NewDocker(sshClient ssh.Interface, rootFs rootfs.Interface, version, arch string) (*Docker, error) {
fileName := fmt.Sprintf(DockerName, version)
file, err := NewFile(Params{
SSHClient: sshClient,
@ -52,13 +58,24 @@ func NewDocker(sshClient ssh.Interface, rootFs rootfs.Interface, version, arch s
return nil, err
}
return &Binary{
file,
DockerID,
version,
arch,
fmt.Sprintf(DockerDownloadURLTmpl, util.ArchAlias(arch), version),
fmt.Sprintf(DockerDownloadURLTmplCN, util.ArchAlias(arch), version),
internal,
}, nil
u := parseURL(DockerURL, fmt.Sprintf(DockerURLPathTmpl, util.ArchAlias(arch), version))
internal := checksum.NewChecksum(DockerID, version, arch)
binary := NewBinary(BinaryParams{
File: file,
ID: DockerID,
Version: version,
Arch: arch,
URL: u,
Checksum: internal,
})
return &Docker{binary}, nil
}
// SetZone override Binary's SetZone method.
func (d *Docker) SetZone(zone string) {
if strings.EqualFold(zone, ZONE) {
d.SetHost(DockerURLCN)
d.SetPath(fmt.Sprintf(DockerURLPathTmplCN, util.ArchAlias(d.arch), d.version))
}
}

View File

@ -19,6 +19,7 @@ package file
import (
"fmt"
"path/filepath"
"strings"
"github.com/kubesphere/kubekey/exp/cluster-api-provider-kubekey/pkg/clients/ssh"
"github.com/kubesphere/kubekey/exp/cluster-api-provider-kubekey/pkg/rootfs"
@ -27,16 +28,19 @@ import (
// Kubeadm info
const (
KubeadmName = "kubeadm"
KubeadmID = "kubeadm"
KubeadmDownloadURLTmpl = "https://storage.googleapis.com/kubernetes-release/release/%s/bin/linux/%s/kubeadm"
KubeadmDownloadURLTmplCN = "https://kubernetes-release.pek3b.qingstor.com/release/%s/bin/linux/%s/kubeadm"
KubeadmName = "kubeadm"
KubeadmID = "kubeadm"
KubeadmURLPathTmpl = "/kubernetes-release/release/%s/bin/linux/%s/kubeadm"
KubeadmURLPathTmplCN = "/release/%s/bin/linux/%s/kubeadm"
)
// NewKubeadm returns a new Binary for kubeadm
func NewKubeadm(sshClient ssh.Interface, rootFs rootfs.Interface, version, arch string) (*Binary, error) {
internal := checksum.NewChecksum(KubeadmID, version, arch)
// Kubeadm is a Binary for kubeadm.
type Kubeadm struct {
*Binary
}
// NewKubeadm returns a new Kubeadm.
func NewKubeadm(sshClient ssh.Interface, rootFs rootfs.Interface, version, arch string) (*Kubeadm, error) {
fileName := KubeadmName
file, err := NewFile(Params{
SSHClient: sshClient,
@ -50,13 +54,24 @@ func NewKubeadm(sshClient ssh.Interface, rootFs rootfs.Interface, version, arch
return nil, err
}
return &Binary{
file,
KubeadmID,
version,
arch,
fmt.Sprintf(KubeadmDownloadURLTmpl, version, arch),
fmt.Sprintf(KubeadmDownloadURLTmplCN, version, arch),
internal,
}, nil
u := parseURL(DefaultDownloadHostGoogle, fmt.Sprintf(KubeadmURLPathTmpl, version, arch))
internal := checksum.NewChecksum(KubeadmID, version, arch)
binary := NewBinary(BinaryParams{
File: file,
ID: KubeadmID,
Version: version,
Arch: arch,
URL: u,
Checksum: internal,
})
return &Kubeadm{binary}, nil
}
// SetZone override Binary's SetZone method.
func (k *Kubeadm) SetZone(zone string) {
if strings.EqualFold(zone, ZONE) {
k.SetHost(DefaultDownloadHostQingStor)
k.SetPath(fmt.Sprintf(KubeadmURLPathTmplCN, k.version, k.arch))
}
}

View File

@ -19,6 +19,7 @@ package file
import (
"fmt"
"path/filepath"
"strings"
"github.com/kubesphere/kubekey/exp/cluster-api-provider-kubekey/pkg/clients/ssh"
"github.com/kubesphere/kubekey/exp/cluster-api-provider-kubekey/pkg/rootfs"
@ -27,17 +28,21 @@ import (
// Kubecni info
const (
KubecniName = "cni-plugins-linux-%s-%s.tgz"
KubecniID = "kubecni"
KubecniDownloadURLTmpl = "https://github.com/containernetworking/plugins/releases/download/%s/cni-plugins-linux-%s-%s.tgz"
KubecniDownloadURLTmplCN = "https://containernetworking.pek3b.qingstor.com/plugins/releases/download/%s/cni-plugins-linux-%s-%s.tgz"
KubecniDefaultVersion = "v0.9.1"
KubecniName = "cni-plugins-linux-%s-%s.tgz"
KubecniID = "kubecni"
KubecniURLPathTmpl = "/containernetworking/plugins/releases/download/%s/cni-plugins-linux-%s-%s.tgz"
KubecniURLCN = "https://containernetworking.pek3b.qingstor.com"
KubecniURLPathTmplCN = "/plugins/releases/download/%s/cni-plugins-linux-%s-%s.tgz"
KubecniDefaultVersion = "v0.9.1"
)
// NewKubecni returns a new Binary for kubecni
func NewKubecni(sshClient ssh.Interface, rootFs rootfs.Interface, version, arch string) (*Binary, error) {
internal := checksum.NewChecksum(KubecniID, version, arch)
// Kubecni is a Binary for kubecni.
type Kubecni struct {
*Binary
}
// NewKubecni returns a new Kubecni.
func NewKubecni(sshClient ssh.Interface, rootFs rootfs.Interface, version, arch string) (*Kubecni, error) {
fileName := fmt.Sprintf(KubecniName, arch, version)
file, err := NewFile(Params{
SSHClient: sshClient,
@ -51,13 +56,24 @@ func NewKubecni(sshClient ssh.Interface, rootFs rootfs.Interface, version, arch
return nil, err
}
return &Binary{
file,
KubecniID,
version,
arch,
fmt.Sprintf(KubecniDownloadURLTmpl, version, arch, version),
fmt.Sprintf(KubecniDownloadURLTmplCN, version, arch, version),
internal,
}, nil
u := parseURL(DefaultDownloadHost, fmt.Sprintf(KubecniURLPathTmpl, version, arch, version))
internal := checksum.NewChecksum(KubecniID, version, arch)
binary := NewBinary(BinaryParams{
File: file,
ID: KubecniID,
Version: version,
Arch: arch,
URL: u,
Checksum: internal,
})
return &Kubecni{binary}, nil
}
// SetZone override Binary's SetZone method.
func (k *Kubecni) SetZone(zone string) {
if strings.EqualFold(zone, ZONE) {
k.SetHost(KubecniURLCN)
k.SetPath(fmt.Sprintf(KubecniURLPathTmplCN, k.version, k.arch, k.version))
}
}

View File

@ -19,6 +19,7 @@ package file
import (
"fmt"
"path/filepath"
"strings"
"github.com/kubesphere/kubekey/exp/cluster-api-provider-kubekey/pkg/clients/ssh"
"github.com/kubesphere/kubekey/exp/cluster-api-provider-kubekey/pkg/rootfs"
@ -27,16 +28,19 @@ import (
// Kubectl info
const (
KubectlName = "kubectl"
KubectlID = "kubectl"
KubectlDownloadURLTmpl = "https://storage.googleapis.com/kubernetes-release/release/%s/bin/linux/%s/kubectl"
KubectlDownloadURLTmplCN = "https://kubernetes-release.pek3b.qingstor.com/release/%s/bin/linux/%s/kubectl"
KubectlName = "kubectl"
KubectlID = "kubectl"
KubectlURLPathTmpl = "/kubernetes-release/release/%s/bin/linux/%s/kubectl"
KubectlURLPathTmplCN = "/release/%s/bin/linux/%s/kubectl"
)
// NewKubectl returns a new Binary for kubectl
func NewKubectl(sshClient ssh.Interface, rootFs rootfs.Interface, version, arch string) (*Binary, error) {
internal := checksum.NewChecksum(KubectlID, version, arch)
// Kubectl is a Binary for kubectl.
type Kubectl struct {
*Binary
}
// NewKubectl returns a new Kubectl.
func NewKubectl(sshClient ssh.Interface, rootFs rootfs.Interface, version, arch string) (*Kubectl, error) {
fileName := KubectlName
file, err := NewFile(Params{
SSHClient: sshClient,
@ -50,13 +54,24 @@ func NewKubectl(sshClient ssh.Interface, rootFs rootfs.Interface, version, arch
return nil, err
}
return &Binary{
file,
KubectlID,
version,
arch,
fmt.Sprintf(KubectlDownloadURLTmpl, version, arch),
fmt.Sprintf(KubectlDownloadURLTmplCN, version, arch),
internal,
}, nil
u := parseURL(DefaultDownloadHostGoogle, fmt.Sprintf(KubectlURLPathTmpl, version, arch))
internal := checksum.NewChecksum(KubectlID, version, arch)
binary := NewBinary(BinaryParams{
File: file,
ID: KubectlID,
Version: version,
Arch: arch,
URL: u,
Checksum: internal,
})
return &Kubectl{binary}, nil
}
// SetZone override Binary's SetZone method.
func (k *Kubectl) SetZone(zone string) {
if strings.EqualFold(zone, ZONE) {
k.SetHost(DefaultDownloadHostQingStor)
k.SetPath(fmt.Sprintf(KubectlURLPathTmplCN, k.version, k.arch))
}
}

View File

@ -19,6 +19,7 @@ package file
import (
"fmt"
"path/filepath"
"strings"
"github.com/kubesphere/kubekey/exp/cluster-api-provider-kubekey/pkg/clients/ssh"
"github.com/kubesphere/kubekey/exp/cluster-api-provider-kubekey/pkg/rootfs"
@ -27,16 +28,19 @@ import (
// kubelet info
const (
KubeletName = "kubelet"
KubeletID = "kubelet"
KubeletDownloadURLTmpl = "https://storage.googleapis.com/kubernetes-release/release/%s/bin/linux/%s/kubelet"
KubeletDownloadURLTmplCN = "https://kubernetes-release.pek3b.qingstor.com/release/%s/bin/linux/%s/kubelet"
KubeletName = "kubelet"
KubeletID = "kubelet"
KubeletURLPathTmpl = "/kubernetes-release/release/%s/bin/linux/%s/kubelet"
KubeletURLPathTmplCN = "/release/%s/bin/linux/%s/kubelet"
)
// NewKubelet returns a new Binary for kubelet
func NewKubelet(sshClient ssh.Interface, rootFs rootfs.Interface, version, arch string) (*Binary, error) {
internal := checksum.NewChecksum(KubeletID, version, arch)
// Kubelet is a Binary for kubelet.
type Kubelet struct {
*Binary
}
// NewKubelet returns a new Kubelet.
func NewKubelet(sshClient ssh.Interface, rootFs rootfs.Interface, version, arch string) (*Kubelet, error) {
fileName := KubeletName
file, err := NewFile(Params{
SSHClient: sshClient,
@ -50,13 +54,24 @@ func NewKubelet(sshClient ssh.Interface, rootFs rootfs.Interface, version, arch
return nil, err
}
return &Binary{
file,
KubeletID,
version,
arch,
fmt.Sprintf(KubeletDownloadURLTmpl, version, arch),
fmt.Sprintf(KubeletDownloadURLTmplCN, version, arch),
internal,
}, nil
u := parseURL(DefaultDownloadHostGoogle, fmt.Sprintf(KubeletURLPathTmpl, version, arch))
internal := checksum.NewChecksum(KubeletID, version, arch)
binary := NewBinary(BinaryParams{
File: file,
ID: KubeletID,
Version: version,
Arch: arch,
URL: u,
Checksum: internal,
})
return &Kubelet{binary}, nil
}
// SetZone override Binary's SetZone method.
func (k *Kubelet) SetZone(zone string) {
if strings.EqualFold(zone, ZONE) {
k.SetHost(DefaultDownloadHostQingStor)
k.SetPath(fmt.Sprintf(KubeletURLPathTmplCN, k.version, k.arch))
}
}

View File

@ -27,17 +27,19 @@ import (
// runc info
const (
RuncName = "runc.%s"
RuncID = "runc"
RuncDownloadURLTmpl = "https://github.com/opencontainers/runc/releases/download/%s/runc.%s"
RuncDownloadURLTmplCN = "https://kubernetes-release.pek3b.qingstor.com/opencontainers/runc/releases/download/%s/runc.%s"
RuncDefaultVersion = "v1.1.1"
RuncName = "runc.%s"
RuncID = "runc"
RuncURLPathTmpl = "/opencontainers/runc/releases/download/%s/runc.%s"
RuncDefaultVersion = "v1.1.1"
)
// NewRunc returns a new Binary for runc
func NewRunc(sshClient ssh.Interface, rootFs rootfs.Interface, version, arch string) (*Binary, error) {
internal := checksum.NewChecksum(RuncID, version, arch)
// Runc is a Binary for runc.
type Runc struct {
*Binary
}
// NewRunc returns a new Runc.
func NewRunc(sshClient ssh.Interface, rootFs rootfs.Interface, version, arch string) (*Runc, error) {
fileName := fmt.Sprintf(RuncName, arch)
file, err := NewFile(Params{
SSHClient: sshClient,
@ -51,13 +53,16 @@ func NewRunc(sshClient ssh.Interface, rootFs rootfs.Interface, version, arch str
return nil, err
}
return &Binary{
file,
RuncID,
version,
arch,
fmt.Sprintf(RuncDownloadURLTmpl, version, arch),
fmt.Sprintf(RuncDownloadURLTmplCN, version, arch),
internal,
}, nil
u := parseURL(DefaultDownloadHost, fmt.Sprintf(RuncURLPathTmpl, version, arch))
internal := checksum.NewChecksum(RuncID, version, arch)
binary := NewBinary(BinaryParams{
File: file,
ID: RuncID,
Version: version,
Arch: arch,
URL: u,
Checksum: internal,
})
return &Runc{binary}, nil
}

View File

@ -18,9 +18,11 @@
package operation
import (
"net/url"
"time"
"github.com/kubesphere/kubekey/exp/cluster-api-provider-kubekey/pkg/service/operation/file"
"github.com/kubesphere/kubekey/exp/cluster-api-provider-kubekey/pkg/service/operation/file/checksum"
)
// File interface defines the operations for normal file which needed to be copied to remote.
@ -42,8 +44,12 @@ type Binary interface {
ID() string
Arch() string
Version() string
URL() string
URL() *url.URL
SetURL(url string)
SetHost(host string)
SetPath(path string)
SetZone(zone string)
SetChecksum(checksum checksum.Interface)
Get(timeout time.Duration) error
CompareChecksum() error
}

View File

@ -5,7 +5,8 @@ kind: KKCluster
metadata:
name: '${CLUSTER_NAME}'
spec:
zone: '${KKZONE}'
component:
zone: '${KKZONE}'
nodes:
auth:
user: '${USER_NAME}'