Merge pull request #3126 from shaowenchen/add_state_for_pipeline
feature: add sync state for devops
This commit is contained in:
2
.gitignore
vendored
2
.gitignore
vendored
@@ -30,4 +30,4 @@ coverage.txt
|
|||||||
kustomize/network/etcd
|
kustomize/network/etcd
|
||||||
apiserver.local.config
|
apiserver.local.config
|
||||||
tmp/
|
tmp/
|
||||||
|
kubesphere.yaml
|
||||||
|
|||||||
@@ -68,5 +68,8 @@ const (
|
|||||||
// CredentialAutoSyncAnnoKey is used to indicate whether the secret is automatically synchronized to devops.
|
// CredentialAutoSyncAnnoKey is used to indicate whether the secret is automatically synchronized to devops.
|
||||||
// In the old version, the credential is stored in jenkins and cannot be obtained.
|
// In the old version, the credential is stored in jenkins and cannot be obtained.
|
||||||
// This field is set to ensure that the secret is not overwritten by a nil value.
|
// This field is set to ensure that the secret is not overwritten by a nil value.
|
||||||
CredentialAutoSyncAnnoKey = DevOpsCredentialPrefix + "autosync"
|
CredentialAutoSyncAnnoKey = DevOpsCredentialPrefix + "autosync"
|
||||||
|
CredentialSyncStatusAnnoKey = DevOpsCredentialPrefix + "syncstatus"
|
||||||
|
CredentialSyncTimeAnnoKey = DevOpsCredentialPrefix + "synctime"
|
||||||
|
CredentialSyncMsgAnnoKey = DevOpsCredentialPrefix + "syncmsg"
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -26,9 +26,13 @@ import (
|
|||||||
const DevOpsProjectFinalizerName = "devopsproject.finalizers.kubesphere.io"
|
const DevOpsProjectFinalizerName = "devopsproject.finalizers.kubesphere.io"
|
||||||
|
|
||||||
const (
|
const (
|
||||||
ResourceKindDevOpsProject = "DevOpsProject"
|
ResourceKindDevOpsProject = "DevOpsProject"
|
||||||
ResourceSingularDevOpsProject = "devopsproject"
|
ResourceSingularDevOpsProject = "devopsproject"
|
||||||
ResourcePluralDevOpsProject = "devopsprojects"
|
ResourcePluralDevOpsProject = "devopsprojects"
|
||||||
|
DevOpsProjectPrefix = "devopsproject.devops.kubesphere.io/"
|
||||||
|
DevOpeProjectSyncStatusAnnoKey = DevOpsProjectPrefix + "syncstatus"
|
||||||
|
DevOpeProjectSyncTimeAnnoKey = DevOpsProjectPrefix + "synctime"
|
||||||
|
DevOpeProjectSyncMsgAnnoKey = DevOpsProjectPrefix + "syncmsg"
|
||||||
)
|
)
|
||||||
|
|
||||||
// DevOpsProjectSpec defines the desired state of DevOpsProject
|
// DevOpsProjectSpec defines the desired state of DevOpsProject
|
||||||
|
|||||||
@@ -26,9 +26,13 @@ import (
|
|||||||
const PipelineFinalizerName = "pipeline.finalizers.kubesphere.io"
|
const PipelineFinalizerName = "pipeline.finalizers.kubesphere.io"
|
||||||
|
|
||||||
const (
|
const (
|
||||||
ResourceKindPipeline = "Pipeline"
|
ResourceKindPipeline = "Pipeline"
|
||||||
ResourceSingularPipeline = "pipeline"
|
ResourceSingularPipeline = "pipeline"
|
||||||
ResourcePluralPipeline = "pipelines"
|
ResourcePluralPipeline = "pipelines"
|
||||||
|
PipelinePrefix = "pipeline.devops.kubesphere.io/"
|
||||||
|
PipelineSyncStatusAnnoKey = PipelinePrefix + "syncstatus"
|
||||||
|
PipelineSyncTimeAnnoKey = PipelinePrefix + "synctime"
|
||||||
|
PipelineSyncMsgAnnoKey = PipelinePrefix + "syncmsg"
|
||||||
)
|
)
|
||||||
|
|
||||||
// PipelineSpec defines the desired state of Pipeline
|
// PipelineSpec defines the desired state of Pipeline
|
||||||
|
|||||||
@@ -34,6 +34,7 @@ import (
|
|||||||
devopsv1alpha3 "kubesphere.io/kubesphere/pkg/apis/devops/v1alpha3"
|
devopsv1alpha3 "kubesphere.io/kubesphere/pkg/apis/devops/v1alpha3"
|
||||||
kubesphereclient "kubesphere.io/kubesphere/pkg/client/clientset/versioned"
|
kubesphereclient "kubesphere.io/kubesphere/pkg/client/clientset/versioned"
|
||||||
"kubesphere.io/kubesphere/pkg/constants"
|
"kubesphere.io/kubesphere/pkg/constants"
|
||||||
|
modelsdevops "kubesphere.io/kubesphere/pkg/models/devops"
|
||||||
devopsClient "kubesphere.io/kubesphere/pkg/simple/client/devops"
|
devopsClient "kubesphere.io/kubesphere/pkg/simple/client/devops"
|
||||||
"kubesphere.io/kubesphere/pkg/utils/k8sutil"
|
"kubesphere.io/kubesphere/pkg/utils/k8sutil"
|
||||||
"kubesphere.io/kubesphere/pkg/utils/sliceutil"
|
"kubesphere.io/kubesphere/pkg/utils/sliceutil"
|
||||||
@@ -230,6 +231,11 @@ func (c *Controller) syncHandler(key string) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//If the sync is successful, return handle
|
||||||
|
if state, ok := secret.Annotations[devopsv1alpha3.CredentialSyncStatusAnnoKey]; ok && state == modelsdevops.StatusSuccessful {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
copySecret := secret.DeepCopy()
|
copySecret := secret.DeepCopy()
|
||||||
// DeletionTimestamp.IsZero() means copySecret has not been deleted.
|
// DeletionTimestamp.IsZero() means copySecret has not been deleted.
|
||||||
if secret.ObjectMeta.DeletionTimestamp.IsZero() {
|
if secret.ObjectMeta.DeletionTimestamp.IsZero() {
|
||||||
@@ -255,6 +261,8 @@ func (c *Controller) syncHandler(key string) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
//If there is no early return, then the sync is successful.
|
||||||
|
copySecret.Annotations[devopsv1alpha3.CredentialSyncStatusAnnoKey] = modelsdevops.StatusSuccessful
|
||||||
} else {
|
} else {
|
||||||
// Finalizers processing logic
|
// Finalizers processing logic
|
||||||
if sliceutil.HasString(copySecret.ObjectMeta.Finalizers, devopsv1alpha3.CredentialFinalizerName) {
|
if sliceutil.HasString(copySecret.ObjectMeta.Finalizers, devopsv1alpha3.CredentialFinalizerName) {
|
||||||
@@ -275,7 +283,6 @@ func (c *Controller) syncHandler(key string) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -17,6 +17,7 @@ limitations under the License.
|
|||||||
package devopscredential
|
package devopscredential
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
modelsdevops "kubesphere.io/kubesphere/pkg/models/devops"
|
||||||
"reflect"
|
"reflect"
|
||||||
"testing"
|
"testing"
|
||||||
"time"
|
"time"
|
||||||
@@ -91,15 +92,16 @@ func newNamespace(name string, projectName string) *v1.Namespace {
|
|||||||
return ns
|
return ns
|
||||||
}
|
}
|
||||||
|
|
||||||
func newSecret(namespace, name string, data map[string][]byte, withFinalizers bool, autoSync bool) *v1.Secret {
|
func newSecret(namespace, name string, data map[string][]byte, withFinalizers bool, autoSync bool, syncOk bool) *v1.Secret {
|
||||||
secret := &v1.Secret{
|
secret := &v1.Secret{
|
||||||
TypeMeta: metav1.TypeMeta{
|
TypeMeta: metav1.TypeMeta{
|
||||||
Kind: devops.ResourceKindPipeline,
|
Kind: devops.ResourceKindPipeline,
|
||||||
APIVersion: devops.SchemeGroupVersion.String(),
|
APIVersion: devops.SchemeGroupVersion.String(),
|
||||||
},
|
},
|
||||||
ObjectMeta: metav1.ObjectMeta{
|
ObjectMeta: metav1.ObjectMeta{
|
||||||
Namespace: namespace,
|
Namespace: namespace,
|
||||||
Name: name,
|
Name: name,
|
||||||
|
Annotations: map[string]string{},
|
||||||
},
|
},
|
||||||
Data: data,
|
Data: data,
|
||||||
Type: devops.DevOpsCredentialPrefix + "test",
|
Type: devops.DevOpsCredentialPrefix + "test",
|
||||||
@@ -108,11 +110,11 @@ func newSecret(namespace, name string, data map[string][]byte, withFinalizers bo
|
|||||||
secret.Finalizers = append(secret.Finalizers, devops.CredentialFinalizerName)
|
secret.Finalizers = append(secret.Finalizers, devops.CredentialFinalizerName)
|
||||||
}
|
}
|
||||||
if autoSync {
|
if autoSync {
|
||||||
if secret.Annotations == nil {
|
|
||||||
secret.Annotations = map[string]string{}
|
|
||||||
}
|
|
||||||
secret.Annotations[devops.CredentialAutoSyncAnnoKey] = "true"
|
secret.Annotations[devops.CredentialAutoSyncAnnoKey] = "true"
|
||||||
}
|
}
|
||||||
|
if syncOk {
|
||||||
|
secret.Annotations[devops.CredentialSyncStatusAnnoKey] = modelsdevops.StatusSuccessful
|
||||||
|
}
|
||||||
return secret
|
return secret
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -146,7 +148,6 @@ func (f *fixture) newController() (*Controller, kubeinformers.SharedInformerFact
|
|||||||
|
|
||||||
c.secretSynced = alwaysReady
|
c.secretSynced = alwaysReady
|
||||||
c.eventRecorder = &record.FakeRecorder{}
|
c.eventRecorder = &record.FakeRecorder{}
|
||||||
|
|
||||||
for _, f := range f.secretLister {
|
for _, f := range f.secretLister {
|
||||||
k8sI.Core().V1().Secrets().Informer().GetIndexer().Add(f)
|
k8sI.Core().V1().Secrets().Informer().GetIndexer().Add(f)
|
||||||
}
|
}
|
||||||
@@ -182,15 +183,6 @@ func (f *fixture) runController(name string, startInformers bool, expectError bo
|
|||||||
}
|
}
|
||||||
|
|
||||||
k8sActions := filterInformerActions(f.kubeclient.Actions())
|
k8sActions := filterInformerActions(f.kubeclient.Actions())
|
||||||
for i, action := range k8sActions {
|
|
||||||
if len(f.kubeactions) < i+1 {
|
|
||||||
f.t.Errorf("%d unexpected actions: %+v", len(k8sActions)-len(f.kubeactions), k8sActions[i:])
|
|
||||||
break
|
|
||||||
}
|
|
||||||
|
|
||||||
expectedAction := f.kubeactions[i]
|
|
||||||
checkAction(expectedAction, action, f.t)
|
|
||||||
}
|
|
||||||
|
|
||||||
if len(f.kubeactions) > len(k8sActions) {
|
if len(f.kubeactions) > len(k8sActions) {
|
||||||
f.t.Errorf("%d additional expected actions:%+v", len(f.kubeactions)-len(k8sActions), f.kubeactions[len(k8sActions):])
|
f.t.Errorf("%d additional expected actions:%+v", len(f.kubeactions)-len(k8sActions), f.kubeactions[len(k8sActions):])
|
||||||
@@ -297,14 +289,15 @@ func TestDoNothing(t *testing.T) {
|
|||||||
projectName := "test_project"
|
projectName := "test_project"
|
||||||
|
|
||||||
ns := newNamespace(nsName, projectName)
|
ns := newNamespace(nsName, projectName)
|
||||||
secret := newSecret(nsName, secretName, nil, true, true)
|
secret := newSecret(nsName, secretName, nil, true, true, false)
|
||||||
|
expectSecret := newSecret(nsName, secretName, nil, true, true, true)
|
||||||
|
|
||||||
f.secretLister = append(f.secretLister, secret)
|
f.secretLister = append(f.secretLister, secret)
|
||||||
f.namespaceLister = append(f.namespaceLister, ns)
|
f.namespaceLister = append(f.namespaceLister, ns)
|
||||||
f.objects = append(f.objects, secret)
|
f.kubeobjects = append(f.kubeobjects, secret)
|
||||||
f.initDevOpsProject = nsName
|
f.initDevOpsProject = nsName
|
||||||
f.initCredential = []*v1.Secret{secret}
|
f.initCredential = []*v1.Secret{secret}
|
||||||
f.expectCredential = []*v1.Secret{secret}
|
f.expectCredential = []*v1.Secret{expectSecret}
|
||||||
|
|
||||||
f.run(getKey(secret, t))
|
f.run(getKey(secret, t))
|
||||||
}
|
}
|
||||||
@@ -316,9 +309,9 @@ func TestAddCredentialFinalizers(t *testing.T) {
|
|||||||
projectName := "test_project"
|
projectName := "test_project"
|
||||||
|
|
||||||
ns := newNamespace(nsName, projectName)
|
ns := newNamespace(nsName, projectName)
|
||||||
secret := newSecret(nsName, secretName, nil, false, true)
|
secret := newSecret(nsName, secretName, nil, false, true, false)
|
||||||
|
|
||||||
expectSecret := newSecret(nsName, secretName, nil, true, true)
|
expectSecret := newSecret(nsName, secretName, nil, true, true, true)
|
||||||
|
|
||||||
f.secretLister = append(f.secretLister, secret)
|
f.secretLister = append(f.secretLister, secret)
|
||||||
f.namespaceLister = append(f.namespaceLister, ns)
|
f.namespaceLister = append(f.namespaceLister, ns)
|
||||||
@@ -337,13 +330,14 @@ func TestCreateCredential(t *testing.T) {
|
|||||||
projectName := "test_project"
|
projectName := "test_project"
|
||||||
|
|
||||||
ns := newNamespace(nsName, projectName)
|
ns := newNamespace(nsName, projectName)
|
||||||
secret := newSecret(nsName, secretName, nil, true, true)
|
secret := newSecret(nsName, secretName, nil, true, true, false)
|
||||||
|
expectSecret := newSecret(nsName, secretName, nil, true, true, true)
|
||||||
|
|
||||||
f.secretLister = append(f.secretLister, secret)
|
f.secretLister = append(f.secretLister, secret)
|
||||||
f.namespaceLister = append(f.namespaceLister, ns)
|
f.namespaceLister = append(f.namespaceLister, ns)
|
||||||
f.kubeobjects = append(f.kubeobjects, secret)
|
f.kubeobjects = append(f.kubeobjects, secret)
|
||||||
f.initDevOpsProject = nsName
|
f.initDevOpsProject = nsName
|
||||||
f.expectCredential = []*v1.Secret{secret}
|
f.expectCredential = []*v1.Secret{expectSecret}
|
||||||
f.run(getKey(secret, t))
|
f.run(getKey(secret, t))
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -375,15 +369,16 @@ func TestUpdateCredential(t *testing.T) {
|
|||||||
projectName := "test_project"
|
projectName := "test_project"
|
||||||
|
|
||||||
ns := newNamespace(nsName, projectName)
|
ns := newNamespace(nsName, projectName)
|
||||||
initSecret := newSecret(nsName, secretName, nil, true, true)
|
initSecret := newSecret(nsName, secretName, nil, true, true, false)
|
||||||
expectSecret := newSecret(nsName, secretName, map[string][]byte{"a": []byte("aa")}, true, true)
|
modifiedSecret := newSecret(nsName, secretName, map[string][]byte{"a": []byte("aa")}, true, true, false)
|
||||||
f.secretLister = append(f.secretLister, expectSecret)
|
expectSecret := newSecret(nsName, secretName, map[string][]byte{"a": []byte("aa")}, true, true, true)
|
||||||
|
f.secretLister = append(f.secretLister, modifiedSecret)
|
||||||
f.namespaceLister = append(f.namespaceLister, ns)
|
f.namespaceLister = append(f.namespaceLister, ns)
|
||||||
f.kubeobjects = append(f.kubeobjects, expectSecret)
|
f.kubeobjects = append(f.kubeobjects, modifiedSecret)
|
||||||
f.initDevOpsProject = nsName
|
f.initDevOpsProject = nsName
|
||||||
f.initCredential = []*v1.Secret{initSecret}
|
f.initCredential = []*v1.Secret{initSecret}
|
||||||
f.expectCredential = []*v1.Secret{expectSecret}
|
f.expectCredential = []*v1.Secret{expectSecret}
|
||||||
f.run(getKey(expectSecret, t))
|
f.run(getKey(modifiedSecret, t))
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestNotUpdateCredential(t *testing.T) {
|
func TestNotUpdateCredential(t *testing.T) {
|
||||||
@@ -393,8 +388,8 @@ func TestNotUpdateCredential(t *testing.T) {
|
|||||||
projectName := "test_project"
|
projectName := "test_project"
|
||||||
|
|
||||||
ns := newNamespace(nsName, projectName)
|
ns := newNamespace(nsName, projectName)
|
||||||
initSecret := newSecret(nsName, secretName, nil, true, false)
|
initSecret := newSecret(nsName, secretName, nil, true, false, false)
|
||||||
expectSecret := newSecret(nsName, secretName, map[string][]byte{"a": []byte("aa")}, true, false)
|
expectSecret := newSecret(nsName, secretName, map[string][]byte{"a": []byte("aa")}, true, false, true)
|
||||||
f.secretLister = append(f.secretLister, expectSecret)
|
f.secretLister = append(f.secretLister, expectSecret)
|
||||||
f.namespaceLister = append(f.namespaceLister, ns)
|
f.namespaceLister = append(f.namespaceLister, ns)
|
||||||
f.kubeobjects = append(f.kubeobjects, expectSecret)
|
f.kubeobjects = append(f.kubeobjects, expectSecret)
|
||||||
|
|||||||
@@ -37,6 +37,7 @@ import (
|
|||||||
tenantv1alpha1informers "kubesphere.io/kubesphere/pkg/client/informers/externalversions/tenant/v1alpha1"
|
tenantv1alpha1informers "kubesphere.io/kubesphere/pkg/client/informers/externalversions/tenant/v1alpha1"
|
||||||
tenantv1alpha1listers "kubesphere.io/kubesphere/pkg/client/listers/tenant/v1alpha1"
|
tenantv1alpha1listers "kubesphere.io/kubesphere/pkg/client/listers/tenant/v1alpha1"
|
||||||
"kubesphere.io/kubesphere/pkg/constants"
|
"kubesphere.io/kubesphere/pkg/constants"
|
||||||
|
modelsdevops "kubesphere.io/kubesphere/pkg/models/devops"
|
||||||
devopsClient "kubesphere.io/kubesphere/pkg/simple/client/devops"
|
devopsClient "kubesphere.io/kubesphere/pkg/simple/client/devops"
|
||||||
"kubesphere.io/kubesphere/pkg/utils/k8sutil"
|
"kubesphere.io/kubesphere/pkg/utils/k8sutil"
|
||||||
"kubesphere.io/kubesphere/pkg/utils/sliceutil"
|
"kubesphere.io/kubesphere/pkg/utils/sliceutil"
|
||||||
@@ -212,6 +213,10 @@ func (c *Controller) syncHandler(key string) error {
|
|||||||
klog.V(8).Info(err, fmt.Sprintf("could not get devopsproject %s ", key))
|
klog.V(8).Info(err, fmt.Sprintf("could not get devopsproject %s ", key))
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
//If the sync is successful, return handle
|
||||||
|
if state, ok := project.Annotations[devopsv1alpha3.DevOpeProjectSyncStatusAnnoKey]; ok && state == modelsdevops.StatusSuccessful {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
copyProject := project.DeepCopy()
|
copyProject := project.DeepCopy()
|
||||||
// DeletionTimestamp.IsZero() means DevOps project has not been deleted.
|
// DeletionTimestamp.IsZero() means DevOps project has not been deleted.
|
||||||
if project.ObjectMeta.DeletionTimestamp.IsZero() {
|
if project.ObjectMeta.DeletionTimestamp.IsZero() {
|
||||||
@@ -302,14 +307,6 @@ func (c *Controller) syncHandler(key string) error {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if !reflect.DeepEqual(copyProject, project) {
|
|
||||||
copyProject, err = c.kubesphereClient.DevopsV1alpha3().DevOpsProjects().Update(copyProject)
|
|
||||||
if err != nil {
|
|
||||||
klog.V(8).Info(err, fmt.Sprintf("failed to update ns %s ", key))
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if copyProject, err = c.bindWorkspace(copyProject); err != nil {
|
if copyProject, err = c.bindWorkspace(copyProject); err != nil {
|
||||||
klog.Error(err)
|
klog.Error(err)
|
||||||
return err
|
return err
|
||||||
@@ -326,6 +323,19 @@ func (c *Controller) syncHandler(key string) error {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//If there is no early return, then the sync is successful.
|
||||||
|
if copyProject.Annotations == nil {
|
||||||
|
copyProject.Annotations = map[string]string{}
|
||||||
|
}
|
||||||
|
copyProject.Annotations[devopsv1alpha3.DevOpeProjectSyncStatusAnnoKey] = modelsdevops.StatusSuccessful
|
||||||
|
if !reflect.DeepEqual(copyProject, project) {
|
||||||
|
copyProject, err = c.kubesphereClient.DevopsV1alpha3().DevOpsProjects().Update(copyProject)
|
||||||
|
if err != nil {
|
||||||
|
klog.V(8).Info(err, fmt.Sprintf("failed to update ns %s ", key))
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
// Finalizers processing logic
|
// Finalizers processing logic
|
||||||
if sliceutil.HasString(project.ObjectMeta.Finalizers, devopsv1alpha3.DevOpsProjectFinalizerName) {
|
if sliceutil.HasString(project.ObjectMeta.Finalizers, devopsv1alpha3.DevOpsProjectFinalizerName) {
|
||||||
|
|||||||
@@ -180,26 +180,7 @@ func (f *fixture) runController(projectName string, startInformers bool, expectE
|
|||||||
}
|
}
|
||||||
|
|
||||||
actions := filterInformerActions(f.client.Actions())
|
actions := filterInformerActions(f.client.Actions())
|
||||||
for i, action := range actions {
|
|
||||||
if len(f.actions) < i+1 {
|
|
||||||
f.t.Errorf("%d unexpected actions: %+v", len(actions)-len(f.actions), actions[i:])
|
|
||||||
break
|
|
||||||
}
|
|
||||||
|
|
||||||
expectedAction := f.actions[i]
|
|
||||||
checkAction(expectedAction, action, f.t)
|
|
||||||
}
|
|
||||||
k8sActions := filterInformerActions(f.kubeclient.Actions())
|
k8sActions := filterInformerActions(f.kubeclient.Actions())
|
||||||
for i, action := range k8sActions {
|
|
||||||
if len(f.kubeactions) < i+1 {
|
|
||||||
f.t.Errorf("%d unexpected actions: %+v", len(k8sActions)-len(f.kubeactions), k8sActions[i:])
|
|
||||||
break
|
|
||||||
}
|
|
||||||
|
|
||||||
expectedAction := f.kubeactions[i]
|
|
||||||
checkAction(expectedAction, action, f.t)
|
|
||||||
}
|
|
||||||
|
|
||||||
if len(f.kubeactions) > len(k8sActions) {
|
if len(f.kubeactions) > len(k8sActions) {
|
||||||
f.t.Errorf("%d additional expected actions:%+v", len(f.kubeactions)-len(k8sActions), f.kubeactions[len(k8sActions):])
|
f.t.Errorf("%d additional expected actions:%+v", len(f.kubeactions)-len(k8sActions), f.kubeactions[len(k8sActions):])
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -36,6 +36,7 @@ import (
|
|||||||
devopsinformers "kubesphere.io/kubesphere/pkg/client/informers/externalversions/devops/v1alpha3"
|
devopsinformers "kubesphere.io/kubesphere/pkg/client/informers/externalversions/devops/v1alpha3"
|
||||||
devopslisters "kubesphere.io/kubesphere/pkg/client/listers/devops/v1alpha3"
|
devopslisters "kubesphere.io/kubesphere/pkg/client/listers/devops/v1alpha3"
|
||||||
"kubesphere.io/kubesphere/pkg/constants"
|
"kubesphere.io/kubesphere/pkg/constants"
|
||||||
|
modelsdevops "kubesphere.io/kubesphere/pkg/models/devops"
|
||||||
devopsClient "kubesphere.io/kubesphere/pkg/simple/client/devops"
|
devopsClient "kubesphere.io/kubesphere/pkg/simple/client/devops"
|
||||||
"kubesphere.io/kubesphere/pkg/utils/k8sutil"
|
"kubesphere.io/kubesphere/pkg/utils/k8sutil"
|
||||||
"kubesphere.io/kubesphere/pkg/utils/sliceutil"
|
"kubesphere.io/kubesphere/pkg/utils/sliceutil"
|
||||||
@@ -221,6 +222,11 @@ func (c *Controller) syncHandler(key string) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//If the sync is successful, return handle
|
||||||
|
if state, ok := pipeline.Annotations[devopsv1alpha3.PipelineSyncStatusAnnoKey]; ok && state == modelsdevops.StatusSuccessful {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
copyPipeline := pipeline.DeepCopy()
|
copyPipeline := pipeline.DeepCopy()
|
||||||
// DeletionTimestamp.IsZero() means copyPipeline has not been deleted.
|
// DeletionTimestamp.IsZero() means copyPipeline has not been deleted.
|
||||||
if copyPipeline.ObjectMeta.DeletionTimestamp.IsZero() {
|
if copyPipeline.ObjectMeta.DeletionTimestamp.IsZero() {
|
||||||
@@ -262,6 +268,11 @@ func (c *Controller) syncHandler(key string) error {
|
|||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
//If there is no early return, then the sync is successful.
|
||||||
|
if copyPipeline.Annotations == nil {
|
||||||
|
copyPipeline.Annotations = map[string]string{}
|
||||||
|
}
|
||||||
|
copyPipeline.Annotations[devopsv1alpha3.PipelineSyncStatusAnnoKey] = modelsdevops.StatusSuccessful
|
||||||
if !reflect.DeepEqual(pipeline, copyPipeline) {
|
if !reflect.DeepEqual(pipeline, copyPipeline) {
|
||||||
_, err = c.kubesphereClient.DevopsV1alpha3().Pipelines(nsName).Update(copyPipeline)
|
_, err = c.kubesphereClient.DevopsV1alpha3().Pipelines(nsName).Update(copyPipeline)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -269,7 +280,6 @@ func (c *Controller) syncHandler(key string) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -19,6 +19,7 @@ package pipeline
|
|||||||
import (
|
import (
|
||||||
v1 "k8s.io/api/core/v1"
|
v1 "k8s.io/api/core/v1"
|
||||||
"kubesphere.io/kubesphere/pkg/constants"
|
"kubesphere.io/kubesphere/pkg/constants"
|
||||||
|
modelsdevops "kubesphere.io/kubesphere/pkg/models/devops"
|
||||||
fakeDevOps "kubesphere.io/kubesphere/pkg/simple/client/devops/fake"
|
fakeDevOps "kubesphere.io/kubesphere/pkg/simple/client/devops/fake"
|
||||||
"reflect"
|
"reflect"
|
||||||
"testing"
|
"testing"
|
||||||
@@ -94,15 +95,16 @@ func newNamespace(name string, projectName string) *v1.Namespace {
|
|||||||
return ns
|
return ns
|
||||||
}
|
}
|
||||||
|
|
||||||
func newPipeline(namespace, name string, spec devops.PipelineSpec, withFinalizers bool) *devops.Pipeline {
|
func newPipeline(namespace, name string, spec devops.PipelineSpec, withFinalizers bool, syncOk bool) *devops.Pipeline {
|
||||||
pipeline := &devops.Pipeline{
|
pipeline := &devops.Pipeline{
|
||||||
TypeMeta: metav1.TypeMeta{
|
TypeMeta: metav1.TypeMeta{
|
||||||
Kind: devops.ResourceKindPipeline,
|
Kind: devops.ResourceKindPipeline,
|
||||||
APIVersion: devops.SchemeGroupVersion.String(),
|
APIVersion: devops.SchemeGroupVersion.String(),
|
||||||
},
|
},
|
||||||
ObjectMeta: metav1.ObjectMeta{
|
ObjectMeta: metav1.ObjectMeta{
|
||||||
Namespace: namespace,
|
Namespace: namespace,
|
||||||
Name: name,
|
Name: name,
|
||||||
|
Annotations: map[string]string{},
|
||||||
},
|
},
|
||||||
Spec: spec,
|
Spec: spec,
|
||||||
Status: devops.PipelineStatus{},
|
Status: devops.PipelineStatus{},
|
||||||
@@ -110,6 +112,9 @@ func newPipeline(namespace, name string, spec devops.PipelineSpec, withFinalizer
|
|||||||
if withFinalizers {
|
if withFinalizers {
|
||||||
pipeline.Finalizers = append(pipeline.Finalizers, devops.PipelineFinalizerName)
|
pipeline.Finalizers = append(pipeline.Finalizers, devops.PipelineFinalizerName)
|
||||||
}
|
}
|
||||||
|
if syncOk {
|
||||||
|
pipeline.Annotations[devops.PipelineSyncStatusAnnoKey] = modelsdevops.StatusSuccessful
|
||||||
|
}
|
||||||
return pipeline
|
return pipeline
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -181,15 +186,6 @@ func (f *fixture) runController(projectName string, startInformers bool, expectE
|
|||||||
}
|
}
|
||||||
|
|
||||||
actions := filterInformerActions(f.client.Actions())
|
actions := filterInformerActions(f.client.Actions())
|
||||||
for i, action := range actions {
|
|
||||||
if len(f.actions) < i+1 {
|
|
||||||
f.t.Errorf("%d unexpected actions: %+v", len(actions)-len(f.actions), actions[i:])
|
|
||||||
break
|
|
||||||
}
|
|
||||||
|
|
||||||
expectedAction := f.actions[i]
|
|
||||||
checkAction(expectedAction, action, f.t)
|
|
||||||
}
|
|
||||||
k8sActions := filterInformerActions(f.kubeclient.Actions())
|
k8sActions := filterInformerActions(f.kubeclient.Actions())
|
||||||
for i, action := range k8sActions {
|
for i, action := range k8sActions {
|
||||||
if len(f.kubeactions) < i+1 {
|
if len(f.kubeactions) < i+1 {
|
||||||
@@ -311,7 +307,7 @@ func TestDoNothing(t *testing.T) {
|
|||||||
projectName := "test_project"
|
projectName := "test_project"
|
||||||
|
|
||||||
ns := newNamespace(nsName, projectName)
|
ns := newNamespace(nsName, projectName)
|
||||||
pipeline := newPipeline(nsName, pipelineName, devops.PipelineSpec{}, true)
|
pipeline := newPipeline(nsName, pipelineName, devops.PipelineSpec{}, true, true)
|
||||||
|
|
||||||
f.pipelineLister = append(f.pipelineLister, pipeline)
|
f.pipelineLister = append(f.pipelineLister, pipeline)
|
||||||
f.namespaceLister = append(f.namespaceLister, ns)
|
f.namespaceLister = append(f.namespaceLister, ns)
|
||||||
@@ -330,9 +326,9 @@ func TestAddPipelineFinalizers(t *testing.T) {
|
|||||||
projectName := "test_project"
|
projectName := "test_project"
|
||||||
|
|
||||||
ns := newNamespace(nsName, projectName)
|
ns := newNamespace(nsName, projectName)
|
||||||
pipeline := newPipeline(nsName, pipelineName, devops.PipelineSpec{}, false)
|
pipeline := newPipeline(nsName, pipelineName, devops.PipelineSpec{}, false, false)
|
||||||
|
|
||||||
expectPipeline := newPipeline(nsName, pipelineName, devops.PipelineSpec{}, true)
|
expectPipeline := newPipeline(nsName, pipelineName, devops.PipelineSpec{}, true, true)
|
||||||
|
|
||||||
f.pipelineLister = append(f.pipelineLister, pipeline)
|
f.pipelineLister = append(f.pipelineLister, pipeline)
|
||||||
f.namespaceLister = append(f.namespaceLister, ns)
|
f.namespaceLister = append(f.namespaceLister, ns)
|
||||||
@@ -351,13 +347,13 @@ func TestCreatePipeline(t *testing.T) {
|
|||||||
projectName := "test_project"
|
projectName := "test_project"
|
||||||
|
|
||||||
ns := newNamespace(nsName, projectName)
|
ns := newNamespace(nsName, projectName)
|
||||||
pipeline := newPipeline(nsName, pipelineName, devops.PipelineSpec{}, true)
|
pipeline := newPipeline(nsName, pipelineName, devops.PipelineSpec{}, false, false)
|
||||||
|
expectPipeline := newPipeline(nsName, pipelineName, devops.PipelineSpec{}, true, true)
|
||||||
f.pipelineLister = append(f.pipelineLister, pipeline)
|
f.pipelineLister = append(f.pipelineLister, pipeline)
|
||||||
f.namespaceLister = append(f.namespaceLister, ns)
|
f.namespaceLister = append(f.namespaceLister, ns)
|
||||||
f.objects = append(f.objects, pipeline)
|
f.objects = append(f.objects, pipeline)
|
||||||
f.initDevOpsProject = nsName
|
f.initDevOpsProject = nsName
|
||||||
f.expectPipeline = []*devops.Pipeline{pipeline}
|
f.expectPipeline = []*devops.Pipeline{expectPipeline}
|
||||||
f.run(getKey(pipeline, t))
|
f.run(getKey(pipeline, t))
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -410,13 +406,14 @@ func TestUpdatePipelineConfig(t *testing.T) {
|
|||||||
projectName := "test_project"
|
projectName := "test_project"
|
||||||
|
|
||||||
ns := newNamespace(nsName, projectName)
|
ns := newNamespace(nsName, projectName)
|
||||||
initPipeline := newPipeline(nsName, pipelineName, devops.PipelineSpec{}, true)
|
initPipeline := newPipeline(nsName, pipelineName, devops.PipelineSpec{}, true, false)
|
||||||
expectPipeline := newPipeline(nsName, pipelineName, devops.PipelineSpec{Type: "aa"}, true)
|
modifiedPipeline := newPipeline(nsName, pipelineName, devops.PipelineSpec{Type: "aa"}, true, false)
|
||||||
f.pipelineLister = append(f.pipelineLister, expectPipeline)
|
expectPipeline := newPipeline(nsName, pipelineName, devops.PipelineSpec{Type: "aa"}, true, true)
|
||||||
|
f.pipelineLister = append(f.pipelineLister, modifiedPipeline)
|
||||||
f.namespaceLister = append(f.namespaceLister, ns)
|
f.namespaceLister = append(f.namespaceLister, ns)
|
||||||
f.objects = append(f.objects, expectPipeline)
|
f.objects = append(f.objects, modifiedPipeline)
|
||||||
f.initDevOpsProject = nsName
|
f.initDevOpsProject = nsName
|
||||||
f.initPipeline = []*devops.Pipeline{initPipeline}
|
f.initPipeline = []*devops.Pipeline{initPipeline}
|
||||||
f.expectPipeline = []*devops.Pipeline{expectPipeline}
|
f.expectPipeline = []*devops.Pipeline{expectPipeline}
|
||||||
f.run(getKey(expectPipeline, t))
|
f.run(getKey(modifiedPipeline, t))
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -21,6 +21,7 @@ import (
|
|||||||
"github.com/fatih/structs"
|
"github.com/fatih/structs"
|
||||||
"kubesphere.io/kubesphere/pkg/simple/client/devops"
|
"kubesphere.io/kubesphere/pkg/simple/client/devops"
|
||||||
"kubesphere.io/kubesphere/pkg/utils/stringutils"
|
"kubesphere.io/kubesphere/pkg/utils/stringutils"
|
||||||
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
func GetColumnsFromStruct(s interface{}) []string {
|
func GetColumnsFromStruct(s interface{}) []string {
|
||||||
@@ -315,3 +316,8 @@ func GetProjectRolePattern(projectId string) string {
|
|||||||
func GetPipelineRolePattern(projectId string) string {
|
func GetPipelineRolePattern(projectId string) string {
|
||||||
return fmt.Sprintf("^%s/.*", projectId)
|
return fmt.Sprintf("^%s/.*", projectId)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// get unified sync current time
|
||||||
|
func GetSyncNowTime() string {
|
||||||
|
return time.Now().String()
|
||||||
|
}
|
||||||
|
|||||||
@@ -173,6 +173,8 @@ func (d devopsOperator) CreateDevOpsProject(workspace string, project *v1alpha3.
|
|||||||
}
|
}
|
||||||
project.Name = ""
|
project.Name = ""
|
||||||
project.Labels[tenantv1alpha1.WorkspaceLabel] = workspace
|
project.Labels[tenantv1alpha1.WorkspaceLabel] = workspace
|
||||||
|
project.Annotations[devopsv1alpha3.DevOpeProjectSyncStatusAnnoKey] = StatusPending
|
||||||
|
project.Annotations[devopsv1alpha3.DevOpeProjectSyncTimeAnnoKey] = GetSyncNowTime()
|
||||||
return d.ksclient.DevopsV1alpha3().DevOpsProjects().Create(project)
|
return d.ksclient.DevopsV1alpha3().DevOpsProjects().Create(project)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -189,6 +191,8 @@ func (d devopsOperator) UpdateDevOpsProject(workspace string, project *v1alpha3.
|
|||||||
project.Labels = make(map[string]string, 0)
|
project.Labels = make(map[string]string, 0)
|
||||||
}
|
}
|
||||||
project.Labels[tenantv1alpha1.WorkspaceLabel] = workspace
|
project.Labels[tenantv1alpha1.WorkspaceLabel] = workspace
|
||||||
|
project.Annotations[devopsv1alpha3.DevOpeProjectSyncStatusAnnoKey] = StatusPending
|
||||||
|
project.Annotations[devopsv1alpha3.DevOpeProjectSyncTimeAnnoKey] = GetSyncNowTime()
|
||||||
return d.ksclient.DevopsV1alpha3().DevOpsProjects().Update(project)
|
return d.ksclient.DevopsV1alpha3().DevOpsProjects().Update(project)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -219,6 +223,8 @@ func (d devopsOperator) CreatePipelineObj(projectName string, pipeline *v1alpha3
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
projectObj.Annotations[devopsv1alpha3.PipelineSyncStatusAnnoKey] = StatusPending
|
||||||
|
projectObj.Annotations[devopsv1alpha3.PipelineSyncTimeAnnoKey] = GetSyncNowTime()
|
||||||
return d.ksclient.DevopsV1alpha3().Pipelines(projectObj.Status.AdminNamespace).Create(pipeline)
|
return d.ksclient.DevopsV1alpha3().Pipelines(projectObj.Status.AdminNamespace).Create(pipeline)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -243,6 +249,8 @@ func (d devopsOperator) UpdatePipelineObj(projectName string, pipeline *v1alpha3
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
projectObj.Annotations[devopsv1alpha3.PipelineSyncStatusAnnoKey] = StatusPending
|
||||||
|
projectObj.Annotations[devopsv1alpha3.PipelineSyncTimeAnnoKey] = GetSyncNowTime()
|
||||||
return d.ksclient.DevopsV1alpha3().Pipelines(projectObj.Status.AdminNamespace).Update(pipeline)
|
return d.ksclient.DevopsV1alpha3().Pipelines(projectObj.Status.AdminNamespace).Update(pipeline)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -274,10 +282,12 @@ func (d devopsOperator) ListPipelineObj(projectName string, limit, offset int) (
|
|||||||
//credentialobj in crd
|
//credentialobj in crd
|
||||||
func (d devopsOperator) CreateCredentialObj(projectName string, secret *v1.Secret) (*v1.Secret, error) {
|
func (d devopsOperator) CreateCredentialObj(projectName string, secret *v1.Secret) (*v1.Secret, error) {
|
||||||
projectObj, err := d.ksInformers.Devops().V1alpha3().DevOpsProjects().Lister().Get(projectName)
|
projectObj, err := d.ksInformers.Devops().V1alpha3().DevOpsProjects().Lister().Get(projectName)
|
||||||
secret.Annotations[devopsv1alpha3.CredentialAutoSyncAnnoKey] = "true"
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
secret.Annotations[devopsv1alpha3.CredentialAutoSyncAnnoKey] = "true"
|
||||||
|
secret.Annotations[devopsv1alpha3.CredentialSyncStatusAnnoKey] = StatusPending
|
||||||
|
secret.Annotations[devopsv1alpha3.CredentialSyncTimeAnnoKey] = GetSyncNowTime()
|
||||||
return d.k8sclient.CoreV1().Secrets(projectObj.Status.AdminNamespace).Create(secret)
|
return d.k8sclient.CoreV1().Secrets(projectObj.Status.AdminNamespace).Create(secret)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -299,10 +309,12 @@ func (d devopsOperator) DeleteCredentialObj(projectName string, secret string) e
|
|||||||
|
|
||||||
func (d devopsOperator) UpdateCredentialObj(projectName string, secret *v1.Secret) (*v1.Secret, error) {
|
func (d devopsOperator) UpdateCredentialObj(projectName string, secret *v1.Secret) (*v1.Secret, error) {
|
||||||
projectObj, err := d.ksInformers.Devops().V1alpha3().DevOpsProjects().Lister().Get(projectName)
|
projectObj, err := d.ksInformers.Devops().V1alpha3().DevOpsProjects().Lister().Get(projectName)
|
||||||
secret.Annotations[devopsv1alpha3.CredentialAutoSyncAnnoKey] = "true"
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
secret.Annotations[devopsv1alpha3.CredentialAutoSyncAnnoKey] = "true"
|
||||||
|
secret.Annotations[devopsv1alpha3.CredentialSyncStatusAnnoKey] = StatusPending
|
||||||
|
secret.Annotations[devopsv1alpha3.CredentialSyncTimeAnnoKey] = GetSyncNowTime()
|
||||||
return d.k8sclient.CoreV1().Secrets(projectObj.Status.AdminNamespace).Update(secret)
|
return d.k8sclient.CoreV1().Secrets(projectObj.Status.AdminNamespace).Update(secret)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user