Advertisement
Guest User

Untitled

a guest
Oct 20th, 2019
92
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 17.10 KB | None | 0 0
  1. package mobiledeveloperconsole
  2.  
  3. import (
  4. "context"
  5. "fmt"
  6. "testing"
  7.  
  8. "github.com/integr8ly/integreatly-operator/pkg/apis/integreatly/v1alpha1"
  9. "github.com/integr8ly/integreatly-operator/pkg/controller/installation/marketplace"
  10. "github.com/integr8ly/integreatly-operator/pkg/controller/installation/products/config"
  11. "github.com/operator-framework/operator-lifecycle-manager/pkg/lib/ownerutil"
  12. "github.com/pkg/errors"
  13. "k8s.io/apimachinery/pkg/runtime"
  14. "sigs.k8s.io/controller-runtime/pkg/client"
  15.  
  16. integreatlyv1alpha1 "github.com/integr8ly/integreatly-operator/pkg/apis/integreatly/v1alpha1"
  17. mdc "github.com/integr8ly/integreatly-operator/pkg/apis/mdc/v1alpha1"
  18. moqclient "github.com/integr8ly/integreatly-operator/pkg/client"
  19. v1Route "github.com/openshift/api/route/v1"
  20. coreosv1 "github.com/operator-framework/operator-lifecycle-manager/pkg/api/apis/operators/v1"
  21. operatorsv1alpha1 "github.com/operator-framework/operator-lifecycle-manager/pkg/api/apis/operators/v1alpha1"
  22. marketplacev1 "github.com/operator-framework/operator-marketplace/pkg/apis/operators/v1"
  23. corev1 "k8s.io/api/core/v1"
  24. metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
  25. pkgclient "sigs.k8s.io/controller-runtime/pkg/client"
  26. fakeclient "sigs.k8s.io/controller-runtime/pkg/client/fake"
  27. )
  28.  
  29. func basicConfigMock() *config.ConfigReadWriterMock {
  30. return &config.ConfigReadWriterMock{
  31. ReadMobileDeveloperConsoleFunc: func() (ready *config.MobileDeveloperConsole, e error) {
  32. return config.NewMobileDeveloperConsole(config.ProductConfig{}), nil
  33. },
  34. WriteConfigFunc: func(config config.ConfigReadable) error {
  35. return nil
  36. },
  37. }
  38. }
  39.  
  40. func basicInstallation() *v1alpha1.Installation {
  41. return &v1alpha1.Installation{
  42. ObjectMeta: metav1.ObjectMeta{
  43. Name: "installation",
  44. Namespace: defaultInstallationNamespace,
  45. },
  46. TypeMeta: metav1.TypeMeta{
  47. Kind: "installation",
  48. APIVersion: v1alpha1.SchemeGroupVersion.String(),
  49. },
  50. }
  51. }
  52.  
  53. func getBuildScheme() (*runtime.Scheme, error) {
  54. scheme := runtime.NewScheme()
  55. err := integreatlyv1alpha1.SchemeBuilder.AddToScheme(scheme)
  56. err = operatorsv1alpha1.AddToScheme(scheme)
  57. err = marketplacev1.SchemeBuilder.AddToScheme(scheme)
  58. err = corev1.SchemeBuilder.AddToScheme(scheme)
  59. err = coreosv1.SchemeBuilder.AddToScheme(scheme)
  60. err = mdc.SchemeBuilder.AddToScheme(scheme)
  61. err = v1Route.AddToScheme(scheme)
  62. return scheme, err
  63. }
  64.  
  65. func TestReconciler_config(t *testing.T) {
  66. cases := []struct {
  67. Name string
  68. ExpectError bool
  69. ExpectedError string
  70. ExpectedStatus v1alpha1.StatusPhase
  71. FakeConfig *config.ConfigReadWriterMock
  72. FakeClient pkgclient.Client
  73. FakeMPM *marketplace.MarketplaceInterfaceMock
  74. Installation *v1alpha1.Installation
  75. }{
  76. {
  77. Name: "test error on failed config",
  78. ExpectError: true,
  79. ExpectedError: "could not read mobile developer console: could not read mdc config",
  80. ExpectedStatus: v1alpha1.PhaseFailed,
  81. Installation: &v1alpha1.Installation{},
  82. FakeClient: fakeclient.NewFakeClient(),
  83. FakeConfig: &config.ConfigReadWriterMock{
  84. ReadMobileDeveloperConsoleFunc: func() (ready *config.MobileDeveloperConsole, e error) {
  85. return nil, errors.New("could not read mdc config")
  86. },
  87. },
  88. },
  89. {
  90. Name: "test namespace is set without fail",
  91. Installation: &v1alpha1.Installation{},
  92. FakeClient: fakeclient.NewFakeClient(),
  93. FakeConfig: &config.ConfigReadWriterMock{
  94. ReadMobileDeveloperConsoleFunc: func() (ready *config.MobileDeveloperConsole, e error) {
  95. return config.NewMobileDeveloperConsole(config.ProductConfig{
  96. "NAMESPACE": "",
  97. }), nil
  98. },
  99. },
  100. },
  101. {
  102. Name: "test subscription phase with error from mpm",
  103. ExpectedStatus: v1alpha1.PhaseFailed,
  104. ExpectError: true,
  105. Installation: &v1alpha1.Installation{},
  106. FakeMPM: &marketplace.MarketplaceInterfaceMock{
  107. InstallOperatorFunc: func(ctx context.Context, serverClient pkgclient.Client, owner ownerutil.Owner, os marketplacev1.OperatorSource, t marketplace.Target, operatorGroupNamespaces []string, approvalStrategy operatorsv1alpha1.Approval) error {
  108. return errors.New("dummy error")
  109. },
  110. },
  111. FakeClient: fakeclient.NewFakeClient(),
  112. FakeConfig: basicConfigMock(),
  113. },
  114. }
  115.  
  116. for _, tc := range cases {
  117. t.Run(tc.Name, func(t *testing.T) {
  118. _, err := NewReconciler(tc.FakeConfig, tc.Installation, tc.FakeMPM)
  119. if err != nil && err.Error() != tc.ExpectedError {
  120. t.Fatalf("unexpected error : '%v', expected: '%v'", err, tc.ExpectedError)
  121. }
  122. if err == nil && tc.ExpectedError != "" {
  123. t.Fatalf("expected error '%v' and got nil", tc.ExpectedError)
  124. }
  125. })
  126. }
  127. }
  128.  
  129. func TestReconciler_reconcileCustomResource(t *testing.T) {
  130. scheme, err := getBuildScheme()
  131. if err != nil {
  132. t.Fatal(err)
  133. }
  134.  
  135. cases := []struct {
  136. Name string
  137. FakeClient pkgclient.Client
  138. FakeConfig *config.ConfigReadWriterMock
  139. Installation *v1alpha1.Installation
  140. ExpectError bool
  141. ExpectedStatus v1alpha1.StatusPhase
  142. FakeMPM *marketplace.MarketplaceInterfaceMock
  143. }{
  144. {
  145. Name: "Test reconcile custom resource returns in progress when successful created",
  146. FakeClient: fakeclient.NewFakeClientWithScheme(scheme),
  147. FakeConfig: basicConfigMock(),
  148. Installation: &v1alpha1.Installation{},
  149. ExpectedStatus: v1alpha1.PhaseCompleted,
  150. },
  151. {
  152. Name: "Test reconcile custom resource returns failed when cr status is failed",
  153. FakeClient: &moqclient.SigsClientInterfaceMock{
  154. CreateFunc: func(ctx context.Context, obj runtime.Object) error {
  155. return errors.New("dummy create error")
  156. },
  157. },
  158. FakeConfig: basicConfigMock(),
  159. Installation: &v1alpha1.Installation{},
  160. ExpectedStatus: v1alpha1.PhaseFailed,
  161. ExpectError: true,
  162. },
  163. }
  164. for _, tc := range cases {
  165. t.Run(tc.Name, func(t *testing.T) {
  166. reconciler, err := NewReconciler(tc.FakeConfig, tc.Installation, tc.FakeMPM)
  167. if err != nil {
  168. t.Fatal("unexpected err ", err)
  169. }
  170.  
  171. phase, err := reconciler.reconcileCustomResource(context.TODO(), tc.FakeClient)
  172. if tc.ExpectError && err == nil {
  173. t.Fatal("expected an error but got none")
  174. }
  175. if !tc.ExpectError && err != nil {
  176. t.Fatal("expected no error but got one ", err)
  177. }
  178. if tc.ExpectedStatus != phase {
  179. t.Fatal("expected phase ", tc.ExpectedStatus, " but got ", phase)
  180. }
  181. })
  182. }
  183. }
  184.  
  185. func TestReconciler_handleProgress(t *testing.T) {
  186. scheme, err := getBuildScheme()
  187. if err != nil {
  188. t.Fatal(err)
  189. }
  190.  
  191. unreadyPods := []runtime.Object{}
  192. for i := 0; i < 2; i++ {
  193. unreadyPods = append(unreadyPods, &corev1.Pod{
  194. ObjectMeta: metav1.ObjectMeta{
  195. Name: fmt.Sprintf("%s-%d", resourceName, i),
  196. Namespace: defaultInstallationNamespace,
  197. },
  198. Status: corev1.PodStatus{
  199. Conditions: []corev1.PodCondition{
  200. corev1.PodCondition{
  201. Type: corev1.ContainersReady,
  202. Status: corev1.ConditionUnknown,
  203. },
  204. },
  205. },
  206. })
  207. }
  208.  
  209. readyPods := []runtime.Object{}
  210. for i := 0; i < 2; i++ {
  211. readyPods = append(readyPods, &corev1.Pod{
  212. ObjectMeta: metav1.ObjectMeta{
  213. Name: fmt.Sprintf("%s-%d", resourceName, i),
  214. Namespace: defaultInstallationNamespace,
  215. },
  216. Status: corev1.PodStatus{
  217. Conditions: []corev1.PodCondition{
  218. corev1.PodCondition{
  219. Type: corev1.ContainersReady,
  220. Status: corev1.ConditionTrue,
  221. },
  222. },
  223. },
  224. })
  225. }
  226.  
  227. cases := []struct {
  228. Name string
  229. ExpectError bool
  230. ExpectedStatus v1alpha1.StatusPhase
  231. ExpectedError string
  232. FakeConfig *config.ConfigReadWriterMock
  233. FakeClient client.Client
  234. FakeMPM *marketplace.MarketplaceInterfaceMock
  235. Installation *v1alpha1.Installation
  236. }{
  237. {
  238. Name: "test failure to list pods",
  239. ExpectedStatus: v1alpha1.PhaseFailed,
  240. ExpectedError: "failed to check mdc installation",
  241. ExpectError: true,
  242. FakeClient: &moqclient.SigsClientInterfaceMock{
  243. ListFunc: func(ctx context.Context, opts *client.ListOptions, list runtime.Object) error {
  244. return errors.New("dummy create error")
  245. },
  246. },
  247. FakeConfig: basicConfigMock(),
  248. Installation: &v1alpha1.Installation{},
  249. },
  250. {
  251. Name: "test unready pods returns phase in progress",
  252. ExpectedStatus: v1alpha1.PhaseInProgress,
  253. FakeClient: moqclient.NewSigsClientMoqWithScheme(scheme, unreadyPods...),
  254. FakeConfig: basicConfigMock(),
  255. Installation: &v1alpha1.Installation{},
  256. },
  257. {
  258. Name: "test ready pods returns phase complete",
  259. ExpectedStatus: v1alpha1.PhaseCompleted,
  260. FakeClient: moqclient.NewSigsClientMoqWithScheme(scheme, readyPods...),
  261. FakeConfig: basicConfigMock(),
  262. Installation: &v1alpha1.Installation{},
  263. },
  264. }
  265.  
  266. for _, tc := range cases {
  267. t.Run(tc.Name, func(t *testing.T) {
  268. reconciler, err := NewReconciler(tc.FakeConfig, tc.Installation, tc.FakeMPM)
  269. if err != nil && err.Error() != tc.ExpectedError {
  270. t.Fatalf("unexpected error : '%v', expected: '%v'", err, tc.ExpectedError)
  271. }
  272.  
  273. status, err := reconciler.handleProgress(context.TODO(), tc.FakeClient)
  274. if err != nil && !tc.ExpectError {
  275. t.Fatalf("expected error but got one: %v", err)
  276. }
  277. if err == nil && tc.ExpectError {
  278. t.Fatal("expected error but got none")
  279. }
  280. if status != tc.ExpectedStatus {
  281. t.Fatalf("Expected status: '%v', got: '%v'", tc.ExpectedStatus, status)
  282. }
  283. })
  284. }
  285. }
  286.  
  287. func TestReconciler_fullReconcile(t *testing.T) {
  288. scheme, err := getBuildScheme()
  289. if err != nil {
  290. t.Fatal(err)
  291. }
  292.  
  293. // initialise runtime objects
  294. objs := []runtime.Object{}
  295. objs = append(objs, &corev1.Namespace{
  296. ObjectMeta: metav1.ObjectMeta{
  297. Name: defaultInstallationNamespace,
  298. OwnerReferences: []metav1.OwnerReference{
  299. {
  300. Name: "installation",
  301. APIVersion: v1alpha1.SchemeGroupVersion.String(),
  302. },
  303. },
  304. },
  305. Status: corev1.NamespaceStatus{
  306. Phase: corev1.NamespaceActive,
  307. },
  308. }, &v1Route.Route{
  309. TypeMeta: metav1.TypeMeta{
  310. Kind: "Route",
  311. APIVersion: "v1",
  312. },
  313. ObjectMeta: metav1.ObjectMeta{
  314. Namespace: defaultInstallationNamespace,
  315. Name: mdcRouteName,
  316. },
  317. })
  318. for i := 0; i < 2; i++ {
  319. objs = append(objs, &corev1.Pod{
  320. ObjectMeta: metav1.ObjectMeta{
  321. Name: fmt.Sprintf("%s-%d", resourceName, i),
  322. Namespace: defaultInstallationNamespace,
  323. },
  324. Status: corev1.PodStatus{
  325. Conditions: []corev1.PodCondition{
  326. corev1.PodCondition{
  327. Type: corev1.ContainersReady,
  328. Status: corev1.ConditionTrue,
  329. },
  330. },
  331. },
  332. })
  333. }
  334.  
  335. cases := []struct {
  336. Name string
  337. ExpectError bool
  338. ExpectedStatus v1alpha1.StatusPhase
  339. ExpectedError string
  340. FakeConfig *config.ConfigReadWriterMock
  341. FakeClient client.Client
  342. FakeMPM *marketplace.MarketplaceInterfaceMock
  343. Installation *v1alpha1.Installation
  344. Product *v1alpha1.InstallationProductStatus
  345. }{
  346. {
  347. Name: "test successful reconcile",
  348. ExpectedStatus: v1alpha1.PhaseCompleted,
  349. FakeClient: moqclient.NewSigsClientMoqWithScheme(scheme, objs...),
  350. FakeConfig: basicConfigMock(),
  351. FakeMPM: &marketplace.MarketplaceInterfaceMock{
  352. InstallOperatorFunc: func(ctx context.Context, serverClient pkgclient.Client, owner ownerutil.Owner, os marketplacev1.OperatorSource, t marketplace.Target, operatorGroupNamespaces []string, approvalStrategy operatorsv1alpha1.Approval) error {
  353. return nil
  354. },
  355. GetSubscriptionInstallPlanFunc: func(ctx context.Context, serverClient client.Client, subName string, ns string) (plan *operatorsv1alpha1.InstallPlan, subscription *operatorsv1alpha1.Subscription, e error) {
  356. return &operatorsv1alpha1.InstallPlan{
  357. ObjectMeta: metav1.ObjectMeta{
  358. Name: "mdc-install-plan",
  359. },
  360. Status: operatorsv1alpha1.InstallPlanStatus{
  361. Phase: operatorsv1alpha1.InstallPlanPhaseComplete,
  362. },
  363. }, &operatorsv1alpha1.Subscription{
  364. Status: operatorsv1alpha1.SubscriptionStatus{
  365. Install: &operatorsv1alpha1.InstallPlanReference{
  366. Name: "mdc-install-plan",
  367. },
  368. },
  369. }, nil
  370. },
  371. },
  372. Installation: basicInstallation(),
  373. Product: &v1alpha1.InstallationProductStatus{},
  374. },
  375. }
  376.  
  377. for _, tc := range cases {
  378. t.Run(tc.Name, func(t *testing.T) {
  379. reconciler, err := NewReconciler(tc.FakeConfig, tc.Installation, tc.FakeMPM)
  380. if err != nil && err.Error() != tc.ExpectedError {
  381. t.Fatalf("unexpected error : '%v', expected: '%v'", err, tc.ExpectedError)
  382. }
  383.  
  384. status, err := reconciler.Reconcile(context.TODO(), tc.Installation, tc.Product, tc.FakeClient)
  385. if err != nil && !tc.ExpectError {
  386. t.Fatalf("expected error but got one: %v", err)
  387. }
  388. if err == nil && tc.ExpectError {
  389. t.Fatal("expected error but got none")
  390. }
  391. if status != tc.ExpectedStatus {
  392. t.Fatalf("Expected status: '%v', got: '%v'", tc.ExpectedStatus, status)
  393. }
  394. })
  395. }
  396. }
  397.  
  398. func TestReconciler_testPhases(t *testing.T) {
  399. scheme, err := getBuildScheme()
  400. if err != nil {
  401. t.Fatal(err)
  402. }
  403.  
  404. cases := []struct {
  405. Name string
  406. ExpectedStatus v1alpha1.StatusPhase
  407. FakeConfig *config.ConfigReadWriterMock
  408. FakeClient pkgclient.Client
  409. FakeMPM *marketplace.MarketplaceInterfaceMock
  410. Installation *v1alpha1.Installation
  411. Product *v1alpha1.InstallationProductStatus
  412. }{
  413. {
  414. Name: "test namespace terminating returns phase in progress",
  415. ExpectedStatus: v1alpha1.PhaseInProgress,
  416. Installation: basicInstallation(),
  417. FakeClient: moqclient.NewSigsClientMoqWithScheme(scheme, &corev1.Namespace{
  418. ObjectMeta: metav1.ObjectMeta{
  419. Name: defaultInstallationNamespace,
  420. OwnerReferences: []metav1.OwnerReference{
  421. {
  422. Name: "installation",
  423. APIVersion: v1alpha1.SchemeGroupVersion.String(),
  424. },
  425. },
  426. },
  427. Status: corev1.NamespaceStatus{
  428. Phase: corev1.NamespaceTerminating,
  429. },
  430. }),
  431. FakeConfig: basicConfigMock(),
  432. FakeMPM: &marketplace.MarketplaceInterfaceMock{
  433. InstallOperatorFunc: func(ctx context.Context, serverClient pkgclient.Client, owner ownerutil.Owner, os marketplacev1.OperatorSource, t marketplace.Target, operatorGroupNamespaces []string, approvalStrategy operatorsv1alpha1.Approval) error {
  434. return nil
  435. },
  436. GetSubscriptionInstallPlanFunc: func(ctx context.Context, serverClient client.Client, subName string, ns string) (plan *operatorsv1alpha1.InstallPlan, subscription *operatorsv1alpha1.Subscription, e error) {
  437. return &operatorsv1alpha1.InstallPlan{}, &operatorsv1alpha1.Subscription{}, nil
  438. },
  439. },
  440. Product: &v1alpha1.InstallationProductStatus{},
  441. },
  442. {
  443. Name: "test subscription creating returns phase in progress",
  444. ExpectedStatus: v1alpha1.PhaseInProgress,
  445. Installation: basicInstallation(),
  446. FakeClient: fakeclient.NewFakeClientWithScheme(scheme),
  447. FakeConfig: basicConfigMock(),
  448. FakeMPM: &marketplace.MarketplaceInterfaceMock{
  449. InstallOperatorFunc: func(ctx context.Context, serverClient pkgclient.Client, owner ownerutil.Owner, os marketplacev1.OperatorSource, t marketplace.Target, operatorGroupNamespaces []string, approvalStrategy operatorsv1alpha1.Approval) error {
  450. return nil
  451. },
  452. GetSubscriptionInstallPlanFunc: func(ctx context.Context, serverClient client.Client, subName string, ns string) (plan *operatorsv1alpha1.InstallPlan, subscription *operatorsv1alpha1.Subscription, e error) {
  453. return &operatorsv1alpha1.InstallPlan{}, &operatorsv1alpha1.Subscription{}, nil
  454. },
  455. },
  456. Product: &v1alpha1.InstallationProductStatus{},
  457. },
  458. {
  459. Name: "test components creating returns phase in progress",
  460. ExpectedStatus: v1alpha1.PhaseInProgress,
  461. Installation: basicInstallation(),
  462. FakeClient: fakeclient.NewFakeClientWithScheme(scheme),
  463. FakeConfig: basicConfigMock(),
  464. FakeMPM: &marketplace.MarketplaceInterfaceMock{
  465. InstallOperatorFunc: func(ctx context.Context, serverClient pkgclient.Client, owner ownerutil.Owner, os marketplacev1.OperatorSource, t marketplace.Target, operatorGroupNamespaces []string, approvalStrategy operatorsv1alpha1.Approval) error {
  466. return nil
  467. },
  468. GetSubscriptionInstallPlanFunc: func(ctx context.Context, serverClient client.Client, subName string, ns string) (plan *operatorsv1alpha1.InstallPlan, subscription *operatorsv1alpha1.Subscription, e error) {
  469. return &operatorsv1alpha1.InstallPlan{
  470. ObjectMeta: metav1.ObjectMeta{
  471. Name: "mdc-install-plan",
  472. Namespace: defaultInstallationNamespace,
  473. },
  474. Status: operatorsv1alpha1.InstallPlanStatus{
  475. Phase: operatorsv1alpha1.InstallPlanPhaseComplete,
  476. },
  477. }, &operatorsv1alpha1.Subscription{
  478. Status: operatorsv1alpha1.SubscriptionStatus{
  479. Install: &operatorsv1alpha1.InstallPlanReference{
  480. Name: "mdc-install-plan",
  481. },
  482. },
  483. }, nil
  484. },
  485. },
  486. Product: &v1alpha1.InstallationProductStatus{},
  487. },
  488. }
  489.  
  490. for _, tc := range cases {
  491. t.Run(tc.Name, func(t *testing.T) {
  492. reconciler, err := NewReconciler(tc.FakeConfig, tc.Installation, tc.FakeMPM)
  493. if err != nil {
  494. t.Fatalf("unexpected error : '%v'", err)
  495. }
  496.  
  497. status, err := reconciler.Reconcile(context.TODO(), tc.Installation, tc.Product, tc.FakeClient)
  498. if err != nil {
  499. t.Fatalf("expected no error but got one: %v", err)
  500. }
  501. if status != tc.ExpectedStatus {
  502. t.Fatalf("Expected status: '%v', got: '%v'", tc.ExpectedStatus, status)
  503. }
  504. })
  505. }
  506. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement