-
Notifications
You must be signed in to change notification settings - Fork 4
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
3036c0f
commit 62b617c
Showing
39 changed files
with
2,705 additions
and
43 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,57 @@ | ||
/* | ||
Copyright 2023. | ||
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 v1alpha1 | ||
|
||
import ( | ||
corev1 "k8s.io/api/core/v1" | ||
) | ||
|
||
type Phase string | ||
|
||
// xx. | ||
const ( | ||
PhaseInitializing = Phase("Initializing") | ||
PhaseProcessing = Phase("Processing") | ||
PhaseSucceeded = Phase("Succeeded") | ||
PhaseFailed = Phase("Failed") | ||
) | ||
|
||
type Ansible struct { | ||
// RemotePlaybook 在远端的 playbook,单个 .tar.gz 压缩包,内容可以是单个 yaml 文件,也可以符合 ansible 要求的目录 | ||
RemotePlaybook *RemotePlaybook `json:"remotePlaybook,omitempty"` | ||
// LocalPlaybook 本地的 playbook,单个 yaml 文件, secret 引用或者 yaml 字符串 | ||
LocalPlaybook *YAMLText `json:"localPlaybook,omitempty"` | ||
// Values 执行 playbook 的参数,yaml 格式,可以是 secret 引用或者 yaml 字符串 | ||
Values *YAMLText `json:"values,omitempty"` | ||
} | ||
|
||
type RemotePlaybook struct { | ||
// URL playbook 在远端的地址,支持 https | ||
URL string `json:"url"` | ||
// Name 要执行的 playbook 文件名,相对于压缩包顶层的位置 | ||
Name string `json:"name"` | ||
// MD5sum 压缩包的 MD5,填写了会进行校验,已经下载过的 playbook 校验通过后跳过重复下载 | ||
MD5sum string `json:"md5sum,omitempty"` | ||
} | ||
|
||
type YAMLText struct { | ||
// SecretRef specifies the secret which stores yaml text. | ||
SecretRef *corev1.SecretReference `json:"secretRef,omitempty"` | ||
// Content is the inline yaml text. | ||
//+kubebuilder:validation:Format=yaml | ||
Content string `json:"content,omitempty"` | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
/* | ||
Copyright 2023 | ||
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. | ||
*/ | ||
|
||
// +k8s:deepcopy-gen=package,register | ||
// +k8s:defaulter-gen=TypeMeta | ||
// +groupName=kubesmart.smtx.io | ||
|
||
package v1alpha1 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,36 @@ | ||
/* | ||
Copyright 2023. | ||
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 v1alpha1 contains API Schema definitions for the kubesmart v1alpha1 API group | ||
// +kubebuilder:object:generate=true | ||
// +groupName=kubesmart.smtx.io | ||
package v1alpha1 | ||
|
||
import ( | ||
"k8s.io/apimachinery/pkg/runtime/schema" | ||
"sigs.k8s.io/controller-runtime/pkg/scheme" | ||
) | ||
|
||
var ( | ||
// GroupVersion is group version used to register these objects. | ||
GroupVersion = schema.GroupVersion{Group: "kubesmart.smtx.io", Version: "v1alpha1"} | ||
|
||
// SchemeBuilder is used to add go types to the GroupVersionKind scheme. | ||
SchemeBuilder = &scheme.Builder{GroupVersion: GroupVersion} | ||
|
||
// AddToScheme adds the types in this group-version to the given scheme. | ||
AddToScheme = SchemeBuilder.AddToScheme | ||
) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,109 @@ | ||
/* | ||
Copyright 2023. | ||
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 v1alpha1 | ||
|
||
import ( | ||
"crypto/sha256" | ||
"encoding/hex" | ||
"encoding/json" | ||
|
||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" | ||
) | ||
|
||
const ( | ||
// HostConfigFinalizer is set on PrepareForCreate callback. | ||
HostConfigFinalizer = "hostconfig.kubesmart.smtx.io" | ||
|
||
// HostConfigReRunAnnotation 表示重新执行. | ||
HostConfigReRunAnnotation = "hostconfig.kubesmart.smtx.io/re-run" | ||
|
||
// HostConfigConfigHashAnnotation 记录 spec.config 哈希值的 annotation,当实际计算的哈希值与记录的不同时,代表配置有变更,需要重新执行. | ||
HostConfigConfigHashAnnotation = "hostconfig.kubesmart.smtx.io/config-hash" | ||
|
||
// HostConfigNodeNameLabel 表示属于哪个节点,如果长度长度超过 63,会用哈希值代替. | ||
HostConfigNodeNameLabel = "hostconfig.kubesmart.smtx.io/node-name" | ||
) | ||
|
||
type HostConfigSpec struct { | ||
NodeName string `json:"nodeName"` | ||
Config Config `json:"config"` | ||
} | ||
|
||
type Config struct { | ||
// Ansible 通过 ansible playbook 完成配置 | ||
Ansible *Ansible `json:"ansible,omitempty"` | ||
// Timeout 执行一次配置的超时时间 | ||
Timeout metav1.Duration `json:"timeout,omitempty"` | ||
} | ||
|
||
type HostConfigStatus struct { | ||
// Phase 当前状态 | ||
Phase Phase `json:"phase"` | ||
FailureReason string `json:"failureReason,omitempty"` | ||
FailureMessage string `json:"failureMessage,omitempty"` | ||
// LastExecutionTime 最后执行的时间戳 | ||
LastExecutionTime *metav1.Time `json:"lastExecutionTime,omitempty"` | ||
} | ||
|
||
// +kubebuilder:object:root=true | ||
// +kubebuilder:resource:path=hostconfigs,scope=Namespaced,categories=kubesmart,shortName=hc | ||
// +kubebuilder:storageversion | ||
// +kubebuilder:subresource:status | ||
// +kubebuilder:printcolumn:name="Phase",type="string",JSONPath=".status.phase",description="the current phase of HostConfig" | ||
// +kubebuilder:printcolumn:name="LastExecutionTime",type="string",JSONPath=".status.lastExecutionTime",description="the last execution time" | ||
// +kubebuilder:printcolumn:name="Age",type="date",JSONPath=".metadata.creationTimestamp",description="Time duration since creation of HostConfig" | ||
|
||
// HostConfig is the Schema for the HostConfig API. | ||
type HostConfig struct { | ||
metav1.TypeMeta `json:",inline"` | ||
metav1.ObjectMeta `json:"metadata,omitempty"` | ||
|
||
Spec HostConfigSpec `json:"spec,omitempty"` | ||
Status HostConfigStatus `json:"status,omitempty"` | ||
} | ||
|
||
//+kubebuilder:object:root=true | ||
|
||
// HostConfigList contains a list of HostConfig. | ||
type HostConfigList struct { | ||
metav1.TypeMeta `json:",inline"` | ||
metav1.ListMeta `json:"metadata,omitempty"` | ||
Items []HostConfig `json:"items"` | ||
} | ||
|
||
func init() { | ||
SchemeBuilder.Register(&HostConfig{}, &HostConfigList{}) | ||
} | ||
|
||
// IsConfigStable returns true if the hash of current config is equal to the hash in annotation. | ||
func (in *HostConfig) IsConfigStable() bool { | ||
annotationHash := GetAnnotation(in, HostConfigConfigHashAnnotation) | ||
currentHash := CalculateHash(in.Spec.Config) | ||
return annotationHash == currentHash | ||
} | ||
|
||
func GetAnnotation(obj metav1.Object, key string) string { | ||
annotations := obj.GetAnnotations() | ||
value, _ := annotations[key] //nolint:gosimple | ||
return value | ||
} | ||
|
||
func CalculateHash(data interface{}) string { | ||
b, _ := json.Marshal(data) //nolint:errchkjson | ||
hashDate := sha256.Sum256(b) | ||
return hex.EncodeToString(hashDate[:]) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,83 @@ | ||
/* | ||
Copyright 2023. | ||
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 v1alpha1 | ||
|
||
import ( | ||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" | ||
) | ||
|
||
const ( | ||
// HostOperationJobFinalizer is set on PrepareForCreate callback. | ||
HostOperationJobFinalizer = "hostoperationjob.kubesmart.smtx.io" | ||
|
||
// HostOperationJobReRunAnnotation 表示重新执行. | ||
HostOperationJobReRunAnnotation = "hostoperationjob.kubesmart.smtx.io/re-run" | ||
|
||
// HostOperationJobNodeNameLabel 表示属于哪个节点,如果长度长度超过 63,会用哈希值代替。 | ||
HostOperationJobNodeNameLabel = "hostoperationjob.kubesmart.smtx.io/node-name" | ||
) | ||
|
||
type HostOperationJobSpec struct { | ||
NodeName string `json:"nodeName"` | ||
Operation Operation `json:"operation"` | ||
} | ||
|
||
type Operation struct { | ||
// Ansible 通过 ansible playbook 完成操作 | ||
Ansible *Ansible `json:"ansible,omitempty"` | ||
// Timeout 执行一次操作的超时时间 | ||
Timeout metav1.Duration `json:"timeout,omitempty"` | ||
} | ||
|
||
type HostOperationJobStatus struct { | ||
// Phase 当前阶段 | ||
Phase Phase `json:"phase"` | ||
FailureReason string `json:"failureReason,omitempty"` | ||
FailureMessage string `json:"failureMessage,omitempty"` | ||
// LastExecutionTime 最后执行的时间戳 | ||
LastExecutionTime *metav1.Time `json:"lastExecutionTime,omitempty"` | ||
} | ||
|
||
// +kubebuilder:object:root=true | ||
// +kubebuilder:resource:path=hostoperationjobs,scope=Namespaced,categories=kubesmart,shortName=hoj | ||
// +kubebuilder:storageversion | ||
// +kubebuilder:subresource:status | ||
// +kubebuilder:printcolumn:name="Phase",type="string",JSONPath=".status.phase",description="the current phase of HostOperationJob" | ||
// +kubebuilder:printcolumn:name="LastExecutionTime",type="string",JSONPath=".status.lastExecutionTime",description="the last execution time" | ||
// +kubebuilder:printcolumn:name="Age",type="date",JSONPath=".metadata.creationTimestamp",description="Time duration since creation of HostOperationJob" | ||
|
||
// HostOperationJob is the Schema for the HostOperationJob API. | ||
type HostOperationJob struct { | ||
metav1.TypeMeta `json:",inline"` | ||
metav1.ObjectMeta `json:"metadata,omitempty"` | ||
|
||
Spec HostOperationJobSpec `json:"spec,omitempty"` | ||
Status HostOperationJobStatus `json:"status,omitempty"` | ||
} | ||
|
||
//+kubebuilder:object:root=true | ||
|
||
// HostOperationJobList contains a list of HostOperationJob. | ||
type HostOperationJobList struct { | ||
metav1.TypeMeta `json:",inline"` | ||
metav1.ListMeta `json:"metadata,omitempty"` | ||
Items []HostOperationJob `json:"items"` | ||
} | ||
|
||
func init() { | ||
SchemeBuilder.Register(&HostOperationJob{}, &HostOperationJobList{}) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,72 @@ | ||
/* | ||
Copyright 2023. | ||
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 v1alpha1 | ||
|
||
import ( | ||
"context" | ||
|
||
corev1 "k8s.io/api/core/v1" | ||
apierrors "k8s.io/apimachinery/pkg/api/errors" | ||
apitypes "k8s.io/apimachinery/pkg/types" | ||
"sigs.k8s.io/controller-runtime/pkg/client" | ||
) | ||
|
||
const ( | ||
valuesYamlKey = "values.yaml" | ||
) | ||
|
||
func (in *YAMLText) IsEmpty() bool { | ||
if in == nil { | ||
return true | ||
} | ||
if in.SecretRef != nil && in.SecretRef.Name == "" && in.Content == "" { | ||
return true | ||
} | ||
return in.SecretRef == nil && in.Content == "" | ||
} | ||
|
||
func (in *YAMLText) getAddonSecretNamespacedName(defaultNamespace string) (apitypes.NamespacedName, bool) { | ||
if in.SecretRef != nil && in.SecretRef.Name != "" { | ||
result := apitypes.NamespacedName{ | ||
Namespace: in.SecretRef.Namespace, | ||
Name: in.SecretRef.Name, | ||
} | ||
if result.Namespace == "" { | ||
result.Namespace = defaultNamespace | ||
} | ||
return result, true | ||
} | ||
return apitypes.NamespacedName{}, false | ||
} | ||
|
||
// GetValuesYaml 优先使用secret,如果不存在尝试使用yaml inline. | ||
func (in *YAMLText) GetValuesYaml(ctx context.Context, c client.Client, defaultNamespace string) (string, error) { | ||
if in.IsEmpty() { | ||
return "", nil | ||
} | ||
secretKey, ok := in.getAddonSecretNamespacedName(defaultNamespace) | ||
if ok { | ||
var err error | ||
secret := &corev1.Secret{} | ||
if err = c.Get(ctx, secretKey, secret); err != nil && !apierrors.IsNotFound(err) { | ||
return "", err | ||
} | ||
return string(secret.Data[valuesYamlKey]), nil | ||
} else { | ||
return in.Content, nil | ||
} | ||
} |
Oops, something went wrong.