├── .gitignore ├── 01-go-training ├── 03-sync │ ├── 01_goroutine │ │ ├── 01 │ │ │ └── 01.go │ │ ├── 02 │ │ │ └── 02.go │ │ ├── 03 │ │ │ └── 03.go │ │ ├── 04 │ │ │ └── 04.go │ │ ├── 05 │ │ │ └── 05.go │ │ ├── 06 │ │ │ └── 06.go │ │ └── 07 │ │ │ ├── 07.go │ │ │ └── reporter.go │ ├── 02_memery_model │ │ └── 01 │ │ │ └── 01.go │ ├── 03_data_race │ │ ├── 01 │ │ │ └── main.go │ │ ├── 02 │ │ │ └── main.go │ │ ├── 03 │ │ │ └── main.go │ │ ├── 04 │ │ │ └── main.go │ │ └── 05 │ │ │ └── main.go │ ├── 04_mutex │ │ ├── 01_mutex │ │ │ └── main.go │ │ └── 02_rwmutex │ │ │ ├── main.go │ │ │ └── main_test.go │ ├── 05_atomic │ │ ├── 01_stack │ │ │ ├── main.go │ │ │ └── main_test.go │ │ ├── main.go │ │ └── main_test.go │ ├── 06_waitgroup │ │ ├── 01 │ │ │ └── main.go │ │ └── 02 │ │ │ └── main.go │ ├── 08_once │ │ └── main.go │ ├── 09_context │ │ ├── 01_timeout │ │ │ └── main.go │ │ ├── 02_cancle │ │ │ └── main.go │ │ ├── 03_value │ │ │ └── main.go │ │ ├── 04_leak │ │ │ └── main.go │ │ └── http_timeout │ │ │ └── main.go │ ├── 10_channel │ │ ├── 01_example │ │ │ └── main.go │ │ ├── 02_close_notify │ │ │ └── main.go │ │ └── main.go │ └── 12_singleflight │ │ └── 1.go ├── 04-project │ └── 10-layout │ │ ├── api │ │ └── product │ │ │ └── app │ │ │ └── v1 │ │ │ ├── v1.pb.go │ │ │ ├── v1.proto │ │ │ ├── v1.swagger.json │ │ │ ├── v1_gin.pb.go │ │ │ └── v1_type.pb.go │ │ ├── cmd │ │ ├── cron │ │ │ ├── main.go │ │ │ └── wire.go │ │ └── server │ │ │ ├── main.go │ │ │ ├── server.go │ │ │ ├── wire.go │ │ │ └── wire_gen.go │ │ ├── config │ │ └── initializer │ │ │ ├── gorm.go │ │ │ └── wire_set.go │ │ ├── go.mod │ │ ├── go.sum │ │ ├── internal │ │ ├── cron │ │ │ └── wire_set.go │ │ ├── domain │ │ │ ├── article.go │ │ │ ├── article_tag.go │ │ │ ├── model.go │ │ │ └── tag.go │ │ ├── mock │ │ │ └── article.go │ │ ├── pkg │ │ │ ├── copier │ │ │ │ └── copier.go │ │ │ └── mock │ │ │ │ └── domain │ │ │ │ └── article.go │ │ └── server │ │ │ ├── repo │ │ │ └── repo.go │ │ │ ├── service │ │ │ └── article.go │ │ │ ├── usecase │ │ │ ├── usecase.go │ │ │ └── usecase_test.go │ │ │ └── wire_set.go │ │ ├── makefile │ │ └── third_party │ │ └── googleapis │ │ ├── LICENSE │ │ ├── README.grpc-gateway │ │ └── google │ │ ├── api │ │ ├── annotations.proto │ │ └── http.proto │ │ └── rpc │ │ ├── code.proto │ │ ├── error_details.proto │ │ └── status.proto ├── 06-micro-service │ └── 06-breaker │ │ ├── go.mod │ │ ├── go.sum │ │ └── hystrix-go-example │ │ └── main.go └── 12-runtime │ └── main.go ├── 02-k8s-operator ├── 02-kind │ ├── kind-ha.yml │ ├── kind.yml │ └── nginx.yml ├── 03-kubebuilder │ ├── .dockerignore │ ├── .gitignore │ ├── Dockerfile │ ├── Makefile │ ├── PROJECT │ ├── api │ │ └── v1 │ │ │ ├── application_types.go │ │ │ ├── groupversion_info.go │ │ │ └── zz_generated.deepcopy.go │ ├── config │ │ ├── crd │ │ │ ├── bases │ │ │ │ └── apps.lailin.xyz_applications.yaml │ │ │ ├── kustomization.yaml │ │ │ ├── kustomizeconfig.yaml │ │ │ └── patches │ │ │ │ ├── cainjection_in_applications.yaml │ │ │ │ └── webhook_in_applications.yaml │ │ ├── default │ │ │ ├── kustomization.yaml │ │ │ ├── manager_auth_proxy_patch.yaml │ │ │ └── manager_config_patch.yaml │ │ ├── manager │ │ │ ├── controller_manager_config.yaml │ │ │ ├── kustomization.yaml │ │ │ └── manager.yaml │ │ ├── prometheus │ │ │ ├── kustomization.yaml │ │ │ └── monitor.yaml │ │ ├── rbac │ │ │ ├── application_editor_role.yaml │ │ │ ├── application_viewer_role.yaml │ │ │ ├── auth_proxy_client_clusterrole.yaml │ │ │ ├── auth_proxy_role.yaml │ │ │ ├── auth_proxy_role_binding.yaml │ │ │ ├── auth_proxy_service.yaml │ │ │ ├── kustomization.yaml │ │ │ ├── leader_election_role.yaml │ │ │ ├── leader_election_role_binding.yaml │ │ │ ├── role.yaml │ │ │ ├── role_binding.yaml │ │ │ └── service_account.yaml │ │ └── samples │ │ │ └── apps_v1_application.yaml │ ├── controllers │ │ ├── application_controller.go │ │ └── suite_test.go │ ├── go.mod │ ├── go.sum │ ├── hack │ │ └── boilerplate.go.txt │ └── main.go ├── 03-node-pool-operator │ ├── .dockerignore │ ├── .gitignore │ ├── Dockerfile │ ├── Makefile │ ├── PROJECT │ ├── api │ │ └── v1 │ │ │ ├── groupversion_info.go │ │ │ ├── nodepool_types.go │ │ │ ├── nodepool_webhook.go │ │ │ ├── nodepool_webhook_test.go │ │ │ ├── webhook_suite_test.go │ │ │ └── zz_generated.deepcopy.go │ ├── config │ │ ├── cert │ │ │ ├── ca.crt │ │ │ ├── ca.key │ │ │ ├── ca.srl │ │ │ ├── csr.conf │ │ │ ├── tls.crt │ │ │ ├── tls.csr │ │ │ └── tls.key │ │ ├── certmanager │ │ │ ├── certificate.yaml │ │ │ ├── kustomization.yaml │ │ │ └── kustomizeconfig.yaml │ │ ├── crd │ │ │ ├── bases │ │ │ │ └── nodes.lailin.xyz_nodepools.yaml │ │ │ ├── kustomization.yaml │ │ │ ├── kustomizeconfig.yaml │ │ │ └── patches │ │ │ │ ├── cainjection_in_nodepools.yaml │ │ │ │ └── webhook_in_nodepools.yaml │ │ ├── default │ │ │ ├── kustomization.yaml │ │ │ ├── manager_auth_proxy_patch.yaml │ │ │ ├── manager_config_patch.yaml │ │ │ ├── manager_webhook_patch.yaml │ │ │ └── webhookcainjection_patch.yaml │ │ ├── dev │ │ │ ├── kustomization.yaml │ │ │ └── webhook_patch.yaml │ │ ├── manager │ │ │ ├── controller_manager_config.yaml │ │ │ ├── kustomization.yaml │ │ │ └── manager.yaml │ │ ├── prometheus │ │ │ ├── kustomization.yaml │ │ │ └── monitor.yaml │ │ ├── rbac │ │ │ ├── auth_proxy_client_clusterrole.yaml │ │ │ ├── auth_proxy_role.yaml │ │ │ ├── auth_proxy_role_binding.yaml │ │ │ ├── auth_proxy_service.yaml │ │ │ ├── kustomization.yaml │ │ │ ├── leader_election_role.yaml │ │ │ ├── leader_election_role_binding.yaml │ │ │ ├── nodepool_editor_role.yaml │ │ │ ├── nodepool_viewer_role.yaml │ │ │ ├── role.yaml │ │ │ ├── role_binding.yaml │ │ │ └── service_account.yaml │ │ ├── samples │ │ │ └── nodes_v1_nodepool.yaml │ │ ├── test │ │ │ └── node-patch.yaml │ │ └── webhook │ │ │ ├── kustomization.yaml │ │ │ ├── kustomizeconfig.yaml │ │ │ ├── manifests.yaml │ │ │ └── service.yaml │ ├── controllers │ │ ├── nodepool_controller.go │ │ └── suite_test.go │ ├── go.mod │ ├── go.sum │ ├── hack │ │ └── boilerplate.go.txt │ └── main.go ├── 05-node-pool-operator │ ├── .dockerignore │ ├── .gitignore │ ├── Dockerfile │ ├── Makefile │ ├── PROJECT │ ├── api │ │ └── v1 │ │ │ ├── groupversion_info.go │ │ │ ├── nodepool_types.go │ │ │ └── zz_generated.deepcopy.go │ ├── config │ │ ├── cert │ │ │ ├── ca.crt │ │ │ ├── ca.key │ │ │ ├── ca.srl │ │ │ ├── csr.conf │ │ │ ├── tls.crt │ │ │ ├── tls.csr │ │ │ └── tls.key │ │ ├── certmanager │ │ │ ├── certificate.yaml │ │ │ ├── kustomization.yaml │ │ │ └── kustomizeconfig.yaml │ │ ├── crd │ │ │ ├── bases │ │ │ │ └── nodes.lailin.xyz_nodepools.yaml │ │ │ ├── kustomization.yaml │ │ │ ├── kustomizeconfig.yaml │ │ │ └── patches │ │ │ │ ├── cainjection_in_nodepools.yaml │ │ │ │ └── webhook_in_nodepools.yaml │ │ ├── default │ │ │ ├── kustomization.yaml │ │ │ ├── manager_auth_proxy_patch.yaml │ │ │ ├── manager_config_patch.yaml │ │ │ ├── manager_webhook_patch.yaml │ │ │ └── webhookcainjection_patch.yaml │ │ ├── dev │ │ │ ├── kustomization.yaml │ │ │ └── webhook_patch.yaml │ │ ├── manager │ │ │ ├── controller_manager_config.yaml │ │ │ ├── kustomization.yaml │ │ │ └── manager.yaml │ │ ├── prometheus │ │ │ ├── kustomization.yaml │ │ │ └── monitor.yaml │ │ ├── rbac │ │ │ ├── auth_proxy_client_clusterrole.yaml │ │ │ ├── auth_proxy_role.yaml │ │ │ ├── auth_proxy_role_binding.yaml │ │ │ ├── auth_proxy_service.yaml │ │ │ ├── kustomization.yaml │ │ │ ├── leader_election_role.yaml │ │ │ ├── leader_election_role_binding.yaml │ │ │ ├── nodepool_editor_role.yaml │ │ │ ├── nodepool_viewer_role.yaml │ │ │ ├── role.yaml │ │ │ ├── role_binding.yaml │ │ │ └── service_account.yaml │ │ ├── samples │ │ │ └── nodes_v1_nodepool.yaml │ │ ├── test │ │ │ └── node-patch.yaml │ │ └── webhook │ │ │ ├── kustomization.yaml │ │ │ ├── kustomizeconfig.yaml │ │ │ ├── manifests.yaml │ │ │ └── service.yaml │ ├── controllers │ │ ├── nodepool_controller.go │ │ └── suite_test.go │ ├── go.mod │ ├── go.sum │ ├── hack │ │ └── boilerplate.go.txt │ └── main.go ├── 06-node-pool-operator │ ├── .dockerignore │ ├── .gitignore │ ├── Dockerfile │ ├── Makefile │ ├── PROJECT │ ├── api │ │ └── v1 │ │ │ ├── groupversion_info.go │ │ │ ├── nodepool_types.go │ │ │ └── zz_generated.deepcopy.go │ ├── config │ │ ├── cert │ │ │ ├── ca.crt │ │ │ ├── ca.key │ │ │ ├── ca.srl │ │ │ ├── csr.conf │ │ │ ├── tls.crt │ │ │ ├── tls.csr │ │ │ └── tls.key │ │ ├── certmanager │ │ │ ├── certificate.yaml │ │ │ ├── kustomization.yaml │ │ │ └── kustomizeconfig.yaml │ │ ├── crd │ │ │ ├── bases │ │ │ │ └── nodes.lailin.xyz_nodepools.yaml │ │ │ ├── kustomization.yaml │ │ │ ├── kustomizeconfig.yaml │ │ │ └── patches │ │ │ │ ├── cainjection_in_nodepools.yaml │ │ │ │ └── webhook_in_nodepools.yaml │ │ ├── default │ │ │ ├── kustomization.yaml │ │ │ ├── manager_auth_proxy_patch.yaml │ │ │ ├── manager_config_patch.yaml │ │ │ ├── manager_webhook_patch.yaml │ │ │ └── webhookcainjection_patch.yaml │ │ ├── dev │ │ │ ├── kustomization.yaml │ │ │ └── webhook_patch.yaml │ │ ├── manager │ │ │ ├── controller_manager_config.yaml │ │ │ ├── kustomization.yaml │ │ │ └── manager.yaml │ │ ├── prometheus │ │ │ ├── kustomization.yaml │ │ │ └── monitor.yaml │ │ ├── rbac │ │ │ ├── auth_proxy_client_clusterrole.yaml │ │ │ ├── auth_proxy_role.yaml │ │ │ ├── auth_proxy_role_binding.yaml │ │ │ ├── auth_proxy_service.yaml │ │ │ ├── kustomization.yaml │ │ │ ├── leader_election_role.yaml │ │ │ ├── leader_election_role_binding.yaml │ │ │ ├── nodepool_editor_role.yaml │ │ │ ├── nodepool_viewer_role.yaml │ │ │ ├── role.yaml │ │ │ ├── role_binding.yaml │ │ │ └── service_account.yaml │ │ ├── samples │ │ │ └── nodes_v1_nodepool.yaml │ │ ├── test │ │ │ └── node-patch.yaml │ │ └── webhook │ │ │ ├── kustomization.yaml │ │ │ ├── kustomizeconfig.yaml │ │ │ ├── manifests.yaml │ │ │ └── service.yaml │ ├── controllers │ │ ├── nodepool_controller.go │ │ └── suite_test.go │ ├── go.mod │ ├── go.sum │ ├── hack │ │ └── boilerplate.go.txt │ └── main.go ├── 07-node-pool-operator │ ├── .dockerignore │ ├── .gitignore │ ├── Dockerfile │ ├── Makefile │ ├── PROJECT │ ├── api │ │ └── v1 │ │ │ ├── groupversion_info.go │ │ │ ├── nodepool_types.go │ │ │ ├── nodepool_types_test.go │ │ │ ├── nodepool_webhook.go │ │ │ ├── nodepool_webhook_test.go │ │ │ ├── webhook_suite_test.go │ │ │ └── zz_generated.deepcopy.go │ ├── config │ │ ├── cert │ │ │ ├── ca.crt │ │ │ ├── ca.key │ │ │ ├── ca.srl │ │ │ ├── csr.conf │ │ │ ├── tls.crt │ │ │ ├── tls.csr │ │ │ └── tls.key │ │ ├── certmanager │ │ │ ├── certificate.yaml │ │ │ ├── kustomization.yaml │ │ │ └── kustomizeconfig.yaml │ │ ├── crd │ │ │ ├── bases │ │ │ │ └── nodes.lailin.xyz_nodepools.yaml │ │ │ ├── kustomization.yaml │ │ │ ├── kustomizeconfig.yaml │ │ │ └── patches │ │ │ │ ├── cainjection_in_nodepools.yaml │ │ │ │ └── webhook_in_nodepools.yaml │ │ ├── default │ │ │ ├── kustomization.yaml │ │ │ ├── manager_auth_proxy_patch.yaml │ │ │ ├── manager_config_patch.yaml │ │ │ ├── manager_webhook_patch.yaml │ │ │ └── webhookcainjection_patch.yaml │ │ ├── dev │ │ │ ├── kustomization.yaml │ │ │ └── webhook_patch.yaml │ │ ├── manager │ │ │ ├── controller_manager_config.yaml │ │ │ ├── kustomization.yaml │ │ │ └── manager.yaml │ │ ├── prometheus │ │ │ ├── kustomization.yaml │ │ │ └── monitor.yaml │ │ ├── rbac │ │ │ ├── auth_proxy_client_clusterrole.yaml │ │ │ ├── auth_proxy_role.yaml │ │ │ ├── auth_proxy_role_binding.yaml │ │ │ ├── auth_proxy_service.yaml │ │ │ ├── kustomization.yaml │ │ │ ├── leader_election_role.yaml │ │ │ ├── leader_election_role_binding.yaml │ │ │ ├── nodepool_editor_role.yaml │ │ │ ├── nodepool_viewer_role.yaml │ │ │ ├── role.yaml │ │ │ ├── role_binding.yaml │ │ │ └── service_account.yaml │ │ ├── samples │ │ │ └── nodes_v1_nodepool.yaml │ │ └── webhook │ │ │ ├── kustomization.yaml │ │ │ ├── kustomizeconfig.yaml │ │ │ ├── manifests.yaml │ │ │ └── service.yaml │ ├── controllers │ │ ├── nodepool_controller.go │ │ └── suite_test.go │ ├── go.mod │ ├── go.sum │ ├── hack │ │ └── boilerplate.go.txt │ └── main.go ├── 08-node-pool-operator │ ├── .dockerignore │ ├── .gitignore │ ├── Dockerfile │ ├── Makefile │ ├── PROJECT │ ├── api │ │ └── v1 │ │ │ ├── groupversion_info.go │ │ │ ├── nodepool_types.go │ │ │ ├── nodepool_webhook.go │ │ │ ├── webhook_suite_test.go │ │ │ └── zz_generated.deepcopy.go │ ├── config │ │ ├── cert │ │ │ ├── ca.crt │ │ │ ├── ca.key │ │ │ ├── ca.srl │ │ │ ├── csr.conf │ │ │ ├── tls.crt │ │ │ ├── tls.csr │ │ │ └── tls.key │ │ ├── certmanager │ │ │ ├── certificate.yaml │ │ │ ├── kustomization.yaml │ │ │ └── kustomizeconfig.yaml │ │ ├── crd │ │ │ ├── bases │ │ │ │ └── nodes.lailin.xyz_nodepools.yaml │ │ │ ├── kustomization.yaml │ │ │ ├── kustomizeconfig.yaml │ │ │ └── patches │ │ │ │ ├── cainjection_in_nodepools.yaml │ │ │ │ └── webhook_in_nodepools.yaml │ │ ├── default │ │ │ ├── kustomization.yaml │ │ │ ├── manager_auth_proxy_patch.yaml │ │ │ ├── manager_config_patch.yaml │ │ │ ├── manager_webhook_patch.yaml │ │ │ └── webhookcainjection_patch.yaml │ │ ├── dev │ │ │ ├── kustomization.yaml │ │ │ └── webhook_patch.yaml │ │ ├── manager │ │ │ ├── controller_manager_config.yaml │ │ │ ├── kustomization.yaml │ │ │ └── manager.yaml │ │ ├── prometheus │ │ │ ├── kustomization.yaml │ │ │ └── monitor.yaml │ │ ├── rbac │ │ │ ├── auth_proxy_client_clusterrole.yaml │ │ │ ├── auth_proxy_role.yaml │ │ │ ├── auth_proxy_role_binding.yaml │ │ │ ├── auth_proxy_service.yaml │ │ │ ├── kustomization.yaml │ │ │ ├── leader_election_role.yaml │ │ │ ├── leader_election_role_binding.yaml │ │ │ ├── nodepool_editor_role.yaml │ │ │ ├── nodepool_viewer_role.yaml │ │ │ ├── role.yaml │ │ │ ├── role_binding.yaml │ │ │ └── service_account.yaml │ │ ├── samples │ │ │ └── nodes_v1_nodepool.yaml │ │ └── webhook │ │ │ ├── kustomization.yaml │ │ │ ├── kustomizeconfig.yaml │ │ │ ├── manifests.yaml │ │ │ └── service.yaml │ ├── controllers │ │ ├── nodepool_controller.go │ │ └── suite_test.go │ ├── go.mod │ ├── go.sum │ ├── hack │ │ └── boilerplate.go.txt │ └── main.go ├── multi-cluster-operator │ ├── .dockerignore │ ├── .gitignore │ ├── Dockerfile │ ├── Makefile │ ├── PROJECT │ ├── README.md │ ├── api │ │ └── v1 │ │ │ ├── groupversion_info.go │ │ │ ├── test_types.go │ │ │ └── zz_generated.deepcopy.go │ ├── config │ │ ├── crd │ │ │ ├── bases │ │ │ │ └── job.lailin.xyz_tests.yaml │ │ │ ├── kustomization.yaml │ │ │ ├── kustomizeconfig.yaml │ │ │ └── patches │ │ │ │ ├── cainjection_in_tests.yaml │ │ │ │ └── webhook_in_tests.yaml │ │ ├── default │ │ │ ├── kustomization.yaml │ │ │ ├── manager_auth_proxy_patch.yaml │ │ │ └── manager_config_patch.yaml │ │ ├── manager │ │ │ ├── controller_manager_config.yaml │ │ │ ├── kustomization.yaml │ │ │ └── manager.yaml │ │ ├── prometheus │ │ │ ├── kustomization.yaml │ │ │ └── monitor.yaml │ │ ├── rbac │ │ │ ├── auth_proxy_client_clusterrole.yaml │ │ │ ├── auth_proxy_role.yaml │ │ │ ├── auth_proxy_role_binding.yaml │ │ │ ├── auth_proxy_service.yaml │ │ │ ├── kustomization.yaml │ │ │ ├── leader_election_role.yaml │ │ │ ├── leader_election_role_binding.yaml │ │ │ ├── role.yaml │ │ │ ├── role_binding.yaml │ │ │ ├── service_account.yaml │ │ │ ├── test_editor_role.yaml │ │ │ └── test_viewer_role.yaml │ │ └── samples │ │ │ └── job_v1_test.yaml │ ├── controllers │ │ ├── suite_test.go │ │ ├── test_controller.go │ │ └── test_job_controller.go │ ├── go.mod │ ├── go.sum │ ├── hack │ │ └── boilerplate.go.txt │ ├── main.go │ └── pkg │ │ └── clusterx │ │ ├── clusters.go │ │ ├── enqueue.go │ │ └── owner.go └── operator-kubebuilder-clientset │ ├── .dockerignore │ ├── .gitignore │ ├── Dockerfile │ ├── Makefile │ ├── PROJECT │ ├── README.md │ ├── api │ └── job │ │ └── v1 │ │ ├── groupversion_info.go │ │ ├── test_types.go │ │ └── zz_generated.deepcopy.go │ ├── client-example │ ├── client-go │ │ └── main.go │ ├── clientset │ │ └── main.go │ └── controller-runtime │ │ └── main.go │ ├── config │ ├── crd │ │ ├── bases │ │ │ └── job.lailin.xyz_tests.yaml │ │ ├── kustomization.yaml │ │ ├── kustomizeconfig.yaml │ │ └── patches │ │ │ ├── cainjection_in_tests.yaml │ │ │ └── webhook_in_tests.yaml │ ├── default │ │ ├── kustomization.yaml │ │ ├── manager_auth_proxy_patch.yaml │ │ └── manager_config_patch.yaml │ ├── manager │ │ ├── kustomization.yaml │ │ └── manager.yaml │ ├── prometheus │ │ ├── kustomization.yaml │ │ └── monitor.yaml │ ├── rbac │ │ ├── auth_proxy_client_clusterrole.yaml │ │ ├── auth_proxy_role.yaml │ │ ├── auth_proxy_role_binding.yaml │ │ ├── auth_proxy_service.yaml │ │ ├── kustomization.yaml │ │ ├── leader_election_role.yaml │ │ ├── leader_election_role_binding.yaml │ │ ├── role.yaml │ │ ├── role_binding.yaml │ │ ├── service_account.yaml │ │ ├── test_editor_role.yaml │ │ └── test_viewer_role.yaml │ └── samples │ │ └── job_v1_test.yaml │ ├── controllers │ ├── suite_test.go │ └── test_controller.go │ ├── go.mod │ ├── go.sum │ ├── hack │ ├── boilerplate.go.txt │ ├── code_generator.go │ ├── gen-client.sh │ └── generate-groups.sh │ ├── main.go │ └── pkg │ └── clientset │ └── v1 │ ├── clientset.go │ ├── doc.go │ ├── fake │ ├── clientset_generated.go │ ├── doc.go │ └── register.go │ ├── scheme │ ├── doc.go │ └── register.go │ └── typed │ └── job │ └── v1 │ ├── doc.go │ ├── fake │ ├── doc.go │ ├── fake_job_client.go │ └── fake_test.go │ ├── generated_expansion.go │ ├── job_client.go │ └── test.go ├── 03-leetcode ├── 01_tree │ ├── 101-symmetric-tree.go │ ├── 105-construct-binary-tree-from-preorder-and-inorder-traversal.go │ ├── 105-construct-binary-tree-from-preorder-and-inorder-traversal_test.go │ ├── 113-path-sum-ii.go │ ├── 113-path-sum-ii_test.go │ ├── 124-binary-tree-maximum-path-sum.go │ ├── 124-binary-tree-maximum-path-sum_test.go │ ├── 199-binary-tree-right-side-view.go │ ├── 199-binary-tree-right-side-view_test.go │ ├── 230-kth-smallest-element-in-a-bst.go │ ├── 230-kth-smallest-element-in-a-bst_test.go │ ├── 543-diameter-of-binary-tree.go │ ├── 662-maximum-width-of-binary-tree.go │ ├── 662-maximum-width-of-binary-tree_test.go │ ├── 94-binary-tree-inorder-traversal.go │ ├── 958-check-completeness-of-a-binary-tree.go │ ├── 958-check-completeness-of-a-binary-tree_test.go │ ├── 98-validate-binary-search-tree.go │ ├── 98-validate-binary-search-tree_test.go │ └── tree.go ├── 02_search │ ├── 162-find-peak-element.go │ ├── 162-find-peak-element_test.go │ ├── 240-search-a-2d-matrix-ii.go │ ├── 862-shortest-subarray-with-sum-at-least-k.go │ └── 862-shortest-subarray-with-sum-at-least-k_test.go ├── 03_list │ ├── 141-linked-list-cycle.go │ ├── 143-reorder-list.go │ ├── 146-lru-cache.go │ ├── 146-lru-cache_test.go │ ├── 148-sort-list.go │ ├── 148-sort-list_test.go │ ├── 160-intersection-of-two-linked-lists.go │ ├── 160-intersection-of-two-linked-lists_test.go │ ├── 206-reverse-linked-list.go │ ├── 206-reverse-linked-list_test.go │ ├── 21-merge-two-sorted-lists.go │ ├── 23-merge-k-sorted-lists.go │ ├── 234-palindrome-linked-list.go │ ├── 234-palindrome-linked-list_test.go │ ├── 25-reverse-nodes-in-k-group.go │ ├── 25-reverse-nodes-in-k-group_test.go │ ├── 92-reverse-linked-list-ii.go │ ├── 92-reverse-linked-list-ii_test.go │ └── list.go ├── 04_stack │ ├── 155-min-stack.go │ ├── 20-valid-parentheses.go │ ├── 224-basic-calculator.go │ ├── 224-basic-calculator_test.go │ ├── 402-remove-k-digits.go │ ├── 402-remove-k-digits_test.go │ ├── 45-132-pattern.go │ ├── 45-132-pattern_test.go │ ├── 71-simplify-path.go │ ├── offer09-yong-liang-ge-zhan-shi-xian-dui-lie-lcof.go │ └── stack.go ├── 05_sort │ └── 56-merge-intervals.go ├── 06_hash │ ├── 1-two-sum.go │ ├── 3-longest-substring-without-repeating-characters.go │ ├── 3-longest-substring-without-repeating-characters_test.go │ ├── 76-minimum-window-substring.go │ └── 76-minimum-window-substring_test.go ├── 07_dp │ ├── 121-best-time-to-buy-and-sell-stock.go │ ├── 121-best-time-to-buy-and-sell-stock_test.go │ ├── 140-word-break-ii.go │ ├── 140-word-break-ii_test.go │ ├── 215-kth-largest-element-in-an-array.go │ ├── 215-kth-largest-element-in-an-array_test.go │ ├── 494-target-sum.go │ ├── 494-target-sum_test.go │ ├── 5-longest-palindromic-substring.go │ └── heap.go ├── go.mod └── go.sum ├── 99-other └── 01-localhost │ ├── Dockerfile │ ├── Makefile │ ├── go.mod │ ├── main.go │ ├── nsswitch.conf │ └── run.sh ├── LICENSE └── README.md /.gitignore: -------------------------------------------------------------------------------- 1 | # Binaries for programs and plugins 2 | *.exe 3 | *.exe~ 4 | *.dll 5 | *.so 6 | *.dylib 7 | 8 | # Test binary, built with `go test -c` 9 | *.test 10 | 11 | # Output of the go coverage tool, specifically when used with LiteIDE 12 | *.out 13 | 14 | # Dependency directories (remove the comment below to include it) 15 | # vendor/ 16 | 17 | bin/ 18 | .idea -------------------------------------------------------------------------------- /01-go-training/03-sync/01_goroutine/01/01.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "log" 5 | "net/http" 6 | _ "net/http/pprof" 7 | ) 8 | 9 | func setup() { 10 | // 这里面有一些初始化的操作 11 | } 12 | 13 | func main() { 14 | setup() 15 | 16 | // 主服务 17 | server() 18 | 19 | // for debug 20 | pprof() 21 | 22 | select {} 23 | } 24 | 25 | func server() { 26 | go func() { 27 | mux := http.NewServeMux() 28 | mux.HandleFunc("/ping", func(w http.ResponseWriter, r *http.Request) { 29 | w.Write([]byte("pong")) 30 | }) 31 | 32 | // 主服务 33 | if err := http.ListenAndServe(":8080", mux); err != nil { 34 | log.Panicf("http server err: %+v", err) 35 | return 36 | } 37 | }() 38 | } 39 | 40 | func pprof() { 41 | // 辅助服务,监听了其他端口,这里是 pprof 服务,用于 debug 42 | go http.ListenAndServe(":8081", nil) 43 | } 44 | -------------------------------------------------------------------------------- /01-go-training/03-sync/01_goroutine/02/02.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "log" 5 | "net/http" 6 | _ "net/http/pprof" 7 | ) 8 | 9 | func setup() { 10 | // 这里面有一些初始化的操作 11 | } 12 | 13 | func main() { 14 | setup() 15 | 16 | // for debug 17 | go pprof() 18 | 19 | // 主服务 20 | go server() 21 | 22 | select {} 23 | } 24 | 25 | func server() { 26 | mux := http.NewServeMux() 27 | mux.HandleFunc("/ping", func(w http.ResponseWriter, r *http.Request) { 28 | w.Write([]byte("pong")) 29 | }) 30 | 31 | // 主服务 32 | if err := http.ListenAndServe(":8080", mux); err != nil { 33 | log.Panicf("http server err: %+v", err) 34 | return 35 | } 36 | } 37 | 38 | func pprof() { 39 | // 辅助服务,监听了其他端口,这里是 pprof 服务,用于 debug 40 | http.ListenAndServe(":8081", nil) 41 | } 42 | -------------------------------------------------------------------------------- /01-go-training/03-sync/01_goroutine/03/03.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "log" 5 | "net/http" 6 | _ "net/http/pprof" 7 | ) 8 | 9 | func setup() { 10 | // 这里面有一些初始化的操作 11 | } 12 | 13 | func main() { 14 | setup() 15 | 16 | // for debug 17 | go pprof() 18 | 19 | // 主服务 20 | server() 21 | } 22 | 23 | func server() { 24 | mux := http.NewServeMux() 25 | mux.HandleFunc("/ping", func(w http.ResponseWriter, r *http.Request) { 26 | w.Write([]byte("pong")) 27 | }) 28 | 29 | // 主服务 30 | if err := http.ListenAndServe(":8080", mux); err != nil { 31 | log.Panicf("http server err: %+v", err) 32 | return 33 | } 34 | } 35 | 36 | func pprof() { 37 | // 辅助服务,监听了其他端口,这里是 pprof 服务,用于 debug 38 | http.ListenAndServe(":8081", nil) 39 | } 40 | -------------------------------------------------------------------------------- /01-go-training/03-sync/02_memery_model/01/01.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | var a, b int 4 | 5 | func f() { 6 | a = 1 7 | b = 2 8 | } 9 | 10 | func g() { 11 | print(b) 12 | print(a) 13 | } 14 | 15 | func main() { 16 | go f() 17 | g() 18 | } 19 | -------------------------------------------------------------------------------- /01-go-training/03-sync/03_data_race/01/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | "sync" 6 | ) 7 | 8 | var wg sync.WaitGroup 9 | var counter int 10 | 11 | func main() { 12 | // 多跑几次来看结果 13 | for i := 0; i < 100000; i++ { 14 | run() 15 | } 16 | } 17 | 18 | func run() { 19 | for i := 1; i <= 2; i++ { 20 | wg.Add(1) 21 | go routine(i) 22 | } 23 | wg.Wait() 24 | fmt.Printf("Final Counter: %d\n", counter) 25 | } 26 | 27 | func routine(id int) { 28 | for i := 0; i < 2; i++ { 29 | value := counter 30 | value++ 31 | counter = value 32 | } 33 | wg.Done() 34 | } 35 | -------------------------------------------------------------------------------- /01-go-training/03-sync/03_data_race/02/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | "sync" 6 | ) 7 | 8 | func main() { 9 | var wg sync.WaitGroup 10 | wg.Add(5) 11 | for i := 0; i < 5; i++ { 12 | go func(i int) { 13 | fmt.Println(i) 14 | wg.Done() 15 | }(i) 16 | } 17 | wg.Wait() 18 | } 19 | -------------------------------------------------------------------------------- /01-go-training/03-sync/03_data_race/03/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "os" 4 | 5 | func main() { 6 | ParallelWrite([]byte("xxx")) 7 | } 8 | 9 | // ParallelWrite writes data to file1 and file2, returns the errors. 10 | func ParallelWrite(data []byte) chan error { 11 | res := make(chan error, 2) 12 | f1, err := os.Create("/tmp/file1") 13 | if err != nil { 14 | res <- err 15 | } else { 16 | go func() { 17 | // This err is shared with the main goroutine, 18 | // so the write races with the write below. 19 | _, err = f1.Write(data) 20 | res <- err 21 | f1.Close() 22 | }() 23 | } 24 | f2, err := os.Create("/tmp/file2") // The second conflicting write to err. 25 | if err != nil { 26 | res <- err 27 | } else { 28 | go func() { 29 | _, err = f2.Write(data) 30 | res <- err 31 | f2.Close() 32 | }() 33 | } 34 | return res 35 | } 36 | -------------------------------------------------------------------------------- /01-go-training/03-sync/03_data_race/04/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "sync" 4 | 5 | func main() { 6 | var wg sync.WaitGroup 7 | 8 | for i := 0; i < 2; i++ { 9 | wg.Add(1) 10 | go func() { 11 | LookupService("xx") 12 | RegisterService("xx", "11") 13 | wg.Done() 14 | }() 15 | } 16 | 17 | wg.Wait() 18 | } 19 | 20 | var service = map[string]string{} 21 | 22 | // RegisterService RegisterService 23 | func RegisterService(name, addr string) { 24 | service[name] = addr 25 | } 26 | 27 | // LookupService LookupService 28 | func LookupService(name string) string { 29 | return service[name] 30 | } 31 | -------------------------------------------------------------------------------- /01-go-training/03-sync/03_data_race/05/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "fmt" 4 | 5 | type IceCreamMaker interface { 6 | // Great a customer. 7 | Hello() 8 | } 9 | 10 | type Ben struct { 11 | name string 12 | } 13 | 14 | func (b *Ben) Hello() { 15 | fmt.Printf("Ben says, \"Hello my name is %s\"\n", b.name) 16 | } 17 | 18 | type Jerry struct { 19 | name string 20 | } 21 | 22 | func (j *Jerry) Hello() { 23 | fmt.Printf("Jerry says, \"Hello my name is %s\"\n", j.name) 24 | } 25 | 26 | func main() { 27 | var ben = &Ben{name: "Ben"} 28 | var jerry = &Jerry{"Jerry"} 29 | var maker IceCreamMaker = ben 30 | 31 | var loop0, loop1 func() 32 | 33 | loop0 = func() { 34 | maker = ben 35 | go loop1() 36 | } 37 | 38 | loop1 = func() { 39 | maker = jerry 40 | go loop0() 41 | } 42 | 43 | go loop0() 44 | 45 | for { 46 | maker.Hello() 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /01-go-training/03-sync/04_mutex/01_mutex/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | "sync" 6 | ) 7 | 8 | var wg sync.WaitGroup 9 | var counter int 10 | var mu sync.Mutex 11 | 12 | func main() { 13 | for i := 1; i <= 2; i++ { 14 | wg.Add(1) 15 | go routine(i) 16 | } 17 | wg.Wait() 18 | fmt.Printf("Final Counter: %d\n", counter) 19 | } 20 | 21 | func routine(id int) { 22 | for i := 0; i < 2; i++ { 23 | mu.Lock() 24 | counter++ 25 | mu.Unlock() 26 | } 27 | wg.Done() 28 | } 29 | -------------------------------------------------------------------------------- /01-go-training/03-sync/04_mutex/02_rwmutex/main_test.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "testing" 5 | ) 6 | 7 | type iConfig interface { 8 | Get() []int 9 | Set([]int) 10 | } 11 | 12 | func bench(b *testing.B, c iConfig) { 13 | b.RunParallel(func(p *testing.PB) { 14 | for p.Next() { 15 | c.Set([]int{100}) 16 | c.Get() 17 | c.Get() 18 | c.Get() 19 | c.Set([]int{100}) 20 | c.Get() 21 | c.Get() 22 | } 23 | }) 24 | } 25 | 26 | func BenchmarkMutexConfig(b *testing.B) { 27 | conf := &MutexConfig{data: []int{1, 2, 3}} 28 | bench(b, conf) 29 | } 30 | 31 | func BenchmarkRWMutexConfig(b *testing.B) { 32 | conf := &RWMutexConfig{data: []int{1, 2, 3}} 33 | bench(b, conf) 34 | } 35 | -------------------------------------------------------------------------------- /01-go-training/03-sync/05_atomic/01_stack/main_test.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "testing" 5 | ) 6 | 7 | func BenchmarkNewLFStack(b *testing.B) { 8 | s := NewLFStack() 9 | b.RunParallel(func(p *testing.PB) { 10 | for p.Next() { 11 | s.Push(1) 12 | } 13 | }) 14 | } 15 | -------------------------------------------------------------------------------- /01-go-training/03-sync/05_atomic/main_test.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "testing" 5 | "time" 6 | ) 7 | 8 | type iConfig interface { 9 | Get() []int 10 | Set([]int) 11 | } 12 | 13 | func bench(b *testing.B, c iConfig) { 14 | go func() { 15 | for { 16 | time.Sleep(1000 * time.Nanosecond) 17 | c.Set([]int{100}) 18 | } 19 | }() 20 | b.RunParallel(func(p *testing.PB) { 21 | for p.Next() { 22 | c.Get() 23 | } 24 | }) 25 | } 26 | 27 | func BenchmarkMutexConfig(b *testing.B) { 28 | conf := &MutexConfig{data: []int{1, 2, 3}} 29 | bench(b, conf) 30 | } 31 | 32 | func BenchmarkRWMutexConfig(b *testing.B) { 33 | conf := &RWMutexConfig{data: []int{1, 2, 3}} 34 | bench(b, conf) 35 | } 36 | 37 | func BenchmarkConfig(b *testing.B) { 38 | conf := &Config{} 39 | conf.Set([]int{}) 40 | bench(b, conf) 41 | } 42 | -------------------------------------------------------------------------------- /01-go-training/03-sync/06_waitgroup/01/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | "sync" 6 | ) 7 | 8 | func worker(i int) { 9 | fmt.Println("worker: ", i) 10 | } 11 | 12 | func main() { 13 | var wg sync.WaitGroup 14 | for i := 0; i < 10; i++ { 15 | wg.Add(1) 16 | go func(i int) { 17 | defer wg.Done() 18 | worker(i) 19 | }(i) 20 | } 21 | wg.Wait() 22 | } 23 | -------------------------------------------------------------------------------- /01-go-training/03-sync/06_waitgroup/02/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "sync" 4 | 5 | func main() { 6 | var wg sync.WaitGroup 7 | wg2 := wg 8 | wg2.Wait() 9 | } 10 | -------------------------------------------------------------------------------- /01-go-training/03-sync/08_once/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | "sync" 6 | ) 7 | 8 | func main() { 9 | var ( 10 | o sync.Once 11 | wg sync.WaitGroup 12 | ) 13 | 14 | for i := 0; i < 10; i++ { 15 | wg.Add(1) 16 | 17 | go func(i int) { 18 | defer wg.Done() 19 | o.Do(func() { 20 | fmt.Println("once", i) 21 | }) 22 | }(i) 23 | } 24 | 25 | wg.Wait() 26 | } 27 | -------------------------------------------------------------------------------- /01-go-training/03-sync/09_context/03_value/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "context" 4 | 5 | var traceID = "trace_id" 6 | 7 | func f1(ctx context.Context) { 8 | 9 | } 10 | 11 | func main() { 12 | 13 | } 14 | -------------------------------------------------------------------------------- /01-go-training/03-sync/09_context/http_timeout/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "net/http" 5 | _ "net/http/pprof" 6 | "time" 7 | ) 8 | 9 | func main() { 10 | mux := http.NewServeMux() 11 | mux.HandleFunc("/", func(rw http.ResponseWriter, r *http.Request) { 12 | // 这里阻塞住,goroutine 不会释放的 13 | time.Sleep(1000 * time.Second) 14 | rw.Write([]byte("hello")) 15 | }) 16 | handler := http.TimeoutHandler(mux, time.Millisecond, "xxx") 17 | go func() { 18 | if err := http.ListenAndServe("0.0.0.0:8066", nil); err != nil { 19 | panic(err) 20 | } 21 | }() 22 | http.ListenAndServe(":8080", handler) 23 | } 24 | -------------------------------------------------------------------------------- /01-go-training/03-sync/10_channel/01_example/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | ) 6 | 7 | func read(c <-chan int) { 8 | fmt.Println("read:", <-c) 9 | } 10 | 11 | func write(c chan<- int) { 12 | c <- 0 13 | } 14 | 15 | func main() { 16 | c := make(chan int) 17 | go read(c) 18 | write(c) 19 | } 20 | -------------------------------------------------------------------------------- /01-go-training/03-sync/10_channel/02_close_notify/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | "time" 6 | ) 7 | 8 | func run(stop <-chan struct{}, done chan<- struct{}) { 9 | // 每一秒打印一次 hello 10 | for { 11 | select { 12 | case <-stop: 13 | fmt.Println("stop...") 14 | done <- struct{}{} 15 | return 16 | case <-time.After(time.Second): 17 | fmt.Println("hello") 18 | } 19 | } 20 | } 21 | 22 | func main() { 23 | // 一对多 24 | stop := make(chan struct{}) 25 | // 多对一 26 | done := make(chan struct{}, 10) 27 | for i := 0; i < 10; i++ { 28 | go run(stop, done) 29 | } 30 | 31 | // 5s 后退出 32 | time.Sleep(5 * time.Second) 33 | close(stop) 34 | 35 | for i := 0; i < 10; i++ { 36 | <-done 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /01-go-training/03-sync/10_channel/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | "time" 6 | ) 7 | 8 | type user struct { 9 | name string 10 | age int8 11 | } 12 | 13 | var u = user{name: "Ankur", age: 25} 14 | var g = u 15 | 16 | func modifyUser(pu *user) { 17 | fmt.Println("modifyUser Received Vaule", pu) 18 | pu.name = "Anand" 19 | } 20 | 21 | func printUser(u <-chan *user) { 22 | time.Sleep(2 * time.Second) 23 | fmt.Println("printUser goRoutine called", <-u) 24 | } 25 | 26 | func main() { 27 | c := make(chan *user, 5) 28 | c <- &g 29 | fmt.Println(g) 30 | // modify g 31 | g = user{name: "Ankur Anand", age: 100} 32 | go printUser(c) 33 | go modifyUser(&g) 34 | time.Sleep(5 * time.Second) 35 | fmt.Println(g) 36 | } 37 | -------------------------------------------------------------------------------- /01-go-training/04-project/10-layout/api/product/app/v1/v1_type.pb.go: -------------------------------------------------------------------------------- 1 | package v1 2 | 3 | import ( 4 | "encoding/json" 5 | errors "errors" 6 | ) 7 | 8 | // UnmarshalJSON sets *m to a copy of data. 9 | func (m *ListArticleTagsResp) UnmarshalJSON(data []byte) error { 10 | if m == nil { 11 | return errors.New("json.RawMessage: UnmarshalJSON on nil pointer") 12 | } 13 | 14 | return json.Unmarshal(data, &m.Tags) 15 | } 16 | 17 | // MarshalJSON returns m as the JSON encoding of m. 18 | func (m *ListArticleTagsResp) MarshalJSON() ([]byte, error) { 19 | if m == nil { 20 | return []byte("null"), nil 21 | } 22 | 23 | return json.Marshal(m.Tags) 24 | } 25 | -------------------------------------------------------------------------------- /01-go-training/04-project/10-layout/cmd/cron/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | -------------------------------------------------------------------------------- /01-go-training/04-project/10-layout/cmd/cron/wire.go: -------------------------------------------------------------------------------- 1 | package main 2 | -------------------------------------------------------------------------------- /01-go-training/04-project/10-layout/cmd/server/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "github.com/gin-gonic/gin" 4 | 5 | func main() { 6 | s, err := NewServices() 7 | if err != nil { 8 | panic(err) 9 | } 10 | 11 | e := gin.Default() 12 | s.register(e) 13 | 14 | // 这里还有优雅中止的一些代码,就不贴了 15 | } 16 | -------------------------------------------------------------------------------- /01-go-training/04-project/10-layout/cmd/server/server.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "github.com/gin-gonic/gin" 5 | "github.com/google/wire" 6 | v1 "github.com/mohuishou/new-project/api/product/app/v1" 7 | "github.com/mohuishou/new-project/config/initializer" 8 | "github.com/mohuishou/new-project/internal/server" 9 | "github.com/mohuishou/new-project/internal/server/service" 10 | ) 11 | 12 | var set = wire.NewSet( 13 | // domains 14 | server.Set, 15 | 16 | // common 17 | initializer.Set, 18 | ) 19 | 20 | type services struct { 21 | article *service.Artcile 22 | } 23 | 24 | func (s *services) register(r gin.IRouter) { 25 | v1.RegisterBlogServiceHTTPServer(r, s.article) 26 | } 27 | -------------------------------------------------------------------------------- /01-go-training/04-project/10-layout/cmd/server/wire.go: -------------------------------------------------------------------------------- 1 | //+build wireinject 2 | 3 | package main 4 | 5 | import ( 6 | "github.com/google/wire" 7 | ) 8 | 9 | // NewServices NewServices 10 | func NewServices() (*services, error) { 11 | panic(wire.Build( 12 | wire.Struct(new(services), "*"), 13 | set, 14 | )) 15 | } 16 | -------------------------------------------------------------------------------- /01-go-training/04-project/10-layout/config/initializer/gorm.go: -------------------------------------------------------------------------------- 1 | package initializer 2 | 3 | import "gorm.io/gorm" 4 | 5 | // NewGorm NewGorm 6 | func NewGorm() *gorm.DB { 7 | return nil 8 | } 9 | -------------------------------------------------------------------------------- /01-go-training/04-project/10-layout/config/initializer/wire_set.go: -------------------------------------------------------------------------------- 1 | package initializer 2 | 3 | import "github.com/google/wire" 4 | 5 | // Set Set 6 | var Set = wire.NewSet( 7 | NewGorm, 8 | ) 9 | -------------------------------------------------------------------------------- /01-go-training/04-project/10-layout/go.mod: -------------------------------------------------------------------------------- 1 | module github.com/mohuishou/new-project 2 | 3 | go 1.16 4 | 5 | require ( 6 | github.com/gin-gonic/gin v1.6.3 7 | github.com/golang/mock v1.5.0 8 | github.com/golang/protobuf v1.4.3 9 | github.com/google/wire v0.5.0 10 | github.com/pkg/errors v0.9.1 11 | github.com/stretchr/testify v1.5.1 12 | google.golang.org/genproto v0.0.0-20210303154014-9728d6b83eeb 13 | google.golang.org/grpc v1.36.0 14 | gorm.io/gorm v1.21.3 15 | ) 16 | -------------------------------------------------------------------------------- /01-go-training/04-project/10-layout/internal/cron/wire_set.go: -------------------------------------------------------------------------------- 1 | package cron 2 | -------------------------------------------------------------------------------- /01-go-training/04-project/10-layout/internal/domain/article_tag.go: -------------------------------------------------------------------------------- 1 | package domain 2 | 3 | // ArticleTag ArticleTag 4 | type ArticleTag struct { 5 | ArticleID uint 6 | TagID uint 7 | } 8 | -------------------------------------------------------------------------------- /01-go-training/04-project/10-layout/internal/domain/model.go: -------------------------------------------------------------------------------- 1 | package domain 2 | 3 | import ( 4 | "gorm.io/gorm" 5 | ) 6 | 7 | // Model 基础结构 8 | type Model gorm.Model 9 | -------------------------------------------------------------------------------- /01-go-training/04-project/10-layout/internal/domain/tag.go: -------------------------------------------------------------------------------- 1 | package domain 2 | 3 | // Tag 标签数据 4 | type Tag struct { 5 | Model 6 | 7 | Key string `json:"key"` 8 | Value string `json:"value"` 9 | } 10 | -------------------------------------------------------------------------------- /01-go-training/04-project/10-layout/internal/pkg/copier/copier.go: -------------------------------------------------------------------------------- 1 | package copier 2 | 3 | import ( 4 | "encoding/json" 5 | 6 | "github.com/pkg/errors" 7 | ) 8 | 9 | // Copy 从一个结构体复制到另一个结构体 10 | func Copy(to, from interface{}) error { 11 | b, err := json.Marshal(from) 12 | if err != nil { 13 | return errors.Wrap(err, "marshal from data err") 14 | } 15 | 16 | err = json.Unmarshal(b, to) 17 | if err != nil { 18 | return errors.Wrap(err, "unmarshal to data err") 19 | } 20 | 21 | return nil 22 | } 23 | -------------------------------------------------------------------------------- /01-go-training/04-project/10-layout/internal/server/wire_set.go: -------------------------------------------------------------------------------- 1 | package server 2 | 3 | import ( 4 | "github.com/google/wire" 5 | "github.com/mohuishou/new-project/internal/server/repo" 6 | "github.com/mohuishou/new-project/internal/server/service" 7 | "github.com/mohuishou/new-project/internal/server/usecase" 8 | ) 9 | 10 | // Set for di 11 | var Set = wire.NewSet( 12 | service.NewArticleService, 13 | usecase.NewArticleUsecase, 14 | repo.NewArticleRepo, 15 | ) 16 | -------------------------------------------------------------------------------- /01-go-training/04-project/10-layout/makefile: -------------------------------------------------------------------------------- 1 | proto_build: 2 | # 根据proto文件编译生成对应的go文件 3 | protoc -I ./api -I ./third_party/googleapis \ 4 | --openapiv2_out ./api --openapiv2_opt logtostderr=true \ 5 | --openapiv2_opt json_names_for_fields=false \ 6 | --go_out ./api --go_opt=paths=source_relative \ 7 | --go-gin_out ./api --go-gin_opt=paths=source_relative \ 8 | api/product/app/v1/*.proto 9 | protoc-go-inject-tag -input=./api/product/app/v1/v1.pb.go 10 | 11 | mockgen: 12 | cd ./internal && for file in `egrep -rnl "type.*?interface" ./domain | grep -v "_test" `; do \ 13 | echo $$file ; \ 14 | cd .. && mockgen -destination="./internal/pkg/mock/$$file" -source="./internal/$$file" && cd ./internal ; \ 15 | done -------------------------------------------------------------------------------- /01-go-training/04-project/10-layout/third_party/googleapis/README.grpc-gateway: -------------------------------------------------------------------------------- 1 | Google APIs 2 | ============ 3 | 4 | Project: Google APIs 5 | URL: https://github.com/google/googleapis 6 | Revision: a9fb190cdb78ed9bb2d6bb3fb5b9ef46effa5df3 7 | License: Apache License 2.0 8 | 9 | 10 | Imported Files 11 | --------------- 12 | 13 | - google/api/annotations.proto 14 | - google/api/http.proto 15 | 16 | 17 | Generated Files 18 | ---------------- 19 | 20 | They are generated from the .proto files by protoc-gen-go. 21 | - google/api/annotations.pb.go 22 | - google/api/http.pb.go 23 | -------------------------------------------------------------------------------- /01-go-training/12-runtime/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | func main() { 4 | data := a() 5 | _ = data 6 | } 7 | 8 | //go:noinline 9 | func a() int { 10 | ta := 2 11 | c := &ta 12 | _ = c 13 | return ta 14 | } 15 | 16 | //go:noinline 17 | func b() *int { 18 | tb := 2 19 | return &tb 20 | } 21 | -------------------------------------------------------------------------------- /02-k8s-operator/02-kind/kind-ha.yml: -------------------------------------------------------------------------------- 1 | kind: Cluster 2 | apiVersion: kind.x-k8s.io/v1alpha4 3 | nodes: 4 | - role: control-plane 5 | - role: worker 6 | - role: worker 7 | -------------------------------------------------------------------------------- /02-k8s-operator/02-kind/kind.yml: -------------------------------------------------------------------------------- 1 | kind: Cluster 2 | apiVersion: kind.x-k8s.io/v1alpha4 3 | nodes: 4 | - role: control-plane 5 | kubeadmConfigPatches: 6 | - | 7 | kind: InitConfiguration 8 | nodeRegistration: 9 | kubeletExtraArgs: 10 | pod-infra-container-image: registry.cn-hangzhou.aliyuncs.com/google_containers/pause-amd64:3.1 11 | - | 12 | kind: ClusterConfiguration 13 | imageRepository: registry.aliyuncs.com/google_containers 14 | - | 15 | kind: JoinConfiguration 16 | nodeRegistration: 17 | kubeletExtraArgs: 18 | pod-infra-container-image: registry.cn-hangzhou.aliyuncs.com/google_containers/pause-amd64:3.1 19 | -------------------------------------------------------------------------------- /02-k8s-operator/02-kind/nginx.yml: -------------------------------------------------------------------------------- 1 | apiVersion: apps/v1 2 | kind: Deployment 3 | metadata: 4 | name: nginx-deployment 5 | labels: 6 | app: nginx 7 | spec: 8 | replicas: 3 9 | selector: 10 | matchLabels: 11 | app: nginx 12 | template: 13 | metadata: 14 | labels: 15 | app: nginx 16 | spec: 17 | containers: 18 | - name: nginx 19 | image: nginx:1.14.2 20 | ports: 21 | - containerPort: 80 22 | -------------------------------------------------------------------------------- /02-k8s-operator/03-kubebuilder/.dockerignore: -------------------------------------------------------------------------------- 1 | # More info: https://docs.docker.com/engine/reference/builder/#dockerignore-file 2 | # Ignore all files which are not go type 3 | !**/*.go 4 | !**/*.mod 5 | !**/*.sum 6 | -------------------------------------------------------------------------------- /02-k8s-operator/03-kubebuilder/.gitignore: -------------------------------------------------------------------------------- 1 | 2 | # Binaries for programs and plugins 3 | *.exe 4 | *.exe~ 5 | *.dll 6 | *.so 7 | *.dylib 8 | bin 9 | testbin/* 10 | 11 | # Test binary, build with `go test -c` 12 | *.test 13 | 14 | # Output of the go coverage tool, specifically when used with LiteIDE 15 | *.out 16 | 17 | # Kubernetes Generated files - skip generated files, except for vendored files 18 | 19 | !vendor/**/zz_generated.* 20 | 21 | # editor and IDE paraphernalia 22 | .idea 23 | *.swp 24 | *.swo 25 | *~ 26 | -------------------------------------------------------------------------------- /02-k8s-operator/03-kubebuilder/PROJECT: -------------------------------------------------------------------------------- 1 | domain: lailin.xyz 2 | layout: 3 | - go.kubebuilder.io/v3 4 | projectName: 02-kubebuilder 5 | repo: github.com/mohuishou/blog-code/k8s-operator/02-kubebuilder 6 | resources: 7 | - api: 8 | crdVersion: v1 9 | namespaced: true 10 | controller: true 11 | domain: lailin.xyz 12 | group: apps 13 | kind: Application 14 | path: github.com/mohuishou/blog-code/k8s-operator/02-kubebuilder/api/v1 15 | version: v1 16 | version: "3" 17 | -------------------------------------------------------------------------------- /02-k8s-operator/03-kubebuilder/config/crd/kustomizeconfig.yaml: -------------------------------------------------------------------------------- 1 | # This file is for teaching kustomize how to substitute name and namespace reference in CRD 2 | nameReference: 3 | - kind: Service 4 | version: v1 5 | fieldSpecs: 6 | - kind: CustomResourceDefinition 7 | version: v1 8 | group: apiextensions.k8s.io 9 | path: spec/conversion/webhook/clientConfig/service/name 10 | 11 | namespace: 12 | - kind: CustomResourceDefinition 13 | version: v1 14 | group: apiextensions.k8s.io 15 | path: spec/conversion/webhook/clientConfig/service/namespace 16 | create: false 17 | 18 | varReference: 19 | - path: metadata/annotations 20 | -------------------------------------------------------------------------------- /02-k8s-operator/03-kubebuilder/config/crd/patches/cainjection_in_applications.yaml: -------------------------------------------------------------------------------- 1 | # The following patch adds a directive for certmanager to inject CA into the CRD 2 | apiVersion: apiextensions.k8s.io/v1 3 | kind: CustomResourceDefinition 4 | metadata: 5 | annotations: 6 | cert-manager.io/inject-ca-from: $(CERTIFICATE_NAMESPACE)/$(CERTIFICATE_NAME) 7 | name: applications.apps.lailin.xyz 8 | -------------------------------------------------------------------------------- /02-k8s-operator/03-kubebuilder/config/crd/patches/webhook_in_applications.yaml: -------------------------------------------------------------------------------- 1 | # The following patch enables a conversion webhook for the CRD 2 | apiVersion: apiextensions.k8s.io/v1 3 | kind: CustomResourceDefinition 4 | metadata: 5 | name: applications.apps.lailin.xyz 6 | spec: 7 | conversion: 8 | strategy: Webhook 9 | webhook: 10 | clientConfig: 11 | service: 12 | namespace: system 13 | name: webhook-service 14 | path: /convert 15 | -------------------------------------------------------------------------------- /02-k8s-operator/03-kubebuilder/config/default/manager_config_patch.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: apps/v1 2 | kind: Deployment 3 | metadata: 4 | name: controller-manager 5 | namespace: system 6 | spec: 7 | template: 8 | spec: 9 | containers: 10 | - name: manager 11 | args: 12 | - "--config=controller_manager_config.yaml" 13 | volumeMounts: 14 | - name: manager-config 15 | mountPath: /controller_manager_config.yaml 16 | subPath: controller_manager_config.yaml 17 | volumes: 18 | - name: manager-config 19 | configMap: 20 | name: manager-config 21 | -------------------------------------------------------------------------------- /02-k8s-operator/03-kubebuilder/config/manager/controller_manager_config.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: controller-runtime.sigs.k8s.io/v1alpha1 2 | kind: ControllerManagerConfig 3 | health: 4 | healthProbeBindAddress: :8081 5 | metrics: 6 | bindAddress: 127.0.0.1:8080 7 | webhook: 8 | port: 9443 9 | leaderElection: 10 | leaderElect: true 11 | resourceName: 6b62871a.lailin.xyz 12 | -------------------------------------------------------------------------------- /02-k8s-operator/03-kubebuilder/config/manager/kustomization.yaml: -------------------------------------------------------------------------------- 1 | resources: 2 | - manager.yaml 3 | 4 | generatorOptions: 5 | disableNameSuffixHash: true 6 | 7 | configMapGenerator: 8 | - name: manager-config 9 | files: 10 | - controller_manager_config.yaml 11 | -------------------------------------------------------------------------------- /02-k8s-operator/03-kubebuilder/config/prometheus/kustomization.yaml: -------------------------------------------------------------------------------- 1 | resources: 2 | - monitor.yaml 3 | -------------------------------------------------------------------------------- /02-k8s-operator/03-kubebuilder/config/prometheus/monitor.yaml: -------------------------------------------------------------------------------- 1 | 2 | # Prometheus Monitor Service (Metrics) 3 | apiVersion: monitoring.coreos.com/v1 4 | kind: ServiceMonitor 5 | metadata: 6 | labels: 7 | control-plane: controller-manager 8 | name: controller-manager-metrics-monitor 9 | namespace: system 10 | spec: 11 | endpoints: 12 | - path: /metrics 13 | port: https 14 | scheme: https 15 | bearerTokenFile: /var/run/secrets/kubernetes.io/serviceaccount/token 16 | tlsConfig: 17 | insecureSkipVerify: true 18 | selector: 19 | matchLabels: 20 | control-plane: controller-manager 21 | -------------------------------------------------------------------------------- /02-k8s-operator/03-kubebuilder/config/rbac/application_editor_role.yaml: -------------------------------------------------------------------------------- 1 | # permissions for end users to edit applications. 2 | apiVersion: rbac.authorization.k8s.io/v1 3 | kind: ClusterRole 4 | metadata: 5 | name: application-editor-role 6 | rules: 7 | - apiGroups: 8 | - apps.lailin.xyz 9 | resources: 10 | - applications 11 | verbs: 12 | - create 13 | - delete 14 | - get 15 | - list 16 | - patch 17 | - update 18 | - watch 19 | - apiGroups: 20 | - apps.lailin.xyz 21 | resources: 22 | - applications/status 23 | verbs: 24 | - get 25 | -------------------------------------------------------------------------------- /02-k8s-operator/03-kubebuilder/config/rbac/application_viewer_role.yaml: -------------------------------------------------------------------------------- 1 | # permissions for end users to view applications. 2 | apiVersion: rbac.authorization.k8s.io/v1 3 | kind: ClusterRole 4 | metadata: 5 | name: application-viewer-role 6 | rules: 7 | - apiGroups: 8 | - apps.lailin.xyz 9 | resources: 10 | - applications 11 | verbs: 12 | - get 13 | - list 14 | - watch 15 | - apiGroups: 16 | - apps.lailin.xyz 17 | resources: 18 | - applications/status 19 | verbs: 20 | - get 21 | -------------------------------------------------------------------------------- /02-k8s-operator/03-kubebuilder/config/rbac/auth_proxy_client_clusterrole.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: rbac.authorization.k8s.io/v1 2 | kind: ClusterRole 3 | metadata: 4 | name: metrics-reader 5 | rules: 6 | - nonResourceURLs: ["/metrics"] 7 | verbs: ["get"] 8 | -------------------------------------------------------------------------------- /02-k8s-operator/03-kubebuilder/config/rbac/auth_proxy_role.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: rbac.authorization.k8s.io/v1 2 | kind: ClusterRole 3 | metadata: 4 | name: proxy-role 5 | rules: 6 | - apiGroups: ["authentication.k8s.io"] 7 | resources: 8 | - tokenreviews 9 | verbs: ["create"] 10 | - apiGroups: ["authorization.k8s.io"] 11 | resources: 12 | - subjectaccessreviews 13 | verbs: ["create"] 14 | -------------------------------------------------------------------------------- /02-k8s-operator/03-kubebuilder/config/rbac/auth_proxy_role_binding.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: rbac.authorization.k8s.io/v1 2 | kind: ClusterRoleBinding 3 | metadata: 4 | name: proxy-rolebinding 5 | roleRef: 6 | apiGroup: rbac.authorization.k8s.io 7 | kind: ClusterRole 8 | name: proxy-role 9 | subjects: 10 | - kind: ServiceAccount 11 | name: controller-manager 12 | namespace: system 13 | -------------------------------------------------------------------------------- /02-k8s-operator/03-kubebuilder/config/rbac/auth_proxy_service.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Service 3 | metadata: 4 | labels: 5 | control-plane: controller-manager 6 | name: controller-manager-metrics-service 7 | namespace: system 8 | spec: 9 | ports: 10 | - name: https 11 | port: 8443 12 | targetPort: https 13 | selector: 14 | control-plane: controller-manager 15 | -------------------------------------------------------------------------------- /02-k8s-operator/03-kubebuilder/config/rbac/kustomization.yaml: -------------------------------------------------------------------------------- 1 | resources: 2 | # All RBAC will be applied under this service account in 3 | # the deployment namespace. You may comment out this resource 4 | # if your manager will use a service account that exists at 5 | # runtime. Be sure to update RoleBinding and ClusterRoleBinding 6 | # subjects if changing service account names. 7 | - service_account.yaml 8 | - role.yaml 9 | - role_binding.yaml 10 | - leader_election_role.yaml 11 | - leader_election_role_binding.yaml 12 | # Comment the following 4 lines if you want to disable 13 | # the auth proxy (https://github.com/brancz/kube-rbac-proxy) 14 | # which protects your /metrics endpoint. 15 | - auth_proxy_service.yaml 16 | - auth_proxy_role.yaml 17 | - auth_proxy_role_binding.yaml 18 | - auth_proxy_client_clusterrole.yaml 19 | -------------------------------------------------------------------------------- /02-k8s-operator/03-kubebuilder/config/rbac/leader_election_role.yaml: -------------------------------------------------------------------------------- 1 | # permissions to do leader election. 2 | apiVersion: rbac.authorization.k8s.io/v1 3 | kind: Role 4 | metadata: 5 | name: leader-election-role 6 | rules: 7 | - apiGroups: 8 | - "" 9 | - coordination.k8s.io 10 | resources: 11 | - configmaps 12 | - leases 13 | verbs: 14 | - get 15 | - list 16 | - watch 17 | - create 18 | - update 19 | - patch 20 | - delete 21 | - apiGroups: 22 | - "" 23 | resources: 24 | - events 25 | verbs: 26 | - create 27 | - patch 28 | -------------------------------------------------------------------------------- /02-k8s-operator/03-kubebuilder/config/rbac/leader_election_role_binding.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: rbac.authorization.k8s.io/v1 2 | kind: RoleBinding 3 | metadata: 4 | name: leader-election-rolebinding 5 | roleRef: 6 | apiGroup: rbac.authorization.k8s.io 7 | kind: Role 8 | name: leader-election-role 9 | subjects: 10 | - kind: ServiceAccount 11 | name: controller-manager 12 | namespace: system 13 | -------------------------------------------------------------------------------- /02-k8s-operator/03-kubebuilder/config/rbac/role.yaml: -------------------------------------------------------------------------------- 1 | 2 | --- 3 | apiVersion: rbac.authorization.k8s.io/v1 4 | kind: ClusterRole 5 | metadata: 6 | creationTimestamp: null 7 | name: manager-role 8 | rules: 9 | - apiGroups: 10 | - apps.lailin.xyz 11 | resources: 12 | - applications 13 | verbs: 14 | - create 15 | - delete 16 | - get 17 | - list 18 | - patch 19 | - update 20 | - watch 21 | - apiGroups: 22 | - apps.lailin.xyz 23 | resources: 24 | - applications/finalizers 25 | verbs: 26 | - update 27 | - apiGroups: 28 | - apps.lailin.xyz 29 | resources: 30 | - applications/status 31 | verbs: 32 | - get 33 | - patch 34 | - update 35 | -------------------------------------------------------------------------------- /02-k8s-operator/03-kubebuilder/config/rbac/role_binding.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: rbac.authorization.k8s.io/v1 2 | kind: ClusterRoleBinding 3 | metadata: 4 | name: manager-rolebinding 5 | roleRef: 6 | apiGroup: rbac.authorization.k8s.io 7 | kind: ClusterRole 8 | name: manager-role 9 | subjects: 10 | - kind: ServiceAccount 11 | name: controller-manager 12 | namespace: system 13 | -------------------------------------------------------------------------------- /02-k8s-operator/03-kubebuilder/config/rbac/service_account.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: ServiceAccount 3 | metadata: 4 | name: controller-manager 5 | namespace: system 6 | -------------------------------------------------------------------------------- /02-k8s-operator/03-kubebuilder/config/samples/apps_v1_application.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: apps.lailin.xyz/v1 2 | kind: Application 3 | metadata: 4 | name: application-sample 5 | spec: 6 | # Add fields here 7 | product: test 8 | -------------------------------------------------------------------------------- /02-k8s-operator/03-kubebuilder/go.mod: -------------------------------------------------------------------------------- 1 | module github.com/mohuishou/blog-code/k8s-operator/02-kubebuilder 2 | 3 | go 1.15 4 | 5 | require ( 6 | github.com/go-logr/logr v0.3.0 7 | github.com/onsi/ginkgo v1.14.1 8 | github.com/onsi/gomega v1.10.2 9 | k8s.io/apimachinery v0.19.2 10 | k8s.io/client-go v0.19.2 11 | sigs.k8s.io/controller-runtime v0.7.2 12 | ) 13 | -------------------------------------------------------------------------------- /02-k8s-operator/03-kubebuilder/hack/boilerplate.go.txt: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2021. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ -------------------------------------------------------------------------------- /02-k8s-operator/03-node-pool-operator/.dockerignore: -------------------------------------------------------------------------------- 1 | # More info: https://docs.docker.com/engine/reference/builder/#dockerignore-file 2 | # Ignore all files which are not go type 3 | !**/*.go 4 | !**/*.mod 5 | !**/*.sum 6 | -------------------------------------------------------------------------------- /02-k8s-operator/03-node-pool-operator/.gitignore: -------------------------------------------------------------------------------- 1 | 2 | # Binaries for programs and plugins 3 | *.exe 4 | *.exe~ 5 | *.dll 6 | *.so 7 | *.dylib 8 | bin 9 | testbin/* 10 | 11 | # Test binary, build with `go test -c` 12 | *.test 13 | 14 | # Output of the go coverage tool, specifically when used with LiteIDE 15 | *.out 16 | 17 | # Kubernetes Generated files - skip generated files, except for vendored files 18 | 19 | !vendor/**/zz_generated.* 20 | 21 | # editor and IDE paraphernalia 22 | .idea 23 | *.swp 24 | *.swo 25 | *~ 26 | -------------------------------------------------------------------------------- /02-k8s-operator/03-node-pool-operator/Dockerfile: -------------------------------------------------------------------------------- 1 | # Build the manager binary 2 | FROM golang:1.15 as builder 3 | 4 | WORKDIR /workspace 5 | # Copy the Go Modules manifests 6 | ENV GOPROXY="https://goproxy.cn" 7 | COPY go.mod go.mod 8 | COPY go.sum go.sum 9 | # cache deps before building and copying source so that we don't need to re-download as much 10 | # and so that source changes don't invalidate our downloaded layer 11 | RUN go mod download 12 | 13 | # Copy the go source 14 | COPY main.go main.go 15 | COPY api/ api/ 16 | COPY controllers/ controllers/ 17 | 18 | # Build 19 | RUN CGO_ENABLED=0 GOOS=linux GOARCH=amd64 GO111MODULE=on go build -a -o manager main.go 20 | 21 | FROM debian:10-slim 22 | WORKDIR / 23 | COPY --from=builder /workspace/manager . 24 | USER 65532:65532 25 | 26 | ENTRYPOINT ["/manager"] -------------------------------------------------------------------------------- /02-k8s-operator/03-node-pool-operator/PROJECT: -------------------------------------------------------------------------------- 1 | domain: lailin.xyz 2 | layout: 3 | - go.kubebuilder.io/v3 4 | projectName: 03-node-pool-operator 5 | repo: github.com/mohuishou/blog-code/k8s-operator/03-node-pool-operator 6 | resources: 7 | - api: 8 | crdVersion: v1 9 | namespaced: true 10 | controller: true 11 | domain: lailin.xyz 12 | group: nodes 13 | kind: NodePool 14 | path: github.com/mohuishou/blog-code/k8s-operator/03-node-pool-operator/api/v1 15 | version: v1 16 | webhooks: 17 | defaulting: true 18 | validation: true 19 | webhookVersion: v1 20 | version: "3" 21 | -------------------------------------------------------------------------------- /02-k8s-operator/03-node-pool-operator/config/cert/ca.srl: -------------------------------------------------------------------------------- 1 | DE97D427DC68A014 2 | -------------------------------------------------------------------------------- /02-k8s-operator/03-node-pool-operator/config/cert/csr.conf: -------------------------------------------------------------------------------- 1 | [ req ] 2 | default_bits = 2048 3 | prompt = no 4 | default_md = sha256 5 | req_extensions = req_ext 6 | distinguished_name = dn 7 | 8 | [ dn ] 9 | C = CN 10 | ST = Guangzhou 11 | L = Shenzhen 12 | CN = host.docker.internal 13 | 14 | [ req_ext ] 15 | subjectAltName = @alt_names 16 | 17 | [ alt_names ] 18 | DNS.1 = host.docker.internal 19 | 20 | [ v3_ext ] 21 | authorityKeyIdentifier=keyid,issuer:always 22 | basicConstraints=CA:FALSE 23 | keyUsage=keyEncipherment,dataEncipherment 24 | extendedKeyUsage=serverAuth,clientAuth 25 | subjectAltName=@alt_names 26 | -------------------------------------------------------------------------------- /02-k8s-operator/03-node-pool-operator/config/certmanager/kustomization.yaml: -------------------------------------------------------------------------------- 1 | resources: 2 | - certificate.yaml 3 | 4 | configurations: 5 | - kustomizeconfig.yaml 6 | -------------------------------------------------------------------------------- /02-k8s-operator/03-node-pool-operator/config/certmanager/kustomizeconfig.yaml: -------------------------------------------------------------------------------- 1 | # This configuration is for teaching kustomize how to update name ref and var substitution 2 | nameReference: 3 | - kind: Issuer 4 | group: cert-manager.io 5 | fieldSpecs: 6 | - kind: Certificate 7 | group: cert-manager.io 8 | path: spec/issuerRef/name 9 | 10 | varReference: 11 | - kind: Certificate 12 | group: cert-manager.io 13 | path: spec/commonName 14 | - kind: Certificate 15 | group: cert-manager.io 16 | path: spec/dnsNames 17 | -------------------------------------------------------------------------------- /02-k8s-operator/03-node-pool-operator/config/crd/kustomizeconfig.yaml: -------------------------------------------------------------------------------- 1 | # This file is for teaching kustomize how to substitute name and namespace reference in CRD 2 | nameReference: 3 | - kind: Service 4 | version: v1 5 | fieldSpecs: 6 | - kind: CustomResourceDefinition 7 | version: v1 8 | group: apiextensions.k8s.io 9 | path: spec/conversion/webhook/clientConfig/service/name 10 | 11 | namespace: 12 | - kind: CustomResourceDefinition 13 | version: v1 14 | group: apiextensions.k8s.io 15 | path: spec/conversion/webhook/clientConfig/service/namespace 16 | create: false 17 | 18 | varReference: 19 | - path: metadata/annotations 20 | -------------------------------------------------------------------------------- /02-k8s-operator/03-node-pool-operator/config/crd/patches/cainjection_in_nodepools.yaml: -------------------------------------------------------------------------------- 1 | # The following patch adds a directive for certmanager to inject CA into the CRD 2 | apiVersion: apiextensions.k8s.io/v1 3 | kind: CustomResourceDefinition 4 | metadata: 5 | annotations: 6 | cert-manager.io/inject-ca-from: $(CERTIFICATE_NAMESPACE)/$(CERTIFICATE_NAME) 7 | name: nodepools.nodes.lailin.xyz 8 | -------------------------------------------------------------------------------- /02-k8s-operator/03-node-pool-operator/config/crd/patches/webhook_in_nodepools.yaml: -------------------------------------------------------------------------------- 1 | # The following patch enables a conversion webhook for the CRD 2 | apiVersion: apiextensions.k8s.io/v1 3 | kind: CustomResourceDefinition 4 | metadata: 5 | name: nodepools.nodes.lailin.xyz 6 | spec: 7 | conversion: 8 | strategy: Webhook 9 | webhook: 10 | clientConfig: 11 | service: 12 | namespace: system 13 | name: webhook-service 14 | path: /convert 15 | -------------------------------------------------------------------------------- /02-k8s-operator/03-node-pool-operator/config/default/manager_config_patch.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: apps/v1 2 | kind: Deployment 3 | metadata: 4 | name: controller-manager 5 | namespace: system 6 | spec: 7 | template: 8 | spec: 9 | containers: 10 | - name: manager 11 | args: 12 | - "--config=controller_manager_config.yaml" 13 | volumeMounts: 14 | - name: manager-config 15 | mountPath: /controller_manager_config.yaml 16 | subPath: controller_manager_config.yaml 17 | volumes: 18 | - name: manager-config 19 | configMap: 20 | name: manager-config 21 | -------------------------------------------------------------------------------- /02-k8s-operator/03-node-pool-operator/config/default/manager_webhook_patch.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: apps/v1 2 | kind: Deployment 3 | metadata: 4 | name: controller-manager 5 | namespace: system 6 | spec: 7 | template: 8 | spec: 9 | containers: 10 | - name: manager 11 | ports: 12 | - containerPort: 9443 13 | name: webhook-server 14 | protocol: TCP 15 | volumeMounts: 16 | - mountPath: /tmp/k8s-webhook-server/serving-certs 17 | name: cert 18 | readOnly: true 19 | volumes: 20 | - name: cert 21 | secret: 22 | defaultMode: 420 23 | secretName: webhook-server-cert 24 | -------------------------------------------------------------------------------- /02-k8s-operator/03-node-pool-operator/config/default/webhookcainjection_patch.yaml: -------------------------------------------------------------------------------- 1 | # This patch add annotation to admission webhook config and 2 | # the variables $(CERTIFICATE_NAMESPACE) and $(CERTIFICATE_NAME) will be substituted by kustomize. 3 | apiVersion: admissionregistration.k8s.io/v1 4 | kind: MutatingWebhookConfiguration 5 | metadata: 6 | name: mutating-webhook-configuration 7 | annotations: 8 | cert-manager.io/inject-ca-from: $(CERTIFICATE_NAMESPACE)/$(CERTIFICATE_NAME) 9 | --- 10 | apiVersion: admissionregistration.k8s.io/v1 11 | kind: ValidatingWebhookConfiguration 12 | metadata: 13 | name: validating-webhook-configuration 14 | annotations: 15 | cert-manager.io/inject-ca-from: $(CERTIFICATE_NAMESPACE)/$(CERTIFICATE_NAME) 16 | -------------------------------------------------------------------------------- /02-k8s-operator/03-node-pool-operator/config/dev/kustomization.yaml: -------------------------------------------------------------------------------- 1 | resources: 2 | - ../default 3 | 4 | patches: 5 | - patch: | 6 | - op: "add" 7 | path: "/webhooks/0/clientConfig/url" 8 | value: "https://host.docker.internal:9443/mutate-nodes-lailin-xyz-v1-nodepool" 9 | target: 10 | kind: MutatingWebhookConfiguration 11 | - patch: | 12 | - op: "add" 13 | path: "/webhooks/0/clientConfig/url" 14 | value: "https://host.docker.internal:9443/validate-nodes-lailin-xyz-v1-nodepool" 15 | target: 16 | kind: ValidatingWebhookConfiguration 17 | - path: webhook_patch.yaml 18 | target: 19 | group: admissionregistration.k8s.io -------------------------------------------------------------------------------- /02-k8s-operator/03-node-pool-operator/config/manager/controller_manager_config.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: controller-runtime.sigs.k8s.io/v1alpha1 2 | kind: ControllerManagerConfig 3 | health: 4 | healthProbeBindAddress: :8081 5 | metrics: 6 | bindAddress: 127.0.0.1:8080 7 | webhook: 8 | port: 9443 9 | leaderElection: 10 | leaderElect: true 11 | resourceName: 97acaccf.lailin.xyz 12 | -------------------------------------------------------------------------------- /02-k8s-operator/03-node-pool-operator/config/manager/kustomization.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: kustomize.config.k8s.io/v1beta1 2 | kind: Kustomization 3 | 4 | resources: 5 | - manager.yaml 6 | 7 | generatorOptions: 8 | disableNameSuffixHash: true 9 | 10 | configMapGenerator: 11 | - files: 12 | - controller_manager_config.yaml 13 | name: manager-config 14 | 15 | images: 16 | - name: controller 17 | newName: controller 18 | newTag: latest 19 | -------------------------------------------------------------------------------- /02-k8s-operator/03-node-pool-operator/config/prometheus/kustomization.yaml: -------------------------------------------------------------------------------- 1 | resources: 2 | - monitor.yaml 3 | -------------------------------------------------------------------------------- /02-k8s-operator/03-node-pool-operator/config/prometheus/monitor.yaml: -------------------------------------------------------------------------------- 1 | 2 | # Prometheus Monitor Service (Metrics) 3 | apiVersion: monitoring.coreos.com/v1 4 | kind: ServiceMonitor 5 | metadata: 6 | labels: 7 | control-plane: controller-manager 8 | name: controller-manager-metrics-monitor 9 | namespace: system 10 | spec: 11 | endpoints: 12 | - path: /metrics 13 | port: https 14 | scheme: https 15 | bearerTokenFile: /var/run/secrets/kubernetes.io/serviceaccount/token 16 | tlsConfig: 17 | insecureSkipVerify: true 18 | selector: 19 | matchLabels: 20 | control-plane: controller-manager 21 | -------------------------------------------------------------------------------- /02-k8s-operator/03-node-pool-operator/config/rbac/auth_proxy_client_clusterrole.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: rbac.authorization.k8s.io/v1 2 | kind: ClusterRole 3 | metadata: 4 | name: metrics-reader 5 | rules: 6 | - nonResourceURLs: ["/metrics"] 7 | verbs: ["get"] 8 | -------------------------------------------------------------------------------- /02-k8s-operator/03-node-pool-operator/config/rbac/auth_proxy_role.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: rbac.authorization.k8s.io/v1 2 | kind: ClusterRole 3 | metadata: 4 | name: proxy-role 5 | rules: 6 | - apiGroups: ["authentication.k8s.io"] 7 | resources: 8 | - tokenreviews 9 | verbs: ["create"] 10 | - apiGroups: ["authorization.k8s.io"] 11 | resources: 12 | - subjectaccessreviews 13 | verbs: ["create"] 14 | -------------------------------------------------------------------------------- /02-k8s-operator/03-node-pool-operator/config/rbac/auth_proxy_role_binding.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: rbac.authorization.k8s.io/v1 2 | kind: ClusterRoleBinding 3 | metadata: 4 | name: proxy-rolebinding 5 | roleRef: 6 | apiGroup: rbac.authorization.k8s.io 7 | kind: ClusterRole 8 | name: proxy-role 9 | subjects: 10 | - kind: ServiceAccount 11 | name: controller-manager 12 | namespace: system 13 | -------------------------------------------------------------------------------- /02-k8s-operator/03-node-pool-operator/config/rbac/auth_proxy_service.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Service 3 | metadata: 4 | labels: 5 | control-plane: controller-manager 6 | name: controller-manager-metrics-service 7 | namespace: system 8 | spec: 9 | ports: 10 | - name: https 11 | port: 8443 12 | targetPort: https 13 | selector: 14 | control-plane: controller-manager 15 | -------------------------------------------------------------------------------- /02-k8s-operator/03-node-pool-operator/config/rbac/kustomization.yaml: -------------------------------------------------------------------------------- 1 | resources: 2 | # All RBAC will be applied under this service account in 3 | # the deployment namespace. You may comment out this resource 4 | # if your manager will use a service account that exists at 5 | # runtime. Be sure to update RoleBinding and ClusterRoleBinding 6 | # subjects if changing service account names. 7 | - service_account.yaml 8 | - role.yaml 9 | - role_binding.yaml 10 | - leader_election_role.yaml 11 | - leader_election_role_binding.yaml 12 | # Comment the following 4 lines if you want to disable 13 | # the auth proxy (https://github.com/brancz/kube-rbac-proxy) 14 | # which protects your /metrics endpoint. 15 | - auth_proxy_service.yaml 16 | - auth_proxy_role.yaml 17 | - auth_proxy_role_binding.yaml 18 | - auth_proxy_client_clusterrole.yaml 19 | -------------------------------------------------------------------------------- /02-k8s-operator/03-node-pool-operator/config/rbac/leader_election_role.yaml: -------------------------------------------------------------------------------- 1 | # permissions to do leader election. 2 | apiVersion: rbac.authorization.k8s.io/v1 3 | kind: Role 4 | metadata: 5 | name: leader-election-role 6 | rules: 7 | - apiGroups: 8 | - "" 9 | - coordination.k8s.io 10 | resources: 11 | - configmaps 12 | - leases 13 | verbs: 14 | - get 15 | - list 16 | - watch 17 | - create 18 | - update 19 | - patch 20 | - delete 21 | - apiGroups: 22 | - "" 23 | resources: 24 | - events 25 | verbs: 26 | - create 27 | - patch 28 | -------------------------------------------------------------------------------- /02-k8s-operator/03-node-pool-operator/config/rbac/leader_election_role_binding.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: rbac.authorization.k8s.io/v1 2 | kind: RoleBinding 3 | metadata: 4 | name: leader-election-rolebinding 5 | roleRef: 6 | apiGroup: rbac.authorization.k8s.io 7 | kind: Role 8 | name: leader-election-role 9 | subjects: 10 | - kind: ServiceAccount 11 | name: controller-manager 12 | namespace: system 13 | -------------------------------------------------------------------------------- /02-k8s-operator/03-node-pool-operator/config/rbac/nodepool_editor_role.yaml: -------------------------------------------------------------------------------- 1 | # permissions for end users to edit nodepools. 2 | apiVersion: rbac.authorization.k8s.io/v1 3 | kind: ClusterRole 4 | metadata: 5 | name: nodepool-editor-role 6 | rules: 7 | - apiGroups: 8 | - nodes.lailin.xyz 9 | resources: 10 | - nodepools 11 | verbs: 12 | - create 13 | - delete 14 | - get 15 | - list 16 | - patch 17 | - update 18 | - watch 19 | - apiGroups: 20 | - nodes.lailin.xyz 21 | resources: 22 | - nodepools/status 23 | verbs: 24 | - get 25 | -------------------------------------------------------------------------------- /02-k8s-operator/03-node-pool-operator/config/rbac/nodepool_viewer_role.yaml: -------------------------------------------------------------------------------- 1 | # permissions for end users to view nodepools. 2 | apiVersion: rbac.authorization.k8s.io/v1 3 | kind: ClusterRole 4 | metadata: 5 | name: nodepool-viewer-role 6 | rules: 7 | - apiGroups: 8 | - nodes.lailin.xyz 9 | resources: 10 | - nodepools 11 | verbs: 12 | - get 13 | - list 14 | - watch 15 | - apiGroups: 16 | - nodes.lailin.xyz 17 | resources: 18 | - nodepools/status 19 | verbs: 20 | - get 21 | -------------------------------------------------------------------------------- /02-k8s-operator/03-node-pool-operator/config/rbac/role.yaml: -------------------------------------------------------------------------------- 1 | 2 | --- 3 | apiVersion: rbac.authorization.k8s.io/v1 4 | kind: ClusterRole 5 | metadata: 6 | creationTimestamp: null 7 | name: manager-role 8 | rules: 9 | - apiGroups: 10 | - nodes.lailin.xyz 11 | resources: 12 | - nodepools 13 | verbs: 14 | - create 15 | - delete 16 | - get 17 | - list 18 | - patch 19 | - update 20 | - watch 21 | - apiGroups: 22 | - nodes.lailin.xyz 23 | resources: 24 | - nodepools/finalizers 25 | verbs: 26 | - update 27 | - apiGroups: 28 | - nodes.lailin.xyz 29 | resources: 30 | - nodepools/status 31 | verbs: 32 | - get 33 | - patch 34 | - update 35 | -------------------------------------------------------------------------------- /02-k8s-operator/03-node-pool-operator/config/rbac/role_binding.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: rbac.authorization.k8s.io/v1 2 | kind: ClusterRoleBinding 3 | metadata: 4 | name: manager-rolebinding 5 | roleRef: 6 | apiGroup: rbac.authorization.k8s.io 7 | kind: ClusterRole 8 | name: manager-role 9 | subjects: 10 | - kind: ServiceAccount 11 | name: controller-manager 12 | namespace: system 13 | -------------------------------------------------------------------------------- /02-k8s-operator/03-node-pool-operator/config/rbac/service_account.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: ServiceAccount 3 | metadata: 4 | name: controller-manager 5 | namespace: system 6 | -------------------------------------------------------------------------------- /02-k8s-operator/03-node-pool-operator/config/samples/nodes_v1_nodepool.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: nodes.lailin.xyz/v1 2 | kind: NodePool 3 | metadata: 4 | name: master 5 | spec: 6 | # taints: 7 | # - key: node-pool.lailin.xyz 8 | # value: master 9 | # effect: NoSchedule 10 | labels: 11 | "node-pool.lailin.xyz/master": "7" 12 | handler: runc 13 | -------------------------------------------------------------------------------- /02-k8s-operator/03-node-pool-operator/config/test/node-patch.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Node 3 | metedata: 4 | labels: 5 | a: b 6 | -------------------------------------------------------------------------------- /02-k8s-operator/03-node-pool-operator/config/webhook/kustomization.yaml: -------------------------------------------------------------------------------- 1 | resources: 2 | - manifests.yaml 3 | - service.yaml 4 | 5 | configurations: 6 | - kustomizeconfig.yaml 7 | -------------------------------------------------------------------------------- /02-k8s-operator/03-node-pool-operator/config/webhook/service.yaml: -------------------------------------------------------------------------------- 1 | 2 | apiVersion: v1 3 | kind: Service 4 | metadata: 5 | name: webhook-service 6 | namespace: system 7 | spec: 8 | ports: 9 | - port: 443 10 | targetPort: 9443 11 | selector: 12 | control-plane: controller-manager 13 | -------------------------------------------------------------------------------- /02-k8s-operator/03-node-pool-operator/go.mod: -------------------------------------------------------------------------------- 1 | module github.com/mohuishou/blog-code/k8s-operator/03-node-pool-operator 2 | 3 | go 1.15 4 | 5 | require ( 6 | github.com/go-logr/logr v0.3.0 7 | github.com/onsi/ginkgo v1.14.1 8 | github.com/onsi/gomega v1.10.2 9 | github.com/pkg/errors v0.9.1 10 | github.com/stretchr/testify v1.5.1 11 | k8s.io/api v0.19.2 12 | k8s.io/apimachinery v0.19.2 13 | k8s.io/client-go v0.19.2 14 | sigs.k8s.io/controller-runtime v0.7.2 15 | ) 16 | -------------------------------------------------------------------------------- /02-k8s-operator/03-node-pool-operator/hack/boilerplate.go.txt: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2021. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ -------------------------------------------------------------------------------- /02-k8s-operator/05-node-pool-operator/.dockerignore: -------------------------------------------------------------------------------- 1 | # More info: https://docs.docker.com/engine/reference/builder/#dockerignore-file 2 | # Ignore all files which are not go type 3 | !**/*.go 4 | !**/*.mod 5 | !**/*.sum 6 | -------------------------------------------------------------------------------- /02-k8s-operator/05-node-pool-operator/.gitignore: -------------------------------------------------------------------------------- 1 | 2 | # Binaries for programs and plugins 3 | *.exe 4 | *.exe~ 5 | *.dll 6 | *.so 7 | *.dylib 8 | bin 9 | testbin/* 10 | 11 | # Test binary, build with `go test -c` 12 | *.test 13 | 14 | # Output of the go coverage tool, specifically when used with LiteIDE 15 | *.out 16 | 17 | # Kubernetes Generated files - skip generated files, except for vendored files 18 | 19 | !vendor/**/zz_generated.* 20 | 21 | # editor and IDE paraphernalia 22 | .idea 23 | *.swp 24 | *.swo 25 | *~ 26 | -------------------------------------------------------------------------------- /02-k8s-operator/05-node-pool-operator/Dockerfile: -------------------------------------------------------------------------------- 1 | # Build the manager binary 2 | FROM golang:1.15 as builder 3 | 4 | WORKDIR /workspace 5 | # Copy the Go Modules manifests 6 | ENV GOPROXY="https://goproxy.cn" 7 | COPY go.mod go.mod 8 | COPY go.sum go.sum 9 | # cache deps before building and copying source so that we don't need to re-download as much 10 | # and so that source changes don't invalidate our downloaded layer 11 | RUN go mod download 12 | 13 | # Copy the go source 14 | COPY main.go main.go 15 | COPY api/ api/ 16 | COPY controllers/ controllers/ 17 | 18 | # Build 19 | RUN CGO_ENABLED=0 GOOS=linux GOARCH=amd64 GO111MODULE=on go build -a -o manager main.go 20 | 21 | FROM debian:10-slim 22 | WORKDIR / 23 | COPY --from=builder /workspace/manager . 24 | USER 65532:65532 25 | 26 | ENTRYPOINT ["/manager"] -------------------------------------------------------------------------------- /02-k8s-operator/05-node-pool-operator/PROJECT: -------------------------------------------------------------------------------- 1 | domain: lailin.xyz 2 | layout: 3 | - go.kubebuilder.io/v3 4 | projectName: 03-node-pool-operator 5 | repo: github.com/mohuishou/blog-code/k8s-operator/03-node-pool-operator 6 | resources: 7 | - api: 8 | crdVersion: v1 9 | namespaced: true 10 | controller: true 11 | domain: lailin.xyz 12 | group: nodes 13 | kind: NodePool 14 | path: github.com/mohuishou/blog-code/k8s-operator/03-node-pool-operator/api/v1 15 | version: v1 16 | webhooks: 17 | defaulting: true 18 | validation: true 19 | webhookVersion: v1 20 | version: "3" 21 | -------------------------------------------------------------------------------- /02-k8s-operator/05-node-pool-operator/config/cert/ca.srl: -------------------------------------------------------------------------------- 1 | DE97D427DC68A014 2 | -------------------------------------------------------------------------------- /02-k8s-operator/05-node-pool-operator/config/cert/csr.conf: -------------------------------------------------------------------------------- 1 | [ req ] 2 | default_bits = 2048 3 | prompt = no 4 | default_md = sha256 5 | req_extensions = req_ext 6 | distinguished_name = dn 7 | 8 | [ dn ] 9 | C = CN 10 | ST = Guangzhou 11 | L = Shenzhen 12 | CN = host.docker.internal 13 | 14 | [ req_ext ] 15 | subjectAltName = @alt_names 16 | 17 | [ alt_names ] 18 | DNS.1 = host.docker.internal 19 | 20 | [ v3_ext ] 21 | authorityKeyIdentifier=keyid,issuer:always 22 | basicConstraints=CA:FALSE 23 | keyUsage=keyEncipherment,dataEncipherment 24 | extendedKeyUsage=serverAuth,clientAuth 25 | subjectAltName=@alt_names 26 | -------------------------------------------------------------------------------- /02-k8s-operator/05-node-pool-operator/config/certmanager/kustomization.yaml: -------------------------------------------------------------------------------- 1 | resources: 2 | - certificate.yaml 3 | 4 | configurations: 5 | - kustomizeconfig.yaml 6 | -------------------------------------------------------------------------------- /02-k8s-operator/05-node-pool-operator/config/certmanager/kustomizeconfig.yaml: -------------------------------------------------------------------------------- 1 | # This configuration is for teaching kustomize how to update name ref and var substitution 2 | nameReference: 3 | - kind: Issuer 4 | group: cert-manager.io 5 | fieldSpecs: 6 | - kind: Certificate 7 | group: cert-manager.io 8 | path: spec/issuerRef/name 9 | 10 | varReference: 11 | - kind: Certificate 12 | group: cert-manager.io 13 | path: spec/commonName 14 | - kind: Certificate 15 | group: cert-manager.io 16 | path: spec/dnsNames 17 | -------------------------------------------------------------------------------- /02-k8s-operator/05-node-pool-operator/config/crd/kustomizeconfig.yaml: -------------------------------------------------------------------------------- 1 | # This file is for teaching kustomize how to substitute name and namespace reference in CRD 2 | nameReference: 3 | - kind: Service 4 | version: v1 5 | fieldSpecs: 6 | - kind: CustomResourceDefinition 7 | version: v1 8 | group: apiextensions.k8s.io 9 | path: spec/conversion/webhook/clientConfig/service/name 10 | 11 | namespace: 12 | - kind: CustomResourceDefinition 13 | version: v1 14 | group: apiextensions.k8s.io 15 | path: spec/conversion/webhook/clientConfig/service/namespace 16 | create: false 17 | 18 | varReference: 19 | - path: metadata/annotations 20 | -------------------------------------------------------------------------------- /02-k8s-operator/05-node-pool-operator/config/crd/patches/cainjection_in_nodepools.yaml: -------------------------------------------------------------------------------- 1 | # The following patch adds a directive for certmanager to inject CA into the CRD 2 | apiVersion: apiextensions.k8s.io/v1 3 | kind: CustomResourceDefinition 4 | metadata: 5 | annotations: 6 | cert-manager.io/inject-ca-from: $(CERTIFICATE_NAMESPACE)/$(CERTIFICATE_NAME) 7 | name: nodepools.nodes.lailin.xyz 8 | -------------------------------------------------------------------------------- /02-k8s-operator/05-node-pool-operator/config/crd/patches/webhook_in_nodepools.yaml: -------------------------------------------------------------------------------- 1 | # The following patch enables a conversion webhook for the CRD 2 | apiVersion: apiextensions.k8s.io/v1 3 | kind: CustomResourceDefinition 4 | metadata: 5 | name: nodepools.nodes.lailin.xyz 6 | spec: 7 | conversion: 8 | strategy: Webhook 9 | webhook: 10 | clientConfig: 11 | service: 12 | namespace: system 13 | name: webhook-service 14 | path: /convert 15 | -------------------------------------------------------------------------------- /02-k8s-operator/05-node-pool-operator/config/default/manager_config_patch.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: apps/v1 2 | kind: Deployment 3 | metadata: 4 | name: controller-manager 5 | namespace: system 6 | spec: 7 | template: 8 | spec: 9 | containers: 10 | - name: manager 11 | args: 12 | - "--config=controller_manager_config.yaml" 13 | volumeMounts: 14 | - name: manager-config 15 | mountPath: /controller_manager_config.yaml 16 | subPath: controller_manager_config.yaml 17 | volumes: 18 | - name: manager-config 19 | configMap: 20 | name: manager-config 21 | -------------------------------------------------------------------------------- /02-k8s-operator/05-node-pool-operator/config/default/manager_webhook_patch.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: apps/v1 2 | kind: Deployment 3 | metadata: 4 | name: controller-manager 5 | namespace: system 6 | spec: 7 | template: 8 | spec: 9 | containers: 10 | - name: manager 11 | ports: 12 | - containerPort: 9443 13 | name: webhook-server 14 | protocol: TCP 15 | volumeMounts: 16 | - mountPath: /tmp/k8s-webhook-server/serving-certs 17 | name: cert 18 | readOnly: true 19 | volumes: 20 | - name: cert 21 | secret: 22 | defaultMode: 420 23 | secretName: webhook-server-cert 24 | -------------------------------------------------------------------------------- /02-k8s-operator/05-node-pool-operator/config/default/webhookcainjection_patch.yaml: -------------------------------------------------------------------------------- 1 | # This patch add annotation to admission webhook config and 2 | # the variables $(CERTIFICATE_NAMESPACE) and $(CERTIFICATE_NAME) will be substituted by kustomize. 3 | apiVersion: admissionregistration.k8s.io/v1 4 | kind: MutatingWebhookConfiguration 5 | metadata: 6 | name: mutating-webhook-configuration 7 | annotations: 8 | cert-manager.io/inject-ca-from: $(CERTIFICATE_NAMESPACE)/$(CERTIFICATE_NAME) 9 | --- 10 | apiVersion: admissionregistration.k8s.io/v1 11 | kind: ValidatingWebhookConfiguration 12 | metadata: 13 | name: validating-webhook-configuration 14 | annotations: 15 | cert-manager.io/inject-ca-from: $(CERTIFICATE_NAMESPACE)/$(CERTIFICATE_NAME) 16 | -------------------------------------------------------------------------------- /02-k8s-operator/05-node-pool-operator/config/dev/kustomization.yaml: -------------------------------------------------------------------------------- 1 | resources: 2 | - ../default 3 | 4 | patches: 5 | - patch: | 6 | - op: "add" 7 | path: "/webhooks/0/clientConfig/url" 8 | value: "https://host.docker.internal:9443/mutate-nodes-lailin-xyz-v1-nodepool" 9 | target: 10 | kind: MutatingWebhookConfiguration 11 | - patch: | 12 | - op: "add" 13 | path: "/webhooks/0/clientConfig/url" 14 | value: "https://host.docker.internal:9443/validate-nodes-lailin-xyz-v1-nodepool" 15 | target: 16 | kind: ValidatingWebhookConfiguration 17 | - path: webhook_patch.yaml 18 | target: 19 | group: admissionregistration.k8s.io -------------------------------------------------------------------------------- /02-k8s-operator/05-node-pool-operator/config/manager/controller_manager_config.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: controller-runtime.sigs.k8s.io/v1alpha1 2 | kind: ControllerManagerConfig 3 | health: 4 | healthProbeBindAddress: :8081 5 | metrics: 6 | bindAddress: 127.0.0.1:8080 7 | webhook: 8 | port: 9443 9 | leaderElection: 10 | leaderElect: true 11 | resourceName: 97acaccf.lailin.xyz 12 | -------------------------------------------------------------------------------- /02-k8s-operator/05-node-pool-operator/config/manager/kustomization.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: kustomize.config.k8s.io/v1beta1 2 | kind: Kustomization 3 | 4 | resources: 5 | - manager.yaml 6 | 7 | generatorOptions: 8 | disableNameSuffixHash: true 9 | 10 | configMapGenerator: 11 | - files: 12 | - controller_manager_config.yaml 13 | name: manager-config 14 | 15 | images: 16 | - name: controller 17 | newName: controller 18 | newTag: latest 19 | -------------------------------------------------------------------------------- /02-k8s-operator/05-node-pool-operator/config/prometheus/kustomization.yaml: -------------------------------------------------------------------------------- 1 | resources: 2 | - monitor.yaml 3 | -------------------------------------------------------------------------------- /02-k8s-operator/05-node-pool-operator/config/prometheus/monitor.yaml: -------------------------------------------------------------------------------- 1 | 2 | # Prometheus Monitor Service (Metrics) 3 | apiVersion: monitoring.coreos.com/v1 4 | kind: ServiceMonitor 5 | metadata: 6 | labels: 7 | control-plane: controller-manager 8 | name: controller-manager-metrics-monitor 9 | namespace: system 10 | spec: 11 | endpoints: 12 | - path: /metrics 13 | port: https 14 | scheme: https 15 | bearerTokenFile: /var/run/secrets/kubernetes.io/serviceaccount/token 16 | tlsConfig: 17 | insecureSkipVerify: true 18 | selector: 19 | matchLabels: 20 | control-plane: controller-manager 21 | -------------------------------------------------------------------------------- /02-k8s-operator/05-node-pool-operator/config/rbac/auth_proxy_client_clusterrole.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: rbac.authorization.k8s.io/v1 2 | kind: ClusterRole 3 | metadata: 4 | name: metrics-reader 5 | rules: 6 | - nonResourceURLs: ["/metrics"] 7 | verbs: ["get"] 8 | -------------------------------------------------------------------------------- /02-k8s-operator/05-node-pool-operator/config/rbac/auth_proxy_role.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: rbac.authorization.k8s.io/v1 2 | kind: ClusterRole 3 | metadata: 4 | name: proxy-role 5 | rules: 6 | - apiGroups: ["authentication.k8s.io"] 7 | resources: 8 | - tokenreviews 9 | verbs: ["create"] 10 | - apiGroups: ["authorization.k8s.io"] 11 | resources: 12 | - subjectaccessreviews 13 | verbs: ["create"] 14 | -------------------------------------------------------------------------------- /02-k8s-operator/05-node-pool-operator/config/rbac/auth_proxy_role_binding.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: rbac.authorization.k8s.io/v1 2 | kind: ClusterRoleBinding 3 | metadata: 4 | name: proxy-rolebinding 5 | roleRef: 6 | apiGroup: rbac.authorization.k8s.io 7 | kind: ClusterRole 8 | name: proxy-role 9 | subjects: 10 | - kind: ServiceAccount 11 | name: controller-manager 12 | namespace: system 13 | -------------------------------------------------------------------------------- /02-k8s-operator/05-node-pool-operator/config/rbac/auth_proxy_service.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Service 3 | metadata: 4 | labels: 5 | control-plane: controller-manager 6 | name: controller-manager-metrics-service 7 | namespace: system 8 | spec: 9 | ports: 10 | - name: https 11 | port: 8443 12 | targetPort: https 13 | selector: 14 | control-plane: controller-manager 15 | -------------------------------------------------------------------------------- /02-k8s-operator/05-node-pool-operator/config/rbac/kustomization.yaml: -------------------------------------------------------------------------------- 1 | resources: 2 | # All RBAC will be applied under this service account in 3 | # the deployment namespace. You may comment out this resource 4 | # if your manager will use a service account that exists at 5 | # runtime. Be sure to update RoleBinding and ClusterRoleBinding 6 | # subjects if changing service account names. 7 | - service_account.yaml 8 | - role.yaml 9 | - role_binding.yaml 10 | - leader_election_role.yaml 11 | - leader_election_role_binding.yaml 12 | # Comment the following 4 lines if you want to disable 13 | # the auth proxy (https://github.com/brancz/kube-rbac-proxy) 14 | # which protects your /metrics endpoint. 15 | - auth_proxy_service.yaml 16 | - auth_proxy_role.yaml 17 | - auth_proxy_role_binding.yaml 18 | - auth_proxy_client_clusterrole.yaml 19 | -------------------------------------------------------------------------------- /02-k8s-operator/05-node-pool-operator/config/rbac/leader_election_role.yaml: -------------------------------------------------------------------------------- 1 | # permissions to do leader election. 2 | apiVersion: rbac.authorization.k8s.io/v1 3 | kind: Role 4 | metadata: 5 | name: leader-election-role 6 | rules: 7 | - apiGroups: 8 | - "" 9 | - coordination.k8s.io 10 | resources: 11 | - configmaps 12 | - leases 13 | verbs: 14 | - get 15 | - list 16 | - watch 17 | - create 18 | - update 19 | - patch 20 | - delete 21 | - apiGroups: 22 | - "" 23 | resources: 24 | - events 25 | verbs: 26 | - create 27 | - patch 28 | -------------------------------------------------------------------------------- /02-k8s-operator/05-node-pool-operator/config/rbac/leader_election_role_binding.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: rbac.authorization.k8s.io/v1 2 | kind: RoleBinding 3 | metadata: 4 | name: leader-election-rolebinding 5 | roleRef: 6 | apiGroup: rbac.authorization.k8s.io 7 | kind: Role 8 | name: leader-election-role 9 | subjects: 10 | - kind: ServiceAccount 11 | name: controller-manager 12 | namespace: system 13 | -------------------------------------------------------------------------------- /02-k8s-operator/05-node-pool-operator/config/rbac/nodepool_editor_role.yaml: -------------------------------------------------------------------------------- 1 | # permissions for end users to edit nodepools. 2 | apiVersion: rbac.authorization.k8s.io/v1 3 | kind: ClusterRole 4 | metadata: 5 | name: nodepool-editor-role 6 | rules: 7 | - apiGroups: 8 | - nodes.lailin.xyz 9 | resources: 10 | - nodepools 11 | verbs: 12 | - create 13 | - delete 14 | - get 15 | - list 16 | - patch 17 | - update 18 | - watch 19 | - apiGroups: 20 | - nodes.lailin.xyz 21 | resources: 22 | - nodepools/status 23 | verbs: 24 | - get 25 | -------------------------------------------------------------------------------- /02-k8s-operator/05-node-pool-operator/config/rbac/nodepool_viewer_role.yaml: -------------------------------------------------------------------------------- 1 | # permissions for end users to view nodepools. 2 | apiVersion: rbac.authorization.k8s.io/v1 3 | kind: ClusterRole 4 | metadata: 5 | name: nodepool-viewer-role 6 | rules: 7 | - apiGroups: 8 | - nodes.lailin.xyz 9 | resources: 10 | - nodepools 11 | verbs: 12 | - get 13 | - list 14 | - watch 15 | - apiGroups: 16 | - nodes.lailin.xyz 17 | resources: 18 | - nodepools/status 19 | verbs: 20 | - get 21 | -------------------------------------------------------------------------------- /02-k8s-operator/05-node-pool-operator/config/rbac/role.yaml: -------------------------------------------------------------------------------- 1 | 2 | --- 3 | apiVersion: rbac.authorization.k8s.io/v1 4 | kind: ClusterRole 5 | metadata: 6 | creationTimestamp: null 7 | name: manager-role 8 | rules: 9 | - apiGroups: 10 | - nodes.lailin.xyz 11 | resources: 12 | - nodepools 13 | verbs: 14 | - create 15 | - delete 16 | - get 17 | - list 18 | - patch 19 | - update 20 | - watch 21 | - apiGroups: 22 | - nodes.lailin.xyz 23 | resources: 24 | - nodepools/finalizers 25 | verbs: 26 | - update 27 | - apiGroups: 28 | - nodes.lailin.xyz 29 | resources: 30 | - nodepools/status 31 | verbs: 32 | - get 33 | - patch 34 | - update 35 | -------------------------------------------------------------------------------- /02-k8s-operator/05-node-pool-operator/config/rbac/role_binding.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: rbac.authorization.k8s.io/v1 2 | kind: ClusterRoleBinding 3 | metadata: 4 | name: manager-rolebinding 5 | roleRef: 6 | apiGroup: rbac.authorization.k8s.io 7 | kind: ClusterRole 8 | name: manager-role 9 | subjects: 10 | - kind: ServiceAccount 11 | name: controller-manager 12 | namespace: system 13 | -------------------------------------------------------------------------------- /02-k8s-operator/05-node-pool-operator/config/rbac/service_account.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: ServiceAccount 3 | metadata: 4 | name: controller-manager 5 | namespace: system 6 | -------------------------------------------------------------------------------- /02-k8s-operator/05-node-pool-operator/config/samples/nodes_v1_nodepool.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: nodes.lailin.xyz/v1 2 | kind: NodePool 3 | metadata: 4 | name: master 5 | spec: 6 | taints: 7 | - key: node-pool.lailin.xyz 8 | value: master 9 | effect: NoSchedule 10 | labels: 11 | "node-pool.lailin.xyz/master": "10" 12 | handler: runc 13 | -------------------------------------------------------------------------------- /02-k8s-operator/05-node-pool-operator/config/test/node-patch.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Node 3 | metedata: 4 | labels: 5 | a: b 6 | -------------------------------------------------------------------------------- /02-k8s-operator/05-node-pool-operator/config/webhook/kustomization.yaml: -------------------------------------------------------------------------------- 1 | resources: 2 | - manifests.yaml 3 | - service.yaml 4 | 5 | configurations: 6 | - kustomizeconfig.yaml 7 | -------------------------------------------------------------------------------- /02-k8s-operator/05-node-pool-operator/config/webhook/service.yaml: -------------------------------------------------------------------------------- 1 | 2 | apiVersion: v1 3 | kind: Service 4 | metadata: 5 | name: webhook-service 6 | namespace: system 7 | spec: 8 | ports: 9 | - port: 443 10 | targetPort: 9443 11 | selector: 12 | control-plane: controller-manager 13 | -------------------------------------------------------------------------------- /02-k8s-operator/05-node-pool-operator/go.mod: -------------------------------------------------------------------------------- 1 | module github.com/mohuishou/blog-code/k8s-operator/05-node-pool-operator 2 | 3 | go 1.15 4 | 5 | require ( 6 | github.com/go-logr/logr v0.3.0 7 | github.com/onsi/ginkgo v1.14.1 8 | github.com/onsi/gomega v1.10.2 9 | github.com/pkg/errors v0.9.1 10 | github.com/stretchr/testify v1.5.1 11 | k8s.io/api v0.19.2 12 | k8s.io/apimachinery v0.19.2 13 | k8s.io/client-go v0.19.2 14 | sigs.k8s.io/controller-runtime v0.7.2 15 | ) 16 | -------------------------------------------------------------------------------- /02-k8s-operator/05-node-pool-operator/hack/boilerplate.go.txt: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2021. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ -------------------------------------------------------------------------------- /02-k8s-operator/06-node-pool-operator/.dockerignore: -------------------------------------------------------------------------------- 1 | # More info: https://docs.docker.com/engine/reference/builder/#dockerignore-file 2 | # Ignore all files which are not go type 3 | !**/*.go 4 | !**/*.mod 5 | !**/*.sum 6 | -------------------------------------------------------------------------------- /02-k8s-operator/06-node-pool-operator/.gitignore: -------------------------------------------------------------------------------- 1 | 2 | # Binaries for programs and plugins 3 | *.exe 4 | *.exe~ 5 | *.dll 6 | *.so 7 | *.dylib 8 | bin 9 | testbin/* 10 | 11 | # Test binary, build with `go test -c` 12 | *.test 13 | 14 | # Output of the go coverage tool, specifically when used with LiteIDE 15 | *.out 16 | 17 | # Kubernetes Generated files - skip generated files, except for vendored files 18 | 19 | !vendor/**/zz_generated.* 20 | 21 | # editor and IDE paraphernalia 22 | .idea 23 | *.swp 24 | *.swo 25 | *~ 26 | -------------------------------------------------------------------------------- /02-k8s-operator/06-node-pool-operator/Dockerfile: -------------------------------------------------------------------------------- 1 | # Build the manager binary 2 | FROM golang:1.15 as builder 3 | 4 | WORKDIR /workspace 5 | # Copy the Go Modules manifests 6 | ENV GOPROXY="https://goproxy.cn" 7 | COPY go.mod go.mod 8 | COPY go.sum go.sum 9 | # cache deps before building and copying source so that we don't need to re-download as much 10 | # and so that source changes don't invalidate our downloaded layer 11 | RUN go mod download 12 | 13 | # Copy the go source 14 | COPY main.go main.go 15 | COPY api/ api/ 16 | COPY controllers/ controllers/ 17 | 18 | # Build 19 | RUN CGO_ENABLED=0 GOOS=linux GOARCH=amd64 GO111MODULE=on go build -a -o manager main.go 20 | 21 | FROM debian:10-slim 22 | WORKDIR / 23 | COPY --from=builder /workspace/manager . 24 | USER 65532:65532 25 | 26 | ENTRYPOINT ["/manager"] -------------------------------------------------------------------------------- /02-k8s-operator/06-node-pool-operator/PROJECT: -------------------------------------------------------------------------------- 1 | domain: lailin.xyz 2 | layout: 3 | - go.kubebuilder.io/v3 4 | projectName: node-pool-operator 5 | repo: github.com/mohuishou/blog-code/k8s-operator/node-pool-operator 6 | resources: 7 | - api: 8 | crdVersion: v1 9 | namespaced: true 10 | controller: true 11 | domain: lailin.xyz 12 | group: nodes 13 | kind: NodePool 14 | path: github.com/mohuishou/blog-code/k8s-operator/node-pool-operator/api/v1 15 | version: v1 16 | webhooks: 17 | defaulting: true 18 | validation: true 19 | webhookVersion: v1 20 | version: "3" 21 | -------------------------------------------------------------------------------- /02-k8s-operator/06-node-pool-operator/config/cert/ca.srl: -------------------------------------------------------------------------------- 1 | DE97D427DC68A014 2 | -------------------------------------------------------------------------------- /02-k8s-operator/06-node-pool-operator/config/cert/csr.conf: -------------------------------------------------------------------------------- 1 | [ req ] 2 | default_bits = 2048 3 | prompt = no 4 | default_md = sha256 5 | req_extensions = req_ext 6 | distinguished_name = dn 7 | 8 | [ dn ] 9 | C = CN 10 | ST = Guangzhou 11 | L = Shenzhen 12 | CN = host.docker.internal 13 | 14 | [ req_ext ] 15 | subjectAltName = @alt_names 16 | 17 | [ alt_names ] 18 | DNS.1 = host.docker.internal 19 | 20 | [ v3_ext ] 21 | authorityKeyIdentifier=keyid,issuer:always 22 | basicConstraints=CA:FALSE 23 | keyUsage=keyEncipherment,dataEncipherment 24 | extendedKeyUsage=serverAuth,clientAuth 25 | subjectAltName=@alt_names 26 | -------------------------------------------------------------------------------- /02-k8s-operator/06-node-pool-operator/config/certmanager/kustomization.yaml: -------------------------------------------------------------------------------- 1 | resources: 2 | - certificate.yaml 3 | 4 | configurations: 5 | - kustomizeconfig.yaml 6 | -------------------------------------------------------------------------------- /02-k8s-operator/06-node-pool-operator/config/certmanager/kustomizeconfig.yaml: -------------------------------------------------------------------------------- 1 | # This configuration is for teaching kustomize how to update name ref and var substitution 2 | nameReference: 3 | - kind: Issuer 4 | group: cert-manager.io 5 | fieldSpecs: 6 | - kind: Certificate 7 | group: cert-manager.io 8 | path: spec/issuerRef/name 9 | 10 | varReference: 11 | - kind: Certificate 12 | group: cert-manager.io 13 | path: spec/commonName 14 | - kind: Certificate 15 | group: cert-manager.io 16 | path: spec/dnsNames 17 | -------------------------------------------------------------------------------- /02-k8s-operator/06-node-pool-operator/config/crd/kustomizeconfig.yaml: -------------------------------------------------------------------------------- 1 | # This file is for teaching kustomize how to substitute name and namespace reference in CRD 2 | nameReference: 3 | - kind: Service 4 | version: v1 5 | fieldSpecs: 6 | - kind: CustomResourceDefinition 7 | version: v1 8 | group: apiextensions.k8s.io 9 | path: spec/conversion/webhook/clientConfig/service/name 10 | 11 | namespace: 12 | - kind: CustomResourceDefinition 13 | version: v1 14 | group: apiextensions.k8s.io 15 | path: spec/conversion/webhook/clientConfig/service/namespace 16 | create: false 17 | 18 | varReference: 19 | - path: metadata/annotations 20 | -------------------------------------------------------------------------------- /02-k8s-operator/06-node-pool-operator/config/crd/patches/cainjection_in_nodepools.yaml: -------------------------------------------------------------------------------- 1 | # The following patch adds a directive for certmanager to inject CA into the CRD 2 | apiVersion: apiextensions.k8s.io/v1 3 | kind: CustomResourceDefinition 4 | metadata: 5 | annotations: 6 | cert-manager.io/inject-ca-from: $(CERTIFICATE_NAMESPACE)/$(CERTIFICATE_NAME) 7 | name: nodepools.nodes.lailin.xyz 8 | -------------------------------------------------------------------------------- /02-k8s-operator/06-node-pool-operator/config/crd/patches/webhook_in_nodepools.yaml: -------------------------------------------------------------------------------- 1 | # The following patch enables a conversion webhook for the CRD 2 | apiVersion: apiextensions.k8s.io/v1 3 | kind: CustomResourceDefinition 4 | metadata: 5 | name: nodepools.nodes.lailin.xyz 6 | spec: 7 | conversion: 8 | strategy: Webhook 9 | webhook: 10 | clientConfig: 11 | service: 12 | namespace: system 13 | name: webhook-service 14 | path: /convert 15 | -------------------------------------------------------------------------------- /02-k8s-operator/06-node-pool-operator/config/default/manager_config_patch.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: apps/v1 2 | kind: Deployment 3 | metadata: 4 | name: controller-manager 5 | namespace: system 6 | spec: 7 | template: 8 | spec: 9 | containers: 10 | - name: manager 11 | args: 12 | - "--config=controller_manager_config.yaml" 13 | volumeMounts: 14 | - name: manager-config 15 | mountPath: /controller_manager_config.yaml 16 | subPath: controller_manager_config.yaml 17 | volumes: 18 | - name: manager-config 19 | configMap: 20 | name: manager-config 21 | -------------------------------------------------------------------------------- /02-k8s-operator/06-node-pool-operator/config/default/manager_webhook_patch.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: apps/v1 2 | kind: Deployment 3 | metadata: 4 | name: controller-manager 5 | namespace: system 6 | spec: 7 | template: 8 | spec: 9 | containers: 10 | - name: manager 11 | ports: 12 | - containerPort: 9443 13 | name: webhook-server 14 | protocol: TCP 15 | volumeMounts: 16 | - mountPath: /tmp/k8s-webhook-server/serving-certs 17 | name: cert 18 | readOnly: true 19 | volumes: 20 | - name: cert 21 | secret: 22 | defaultMode: 420 23 | secretName: webhook-server-cert 24 | -------------------------------------------------------------------------------- /02-k8s-operator/06-node-pool-operator/config/default/webhookcainjection_patch.yaml: -------------------------------------------------------------------------------- 1 | # This patch add annotation to admission webhook config and 2 | # the variables $(CERTIFICATE_NAMESPACE) and $(CERTIFICATE_NAME) will be substituted by kustomize. 3 | apiVersion: admissionregistration.k8s.io/v1 4 | kind: MutatingWebhookConfiguration 5 | metadata: 6 | name: mutating-webhook-configuration 7 | annotations: 8 | cert-manager.io/inject-ca-from: $(CERTIFICATE_NAMESPACE)/$(CERTIFICATE_NAME) 9 | --- 10 | apiVersion: admissionregistration.k8s.io/v1 11 | kind: ValidatingWebhookConfiguration 12 | metadata: 13 | name: validating-webhook-configuration 14 | annotations: 15 | cert-manager.io/inject-ca-from: $(CERTIFICATE_NAMESPACE)/$(CERTIFICATE_NAME) 16 | -------------------------------------------------------------------------------- /02-k8s-operator/06-node-pool-operator/config/dev/kustomization.yaml: -------------------------------------------------------------------------------- 1 | resources: 2 | - ../default 3 | 4 | patches: 5 | - patch: | 6 | - op: "add" 7 | path: "/webhooks/0/clientConfig/url" 8 | value: "https://host.docker.internal:9443/mutate-nodes-lailin-xyz-v1-nodepool" 9 | target: 10 | kind: MutatingWebhookConfiguration 11 | - patch: | 12 | - op: "add" 13 | path: "/webhooks/0/clientConfig/url" 14 | value: "https://host.docker.internal:9443/validate-nodes-lailin-xyz-v1-nodepool" 15 | target: 16 | kind: ValidatingWebhookConfiguration 17 | - path: webhook_patch.yaml 18 | target: 19 | group: admissionregistration.k8s.io -------------------------------------------------------------------------------- /02-k8s-operator/06-node-pool-operator/config/manager/controller_manager_config.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: controller-runtime.sigs.k8s.io/v1alpha1 2 | kind: ControllerManagerConfig 3 | health: 4 | healthProbeBindAddress: :8081 5 | metrics: 6 | bindAddress: 127.0.0.1:8080 7 | webhook: 8 | port: 9443 9 | leaderElection: 10 | leaderElect: true 11 | resourceName: 97acaccf.lailin.xyz 12 | -------------------------------------------------------------------------------- /02-k8s-operator/06-node-pool-operator/config/manager/kustomization.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: kustomize.config.k8s.io/v1beta1 2 | kind: Kustomization 3 | 4 | resources: 5 | - manager.yaml 6 | 7 | generatorOptions: 8 | disableNameSuffixHash: true 9 | 10 | configMapGenerator: 11 | - files: 12 | - controller_manager_config.yaml 13 | name: manager-config 14 | 15 | images: 16 | - name: controller 17 | newName: controller 18 | newTag: latest 19 | -------------------------------------------------------------------------------- /02-k8s-operator/06-node-pool-operator/config/prometheus/kustomization.yaml: -------------------------------------------------------------------------------- 1 | resources: 2 | - monitor.yaml 3 | -------------------------------------------------------------------------------- /02-k8s-operator/06-node-pool-operator/config/prometheus/monitor.yaml: -------------------------------------------------------------------------------- 1 | 2 | # Prometheus Monitor Service (Metrics) 3 | apiVersion: monitoring.coreos.com/v1 4 | kind: ServiceMonitor 5 | metadata: 6 | labels: 7 | control-plane: controller-manager 8 | name: controller-manager-metrics-monitor 9 | namespace: system 10 | spec: 11 | endpoints: 12 | - path: /metrics 13 | port: https 14 | scheme: https 15 | bearerTokenFile: /var/run/secrets/kubernetes.io/serviceaccount/token 16 | tlsConfig: 17 | insecureSkipVerify: true 18 | selector: 19 | matchLabels: 20 | control-plane: controller-manager 21 | -------------------------------------------------------------------------------- /02-k8s-operator/06-node-pool-operator/config/rbac/auth_proxy_client_clusterrole.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: rbac.authorization.k8s.io/v1 2 | kind: ClusterRole 3 | metadata: 4 | name: metrics-reader 5 | rules: 6 | - nonResourceURLs: ["/metrics"] 7 | verbs: ["get"] 8 | -------------------------------------------------------------------------------- /02-k8s-operator/06-node-pool-operator/config/rbac/auth_proxy_role.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: rbac.authorization.k8s.io/v1 2 | kind: ClusterRole 3 | metadata: 4 | name: proxy-role 5 | rules: 6 | - apiGroups: ["authentication.k8s.io"] 7 | resources: 8 | - tokenreviews 9 | verbs: ["create"] 10 | - apiGroups: ["authorization.k8s.io"] 11 | resources: 12 | - subjectaccessreviews 13 | verbs: ["create"] 14 | -------------------------------------------------------------------------------- /02-k8s-operator/06-node-pool-operator/config/rbac/auth_proxy_role_binding.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: rbac.authorization.k8s.io/v1 2 | kind: ClusterRoleBinding 3 | metadata: 4 | name: proxy-rolebinding 5 | roleRef: 6 | apiGroup: rbac.authorization.k8s.io 7 | kind: ClusterRole 8 | name: proxy-role 9 | subjects: 10 | - kind: ServiceAccount 11 | name: controller-manager 12 | namespace: system 13 | -------------------------------------------------------------------------------- /02-k8s-operator/06-node-pool-operator/config/rbac/auth_proxy_service.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Service 3 | metadata: 4 | labels: 5 | control-plane: controller-manager 6 | name: controller-manager-metrics-service 7 | namespace: system 8 | spec: 9 | ports: 10 | - name: https 11 | port: 8443 12 | targetPort: https 13 | selector: 14 | control-plane: controller-manager 15 | -------------------------------------------------------------------------------- /02-k8s-operator/06-node-pool-operator/config/rbac/kustomization.yaml: -------------------------------------------------------------------------------- 1 | resources: 2 | # All RBAC will be applied under this service account in 3 | # the deployment namespace. You may comment out this resource 4 | # if your manager will use a service account that exists at 5 | # runtime. Be sure to update RoleBinding and ClusterRoleBinding 6 | # subjects if changing service account names. 7 | - service_account.yaml 8 | - role.yaml 9 | - role_binding.yaml 10 | - leader_election_role.yaml 11 | - leader_election_role_binding.yaml 12 | # Comment the following 4 lines if you want to disable 13 | # the auth proxy (https://github.com/brancz/kube-rbac-proxy) 14 | # which protects your /metrics endpoint. 15 | - auth_proxy_service.yaml 16 | - auth_proxy_role.yaml 17 | - auth_proxy_role_binding.yaml 18 | - auth_proxy_client_clusterrole.yaml 19 | -------------------------------------------------------------------------------- /02-k8s-operator/06-node-pool-operator/config/rbac/leader_election_role.yaml: -------------------------------------------------------------------------------- 1 | # permissions to do leader election. 2 | apiVersion: rbac.authorization.k8s.io/v1 3 | kind: Role 4 | metadata: 5 | name: leader-election-role 6 | rules: 7 | - apiGroups: 8 | - "" 9 | - coordination.k8s.io 10 | resources: 11 | - configmaps 12 | - leases 13 | verbs: 14 | - get 15 | - list 16 | - watch 17 | - create 18 | - update 19 | - patch 20 | - delete 21 | - apiGroups: 22 | - "" 23 | resources: 24 | - events 25 | verbs: 26 | - create 27 | - patch 28 | -------------------------------------------------------------------------------- /02-k8s-operator/06-node-pool-operator/config/rbac/leader_election_role_binding.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: rbac.authorization.k8s.io/v1 2 | kind: RoleBinding 3 | metadata: 4 | name: leader-election-rolebinding 5 | roleRef: 6 | apiGroup: rbac.authorization.k8s.io 7 | kind: Role 8 | name: leader-election-role 9 | subjects: 10 | - kind: ServiceAccount 11 | name: controller-manager 12 | namespace: system 13 | -------------------------------------------------------------------------------- /02-k8s-operator/06-node-pool-operator/config/rbac/nodepool_editor_role.yaml: -------------------------------------------------------------------------------- 1 | # permissions for end users to edit nodepools. 2 | apiVersion: rbac.authorization.k8s.io/v1 3 | kind: ClusterRole 4 | metadata: 5 | name: nodepool-editor-role 6 | rules: 7 | - apiGroups: 8 | - nodes.lailin.xyz 9 | resources: 10 | - nodepools 11 | verbs: 12 | - create 13 | - delete 14 | - get 15 | - list 16 | - patch 17 | - update 18 | - watch 19 | - apiGroups: 20 | - nodes.lailin.xyz 21 | resources: 22 | - nodepools/status 23 | verbs: 24 | - get 25 | -------------------------------------------------------------------------------- /02-k8s-operator/06-node-pool-operator/config/rbac/nodepool_viewer_role.yaml: -------------------------------------------------------------------------------- 1 | # permissions for end users to view nodepools. 2 | apiVersion: rbac.authorization.k8s.io/v1 3 | kind: ClusterRole 4 | metadata: 5 | name: nodepool-viewer-role 6 | rules: 7 | - apiGroups: 8 | - nodes.lailin.xyz 9 | resources: 10 | - nodepools 11 | verbs: 12 | - get 13 | - list 14 | - watch 15 | - apiGroups: 16 | - nodes.lailin.xyz 17 | resources: 18 | - nodepools/status 19 | verbs: 20 | - get 21 | -------------------------------------------------------------------------------- /02-k8s-operator/06-node-pool-operator/config/rbac/role.yaml: -------------------------------------------------------------------------------- 1 | 2 | --- 3 | apiVersion: rbac.authorization.k8s.io/v1 4 | kind: ClusterRole 5 | metadata: 6 | creationTimestamp: null 7 | name: manager-role 8 | rules: 9 | - apiGroups: 10 | - nodes.lailin.xyz 11 | resources: 12 | - nodepools 13 | verbs: 14 | - create 15 | - delete 16 | - get 17 | - list 18 | - patch 19 | - update 20 | - watch 21 | - apiGroups: 22 | - nodes.lailin.xyz 23 | resources: 24 | - nodepools/finalizers 25 | verbs: 26 | - update 27 | - apiGroups: 28 | - nodes.lailin.xyz 29 | resources: 30 | - nodepools/status 31 | verbs: 32 | - get 33 | - patch 34 | - update 35 | -------------------------------------------------------------------------------- /02-k8s-operator/06-node-pool-operator/config/rbac/role_binding.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: rbac.authorization.k8s.io/v1 2 | kind: ClusterRoleBinding 3 | metadata: 4 | name: manager-rolebinding 5 | roleRef: 6 | apiGroup: rbac.authorization.k8s.io 7 | kind: ClusterRole 8 | name: manager-role 9 | subjects: 10 | - kind: ServiceAccount 11 | name: controller-manager 12 | namespace: system 13 | -------------------------------------------------------------------------------- /02-k8s-operator/06-node-pool-operator/config/rbac/service_account.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: ServiceAccount 3 | metadata: 4 | name: controller-manager 5 | namespace: system 6 | -------------------------------------------------------------------------------- /02-k8s-operator/06-node-pool-operator/config/samples/nodes_v1_nodepool.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: nodes.lailin.xyz/v1 2 | kind: NodePool 3 | metadata: 4 | name: worker 5 | spec: 6 | taints: 7 | - key: node-pool.lailin.xyz 8 | value: worker 9 | effect: NoSchedule 10 | labels: 11 | "node-pool.lailin.xyz/worker": "10" 12 | handler: runc 13 | -------------------------------------------------------------------------------- /02-k8s-operator/06-node-pool-operator/config/test/node-patch.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Node 3 | metedata: 4 | labels: 5 | a: b 6 | -------------------------------------------------------------------------------- /02-k8s-operator/06-node-pool-operator/config/webhook/kustomization.yaml: -------------------------------------------------------------------------------- 1 | resources: 2 | - manifests.yaml 3 | - service.yaml 4 | 5 | configurations: 6 | - kustomizeconfig.yaml 7 | -------------------------------------------------------------------------------- /02-k8s-operator/06-node-pool-operator/config/webhook/service.yaml: -------------------------------------------------------------------------------- 1 | 2 | apiVersion: v1 3 | kind: Service 4 | metadata: 5 | name: webhook-service 6 | namespace: system 7 | spec: 8 | ports: 9 | - port: 443 10 | targetPort: 9443 11 | selector: 12 | control-plane: controller-manager 13 | -------------------------------------------------------------------------------- /02-k8s-operator/06-node-pool-operator/go.mod: -------------------------------------------------------------------------------- 1 | module github.com/mohuishou/blog-code/k8s-operator/node-pool-operator 2 | 3 | go 1.15 4 | 5 | require ( 6 | github.com/go-logr/logr v0.3.0 7 | github.com/onsi/ginkgo v1.14.1 8 | github.com/onsi/gomega v1.10.2 9 | github.com/pkg/errors v0.9.1 10 | github.com/stretchr/testify v1.5.1 11 | k8s.io/api v0.19.2 12 | k8s.io/apimachinery v0.19.2 13 | k8s.io/client-go v0.19.2 14 | sigs.k8s.io/controller-runtime v0.7.2 15 | ) 16 | -------------------------------------------------------------------------------- /02-k8s-operator/06-node-pool-operator/hack/boilerplate.go.txt: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2021. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ -------------------------------------------------------------------------------- /02-k8s-operator/07-node-pool-operator/.dockerignore: -------------------------------------------------------------------------------- 1 | # More info: https://docs.docker.com/engine/reference/builder/#dockerignore-file 2 | # Ignore all files which are not go type 3 | !**/*.go 4 | !**/*.mod 5 | !**/*.sum 6 | -------------------------------------------------------------------------------- /02-k8s-operator/07-node-pool-operator/.gitignore: -------------------------------------------------------------------------------- 1 | 2 | # Binaries for programs and plugins 3 | *.exe 4 | *.exe~ 5 | *.dll 6 | *.so 7 | *.dylib 8 | bin 9 | testbin/* 10 | 11 | # Test binary, build with `go test -c` 12 | *.test 13 | 14 | # Output of the go coverage tool, specifically when used with LiteIDE 15 | *.out 16 | 17 | # Kubernetes Generated files - skip generated files, except for vendored files 18 | 19 | !vendor/**/zz_generated.* 20 | 21 | # editor and IDE paraphernalia 22 | .idea 23 | *.swp 24 | *.swo 25 | *~ 26 | -------------------------------------------------------------------------------- /02-k8s-operator/07-node-pool-operator/Dockerfile: -------------------------------------------------------------------------------- 1 | # Build the manager binary 2 | FROM golang:1.15 as builder 3 | 4 | WORKDIR /workspace 5 | # Copy the Go Modules manifests 6 | ENV GOPROXY="https://goproxy.cn" 7 | COPY go.mod go.mod 8 | COPY go.sum go.sum 9 | # cache deps before building and copying source so that we don't need to re-download as much 10 | # and so that source changes don't invalidate our downloaded layer 11 | RUN go mod download 12 | 13 | # Copy the go source 14 | COPY main.go main.go 15 | COPY api/ api/ 16 | COPY controllers/ controllers/ 17 | 18 | # Build 19 | RUN CGO_ENABLED=0 GOOS=linux GOARCH=amd64 GO111MODULE=on go build -a -o manager main.go 20 | 21 | FROM debian:10-slim 22 | WORKDIR / 23 | COPY --from=builder /workspace/manager . 24 | USER 65532:65532 25 | 26 | ENTRYPOINT ["/manager"] -------------------------------------------------------------------------------- /02-k8s-operator/07-node-pool-operator/PROJECT: -------------------------------------------------------------------------------- 1 | domain: lailin.xyz 2 | layout: 3 | - go.kubebuilder.io/v3 4 | projectName: node-pool-operator 5 | repo: github.com/mohuishou/blog-code/k8s-operator/node-pool-operator 6 | resources: 7 | - api: 8 | crdVersion: v1 9 | namespaced: true 10 | controller: true 11 | domain: lailin.xyz 12 | group: nodes 13 | kind: NodePool 14 | path: github.com/mohuishou/blog-code/k8s-operator/node-pool-operator/api/v1 15 | version: v1 16 | webhooks: 17 | defaulting: true 18 | validation: true 19 | webhookVersion: v1 20 | version: "3" 21 | -------------------------------------------------------------------------------- /02-k8s-operator/07-node-pool-operator/config/cert/ca.srl: -------------------------------------------------------------------------------- 1 | DE97D427DC68A014 2 | -------------------------------------------------------------------------------- /02-k8s-operator/07-node-pool-operator/config/cert/csr.conf: -------------------------------------------------------------------------------- 1 | [ req ] 2 | default_bits = 2048 3 | prompt = no 4 | default_md = sha256 5 | req_extensions = req_ext 6 | distinguished_name = dn 7 | 8 | [ dn ] 9 | C = CN 10 | ST = Guangzhou 11 | L = Shenzhen 12 | CN = host.docker.internal 13 | 14 | [ req_ext ] 15 | subjectAltName = @alt_names 16 | 17 | [ alt_names ] 18 | DNS.1 = host.docker.internal 19 | 20 | [ v3_ext ] 21 | authorityKeyIdentifier=keyid,issuer:always 22 | basicConstraints=CA:FALSE 23 | keyUsage=keyEncipherment,dataEncipherment 24 | extendedKeyUsage=serverAuth,clientAuth 25 | subjectAltName=@alt_names 26 | -------------------------------------------------------------------------------- /02-k8s-operator/07-node-pool-operator/config/certmanager/kustomization.yaml: -------------------------------------------------------------------------------- 1 | resources: 2 | - certificate.yaml 3 | 4 | configurations: 5 | - kustomizeconfig.yaml 6 | -------------------------------------------------------------------------------- /02-k8s-operator/07-node-pool-operator/config/certmanager/kustomizeconfig.yaml: -------------------------------------------------------------------------------- 1 | # This configuration is for teaching kustomize how to update name ref and var substitution 2 | nameReference: 3 | - kind: Issuer 4 | group: cert-manager.io 5 | fieldSpecs: 6 | - kind: Certificate 7 | group: cert-manager.io 8 | path: spec/issuerRef/name 9 | 10 | varReference: 11 | - kind: Certificate 12 | group: cert-manager.io 13 | path: spec/commonName 14 | - kind: Certificate 15 | group: cert-manager.io 16 | path: spec/dnsNames 17 | -------------------------------------------------------------------------------- /02-k8s-operator/07-node-pool-operator/config/crd/kustomizeconfig.yaml: -------------------------------------------------------------------------------- 1 | # This file is for teaching kustomize how to substitute name and namespace reference in CRD 2 | nameReference: 3 | - kind: Service 4 | version: v1 5 | fieldSpecs: 6 | - kind: CustomResourceDefinition 7 | version: v1 8 | group: apiextensions.k8s.io 9 | path: spec/conversion/webhook/clientConfig/service/name 10 | 11 | namespace: 12 | - kind: CustomResourceDefinition 13 | version: v1 14 | group: apiextensions.k8s.io 15 | path: spec/conversion/webhook/clientConfig/service/namespace 16 | create: false 17 | 18 | varReference: 19 | - path: metadata/annotations 20 | -------------------------------------------------------------------------------- /02-k8s-operator/07-node-pool-operator/config/crd/patches/cainjection_in_nodepools.yaml: -------------------------------------------------------------------------------- 1 | # The following patch adds a directive for certmanager to inject CA into the CRD 2 | apiVersion: apiextensions.k8s.io/v1 3 | kind: CustomResourceDefinition 4 | metadata: 5 | annotations: 6 | cert-manager.io/inject-ca-from: $(CERTIFICATE_NAMESPACE)/$(CERTIFICATE_NAME) 7 | name: nodepools.nodes.lailin.xyz 8 | -------------------------------------------------------------------------------- /02-k8s-operator/07-node-pool-operator/config/crd/patches/webhook_in_nodepools.yaml: -------------------------------------------------------------------------------- 1 | # The following patch enables a conversion webhook for the CRD 2 | apiVersion: apiextensions.k8s.io/v1 3 | kind: CustomResourceDefinition 4 | metadata: 5 | name: nodepools.nodes.lailin.xyz 6 | spec: 7 | conversion: 8 | strategy: Webhook 9 | webhook: 10 | clientConfig: 11 | service: 12 | namespace: system 13 | name: webhook-service 14 | path: /convert 15 | -------------------------------------------------------------------------------- /02-k8s-operator/07-node-pool-operator/config/default/manager_config_patch.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: apps/v1 2 | kind: Deployment 3 | metadata: 4 | name: controller-manager 5 | namespace: system 6 | spec: 7 | template: 8 | spec: 9 | containers: 10 | - name: manager 11 | args: 12 | - "--config=controller_manager_config.yaml" 13 | volumeMounts: 14 | - name: manager-config 15 | mountPath: /controller_manager_config.yaml 16 | subPath: controller_manager_config.yaml 17 | volumes: 18 | - name: manager-config 19 | configMap: 20 | name: manager-config 21 | -------------------------------------------------------------------------------- /02-k8s-operator/07-node-pool-operator/config/default/manager_webhook_patch.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: apps/v1 2 | kind: Deployment 3 | metadata: 4 | name: controller-manager 5 | namespace: system 6 | spec: 7 | template: 8 | spec: 9 | containers: 10 | - name: manager 11 | ports: 12 | - containerPort: 9443 13 | name: webhook-server 14 | protocol: TCP 15 | volumeMounts: 16 | - mountPath: /tmp/k8s-webhook-server/serving-certs 17 | name: cert 18 | readOnly: true 19 | volumes: 20 | - name: cert 21 | secret: 22 | defaultMode: 420 23 | secretName: webhook-server-cert 24 | -------------------------------------------------------------------------------- /02-k8s-operator/07-node-pool-operator/config/default/webhookcainjection_patch.yaml: -------------------------------------------------------------------------------- 1 | # This patch add annotation to admission webhook config and 2 | # the variables $(CERTIFICATE_NAMESPACE) and $(CERTIFICATE_NAME) will be substituted by kustomize. 3 | apiVersion: admissionregistration.k8s.io/v1 4 | kind: MutatingWebhookConfiguration 5 | metadata: 6 | name: mutating-webhook-configuration 7 | annotations: 8 | cert-manager.io/inject-ca-from: $(CERTIFICATE_NAMESPACE)/$(CERTIFICATE_NAME) 9 | --- 10 | apiVersion: admissionregistration.k8s.io/v1 11 | kind: ValidatingWebhookConfiguration 12 | metadata: 13 | name: validating-webhook-configuration 14 | annotations: 15 | cert-manager.io/inject-ca-from: $(CERTIFICATE_NAMESPACE)/$(CERTIFICATE_NAME) 16 | -------------------------------------------------------------------------------- /02-k8s-operator/07-node-pool-operator/config/dev/kustomization.yaml: -------------------------------------------------------------------------------- 1 | resources: 2 | - ../default 3 | 4 | patches: 5 | - patch: | 6 | - op: "add" 7 | path: "/webhooks/0/clientConfig/url" 8 | value: "https://host.docker.internal:9443/mutate-nodes-lailin-xyz-v1-nodepool" 9 | target: 10 | kind: MutatingWebhookConfiguration 11 | - patch: | 12 | - op: "add" 13 | path: "/webhooks/0/clientConfig/url" 14 | value: "https://host.docker.internal:9443/validate-nodes-lailin-xyz-v1-nodepool" 15 | target: 16 | kind: ValidatingWebhookConfiguration 17 | - path: webhook_patch.yaml 18 | target: 19 | group: admissionregistration.k8s.io -------------------------------------------------------------------------------- /02-k8s-operator/07-node-pool-operator/config/manager/controller_manager_config.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: controller-runtime.sigs.k8s.io/v1alpha1 2 | kind: ControllerManagerConfig 3 | health: 4 | healthProbeBindAddress: :8081 5 | metrics: 6 | bindAddress: 127.0.0.1:8080 7 | webhook: 8 | port: 9443 9 | leaderElection: 10 | leaderElect: true 11 | resourceName: 97acaccf.lailin.xyz 12 | -------------------------------------------------------------------------------- /02-k8s-operator/07-node-pool-operator/config/manager/kustomization.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: kustomize.config.k8s.io/v1beta1 2 | kind: Kustomization 3 | 4 | resources: 5 | - manager.yaml 6 | 7 | generatorOptions: 8 | disableNameSuffixHash: true 9 | 10 | configMapGenerator: 11 | - files: 12 | - controller_manager_config.yaml 13 | name: manager-config 14 | 15 | images: 16 | - name: controller 17 | newName: controller 18 | newTag: latest-2 19 | -------------------------------------------------------------------------------- /02-k8s-operator/07-node-pool-operator/config/prometheus/kustomization.yaml: -------------------------------------------------------------------------------- 1 | resources: 2 | - monitor.yaml 3 | -------------------------------------------------------------------------------- /02-k8s-operator/07-node-pool-operator/config/prometheus/monitor.yaml: -------------------------------------------------------------------------------- 1 | 2 | # Prometheus Monitor Service (Metrics) 3 | apiVersion: monitoring.coreos.com/v1 4 | kind: ServiceMonitor 5 | metadata: 6 | labels: 7 | control-plane: controller-manager 8 | name: controller-manager-metrics-monitor 9 | namespace: system 10 | spec: 11 | endpoints: 12 | - path: /metrics 13 | port: https 14 | scheme: https 15 | bearerTokenFile: /var/run/secrets/kubernetes.io/serviceaccount/token 16 | tlsConfig: 17 | insecureSkipVerify: true 18 | selector: 19 | matchLabels: 20 | control-plane: controller-manager 21 | -------------------------------------------------------------------------------- /02-k8s-operator/07-node-pool-operator/config/rbac/auth_proxy_client_clusterrole.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: rbac.authorization.k8s.io/v1 2 | kind: ClusterRole 3 | metadata: 4 | name: metrics-reader 5 | rules: 6 | - nonResourceURLs: ["/metrics"] 7 | verbs: ["get"] 8 | -------------------------------------------------------------------------------- /02-k8s-operator/07-node-pool-operator/config/rbac/auth_proxy_role.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: rbac.authorization.k8s.io/v1 2 | kind: ClusterRole 3 | metadata: 4 | name: proxy-role 5 | rules: 6 | - apiGroups: ["authentication.k8s.io"] 7 | resources: 8 | - tokenreviews 9 | verbs: ["create"] 10 | - apiGroups: ["authorization.k8s.io"] 11 | resources: 12 | - subjectaccessreviews 13 | verbs: ["create"] 14 | -------------------------------------------------------------------------------- /02-k8s-operator/07-node-pool-operator/config/rbac/auth_proxy_role_binding.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: rbac.authorization.k8s.io/v1 2 | kind: ClusterRoleBinding 3 | metadata: 4 | name: proxy-rolebinding 5 | roleRef: 6 | apiGroup: rbac.authorization.k8s.io 7 | kind: ClusterRole 8 | name: proxy-role 9 | subjects: 10 | - kind: ServiceAccount 11 | name: controller-manager 12 | namespace: system 13 | -------------------------------------------------------------------------------- /02-k8s-operator/07-node-pool-operator/config/rbac/auth_proxy_service.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Service 3 | metadata: 4 | labels: 5 | control-plane: controller-manager 6 | name: controller-manager-metrics-service 7 | namespace: system 8 | spec: 9 | ports: 10 | - name: https 11 | port: 8443 12 | targetPort: https 13 | selector: 14 | control-plane: controller-manager 15 | -------------------------------------------------------------------------------- /02-k8s-operator/07-node-pool-operator/config/rbac/kustomization.yaml: -------------------------------------------------------------------------------- 1 | resources: 2 | # All RBAC will be applied under this service account in 3 | # the deployment namespace. You may comment out this resource 4 | # if your manager will use a service account that exists at 5 | # runtime. Be sure to update RoleBinding and ClusterRoleBinding 6 | # subjects if changing service account names. 7 | - service_account.yaml 8 | - role.yaml 9 | - role_binding.yaml 10 | - leader_election_role.yaml 11 | - leader_election_role_binding.yaml 12 | # Comment the following 4 lines if you want to disable 13 | # the auth proxy (https://github.com/brancz/kube-rbac-proxy) 14 | # which protects your /metrics endpoint. 15 | - auth_proxy_service.yaml 16 | - auth_proxy_role.yaml 17 | - auth_proxy_role_binding.yaml 18 | - auth_proxy_client_clusterrole.yaml 19 | -------------------------------------------------------------------------------- /02-k8s-operator/07-node-pool-operator/config/rbac/leader_election_role.yaml: -------------------------------------------------------------------------------- 1 | # permissions to do leader election. 2 | apiVersion: rbac.authorization.k8s.io/v1 3 | kind: Role 4 | metadata: 5 | name: leader-election-role 6 | rules: 7 | - apiGroups: 8 | - "" 9 | - coordination.k8s.io 10 | resources: 11 | - configmaps 12 | - leases 13 | verbs: 14 | - get 15 | - list 16 | - watch 17 | - create 18 | - update 19 | - patch 20 | - delete 21 | - apiGroups: 22 | - "" 23 | resources: 24 | - events 25 | verbs: 26 | - create 27 | - patch 28 | -------------------------------------------------------------------------------- /02-k8s-operator/07-node-pool-operator/config/rbac/leader_election_role_binding.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: rbac.authorization.k8s.io/v1 2 | kind: RoleBinding 3 | metadata: 4 | name: leader-election-rolebinding 5 | roleRef: 6 | apiGroup: rbac.authorization.k8s.io 7 | kind: Role 8 | name: leader-election-role 9 | subjects: 10 | - kind: ServiceAccount 11 | name: controller-manager 12 | namespace: system 13 | -------------------------------------------------------------------------------- /02-k8s-operator/07-node-pool-operator/config/rbac/nodepool_editor_role.yaml: -------------------------------------------------------------------------------- 1 | # permissions for end users to edit nodepools. 2 | apiVersion: rbac.authorization.k8s.io/v1 3 | kind: ClusterRole 4 | metadata: 5 | name: nodepool-editor-role 6 | rules: 7 | - apiGroups: 8 | - nodes.lailin.xyz 9 | resources: 10 | - nodepools 11 | verbs: 12 | - create 13 | - delete 14 | - get 15 | - list 16 | - patch 17 | - update 18 | - watch 19 | - apiGroups: 20 | - nodes.lailin.xyz 21 | resources: 22 | - nodepools/status 23 | verbs: 24 | - get 25 | -------------------------------------------------------------------------------- /02-k8s-operator/07-node-pool-operator/config/rbac/nodepool_viewer_role.yaml: -------------------------------------------------------------------------------- 1 | # permissions for end users to view nodepools. 2 | apiVersion: rbac.authorization.k8s.io/v1 3 | kind: ClusterRole 4 | metadata: 5 | name: nodepool-viewer-role 6 | rules: 7 | - apiGroups: 8 | - nodes.lailin.xyz 9 | resources: 10 | - nodepools 11 | verbs: 12 | - get 13 | - list 14 | - watch 15 | - apiGroups: 16 | - nodes.lailin.xyz 17 | resources: 18 | - nodepools/status 19 | verbs: 20 | - get 21 | -------------------------------------------------------------------------------- /02-k8s-operator/07-node-pool-operator/config/rbac/role.yaml: -------------------------------------------------------------------------------- 1 | 2 | --- 3 | apiVersion: rbac.authorization.k8s.io/v1 4 | kind: ClusterRole 5 | metadata: 6 | creationTimestamp: null 7 | name: manager-role 8 | rules: 9 | - apiGroups: 10 | - nodes.lailin.xyz 11 | resources: 12 | - nodepools 13 | verbs: 14 | - create 15 | - delete 16 | - get 17 | - list 18 | - patch 19 | - update 20 | - watch 21 | - apiGroups: 22 | - nodes.lailin.xyz 23 | resources: 24 | - nodepools/finalizers 25 | verbs: 26 | - update 27 | - apiGroups: 28 | - nodes.lailin.xyz 29 | resources: 30 | - nodepools/status 31 | verbs: 32 | - get 33 | - patch 34 | - update 35 | -------------------------------------------------------------------------------- /02-k8s-operator/07-node-pool-operator/config/rbac/role_binding.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: rbac.authorization.k8s.io/v1 2 | kind: ClusterRoleBinding 3 | metadata: 4 | name: manager-rolebinding 5 | roleRef: 6 | apiGroup: rbac.authorization.k8s.io 7 | kind: ClusterRole 8 | name: manager-role 9 | subjects: 10 | - kind: ServiceAccount 11 | name: controller-manager 12 | namespace: system 13 | -------------------------------------------------------------------------------- /02-k8s-operator/07-node-pool-operator/config/rbac/service_account.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: ServiceAccount 3 | metadata: 4 | name: controller-manager 5 | namespace: system 6 | -------------------------------------------------------------------------------- /02-k8s-operator/07-node-pool-operator/config/samples/nodes_v1_nodepool.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: nodes.lailin.xyz/v1 2 | kind: NodePool 3 | metadata: 4 | name: worker 5 | spec: 6 | labels: 7 | "node-pool.lailin.xyz/xxx": "10" 8 | handler: runc 9 | -------------------------------------------------------------------------------- /02-k8s-operator/07-node-pool-operator/config/webhook/kustomization.yaml: -------------------------------------------------------------------------------- 1 | resources: 2 | - manifests.yaml 3 | - service.yaml 4 | 5 | configurations: 6 | - kustomizeconfig.yaml 7 | -------------------------------------------------------------------------------- /02-k8s-operator/07-node-pool-operator/config/webhook/service.yaml: -------------------------------------------------------------------------------- 1 | 2 | apiVersion: v1 3 | kind: Service 4 | metadata: 5 | name: webhook-service 6 | namespace: system 7 | spec: 8 | ports: 9 | - port: 443 10 | targetPort: 9443 11 | selector: 12 | control-plane: controller-manager 13 | -------------------------------------------------------------------------------- /02-k8s-operator/07-node-pool-operator/go.mod: -------------------------------------------------------------------------------- 1 | module github.com/mohuishou/blog-code/k8s-operator/node-pool-operator 2 | 3 | go 1.15 4 | 5 | require ( 6 | github.com/go-logr/logr v0.3.0 7 | github.com/onsi/ginkgo v1.14.1 8 | github.com/onsi/gomega v1.10.2 9 | github.com/pkg/errors v0.9.1 10 | github.com/stretchr/testify v1.5.1 11 | k8s.io/api v0.19.2 12 | k8s.io/apimachinery v0.19.2 13 | k8s.io/client-go v0.19.2 14 | sigs.k8s.io/controller-runtime v0.7.2 15 | ) 16 | -------------------------------------------------------------------------------- /02-k8s-operator/07-node-pool-operator/hack/boilerplate.go.txt: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2021. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ -------------------------------------------------------------------------------- /02-k8s-operator/08-node-pool-operator/.dockerignore: -------------------------------------------------------------------------------- 1 | # More info: https://docs.docker.com/engine/reference/builder/#dockerignore-file 2 | # Ignore all files which are not go type 3 | !**/*.go 4 | !**/*.mod 5 | !**/*.sum 6 | -------------------------------------------------------------------------------- /02-k8s-operator/08-node-pool-operator/.gitignore: -------------------------------------------------------------------------------- 1 | 2 | # Binaries for programs and plugins 3 | *.exe 4 | *.exe~ 5 | *.dll 6 | *.so 7 | *.dylib 8 | bin 9 | testbin/* 10 | 11 | # Test binary, build with `go test -c` 12 | *.test 13 | 14 | # Output of the go coverage tool, specifically when used with LiteIDE 15 | *.out 16 | 17 | # Kubernetes Generated files - skip generated files, except for vendored files 18 | 19 | !vendor/**/zz_generated.* 20 | 21 | # editor and IDE paraphernalia 22 | .idea 23 | *.swp 24 | *.swo 25 | *~ 26 | -------------------------------------------------------------------------------- /02-k8s-operator/08-node-pool-operator/Dockerfile: -------------------------------------------------------------------------------- 1 | # Build the manager binary 2 | FROM golang:1.15 as builder 3 | 4 | WORKDIR /workspace 5 | # Copy the Go Modules manifests 6 | ENV GOPROXY="https://goproxy.cn" 7 | COPY go.mod go.mod 8 | COPY go.sum go.sum 9 | # cache deps before building and copying source so that we don't need to re-download as much 10 | # and so that source changes don't invalidate our downloaded layer 11 | RUN go mod download 12 | 13 | # Copy the go source 14 | COPY main.go main.go 15 | COPY api/ api/ 16 | COPY controllers/ controllers/ 17 | 18 | # Build 19 | RUN CGO_ENABLED=0 GOOS=linux GOARCH=amd64 GO111MODULE=on go build -a -o manager main.go 20 | 21 | FROM debian:10-slim 22 | WORKDIR / 23 | COPY --from=builder /workspace/manager . 24 | USER 65532:65532 25 | 26 | ENTRYPOINT ["/manager"] -------------------------------------------------------------------------------- /02-k8s-operator/08-node-pool-operator/PROJECT: -------------------------------------------------------------------------------- 1 | domain: lailin.xyz 2 | layout: 3 | - go.kubebuilder.io/v3 4 | projectName: node-pool-operator 5 | repo: github.com/mohuishou/blog-code/k8s-operator/node-pool-operator 6 | resources: 7 | - api: 8 | crdVersion: v1 9 | namespaced: true 10 | controller: true 11 | domain: lailin.xyz 12 | group: nodes 13 | kind: NodePool 14 | path: github.com/mohuishou/blog-code/k8s-operator/node-pool-operator/api/v1 15 | version: v1 16 | webhooks: 17 | defaulting: true 18 | validation: true 19 | webhookVersion: v1 20 | version: "3" 21 | -------------------------------------------------------------------------------- /02-k8s-operator/08-node-pool-operator/config/cert/ca.srl: -------------------------------------------------------------------------------- 1 | DE97D427DC68A014 2 | -------------------------------------------------------------------------------- /02-k8s-operator/08-node-pool-operator/config/cert/csr.conf: -------------------------------------------------------------------------------- 1 | [ req ] 2 | default_bits = 2048 3 | prompt = no 4 | default_md = sha256 5 | req_extensions = req_ext 6 | distinguished_name = dn 7 | 8 | [ dn ] 9 | C = CN 10 | ST = Guangzhou 11 | L = Shenzhen 12 | CN = host.docker.internal 13 | 14 | [ req_ext ] 15 | subjectAltName = @alt_names 16 | 17 | [ alt_names ] 18 | DNS.1 = host.docker.internal 19 | 20 | [ v3_ext ] 21 | authorityKeyIdentifier=keyid,issuer:always 22 | basicConstraints=CA:FALSE 23 | keyUsage=keyEncipherment,dataEncipherment 24 | extendedKeyUsage=serverAuth,clientAuth 25 | subjectAltName=@alt_names 26 | -------------------------------------------------------------------------------- /02-k8s-operator/08-node-pool-operator/config/certmanager/kustomization.yaml: -------------------------------------------------------------------------------- 1 | resources: 2 | - certificate.yaml 3 | 4 | configurations: 5 | - kustomizeconfig.yaml 6 | -------------------------------------------------------------------------------- /02-k8s-operator/08-node-pool-operator/config/certmanager/kustomizeconfig.yaml: -------------------------------------------------------------------------------- 1 | # This configuration is for teaching kustomize how to update name ref and var substitution 2 | nameReference: 3 | - kind: Issuer 4 | group: cert-manager.io 5 | fieldSpecs: 6 | - kind: Certificate 7 | group: cert-manager.io 8 | path: spec/issuerRef/name 9 | 10 | varReference: 11 | - kind: Certificate 12 | group: cert-manager.io 13 | path: spec/commonName 14 | - kind: Certificate 15 | group: cert-manager.io 16 | path: spec/dnsNames 17 | -------------------------------------------------------------------------------- /02-k8s-operator/08-node-pool-operator/config/crd/kustomizeconfig.yaml: -------------------------------------------------------------------------------- 1 | # This file is for teaching kustomize how to substitute name and namespace reference in CRD 2 | nameReference: 3 | - kind: Service 4 | version: v1 5 | fieldSpecs: 6 | - kind: CustomResourceDefinition 7 | version: v1 8 | group: apiextensions.k8s.io 9 | path: spec/conversion/webhook/clientConfig/service/name 10 | 11 | namespace: 12 | - kind: CustomResourceDefinition 13 | version: v1 14 | group: apiextensions.k8s.io 15 | path: spec/conversion/webhook/clientConfig/service/namespace 16 | create: false 17 | 18 | varReference: 19 | - path: metadata/annotations 20 | -------------------------------------------------------------------------------- /02-k8s-operator/08-node-pool-operator/config/crd/patches/cainjection_in_nodepools.yaml: -------------------------------------------------------------------------------- 1 | # The following patch adds a directive for certmanager to inject CA into the CRD 2 | apiVersion: apiextensions.k8s.io/v1 3 | kind: CustomResourceDefinition 4 | metadata: 5 | annotations: 6 | cert-manager.io/inject-ca-from: $(CERTIFICATE_NAMESPACE)/$(CERTIFICATE_NAME) 7 | name: nodepools.nodes.lailin.xyz 8 | -------------------------------------------------------------------------------- /02-k8s-operator/08-node-pool-operator/config/crd/patches/webhook_in_nodepools.yaml: -------------------------------------------------------------------------------- 1 | # The following patch enables a conversion webhook for the CRD 2 | apiVersion: apiextensions.k8s.io/v1 3 | kind: CustomResourceDefinition 4 | metadata: 5 | name: nodepools.nodes.lailin.xyz 6 | spec: 7 | conversion: 8 | strategy: Webhook 9 | webhook: 10 | clientConfig: 11 | service: 12 | namespace: system 13 | name: webhook-service 14 | path: /convert 15 | -------------------------------------------------------------------------------- /02-k8s-operator/08-node-pool-operator/config/default/manager_config_patch.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: apps/v1 2 | kind: Deployment 3 | metadata: 4 | name: controller-manager 5 | namespace: system 6 | spec: 7 | template: 8 | spec: 9 | containers: 10 | - name: manager 11 | args: 12 | - "--config=controller_manager_config.yaml" 13 | volumeMounts: 14 | - name: manager-config 15 | mountPath: /controller_manager_config.yaml 16 | subPath: controller_manager_config.yaml 17 | volumes: 18 | - name: manager-config 19 | configMap: 20 | name: manager-config 21 | -------------------------------------------------------------------------------- /02-k8s-operator/08-node-pool-operator/config/default/manager_webhook_patch.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: apps/v1 2 | kind: Deployment 3 | metadata: 4 | name: controller-manager 5 | namespace: system 6 | spec: 7 | template: 8 | spec: 9 | containers: 10 | - name: manager 11 | ports: 12 | - containerPort: 9443 13 | name: webhook-server 14 | protocol: TCP 15 | volumeMounts: 16 | - mountPath: /tmp/k8s-webhook-server/serving-certs 17 | name: cert 18 | readOnly: true 19 | volumes: 20 | - name: cert 21 | secret: 22 | defaultMode: 420 23 | secretName: webhook-server-cert 24 | -------------------------------------------------------------------------------- /02-k8s-operator/08-node-pool-operator/config/default/webhookcainjection_patch.yaml: -------------------------------------------------------------------------------- 1 | # This patch add annotation to admission webhook config and 2 | # the variables $(CERTIFICATE_NAMESPACE) and $(CERTIFICATE_NAME) will be substituted by kustomize. 3 | apiVersion: admissionregistration.k8s.io/v1 4 | kind: MutatingWebhookConfiguration 5 | metadata: 6 | name: mutating-webhook-configuration 7 | annotations: 8 | cert-manager.io/inject-ca-from: $(CERTIFICATE_NAMESPACE)/$(CERTIFICATE_NAME) 9 | --- 10 | apiVersion: admissionregistration.k8s.io/v1 11 | kind: ValidatingWebhookConfiguration 12 | metadata: 13 | name: validating-webhook-configuration 14 | annotations: 15 | cert-manager.io/inject-ca-from: $(CERTIFICATE_NAMESPACE)/$(CERTIFICATE_NAME) 16 | -------------------------------------------------------------------------------- /02-k8s-operator/08-node-pool-operator/config/dev/kustomization.yaml: -------------------------------------------------------------------------------- 1 | resources: 2 | - ../default 3 | 4 | patches: 5 | - patch: | 6 | - op: "add" 7 | path: "/webhooks/0/clientConfig/url" 8 | value: "https://host.docker.internal:9443/mutate-nodes-lailin-xyz-v1-nodepool" 9 | target: 10 | kind: MutatingWebhookConfiguration 11 | - patch: | 12 | - op: "add" 13 | path: "/webhooks/0/clientConfig/url" 14 | value: "https://host.docker.internal:9443/validate-nodes-lailin-xyz-v1-nodepool" 15 | target: 16 | kind: ValidatingWebhookConfiguration 17 | - path: webhook_patch.yaml 18 | target: 19 | group: admissionregistration.k8s.io -------------------------------------------------------------------------------- /02-k8s-operator/08-node-pool-operator/config/manager/controller_manager_config.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: controller-runtime.sigs.k8s.io/v1alpha1 2 | kind: ControllerManagerConfig 3 | health: 4 | healthProbeBindAddress: :8081 5 | metrics: 6 | bindAddress: 127.0.0.1:8080 7 | webhook: 8 | port: 9443 9 | leaderElection: 10 | leaderElect: true 11 | resourceName: 97acaccf.lailin.xyz 12 | -------------------------------------------------------------------------------- /02-k8s-operator/08-node-pool-operator/config/manager/kustomization.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: kustomize.config.k8s.io/v1beta1 2 | kind: Kustomization 3 | 4 | resources: 5 | - manager.yaml 6 | 7 | generatorOptions: 8 | disableNameSuffixHash: true 9 | 10 | configMapGenerator: 11 | - files: 12 | - controller_manager_config.yaml 13 | name: manager-config 14 | 15 | images: 16 | - name: controller 17 | newName: controller 18 | newTag: latest-2 19 | -------------------------------------------------------------------------------- /02-k8s-operator/08-node-pool-operator/config/prometheus/kustomization.yaml: -------------------------------------------------------------------------------- 1 | resources: 2 | - monitor.yaml 3 | -------------------------------------------------------------------------------- /02-k8s-operator/08-node-pool-operator/config/prometheus/monitor.yaml: -------------------------------------------------------------------------------- 1 | 2 | # Prometheus Monitor Service (Metrics) 3 | apiVersion: monitoring.coreos.com/v1 4 | kind: ServiceMonitor 5 | metadata: 6 | labels: 7 | control-plane: controller-manager 8 | name: controller-manager-metrics-monitor 9 | namespace: system 10 | spec: 11 | endpoints: 12 | - path: /metrics 13 | port: https 14 | scheme: https 15 | bearerTokenFile: /var/run/secrets/kubernetes.io/serviceaccount/token 16 | tlsConfig: 17 | insecureSkipVerify: true 18 | selector: 19 | matchLabels: 20 | control-plane: controller-manager 21 | -------------------------------------------------------------------------------- /02-k8s-operator/08-node-pool-operator/config/rbac/auth_proxy_client_clusterrole.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: rbac.authorization.k8s.io/v1 2 | kind: ClusterRole 3 | metadata: 4 | name: metrics-reader 5 | rules: 6 | - nonResourceURLs: ["/metrics"] 7 | verbs: ["get"] 8 | -------------------------------------------------------------------------------- /02-k8s-operator/08-node-pool-operator/config/rbac/auth_proxy_role.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: rbac.authorization.k8s.io/v1 2 | kind: ClusterRole 3 | metadata: 4 | name: proxy-role 5 | rules: 6 | - apiGroups: ["authentication.k8s.io"] 7 | resources: 8 | - tokenreviews 9 | verbs: ["create"] 10 | - apiGroups: ["authorization.k8s.io"] 11 | resources: 12 | - subjectaccessreviews 13 | verbs: ["create"] 14 | -------------------------------------------------------------------------------- /02-k8s-operator/08-node-pool-operator/config/rbac/auth_proxy_role_binding.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: rbac.authorization.k8s.io/v1 2 | kind: ClusterRoleBinding 3 | metadata: 4 | name: proxy-rolebinding 5 | roleRef: 6 | apiGroup: rbac.authorization.k8s.io 7 | kind: ClusterRole 8 | name: proxy-role 9 | subjects: 10 | - kind: ServiceAccount 11 | name: controller-manager 12 | namespace: system 13 | -------------------------------------------------------------------------------- /02-k8s-operator/08-node-pool-operator/config/rbac/auth_proxy_service.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Service 3 | metadata: 4 | labels: 5 | control-plane: controller-manager 6 | name: controller-manager-metrics-service 7 | namespace: system 8 | spec: 9 | ports: 10 | - name: https 11 | port: 8443 12 | targetPort: https 13 | selector: 14 | control-plane: controller-manager 15 | -------------------------------------------------------------------------------- /02-k8s-operator/08-node-pool-operator/config/rbac/kustomization.yaml: -------------------------------------------------------------------------------- 1 | resources: 2 | # All RBAC will be applied under this service account in 3 | # the deployment namespace. You may comment out this resource 4 | # if your manager will use a service account that exists at 5 | # runtime. Be sure to update RoleBinding and ClusterRoleBinding 6 | # subjects if changing service account names. 7 | - service_account.yaml 8 | - role.yaml 9 | - role_binding.yaml 10 | - leader_election_role.yaml 11 | - leader_election_role_binding.yaml 12 | # Comment the following 4 lines if you want to disable 13 | # the auth proxy (https://github.com/brancz/kube-rbac-proxy) 14 | # which protects your /metrics endpoint. 15 | - auth_proxy_service.yaml 16 | - auth_proxy_role.yaml 17 | - auth_proxy_role_binding.yaml 18 | - auth_proxy_client_clusterrole.yaml 19 | -------------------------------------------------------------------------------- /02-k8s-operator/08-node-pool-operator/config/rbac/leader_election_role.yaml: -------------------------------------------------------------------------------- 1 | # permissions to do leader election. 2 | apiVersion: rbac.authorization.k8s.io/v1 3 | kind: Role 4 | metadata: 5 | name: leader-election-role 6 | rules: 7 | - apiGroups: 8 | - "" 9 | - coordination.k8s.io 10 | resources: 11 | - configmaps 12 | - leases 13 | verbs: 14 | - get 15 | - list 16 | - watch 17 | - create 18 | - update 19 | - patch 20 | - delete 21 | - apiGroups: 22 | - "" 23 | resources: 24 | - events 25 | verbs: 26 | - create 27 | - patch 28 | -------------------------------------------------------------------------------- /02-k8s-operator/08-node-pool-operator/config/rbac/leader_election_role_binding.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: rbac.authorization.k8s.io/v1 2 | kind: RoleBinding 3 | metadata: 4 | name: leader-election-rolebinding 5 | roleRef: 6 | apiGroup: rbac.authorization.k8s.io 7 | kind: Role 8 | name: leader-election-role 9 | subjects: 10 | - kind: ServiceAccount 11 | name: controller-manager 12 | namespace: system 13 | -------------------------------------------------------------------------------- /02-k8s-operator/08-node-pool-operator/config/rbac/nodepool_editor_role.yaml: -------------------------------------------------------------------------------- 1 | # permissions for end users to edit nodepools. 2 | apiVersion: rbac.authorization.k8s.io/v1 3 | kind: ClusterRole 4 | metadata: 5 | name: nodepool-editor-role 6 | rules: 7 | - apiGroups: 8 | - nodes.lailin.xyz 9 | resources: 10 | - nodepools 11 | verbs: 12 | - create 13 | - delete 14 | - get 15 | - list 16 | - patch 17 | - update 18 | - watch 19 | - apiGroups: 20 | - nodes.lailin.xyz 21 | resources: 22 | - nodepools/status 23 | verbs: 24 | - get 25 | -------------------------------------------------------------------------------- /02-k8s-operator/08-node-pool-operator/config/rbac/nodepool_viewer_role.yaml: -------------------------------------------------------------------------------- 1 | # permissions for end users to view nodepools. 2 | apiVersion: rbac.authorization.k8s.io/v1 3 | kind: ClusterRole 4 | metadata: 5 | name: nodepool-viewer-role 6 | rules: 7 | - apiGroups: 8 | - nodes.lailin.xyz 9 | resources: 10 | - nodepools 11 | verbs: 12 | - get 13 | - list 14 | - watch 15 | - apiGroups: 16 | - nodes.lailin.xyz 17 | resources: 18 | - nodepools/status 19 | verbs: 20 | - get 21 | -------------------------------------------------------------------------------- /02-k8s-operator/08-node-pool-operator/config/rbac/role.yaml: -------------------------------------------------------------------------------- 1 | 2 | --- 3 | apiVersion: rbac.authorization.k8s.io/v1 4 | kind: ClusterRole 5 | metadata: 6 | creationTimestamp: null 7 | name: manager-role 8 | rules: 9 | - apiGroups: 10 | - nodes.lailin.xyz 11 | resources: 12 | - nodepools 13 | verbs: 14 | - create 15 | - delete 16 | - get 17 | - list 18 | - patch 19 | - update 20 | - watch 21 | - apiGroups: 22 | - nodes.lailin.xyz 23 | resources: 24 | - nodepools/finalizers 25 | verbs: 26 | - update 27 | - apiGroups: 28 | - nodes.lailin.xyz 29 | resources: 30 | - nodepools/status 31 | verbs: 32 | - get 33 | - patch 34 | - update 35 | -------------------------------------------------------------------------------- /02-k8s-operator/08-node-pool-operator/config/rbac/role_binding.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: rbac.authorization.k8s.io/v1 2 | kind: ClusterRoleBinding 3 | metadata: 4 | name: manager-rolebinding 5 | roleRef: 6 | apiGroup: rbac.authorization.k8s.io 7 | kind: ClusterRole 8 | name: manager-role 9 | subjects: 10 | - kind: ServiceAccount 11 | name: controller-manager 12 | namespace: system 13 | -------------------------------------------------------------------------------- /02-k8s-operator/08-node-pool-operator/config/rbac/service_account.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: ServiceAccount 3 | metadata: 4 | name: controller-manager 5 | namespace: system 6 | -------------------------------------------------------------------------------- /02-k8s-operator/08-node-pool-operator/config/samples/nodes_v1_nodepool.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: nodes.lailin.xyz/v1 2 | kind: NodePool 3 | metadata: 4 | name: worker 5 | spec: 6 | labels: 7 | "node-pool.lailin.xyz/xxx": "10" 8 | handler: runc 9 | -------------------------------------------------------------------------------- /02-k8s-operator/08-node-pool-operator/config/webhook/kustomization.yaml: -------------------------------------------------------------------------------- 1 | resources: 2 | - manifests.yaml 3 | - service.yaml 4 | 5 | configurations: 6 | - kustomizeconfig.yaml 7 | -------------------------------------------------------------------------------- /02-k8s-operator/08-node-pool-operator/config/webhook/service.yaml: -------------------------------------------------------------------------------- 1 | 2 | apiVersion: v1 3 | kind: Service 4 | metadata: 5 | name: webhook-service 6 | namespace: system 7 | spec: 8 | ports: 9 | - port: 443 10 | targetPort: 9443 11 | selector: 12 | control-plane: controller-manager 13 | -------------------------------------------------------------------------------- /02-k8s-operator/08-node-pool-operator/go.mod: -------------------------------------------------------------------------------- 1 | module github.com/mohuishou/blog-code/k8s-operator/node-pool-operator 2 | 3 | go 1.15 4 | 5 | require ( 6 | github.com/go-logr/logr v0.3.0 7 | github.com/onsi/ginkgo v1.14.1 8 | github.com/onsi/gomega v1.10.2 9 | github.com/pkg/errors v0.9.1 10 | github.com/stretchr/testify v1.5.1 11 | k8s.io/api v0.19.2 12 | k8s.io/apimachinery v0.19.2 13 | k8s.io/client-go v0.19.2 14 | sigs.k8s.io/controller-runtime v0.7.2 15 | ) 16 | -------------------------------------------------------------------------------- /02-k8s-operator/08-node-pool-operator/hack/boilerplate.go.txt: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2021. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ -------------------------------------------------------------------------------- /02-k8s-operator/multi-cluster-operator/.dockerignore: -------------------------------------------------------------------------------- 1 | # More info: https://docs.docker.com/engine/reference/builder/#dockerignore-file 2 | # Ignore build and test binaries. 3 | bin/ 4 | testbin/ 5 | -------------------------------------------------------------------------------- /02-k8s-operator/multi-cluster-operator/.gitignore: -------------------------------------------------------------------------------- 1 | 2 | # Binaries for programs and plugins 3 | *.exe 4 | *.exe~ 5 | *.dll 6 | *.so 7 | *.dylib 8 | bin 9 | testbin/* 10 | 11 | # Test binary, build with `go test -c` 12 | *.test 13 | 14 | # Output of the go coverage tool, specifically when used with LiteIDE 15 | *.out 16 | 17 | # Kubernetes Generated files - skip generated files, except for vendored files 18 | 19 | !vendor/**/zz_generated.* 20 | 21 | # editor and IDE paraphernalia 22 | .idea 23 | *.swp 24 | *.swo 25 | *~ 26 | -------------------------------------------------------------------------------- /02-k8s-operator/multi-cluster-operator/PROJECT: -------------------------------------------------------------------------------- 1 | domain: lailin.xyz 2 | layout: 3 | - go.kubebuilder.io/v3 4 | projectName: multi-cluster-operator 5 | repo: github.com/mohuishou/blog-code/02-k8s-operator/multi-cluster-operator 6 | resources: 7 | - api: 8 | crdVersion: v1 9 | namespaced: true 10 | controller: true 11 | domain: lailin.xyz 12 | group: job 13 | kind: Test 14 | path: github.com/mohuishou/blog-code/02-k8s-operator/multi-cluster-operator/api/v1 15 | version: v1 16 | version: "3" 17 | -------------------------------------------------------------------------------- /02-k8s-operator/multi-cluster-operator/config/crd/kustomizeconfig.yaml: -------------------------------------------------------------------------------- 1 | # This file is for teaching kustomize how to substitute name and namespace reference in CRD 2 | nameReference: 3 | - kind: Service 4 | version: v1 5 | fieldSpecs: 6 | - kind: CustomResourceDefinition 7 | version: v1 8 | group: apiextensions.k8s.io 9 | path: spec/conversion/webhook/clientConfig/service/name 10 | 11 | namespace: 12 | - kind: CustomResourceDefinition 13 | version: v1 14 | group: apiextensions.k8s.io 15 | path: spec/conversion/webhook/clientConfig/service/namespace 16 | create: false 17 | 18 | varReference: 19 | - path: metadata/annotations 20 | -------------------------------------------------------------------------------- /02-k8s-operator/multi-cluster-operator/config/crd/patches/cainjection_in_tests.yaml: -------------------------------------------------------------------------------- 1 | # The following patch adds a directive for certmanager to inject CA into the CRD 2 | apiVersion: apiextensions.k8s.io/v1 3 | kind: CustomResourceDefinition 4 | metadata: 5 | annotations: 6 | cert-manager.io/inject-ca-from: $(CERTIFICATE_NAMESPACE)/$(CERTIFICATE_NAME) 7 | name: tests.job.lailin.xyz 8 | -------------------------------------------------------------------------------- /02-k8s-operator/multi-cluster-operator/config/crd/patches/webhook_in_tests.yaml: -------------------------------------------------------------------------------- 1 | # The following patch enables a conversion webhook for the CRD 2 | apiVersion: apiextensions.k8s.io/v1 3 | kind: CustomResourceDefinition 4 | metadata: 5 | name: tests.job.lailin.xyz 6 | spec: 7 | conversion: 8 | strategy: Webhook 9 | webhook: 10 | clientConfig: 11 | service: 12 | namespace: system 13 | name: webhook-service 14 | path: /convert 15 | conversionReviewVersions: 16 | - v1 17 | -------------------------------------------------------------------------------- /02-k8s-operator/multi-cluster-operator/config/default/manager_config_patch.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: apps/v1 2 | kind: Deployment 3 | metadata: 4 | name: controller-manager 5 | namespace: system 6 | spec: 7 | template: 8 | spec: 9 | containers: 10 | - name: manager 11 | args: 12 | - "--config=controller_manager_config.yaml" 13 | volumeMounts: 14 | - name: manager-config 15 | mountPath: /controller_manager_config.yaml 16 | subPath: controller_manager_config.yaml 17 | volumes: 18 | - name: manager-config 19 | configMap: 20 | name: manager-config 21 | -------------------------------------------------------------------------------- /02-k8s-operator/multi-cluster-operator/config/manager/controller_manager_config.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: controller-runtime.sigs.k8s.io/v1alpha1 2 | kind: ControllerManagerConfig 3 | health: 4 | healthProbeBindAddress: :8081 5 | metrics: 6 | bindAddress: 127.0.0.1:8080 7 | webhook: 8 | port: 9443 9 | leaderElection: 10 | leaderElect: true 11 | resourceName: 6837ed1d.lailin.xyz 12 | -------------------------------------------------------------------------------- /02-k8s-operator/multi-cluster-operator/config/manager/kustomization.yaml: -------------------------------------------------------------------------------- 1 | resources: 2 | - manager.yaml 3 | 4 | generatorOptions: 5 | disableNameSuffixHash: true 6 | 7 | configMapGenerator: 8 | - name: manager-config 9 | files: 10 | - controller_manager_config.yaml 11 | -------------------------------------------------------------------------------- /02-k8s-operator/multi-cluster-operator/config/prometheus/kustomization.yaml: -------------------------------------------------------------------------------- 1 | resources: 2 | - monitor.yaml 3 | -------------------------------------------------------------------------------- /02-k8s-operator/multi-cluster-operator/config/prometheus/monitor.yaml: -------------------------------------------------------------------------------- 1 | 2 | # Prometheus Monitor Service (Metrics) 3 | apiVersion: monitoring.coreos.com/v1 4 | kind: ServiceMonitor 5 | metadata: 6 | labels: 7 | control-plane: controller-manager 8 | name: controller-manager-metrics-monitor 9 | namespace: system 10 | spec: 11 | endpoints: 12 | - path: /metrics 13 | port: https 14 | scheme: https 15 | bearerTokenFile: /var/run/secrets/kubernetes.io/serviceaccount/token 16 | tlsConfig: 17 | insecureSkipVerify: true 18 | selector: 19 | matchLabels: 20 | control-plane: controller-manager 21 | -------------------------------------------------------------------------------- /02-k8s-operator/multi-cluster-operator/config/rbac/auth_proxy_client_clusterrole.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: rbac.authorization.k8s.io/v1 2 | kind: ClusterRole 3 | metadata: 4 | name: metrics-reader 5 | rules: 6 | - nonResourceURLs: 7 | - "/metrics" 8 | verbs: 9 | - get 10 | -------------------------------------------------------------------------------- /02-k8s-operator/multi-cluster-operator/config/rbac/auth_proxy_role.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: rbac.authorization.k8s.io/v1 2 | kind: ClusterRole 3 | metadata: 4 | name: proxy-role 5 | rules: 6 | - apiGroups: 7 | - authentication.k8s.io 8 | resources: 9 | - tokenreviews 10 | verbs: 11 | - create 12 | - apiGroups: 13 | - authorization.k8s.io 14 | resources: 15 | - subjectaccessreviews 16 | verbs: 17 | - create 18 | -------------------------------------------------------------------------------- /02-k8s-operator/multi-cluster-operator/config/rbac/auth_proxy_role_binding.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: rbac.authorization.k8s.io/v1 2 | kind: ClusterRoleBinding 3 | metadata: 4 | name: proxy-rolebinding 5 | roleRef: 6 | apiGroup: rbac.authorization.k8s.io 7 | kind: ClusterRole 8 | name: proxy-role 9 | subjects: 10 | - kind: ServiceAccount 11 | name: controller-manager 12 | namespace: system 13 | -------------------------------------------------------------------------------- /02-k8s-operator/multi-cluster-operator/config/rbac/auth_proxy_service.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Service 3 | metadata: 4 | labels: 5 | control-plane: controller-manager 6 | name: controller-manager-metrics-service 7 | namespace: system 8 | spec: 9 | ports: 10 | - name: https 11 | port: 8443 12 | protocol: TCP 13 | targetPort: https 14 | selector: 15 | control-plane: controller-manager 16 | -------------------------------------------------------------------------------- /02-k8s-operator/multi-cluster-operator/config/rbac/kustomization.yaml: -------------------------------------------------------------------------------- 1 | resources: 2 | # All RBAC will be applied under this service account in 3 | # the deployment namespace. You may comment out this resource 4 | # if your manager will use a service account that exists at 5 | # runtime. Be sure to update RoleBinding and ClusterRoleBinding 6 | # subjects if changing service account names. 7 | - service_account.yaml 8 | - role.yaml 9 | - role_binding.yaml 10 | - leader_election_role.yaml 11 | - leader_election_role_binding.yaml 12 | # Comment the following 4 lines if you want to disable 13 | # the auth proxy (https://github.com/brancz/kube-rbac-proxy) 14 | # which protects your /metrics endpoint. 15 | - auth_proxy_service.yaml 16 | - auth_proxy_role.yaml 17 | - auth_proxy_role_binding.yaml 18 | - auth_proxy_client_clusterrole.yaml 19 | -------------------------------------------------------------------------------- /02-k8s-operator/multi-cluster-operator/config/rbac/leader_election_role.yaml: -------------------------------------------------------------------------------- 1 | # permissions to do leader election. 2 | apiVersion: rbac.authorization.k8s.io/v1 3 | kind: Role 4 | metadata: 5 | name: leader-election-role 6 | rules: 7 | - apiGroups: 8 | - "" 9 | resources: 10 | - configmaps 11 | verbs: 12 | - get 13 | - list 14 | - watch 15 | - create 16 | - update 17 | - patch 18 | - delete 19 | - apiGroups: 20 | - coordination.k8s.io 21 | resources: 22 | - leases 23 | verbs: 24 | - get 25 | - list 26 | - watch 27 | - create 28 | - update 29 | - patch 30 | - delete 31 | - apiGroups: 32 | - "" 33 | resources: 34 | - events 35 | verbs: 36 | - create 37 | - patch 38 | -------------------------------------------------------------------------------- /02-k8s-operator/multi-cluster-operator/config/rbac/leader_election_role_binding.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: rbac.authorization.k8s.io/v1 2 | kind: RoleBinding 3 | metadata: 4 | name: leader-election-rolebinding 5 | roleRef: 6 | apiGroup: rbac.authorization.k8s.io 7 | kind: Role 8 | name: leader-election-role 9 | subjects: 10 | - kind: ServiceAccount 11 | name: controller-manager 12 | namespace: system 13 | -------------------------------------------------------------------------------- /02-k8s-operator/multi-cluster-operator/config/rbac/role.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | apiVersion: rbac.authorization.k8s.io/v1 3 | kind: ClusterRole 4 | metadata: 5 | creationTimestamp: null 6 | name: manager-role 7 | rules: 8 | - apiGroups: 9 | - job.lailin.xyz 10 | resources: 11 | - tests 12 | verbs: 13 | - create 14 | - delete 15 | - get 16 | - list 17 | - patch 18 | - update 19 | - watch 20 | - apiGroups: 21 | - job.lailin.xyz 22 | resources: 23 | - tests/finalizers 24 | verbs: 25 | - update 26 | - apiGroups: 27 | - job.lailin.xyz 28 | resources: 29 | - tests/status 30 | verbs: 31 | - get 32 | - patch 33 | - update 34 | -------------------------------------------------------------------------------- /02-k8s-operator/multi-cluster-operator/config/rbac/role_binding.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: rbac.authorization.k8s.io/v1 2 | kind: ClusterRoleBinding 3 | metadata: 4 | name: manager-rolebinding 5 | roleRef: 6 | apiGroup: rbac.authorization.k8s.io 7 | kind: ClusterRole 8 | name: manager-role 9 | subjects: 10 | - kind: ServiceAccount 11 | name: controller-manager 12 | namespace: system 13 | -------------------------------------------------------------------------------- /02-k8s-operator/multi-cluster-operator/config/rbac/service_account.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: ServiceAccount 3 | metadata: 4 | name: controller-manager 5 | namespace: system 6 | -------------------------------------------------------------------------------- /02-k8s-operator/multi-cluster-operator/config/rbac/test_editor_role.yaml: -------------------------------------------------------------------------------- 1 | # permissions for end users to edit tests. 2 | apiVersion: rbac.authorization.k8s.io/v1 3 | kind: ClusterRole 4 | metadata: 5 | name: test-editor-role 6 | rules: 7 | - apiGroups: 8 | - job.lailin.xyz 9 | resources: 10 | - tests 11 | verbs: 12 | - create 13 | - delete 14 | - get 15 | - list 16 | - patch 17 | - update 18 | - watch 19 | - apiGroups: 20 | - job.lailin.xyz 21 | resources: 22 | - tests/status 23 | verbs: 24 | - get 25 | -------------------------------------------------------------------------------- /02-k8s-operator/multi-cluster-operator/config/rbac/test_viewer_role.yaml: -------------------------------------------------------------------------------- 1 | # permissions for end users to view tests. 2 | apiVersion: rbac.authorization.k8s.io/v1 3 | kind: ClusterRole 4 | metadata: 5 | name: test-viewer-role 6 | rules: 7 | - apiGroups: 8 | - job.lailin.xyz 9 | resources: 10 | - tests 11 | verbs: 12 | - get 13 | - list 14 | - watch 15 | - apiGroups: 16 | - job.lailin.xyz 17 | resources: 18 | - tests/status 19 | verbs: 20 | - get 21 | -------------------------------------------------------------------------------- /02-k8s-operator/multi-cluster-operator/config/samples/job_v1_test.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: job.lailin.xyz/v1 2 | kind: Test 3 | metadata: 4 | name: test-sample 5 | spec: 6 | image: busybox 7 | -------------------------------------------------------------------------------- /02-k8s-operator/multi-cluster-operator/hack/boilerplate.go.txt: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2022. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ -------------------------------------------------------------------------------- /02-k8s-operator/multi-cluster-operator/pkg/clusterx/enqueue.go: -------------------------------------------------------------------------------- 1 | package clusterx 2 | 3 | import ( 4 | "k8s.io/apimachinery/pkg/types" 5 | "sigs.k8s.io/controller-runtime/pkg/client" 6 | "sigs.k8s.io/controller-runtime/pkg/handler" 7 | "sigs.k8s.io/controller-runtime/pkg/reconcile" 8 | ) 9 | 10 | // MuiltClustersEnqueue 多集群入队器 11 | // 将集群名称附加在 Namespace 上 12 | func MuiltClustersEnqueue(clusterName string) handler.EventHandler { 13 | return handler.EnqueueRequestsFromMapFunc(func(o client.Object) []reconcile.Request { 14 | return []reconcile.Request{ 15 | { 16 | NamespacedName: types.NamespacedName{ 17 | Name: o.GetName(), 18 | Namespace: clusterName + ClusterSeparator + o.GetNamespace(), 19 | }, 20 | }, 21 | } 22 | }) 23 | } 24 | -------------------------------------------------------------------------------- /02-k8s-operator/operator-kubebuilder-clientset/.dockerignore: -------------------------------------------------------------------------------- 1 | # More info: https://docs.docker.com/engine/reference/builder/#dockerignore-file 2 | # Ignore build and test binaries. 3 | bin/ 4 | testbin/ 5 | -------------------------------------------------------------------------------- /02-k8s-operator/operator-kubebuilder-clientset/.gitignore: -------------------------------------------------------------------------------- 1 | 2 | # Binaries for programs and plugins 3 | *.exe 4 | *.exe~ 5 | *.dll 6 | *.so 7 | *.dylib 8 | bin 9 | testbin/* 10 | Dockerfile.cross 11 | 12 | # Test binary, build with `go test -c` 13 | *.test 14 | 15 | # Output of the go coverage tool, specifically when used with LiteIDE 16 | *.out 17 | 18 | # Kubernetes Generated files - skip generated files, except for vendored files 19 | 20 | !vendor/**/zz_generated.* 21 | 22 | # editor and IDE paraphernalia 23 | .idea 24 | *.swp 25 | *.swo 26 | *~ 27 | -------------------------------------------------------------------------------- /02-k8s-operator/operator-kubebuilder-clientset/PROJECT: -------------------------------------------------------------------------------- 1 | domain: lailin.xyz 2 | layout: 3 | - go.kubebuilder.io/v3 4 | projectName: operator-kubebuilder-clientset 5 | repo: github.com/mohuishou/blog-code/02-k8s-operator/operator-kubebuilder-clientset 6 | resources: 7 | - api: 8 | crdVersion: v1 9 | namespaced: true 10 | controller: true 11 | domain: lailin.xyz 12 | group: job 13 | kind: Test 14 | path: github.com/mohuishou/blog-code/02-k8s-operator/operator-kubebuilder-clientset/api/job/v1 15 | version: v1 16 | version: "3" 17 | -------------------------------------------------------------------------------- /02-k8s-operator/operator-kubebuilder-clientset/config/crd/kustomizeconfig.yaml: -------------------------------------------------------------------------------- 1 | # This file is for teaching kustomize how to substitute name and namespace reference in CRD 2 | nameReference: 3 | - kind: Service 4 | version: v1 5 | fieldSpecs: 6 | - kind: CustomResourceDefinition 7 | version: v1 8 | group: apiextensions.k8s.io 9 | path: spec/conversion/webhook/clientConfig/service/name 10 | 11 | namespace: 12 | - kind: CustomResourceDefinition 13 | version: v1 14 | group: apiextensions.k8s.io 15 | path: spec/conversion/webhook/clientConfig/service/namespace 16 | create: false 17 | 18 | varReference: 19 | - path: metadata/annotations 20 | -------------------------------------------------------------------------------- /02-k8s-operator/operator-kubebuilder-clientset/config/crd/patches/cainjection_in_tests.yaml: -------------------------------------------------------------------------------- 1 | # The following patch adds a directive for certmanager to inject CA into the CRD 2 | apiVersion: apiextensions.k8s.io/v1 3 | kind: CustomResourceDefinition 4 | metadata: 5 | annotations: 6 | cert-manager.io/inject-ca-from: $(CERTIFICATE_NAMESPACE)/$(CERTIFICATE_NAME) 7 | name: tests.job.lailin.xyz 8 | -------------------------------------------------------------------------------- /02-k8s-operator/operator-kubebuilder-clientset/config/crd/patches/webhook_in_tests.yaml: -------------------------------------------------------------------------------- 1 | # The following patch enables a conversion webhook for the CRD 2 | apiVersion: apiextensions.k8s.io/v1 3 | kind: CustomResourceDefinition 4 | metadata: 5 | name: tests.job.lailin.xyz 6 | spec: 7 | conversion: 8 | strategy: Webhook 9 | webhook: 10 | clientConfig: 11 | service: 12 | namespace: system 13 | name: webhook-service 14 | path: /convert 15 | conversionReviewVersions: 16 | - v1 17 | -------------------------------------------------------------------------------- /02-k8s-operator/operator-kubebuilder-clientset/config/default/manager_config_patch.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: apps/v1 2 | kind: Deployment 3 | metadata: 4 | name: controller-manager 5 | namespace: system 6 | spec: 7 | template: 8 | spec: 9 | containers: 10 | - name: manager 11 | -------------------------------------------------------------------------------- /02-k8s-operator/operator-kubebuilder-clientset/config/manager/kustomization.yaml: -------------------------------------------------------------------------------- 1 | resources: 2 | - manager.yaml 3 | -------------------------------------------------------------------------------- /02-k8s-operator/operator-kubebuilder-clientset/config/prometheus/kustomization.yaml: -------------------------------------------------------------------------------- 1 | resources: 2 | - monitor.yaml 3 | -------------------------------------------------------------------------------- /02-k8s-operator/operator-kubebuilder-clientset/config/rbac/auth_proxy_client_clusterrole.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: rbac.authorization.k8s.io/v1 2 | kind: ClusterRole 3 | metadata: 4 | labels: 5 | app.kubernetes.io/name: clusterrole 6 | app.kubernetes.io/instance: metrics-reader 7 | app.kubernetes.io/component: kube-rbac-proxy 8 | app.kubernetes.io/created-by: operator-kubebuilder-clientset 9 | app.kubernetes.io/part-of: operator-kubebuilder-clientset 10 | app.kubernetes.io/managed-by: kustomize 11 | name: metrics-reader 12 | rules: 13 | - nonResourceURLs: 14 | - "/metrics" 15 | verbs: 16 | - get 17 | -------------------------------------------------------------------------------- /02-k8s-operator/operator-kubebuilder-clientset/config/rbac/auth_proxy_role.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: rbac.authorization.k8s.io/v1 2 | kind: ClusterRole 3 | metadata: 4 | labels: 5 | app.kubernetes.io/name: clusterrole 6 | app.kubernetes.io/instance: proxy-role 7 | app.kubernetes.io/component: kube-rbac-proxy 8 | app.kubernetes.io/created-by: operator-kubebuilder-clientset 9 | app.kubernetes.io/part-of: operator-kubebuilder-clientset 10 | app.kubernetes.io/managed-by: kustomize 11 | name: proxy-role 12 | rules: 13 | - apiGroups: 14 | - authentication.k8s.io 15 | resources: 16 | - tokenreviews 17 | verbs: 18 | - create 19 | - apiGroups: 20 | - authorization.k8s.io 21 | resources: 22 | - subjectaccessreviews 23 | verbs: 24 | - create 25 | -------------------------------------------------------------------------------- /02-k8s-operator/operator-kubebuilder-clientset/config/rbac/auth_proxy_role_binding.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: rbac.authorization.k8s.io/v1 2 | kind: ClusterRoleBinding 3 | metadata: 4 | labels: 5 | app.kubernetes.io/name: clusterrolebinding 6 | app.kubernetes.io/instance: proxy-rolebinding 7 | app.kubernetes.io/component: kube-rbac-proxy 8 | app.kubernetes.io/created-by: operator-kubebuilder-clientset 9 | app.kubernetes.io/part-of: operator-kubebuilder-clientset 10 | app.kubernetes.io/managed-by: kustomize 11 | name: proxy-rolebinding 12 | roleRef: 13 | apiGroup: rbac.authorization.k8s.io 14 | kind: ClusterRole 15 | name: proxy-role 16 | subjects: 17 | - kind: ServiceAccount 18 | name: controller-manager 19 | namespace: system 20 | -------------------------------------------------------------------------------- /02-k8s-operator/operator-kubebuilder-clientset/config/rbac/auth_proxy_service.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Service 3 | metadata: 4 | labels: 5 | control-plane: controller-manager 6 | app.kubernetes.io/name: service 7 | app.kubernetes.io/instance: controller-manager-metrics-service 8 | app.kubernetes.io/component: kube-rbac-proxy 9 | app.kubernetes.io/created-by: operator-kubebuilder-clientset 10 | app.kubernetes.io/part-of: operator-kubebuilder-clientset 11 | app.kubernetes.io/managed-by: kustomize 12 | name: controller-manager-metrics-service 13 | namespace: system 14 | spec: 15 | ports: 16 | - name: https 17 | port: 8443 18 | protocol: TCP 19 | targetPort: https 20 | selector: 21 | control-plane: controller-manager 22 | -------------------------------------------------------------------------------- /02-k8s-operator/operator-kubebuilder-clientset/config/rbac/kustomization.yaml: -------------------------------------------------------------------------------- 1 | resources: 2 | # All RBAC will be applied under this service account in 3 | # the deployment namespace. You may comment out this resource 4 | # if your manager will use a service account that exists at 5 | # runtime. Be sure to update RoleBinding and ClusterRoleBinding 6 | # subjects if changing service account names. 7 | - service_account.yaml 8 | - role.yaml 9 | - role_binding.yaml 10 | - leader_election_role.yaml 11 | - leader_election_role_binding.yaml 12 | # Comment the following 4 lines if you want to disable 13 | # the auth proxy (https://github.com/brancz/kube-rbac-proxy) 14 | # which protects your /metrics endpoint. 15 | - auth_proxy_service.yaml 16 | - auth_proxy_role.yaml 17 | - auth_proxy_role_binding.yaml 18 | - auth_proxy_client_clusterrole.yaml 19 | -------------------------------------------------------------------------------- /02-k8s-operator/operator-kubebuilder-clientset/config/rbac/leader_election_role_binding.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: rbac.authorization.k8s.io/v1 2 | kind: RoleBinding 3 | metadata: 4 | labels: 5 | app.kubernetes.io/name: rolebinding 6 | app.kubernetes.io/instance: leader-election-rolebinding 7 | app.kubernetes.io/component: rbac 8 | app.kubernetes.io/created-by: operator-kubebuilder-clientset 9 | app.kubernetes.io/part-of: operator-kubebuilder-clientset 10 | app.kubernetes.io/managed-by: kustomize 11 | name: leader-election-rolebinding 12 | roleRef: 13 | apiGroup: rbac.authorization.k8s.io 14 | kind: Role 15 | name: leader-election-role 16 | subjects: 17 | - kind: ServiceAccount 18 | name: controller-manager 19 | namespace: system 20 | -------------------------------------------------------------------------------- /02-k8s-operator/operator-kubebuilder-clientset/config/rbac/role.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | apiVersion: rbac.authorization.k8s.io/v1 3 | kind: ClusterRole 4 | metadata: 5 | creationTimestamp: null 6 | name: manager-role 7 | rules: 8 | - apiGroups: 9 | - job.lailin.xyz 10 | resources: 11 | - tests 12 | verbs: 13 | - create 14 | - delete 15 | - get 16 | - list 17 | - patch 18 | - update 19 | - watch 20 | - apiGroups: 21 | - job.lailin.xyz 22 | resources: 23 | - tests/finalizers 24 | verbs: 25 | - update 26 | - apiGroups: 27 | - job.lailin.xyz 28 | resources: 29 | - tests/status 30 | verbs: 31 | - get 32 | - patch 33 | - update 34 | -------------------------------------------------------------------------------- /02-k8s-operator/operator-kubebuilder-clientset/config/rbac/role_binding.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: rbac.authorization.k8s.io/v1 2 | kind: ClusterRoleBinding 3 | metadata: 4 | labels: 5 | app.kubernetes.io/name: clusterrolebinding 6 | app.kubernetes.io/instance: manager-rolebinding 7 | app.kubernetes.io/component: rbac 8 | app.kubernetes.io/created-by: operator-kubebuilder-clientset 9 | app.kubernetes.io/part-of: operator-kubebuilder-clientset 10 | app.kubernetes.io/managed-by: kustomize 11 | name: manager-rolebinding 12 | roleRef: 13 | apiGroup: rbac.authorization.k8s.io 14 | kind: ClusterRole 15 | name: manager-role 16 | subjects: 17 | - kind: ServiceAccount 18 | name: controller-manager 19 | namespace: system 20 | -------------------------------------------------------------------------------- /02-k8s-operator/operator-kubebuilder-clientset/config/rbac/service_account.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: ServiceAccount 3 | metadata: 4 | labels: 5 | app.kubernetes.io/name: serviceaccount 6 | app.kuberentes.io/instance: controller-manager 7 | app.kubernetes.io/component: rbac 8 | app.kubernetes.io/created-by: operator-kubebuilder-clientset 9 | app.kubernetes.io/part-of: operator-kubebuilder-clientset 10 | app.kubernetes.io/managed-by: kustomize 11 | name: controller-manager 12 | namespace: system 13 | -------------------------------------------------------------------------------- /02-k8s-operator/operator-kubebuilder-clientset/config/rbac/test_editor_role.yaml: -------------------------------------------------------------------------------- 1 | # permissions for end users to edit tests. 2 | apiVersion: rbac.authorization.k8s.io/v1 3 | kind: ClusterRole 4 | metadata: 5 | labels: 6 | app.kubernetes.io/name: clusterrole 7 | app.kubernetes.io/instance: test-editor-role 8 | app.kubernetes.io/component: rbac 9 | app.kubernetes.io/created-by: operator-kubebuilder-clientset 10 | app.kubernetes.io/part-of: operator-kubebuilder-clientset 11 | app.kubernetes.io/managed-by: kustomize 12 | name: test-editor-role 13 | rules: 14 | - apiGroups: 15 | - job.lailin.xyz 16 | resources: 17 | - tests 18 | verbs: 19 | - create 20 | - delete 21 | - get 22 | - list 23 | - patch 24 | - update 25 | - watch 26 | - apiGroups: 27 | - job.lailin.xyz 28 | resources: 29 | - tests/status 30 | verbs: 31 | - get 32 | -------------------------------------------------------------------------------- /02-k8s-operator/operator-kubebuilder-clientset/config/rbac/test_viewer_role.yaml: -------------------------------------------------------------------------------- 1 | # permissions for end users to view tests. 2 | apiVersion: rbac.authorization.k8s.io/v1 3 | kind: ClusterRole 4 | metadata: 5 | labels: 6 | app.kubernetes.io/name: clusterrole 7 | app.kubernetes.io/instance: test-viewer-role 8 | app.kubernetes.io/component: rbac 9 | app.kubernetes.io/created-by: operator-kubebuilder-clientset 10 | app.kubernetes.io/part-of: operator-kubebuilder-clientset 11 | app.kubernetes.io/managed-by: kustomize 12 | name: test-viewer-role 13 | rules: 14 | - apiGroups: 15 | - job.lailin.xyz 16 | resources: 17 | - tests 18 | verbs: 19 | - get 20 | - list 21 | - watch 22 | - apiGroups: 23 | - job.lailin.xyz 24 | resources: 25 | - tests/status 26 | verbs: 27 | - get 28 | -------------------------------------------------------------------------------- /02-k8s-operator/operator-kubebuilder-clientset/config/samples/job_v1_test.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: job.lailin.xyz/v1 2 | kind: Test 3 | metadata: 4 | labels: 5 | app.kubernetes.io/name: test 6 | app.kubernetes.io/instance: test-sample 7 | app.kubernetes.io/part-of: operator-kubebuilder-clientset 8 | app.kuberentes.io/managed-by: kustomize 9 | app.kubernetes.io/created-by: operator-kubebuilder-clientset 10 | name: test-sample 11 | spec: 12 | foo: "test" 13 | -------------------------------------------------------------------------------- /02-k8s-operator/operator-kubebuilder-clientset/hack/boilerplate.go.txt: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2022. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ -------------------------------------------------------------------------------- /02-k8s-operator/operator-kubebuilder-clientset/hack/code_generator.go: -------------------------------------------------------------------------------- 1 | //go:build tools 2 | // +build tools 3 | 4 | package hack 5 | 6 | import _ "k8s.io/code-generator" // code-generator TODO 7 | -------------------------------------------------------------------------------- /02-k8s-operator/operator-kubebuilder-clientset/pkg/clientset/v1/doc.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright The Kubernetes Authors. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | // Code generated by client-gen. DO NOT EDIT. 18 | 19 | // This package has the automatically generated clientset. 20 | package v1 21 | -------------------------------------------------------------------------------- /02-k8s-operator/operator-kubebuilder-clientset/pkg/clientset/v1/fake/doc.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright The Kubernetes Authors. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | // Code generated by client-gen. DO NOT EDIT. 18 | 19 | // This package has the automatically generated fake clientset. 20 | package fake 21 | -------------------------------------------------------------------------------- /02-k8s-operator/operator-kubebuilder-clientset/pkg/clientset/v1/scheme/doc.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright The Kubernetes Authors. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | // Code generated by client-gen. DO NOT EDIT. 18 | 19 | // This package contains the scheme of the automatically generated clientset. 20 | package scheme 21 | -------------------------------------------------------------------------------- /02-k8s-operator/operator-kubebuilder-clientset/pkg/clientset/v1/typed/job/v1/doc.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright The Kubernetes Authors. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | // Code generated by client-gen. DO NOT EDIT. 18 | 19 | // This package has the automatically generated typed clients. 20 | package v1 21 | -------------------------------------------------------------------------------- /02-k8s-operator/operator-kubebuilder-clientset/pkg/clientset/v1/typed/job/v1/fake/doc.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright The Kubernetes Authors. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | // Code generated by client-gen. DO NOT EDIT. 18 | 19 | // Package fake has the automatically generated clients. 20 | package fake 21 | -------------------------------------------------------------------------------- /02-k8s-operator/operator-kubebuilder-clientset/pkg/clientset/v1/typed/job/v1/generated_expansion.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright The Kubernetes Authors. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | // Code generated by client-gen. DO NOT EDIT. 18 | 19 | package v1 20 | 21 | type TestExpansion interface{} 22 | -------------------------------------------------------------------------------- /03-leetcode/01_tree/101-symmetric-tree.go: -------------------------------------------------------------------------------- 1 | package tree 2 | 3 | func isSymmetric(root *TreeNode) bool { 4 | current := []*TreeNode{root} 5 | for len(current) > 0 { 6 | next := []*TreeNode{} 7 | for i := 0; i < len(current); i++ { 8 | node := current[i] 9 | other := current[len(current)-i-1] 10 | 11 | if node == nil && other == nil { 12 | continue 13 | } 14 | 15 | if node == nil || other == nil { 16 | return false 17 | } 18 | 19 | if node.Val != other.Val { 20 | return false 21 | } 22 | 23 | next = append(next, node.Left, node.Right) 24 | } 25 | current = next 26 | } 27 | return true 28 | } 29 | -------------------------------------------------------------------------------- /03-leetcode/01_tree/105-construct-binary-tree-from-preorder-and-inorder-traversal.go: -------------------------------------------------------------------------------- 1 | package tree 2 | 3 | func buildTree(preorder []int, inorder []int) *TreeNode { 4 | if len(preorder) == 0 { 5 | return nil 6 | } 7 | 8 | root := &TreeNode{Val: preorder[0]} 9 | 10 | // 找到交界位置 11 | i := 0 12 | for ; i < len(inorder); i++ { 13 | if preorder[0] == inorder[i] { 14 | break 15 | } 16 | } 17 | 18 | root.Left = buildTree(preorder[1:i+1], inorder[:i]) 19 | root.Right = buildTree(preorder[i+1:], inorder[i+1:]) 20 | return root 21 | } 22 | -------------------------------------------------------------------------------- /03-leetcode/01_tree/105-construct-binary-tree-from-preorder-and-inorder-traversal_test.go: -------------------------------------------------------------------------------- 1 | package tree 2 | 3 | import ( 4 | "testing" 5 | 6 | "github.com/stretchr/testify/assert" 7 | ) 8 | 9 | func Test_buildTree(t *testing.T) { 10 | tests := []struct { 11 | name string 12 | preorder []int 13 | inorder []int 14 | want []int 15 | }{ 16 | { 17 | preorder: []int{}, 18 | inorder: []int{}, 19 | want: nil, 20 | }, 21 | { 22 | preorder: []int{3, 9, 20, 15, 7}, 23 | inorder: []int{9, 3, 15, 20, 7}, 24 | want: []int{3, 9, 20, null, null, 15, 7}, 25 | }, 26 | } 27 | for _, tt := range tests { 28 | t.Run(tt.name, func(t *testing.T) { 29 | got := buildTree(tt.preorder, tt.inorder) 30 | assert.Equal(t, tt.want, got.array()) 31 | }) 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /03-leetcode/01_tree/113-path-sum-ii.go: -------------------------------------------------------------------------------- 1 | package tree 2 | 3 | func pathSum(root *TreeNode, targetSum int) [][]int { 4 | if root == nil { 5 | return nil 6 | } 7 | 8 | if root.Val == targetSum && root.Left == nil && root.Right == nil { 9 | return [][]int{{root.Val}} 10 | } 11 | 12 | var res [][]int 13 | 14 | if data := pathSum(root.Left, targetSum-root.Val); data != nil { 15 | for _, n := range data { 16 | res = append(res, append([]int{root.Val}, n...)) 17 | } 18 | } 19 | if data := pathSum(root.Right, targetSum-root.Val); data != nil { 20 | for _, n := range data { 21 | res = append(res, append([]int{root.Val}, n...)) 22 | } 23 | } 24 | return res 25 | } 26 | -------------------------------------------------------------------------------- /03-leetcode/01_tree/113-path-sum-ii_test.go: -------------------------------------------------------------------------------- 1 | package tree 2 | 3 | import ( 4 | "testing" 5 | 6 | "github.com/stretchr/testify/assert" 7 | ) 8 | 9 | func Test_pathSum(t *testing.T) { 10 | type args struct { 11 | root []int 12 | targetSum int 13 | } 14 | tests := []struct { 15 | name string 16 | args args 17 | want [][]int 18 | }{ 19 | { 20 | args: args{ 21 | root: []int{5, 4, 8, 11, null, 13, 4, 7, 2, null, null, 5, 1}, 22 | targetSum: 22, 23 | }, 24 | want: [][]int{{5, 4, 11, 2}, {5, 8, 4, 5}}, 25 | }, 26 | } 27 | for _, tt := range tests { 28 | t.Run(tt.name, func(t *testing.T) { 29 | tree := NewTreeNode(tt.args.root, 0) 30 | t.Log(tree.array()) 31 | assert.Equal(t, tt.want, pathSum(tree, tt.args.targetSum)) 32 | }) 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /03-leetcode/01_tree/124-binary-tree-maximum-path-sum.go: -------------------------------------------------------------------------------- 1 | package tree 2 | 3 | // 计算节点的最大贡献值 4 | var sum int 5 | 6 | func maxPathSum(root *TreeNode) int { 7 | sum = -1e9 8 | maxPathSumGain(root) 9 | return sum 10 | } 11 | 12 | func maxPathSumGain(root *TreeNode) int { 13 | if root == nil { 14 | return 0 15 | } 16 | 17 | // 子节点只有大于 0 才能产生贡献 18 | left := max(maxPathSumGain(root.Left), 0) 19 | right := max(maxPathSumGain(root.Right), 0) 20 | sum = max(left+root.Val+right, sum) 21 | 22 | return max(root.Val+left, root.Val+right) 23 | } 24 | 25 | func max(data ...int) int { 26 | var res int = -1e9 27 | for _, v := range data { 28 | if v > res { 29 | res = v 30 | } 31 | } 32 | return res 33 | } 34 | -------------------------------------------------------------------------------- /03-leetcode/01_tree/124-binary-tree-maximum-path-sum_test.go: -------------------------------------------------------------------------------- 1 | package tree 2 | 3 | import ( 4 | "testing" 5 | 6 | "github.com/stretchr/testify/assert" 7 | ) 8 | 9 | func Test_maxPathSum(t *testing.T) { 10 | tests := []struct { 11 | name string 12 | tree []int 13 | want int 14 | }{ 15 | { 16 | tree: []int{1, 2, 3}, 17 | want: 6, 18 | }, 19 | { 20 | tree: []int{-10, 9, 20, null, null, 15, 7}, 21 | want: 42, 22 | }, 23 | } 24 | for _, tt := range tests { 25 | t.Run(tt.name, func(t *testing.T) { 26 | assert.Equal(t, tt.want, maxPathSum(NewTreeNode(tt.tree, 0))) 27 | }) 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /03-leetcode/01_tree/199-binary-tree-right-side-view.go: -------------------------------------------------------------------------------- 1 | package tree 2 | 3 | /** 4 | * Definition for a binary tree node. 5 | * type TreeNode struct { 6 | * Val int 7 | * Left *TreeNode 8 | * Right *TreeNode 9 | * } 10 | */ 11 | func rightSideView(root *TreeNode) []int { 12 | var res []int 13 | if root == nil { 14 | return res 15 | } 16 | 17 | current := []*TreeNode{root} 18 | 19 | for len(current) > 0 { 20 | res = append(res, current[len(current)-1].Val) 21 | var next []*TreeNode 22 | 23 | for _, n := range current { 24 | if n.Left != nil { 25 | next = append(next, n.Left) 26 | } 27 | if n.Right != nil { 28 | next = append(next, n.Right) 29 | } 30 | } 31 | current = next 32 | } 33 | return res 34 | } 35 | -------------------------------------------------------------------------------- /03-leetcode/01_tree/199-binary-tree-right-side-view_test.go: -------------------------------------------------------------------------------- 1 | package tree 2 | 3 | import ( 4 | "reflect" 5 | "testing" 6 | ) 7 | 8 | func Test_rightSideView(t *testing.T) { 9 | 10 | tests := []struct { 11 | name string 12 | tree []int 13 | want []int 14 | }{ 15 | { 16 | tree: []int{1, 2, 3, null, 5, null, 4}, 17 | want: []int{1, 3, 4}, 18 | }, 19 | { 20 | tree: []int{}, 21 | want: nil, 22 | }, 23 | } 24 | for _, tt := range tests { 25 | t.Run(tt.name, func(t *testing.T) { 26 | root := NewTreeNode(tt.tree, 0) 27 | if got := rightSideView(root); !reflect.DeepEqual(got, tt.want) { 28 | t.Errorf("rightSideView() = %v, want %v", got, tt.want) 29 | } 30 | }) 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /03-leetcode/01_tree/230-kth-smallest-element-in-a-bst.go: -------------------------------------------------------------------------------- 1 | package tree 2 | 3 | /** 4 | * Definition for a binary tree node. 5 | * type TreeNode struct { 6 | * Val int 7 | * Left *TreeNode 8 | * Right *TreeNode 9 | * } 10 | */ 11 | 12 | var kthSmallestIndex int 13 | 14 | func kthSmallest(root *TreeNode, k int) int { 15 | kthSmallestIndex = 0 16 | n := kthSmallestSearch(root, k) 17 | if n == nil { 18 | return -1 19 | } 20 | return n.Val 21 | } 22 | 23 | func kthSmallestSearch(root *TreeNode, k int) *TreeNode { 24 | if root == nil { 25 | return nil 26 | } 27 | if data := kthSmallestSearch(root.Left, k); data != nil { 28 | return data 29 | } 30 | kthSmallestIndex++ 31 | if kthSmallestIndex == k { 32 | return root 33 | } 34 | if data := kthSmallestSearch(root.Right, k); data != nil { 35 | return data 36 | } 37 | return nil 38 | } 39 | -------------------------------------------------------------------------------- /03-leetcode/01_tree/230-kth-smallest-element-in-a-bst_test.go: -------------------------------------------------------------------------------- 1 | package tree 2 | 3 | import "testing" 4 | 5 | func Test_kthSmallest(t *testing.T) { 6 | type args struct { 7 | data []int 8 | k int 9 | } 10 | tests := []struct { 11 | name string 12 | args args 13 | want int 14 | }{ 15 | { 16 | args: args{ 17 | data: []int{5, 3, 6, 2, 4, null, null, 1}, 18 | k: 3, 19 | }, 20 | want: 3, 21 | }, 22 | } 23 | for _, tt := range tests { 24 | t.Run(tt.name, func(t *testing.T) { 25 | if got := kthSmallest(NewTreeNode(tt.args.data, 0), tt.args.k); got != tt.want { 26 | t.Errorf("kthSmallest() = %v, want %v", got, tt.want) 27 | } 28 | }) 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /03-leetcode/01_tree/543-diameter-of-binary-tree.go: -------------------------------------------------------------------------------- 1 | package tree 2 | 3 | func diameterOfBinaryTree(root *TreeNode) int { 4 | if root == nil { 5 | return 0 6 | } 7 | res := 0 8 | var helper func(n *TreeNode) int 9 | helper = func(n *TreeNode) int { 10 | if n == nil { 11 | return 0 12 | } 13 | 14 | left := helper(n.Left) 15 | right := helper(n.Right) 16 | res = max(res, left+right) 17 | return max(left, right) + 1 18 | } 19 | helper(root) 20 | return res 21 | } 22 | -------------------------------------------------------------------------------- /03-leetcode/01_tree/662-maximum-width-of-binary-tree.go: -------------------------------------------------------------------------------- 1 | package tree 2 | 3 | func widthOfBinaryTree(root *TreeNode) int { 4 | if root == nil { 5 | return 0 6 | } 7 | root.Val = 0 8 | current := []*TreeNode{root} 9 | max := 0 10 | for len(current) > 0 { 11 | var next []*TreeNode 12 | 13 | for _, n := range current { 14 | if n.Left != nil { 15 | n.Left.Val = 2 * n.Val 16 | next = append(next, n.Left) 17 | } 18 | if n.Right != nil { 19 | n.Right.Val = 2*n.Val + 1 20 | next = append(next, n.Right) 21 | } 22 | } 23 | val := current[len(current)-1].Val + 1 - current[0].Val 24 | if val > max { 25 | max = val 26 | } 27 | current = next 28 | } 29 | return max 30 | } 31 | -------------------------------------------------------------------------------- /03-leetcode/01_tree/662-maximum-width-of-binary-tree_test.go: -------------------------------------------------------------------------------- 1 | package tree 2 | 3 | import ( 4 | "testing" 5 | 6 | "github.com/stretchr/testify/assert" 7 | ) 8 | 9 | func Test_widthOfBinaryTree(t *testing.T) { 10 | 11 | tests := []struct { 12 | name string 13 | tree []int 14 | want int 15 | }{ 16 | { 17 | tree: []int{1, 3, 2, 5, null, null, 9, 6, null, null, 7}, 18 | want: 8, 19 | }, 20 | } 21 | for _, tt := range tests { 22 | t.Run(tt.name, func(t *testing.T) { 23 | assert.Equal(t, tt.want, widthOfBinaryTree(NewTree(tt.tree))) 24 | }) 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /03-leetcode/01_tree/958-check-completeness-of-a-binary-tree.go: -------------------------------------------------------------------------------- 1 | package tree 2 | 3 | func isCompleteTree(root *TreeNode) bool { 4 | current := []*TreeNode{root} 5 | isOver := true 6 | for len(current) > 0 { 7 | var next []*TreeNode 8 | hasNil := false 9 | for _, n := range current { 10 | if n == nil { 11 | hasNil = true 12 | continue 13 | } 14 | next = append(next, n.Left, n.Right) 15 | if hasNil { 16 | return false 17 | } 18 | } 19 | if !isOver && len(next) > 0 { 20 | return false 21 | } 22 | isOver = !hasNil 23 | current = next 24 | } 25 | return true 26 | } 27 | -------------------------------------------------------------------------------- /03-leetcode/01_tree/958-check-completeness-of-a-binary-tree_test.go: -------------------------------------------------------------------------------- 1 | package tree 2 | 3 | import ( 4 | "testing" 5 | 6 | "github.com/stretchr/testify/assert" 7 | ) 8 | 9 | func Test_isCompleteTree(t *testing.T) { 10 | tests := []struct { 11 | name string 12 | tree []int 13 | want bool 14 | }{ 15 | { 16 | tree: []int{1, 2, 3, 4, 5, 6}, 17 | want: true, 18 | }, 19 | } 20 | for _, tt := range tests { 21 | t.Run(tt.name, func(t *testing.T) { 22 | assert.Equal(t, tt.want, isCompleteTree(NewTreeNode(tt.tree, 0))) 23 | }) 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /03-leetcode/01_tree/98-validate-binary-search-tree.go: -------------------------------------------------------------------------------- 1 | package tree 2 | 3 | func isValidBST(root *TreeNode) bool { 4 | _, _, valid := isValidBSTSearch(root) 5 | return valid 6 | } 7 | 8 | func isValidBSTSearch(root *TreeNode) (min, max int, valid bool) { 9 | min, max = root.Val, root.Val 10 | 11 | if root.Left != nil { 12 | lmin, lmax, valid := isValidBSTSearch(root.Left) 13 | if !valid { 14 | return lmin, lmax, valid 15 | } 16 | 17 | if lmax >= root.Val { 18 | return min, max, false 19 | } 20 | min = lmin 21 | } 22 | 23 | if root.Right != nil { 24 | rmin, rmax, valid := isValidBSTSearch(root.Right) 25 | if !valid { 26 | return min, max, valid 27 | } 28 | 29 | if rmin <= root.Val { 30 | return min, max, false 31 | } 32 | max = rmax 33 | } 34 | 35 | return min, max, true 36 | } 37 | -------------------------------------------------------------------------------- /03-leetcode/01_tree/98-validate-binary-search-tree_test.go: -------------------------------------------------------------------------------- 1 | package tree 2 | 3 | import ( 4 | "testing" 5 | 6 | "github.com/stretchr/testify/assert" 7 | ) 8 | 9 | func Test_isValidBST(t *testing.T) { 10 | 11 | tests := []struct { 12 | name string 13 | tree []int 14 | want bool 15 | }{ 16 | { 17 | tree: []int{1, 1}, 18 | want: false, 19 | }, 20 | { 21 | tree: []int{5, 4, 6, null, null, 3, 7}, 22 | want: false, 23 | }, 24 | { 25 | tree: []int{5, 1, 4, null, null, 3, 6}, 26 | want: false, 27 | }, 28 | } 29 | for _, tt := range tests { 30 | t.Run(tt.name, func(t *testing.T) { 31 | assert.Equal(t, tt.want, isValidBST(NewTreeNode(tt.tree, 0))) 32 | }) 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /03-leetcode/02_search/162-find-peak-element.go: -------------------------------------------------------------------------------- 1 | package search 2 | 3 | import "math" 4 | 5 | // 迭代法 6 | func findPeakElement(nums []int) int { 7 | nums = append(nums, -math.MaxInt32) 8 | nums = append([]int{-math.MaxInt32}, nums...) 9 | for i := 1; i < len(nums)-1; i++ { 10 | if nums[i] > nums[i+1] && nums[i] > nums[i-1] { 11 | return i - 1 12 | } 13 | } 14 | return 0 15 | } 16 | 17 | // findPeakElement2 2分法 18 | func findPeakElement2(nums []int) int { 19 | left, right := 0, len(nums)-1 20 | for left <= right { 21 | mid := left + (right-left)/2 22 | if mid+1 >= len(nums) || nums[mid] > nums[mid+1] { 23 | if mid == 0 || nums[mid] > nums[mid-1] { 24 | return mid 25 | } 26 | right = mid - 1 27 | } else { 28 | left = mid + 1 29 | } 30 | } 31 | return 0 32 | } 33 | -------------------------------------------------------------------------------- /03-leetcode/02_search/162-find-peak-element_test.go: -------------------------------------------------------------------------------- 1 | package search 2 | 3 | import "testing" 4 | 5 | func Test_findPeakElement2(t *testing.T) { 6 | 7 | tests := []struct { 8 | name string 9 | args []int 10 | want int 11 | }{ 12 | { 13 | args: []int{1, 2, 3, 1}, 14 | want: 2, 15 | }, 16 | } 17 | for _, tt := range tests { 18 | t.Run(tt.name, func(t *testing.T) { 19 | if got := findPeakElement2(tt.args); got != tt.want { 20 | t.Errorf("findPeakElement2() = %v, want %v", got, tt.want) 21 | } 22 | }) 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /03-leetcode/02_search/240-search-a-2d-matrix-ii.go: -------------------------------------------------------------------------------- 1 | package search 2 | 3 | func searchMatrix(matrix [][]int, target int) bool { 4 | for _, row := range matrix { 5 | start, end := 0, len(row)-1 6 | for start <= end { 7 | mid := start + (end-start)/2 8 | if row[mid] < target { 9 | start = mid + 1 10 | } else if row[mid] == target { 11 | return true 12 | } else { 13 | end = mid - 1 14 | } 15 | } 16 | } 17 | return false 18 | } 19 | -------------------------------------------------------------------------------- /03-leetcode/03_list/141-linked-list-cycle.go: -------------------------------------------------------------------------------- 1 | package list 2 | 3 | func hasCycle(head *ListNode) bool { 4 | if head == nil { 5 | return false 6 | } 7 | slow, fast := head, head.Next 8 | for fast != nil && fast.Next != nil { 9 | if slow == fast { 10 | return true 11 | } 12 | fast = fast.Next.Next 13 | slow = slow.Next 14 | } 15 | return false 16 | } 17 | -------------------------------------------------------------------------------- /03-leetcode/03_list/143-reorder-list.go: -------------------------------------------------------------------------------- 1 | package list 2 | 3 | func reorderList(head *ListNode) { 4 | var data []*ListNode 5 | for head != nil { 6 | data = append(data, head) 7 | next := head.Next 8 | head.Next = nil 9 | head = next 10 | } 11 | 12 | start, end := 0, len(data)-1 13 | for start < end { 14 | data[start].Next = data[end] 15 | if start+1 < end { 16 | data[end].Next = data[start+1] 17 | } 18 | start++ 19 | end-- 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /03-leetcode/03_list/146-lru-cache_test.go: -------------------------------------------------------------------------------- 1 | package list 2 | 3 | import ( 4 | "testing" 5 | ) 6 | 7 | func TestConstructor(t *testing.T) { 8 | lRUCache := Constructor(2) 9 | lRUCache.Put(1, 1) // 缓存是 {1=1} 10 | lRUCache.Put(2, 2) // 缓存是 {1=1, 2=2} 11 | lRUCache.Get(1) // 返回 1 12 | lRUCache.Put(3, 3) // 该操作会使得关键字 2 作废,缓存是 {1=1, 3=3} 13 | lRUCache.Get(2) // 返回 -1 (未找到) 14 | lRUCache.Put(4, 4) // 该操作会使得关键字 1 作废,缓存是 {4=4, 3=3} 15 | lRUCache.Get(1) // 返回 -1 (未找到) 16 | lRUCache.Get(3) // 返回 3 17 | lRUCache.Get(4) // 返回 4 18 | } 19 | -------------------------------------------------------------------------------- /03-leetcode/03_list/148-sort-list_test.go: -------------------------------------------------------------------------------- 1 | package list 2 | 3 | import ( 4 | "testing" 5 | 6 | "github.com/stretchr/testify/assert" 7 | ) 8 | 9 | func Test_sortList(t *testing.T) { 10 | 11 | tests := []struct { 12 | name string 13 | list []int 14 | want []int 15 | }{ 16 | { 17 | list: []int{4, 2, 1, 3}, 18 | want: []int{1, 2, 3, 4}, 19 | }, 20 | } 21 | for _, tt := range tests { 22 | t.Run(tt.name, func(t *testing.T) { 23 | assert.Equal(t, tt.want, sortList2(NewList(tt.list)).array()) 24 | }) 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /03-leetcode/03_list/160-intersection-of-two-linked-lists.go: -------------------------------------------------------------------------------- 1 | package list 2 | 3 | func getIntersectionNode(headA, headB *ListNode) *ListNode { 4 | // 1. 第一步找到两个链表的结尾 5 | a, b := headA, headB 6 | stackA, stackB := []*ListNode{}, []*ListNode{} 7 | for a.Next != nil { 8 | stackA = append(stackA, a) 9 | a = a.Next 10 | } 11 | 12 | for b.Next != nil { 13 | stackB = append(stackB, b) 14 | b = b.Next 15 | } 16 | 17 | if a != b { 18 | return nil 19 | } 20 | 21 | for i := 1; i <= len(stackA) && i <= len(stackB); i++ { 22 | if stackA[len(stackA)-i] != stackB[len(stackB)-i] { 23 | break 24 | } 25 | a = stackA[len(stackA)-i] 26 | } 27 | 28 | return a 29 | } 30 | -------------------------------------------------------------------------------- /03-leetcode/03_list/160-intersection-of-two-linked-lists_test.go: -------------------------------------------------------------------------------- 1 | package list 2 | 3 | import ( 4 | "fmt" 5 | "testing" 6 | 7 | "github.com/stretchr/testify/assert" 8 | ) 9 | 10 | func Test_getIntersectionNode(t *testing.T) { 11 | headA := NewList([]int{4, 1, 8, 4, 5}) 12 | headB := NewList([]int{5, 6, 1}) 13 | headB.Next.Next.Next = headA.Next.Next 14 | // headA := NewList([]int{2, 6, 4}) 15 | // headB := NewList([]int{5, 1}) 16 | fmt.Println(headA.array(), headB.array()) 17 | assert.Equal(t, headA.Next.Next, getIntersectionNode(headA, headB)) 18 | } 19 | -------------------------------------------------------------------------------- /03-leetcode/03_list/206-reverse-linked-list.go: -------------------------------------------------------------------------------- 1 | package list 2 | 3 | func reverseList(head *ListNode) *ListNode { 4 | if head == nil || head.Next == nil { 5 | return head 6 | } 7 | 8 | current := head 9 | next := current.Next 10 | current.Next = nil 11 | for next != nil { 12 | n := next.Next 13 | next.Next = current 14 | current = next 15 | next = n 16 | } 17 | return current 18 | } 19 | -------------------------------------------------------------------------------- /03-leetcode/03_list/206-reverse-linked-list_test.go: -------------------------------------------------------------------------------- 1 | package list 2 | 3 | import ( 4 | "testing" 5 | 6 | "github.com/stretchr/testify/assert" 7 | ) 8 | 9 | func Test_reverseList(t *testing.T) { 10 | 11 | tests := []struct { 12 | name string 13 | list []int 14 | want []int 15 | }{ 16 | { 17 | list: []int{1, 2, 3, 4, 5}, 18 | want: []int{5, 4, 3, 2, 1}, 19 | }, 20 | } 21 | for _, tt := range tests { 22 | t.Run(tt.name, func(t *testing.T) { 23 | assert.Equal(t, tt.want, reverseList(NewList(tt.list)).array()) 24 | }) 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /03-leetcode/03_list/21-merge-two-sorted-lists.go: -------------------------------------------------------------------------------- 1 | package list 2 | 3 | func mergeTwoLists(l1 *ListNode, l2 *ListNode) *ListNode { 4 | res := &ListNode{} 5 | n := res 6 | for l1 != nil && l2 != nil { 7 | 8 | if l1.Val > l2.Val { 9 | n.Next = l2 10 | l2 = l2.Next 11 | } else { 12 | n.Next = l1 13 | l1 = l1.Next 14 | } 15 | n = n.Next 16 | } 17 | if l1 == nil { 18 | n.Next = l2 19 | } 20 | if l2 == nil { 21 | n.Next = l1 22 | } 23 | return res.Next 24 | } 25 | -------------------------------------------------------------------------------- /03-leetcode/03_list/23-merge-k-sorted-lists.go: -------------------------------------------------------------------------------- 1 | package list 2 | 3 | import "math" 4 | 5 | func mergeKLists(lists []*ListNode) *ListNode { 6 | res := &ListNode{} 7 | n := res 8 | for len(lists) > 0 { 9 | min := &ListNode{Val: math.MaxInt32} 10 | minIndex := -1 11 | for i, l := range lists { 12 | if l == nil { 13 | continue 14 | } 15 | if l.Val < min.Val { 16 | min = l 17 | minIndex = i 18 | } 19 | } 20 | if minIndex == -1 { 21 | break 22 | } 23 | lists[minIndex] = lists[minIndex].Next 24 | n.Next = min 25 | n = min 26 | } 27 | return res.Next 28 | } 29 | -------------------------------------------------------------------------------- /03-leetcode/03_list/234-palindrome-linked-list.go: -------------------------------------------------------------------------------- 1 | package list 2 | 3 | func isPalindrome(head *ListNode) bool { 4 | n := head 5 | var stack []int 6 | for n != nil { 7 | stack = append(stack, n.Val) 8 | n = n.Next 9 | } 10 | for i := 0; i < len(stack)-1-i; i++ { 11 | if stack[i] != stack[len(stack)-1-i] { 12 | return false 13 | } 14 | } 15 | return true 16 | } 17 | -------------------------------------------------------------------------------- /03-leetcode/03_list/234-palindrome-linked-list_test.go: -------------------------------------------------------------------------------- 1 | package list 2 | 3 | import ( 4 | "testing" 5 | 6 | "github.com/stretchr/testify/assert" 7 | ) 8 | 9 | func Test_isPalindrome(t *testing.T) { 10 | tests := []struct { 11 | name string 12 | list []int 13 | want bool 14 | }{ 15 | { 16 | list: []int{1, 2, 2, 1}, 17 | want: true, 18 | }, 19 | } 20 | for _, tt := range tests { 21 | t.Run(tt.name, func(t *testing.T) { 22 | assert.Equal(t, tt.want, isPalindrome(NewList(tt.list))) 23 | }) 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /03-leetcode/03_list/25-reverse-nodes-in-k-group_test.go: -------------------------------------------------------------------------------- 1 | package list 2 | 3 | import ( 4 | "testing" 5 | 6 | "github.com/stretchr/testify/assert" 7 | ) 8 | 9 | func Test_reverseKGroup(t *testing.T) { 10 | type args struct { 11 | head *ListNode 12 | k int 13 | } 14 | tests := []struct { 15 | name string 16 | list []int 17 | k int 18 | want []int 19 | }{ 20 | // { 21 | // list: []int{1, 2, 3, 4, 5}, 22 | // k: 3, 23 | // want: []int{3, 2, 1, 4, 5}, 24 | // }, 25 | { 26 | list: []int{1, 2, 3, 4, 5}, 27 | k: 2, 28 | want: []int{2, 1, 4, 3, 5}, 29 | }, 30 | } 31 | for _, tt := range tests { 32 | t.Run(tt.name, func(t *testing.T) { 33 | head := NewList(tt.list) 34 | assert.Equal(t, tt.want, reverseKGroup(head, tt.k).array()) 35 | }) 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /03-leetcode/03_list/92-reverse-linked-list-ii.go: -------------------------------------------------------------------------------- 1 | package list 2 | 3 | func reverseBetween(head *ListNode, left int, right int) *ListNode { 4 | stack := make([]*ListNode, right-left+1) 5 | node := &ListNode{Next: head} 6 | prev := node 7 | for i := 1; i <= right; i++ { 8 | if i == left-1 { 9 | prev = head 10 | } 11 | if i >= left { 12 | stack[i-left] = head 13 | } 14 | head = head.Next 15 | } 16 | for i := len(stack) - 1; i >= 0; i-- { 17 | prev.Next = stack[i] 18 | prev = stack[i] 19 | } 20 | prev.Next = head 21 | 22 | return node.Next 23 | } 24 | -------------------------------------------------------------------------------- /03-leetcode/03_list/list.go: -------------------------------------------------------------------------------- 1 | package list 2 | 3 | // ListNode 链表节点 4 | type ListNode struct { 5 | Val int 6 | Next *ListNode 7 | } 8 | 9 | func NewList(data []int) *ListNode { 10 | if len(data) == 0 { 11 | return nil 12 | } 13 | 14 | head := &ListNode{Val: data[0]} 15 | n := head 16 | for i := 1; i < len(data); i++ { 17 | n.Next = &ListNode{Val: data[i]} 18 | n = n.Next 19 | } 20 | 21 | return head 22 | } 23 | 24 | func (n *ListNode) array() []int { 25 | var res []int 26 | for n != nil { 27 | res = append(res, n.Val) 28 | n = n.Next 29 | } 30 | return res 31 | } 32 | -------------------------------------------------------------------------------- /03-leetcode/04_stack/20-valid-parentheses.go: -------------------------------------------------------------------------------- 1 | package stack 2 | 3 | import "strings" 4 | 5 | func isValid(s string) bool { 6 | ss := strings.Split(s, "") 7 | var stack []string 8 | for i := len(ss) - 1; i >= 0; i-- { 9 | switch ss[i] { 10 | case ")": 11 | stack = append(stack, "(") 12 | case "]": 13 | stack = append(stack, "[") 14 | case "}": 15 | stack = append(stack, "{") 16 | default: 17 | if len(stack) == 0 { 18 | return false 19 | } 20 | val := stack[len(stack)-1] 21 | stack = stack[:len(stack)-1] 22 | if ss[i] != val { 23 | return false 24 | } 25 | } 26 | } 27 | 28 | return len(stack) == 0 29 | } 30 | -------------------------------------------------------------------------------- /03-leetcode/04_stack/224-basic-calculator_test.go: -------------------------------------------------------------------------------- 1 | package stack 2 | 3 | import "testing" 4 | 5 | func Test_calculate(t *testing.T) { 6 | type args struct { 7 | s string 8 | } 9 | tests := []struct { 10 | name string 11 | args args 12 | want int 13 | }{ 14 | { 15 | args: args{s: "(1+(4+5+2)-3)+(6+8)"}, 16 | want: 23, 17 | }, 18 | { 19 | args: args{s: "-(1+2)"}, 20 | want: -3, 21 | }, 22 | { 23 | args: args{s: " 2-1 + 2 "}, 24 | want: 3, 25 | }, 26 | { 27 | args: args{s: "1 + 1"}, 28 | want: 2, 29 | }, 30 | } 31 | for _, tt := range tests { 32 | t.Run(tt.name, func(t *testing.T) { 33 | if got := calculate(tt.args.s); got != tt.want { 34 | t.Errorf("calculate() = %v, want %v", got, tt.want) 35 | } 36 | }) 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /03-leetcode/04_stack/402-remove-k-digits.go: -------------------------------------------------------------------------------- 1 | package stack 2 | 3 | func removeKdigits(num string, k int) string { 4 | for next := []byte{}; k > 0 && len(next) < len(num); num = string(next) { 5 | i := 0 6 | for ; k > 0 && i < len(num)-1; i++ { 7 | // 首位数字 0 直接丢弃 8 | if len(next) == 0 && num[i] == '0' { 9 | continue 10 | } 11 | if num[i] > num[i+1] { 12 | k = k - 1 13 | } else { 14 | next = append(next, num[i]) 15 | } 16 | } 17 | if i < len(num) { 18 | next = append(next, num[i:]...) 19 | } 20 | } 21 | 22 | // 移除首位 0 23 | i := 0 24 | for ; i < len(num) && num[i] == '0'; i++ { 25 | } 26 | num = num[i:] 27 | 28 | if len(num) <= k || i == len(num) { 29 | return "0" 30 | } 31 | 32 | return num[k:] 33 | } 34 | -------------------------------------------------------------------------------- /03-leetcode/04_stack/45-132-pattern.go: -------------------------------------------------------------------------------- 1 | package stack 2 | 3 | import "math" 4 | 5 | // https://leetcode-cn.com/problems/132-pattern/solution/xiang-xin-ke-xue-xi-lie-xiang-jie-wei-he-95gt/ 6 | func find132pattern(nums []int) bool { 7 | k := math.MinInt64 8 | var stack []int 9 | for i := len(nums) - 1; i >= 0; i-- { 10 | if nums[i] < k { 11 | return true 12 | } 13 | j := len(stack) - 1 14 | for ; j >= 0 && stack[j] < nums[i]; j-- { 15 | if stack[j] > k { 16 | k = stack[j] 17 | } 18 | } 19 | stack = stack[:j+1] 20 | stack = append(stack, nums[i]) 21 | } 22 | return false 23 | } 24 | -------------------------------------------------------------------------------- /03-leetcode/04_stack/45-132-pattern_test.go: -------------------------------------------------------------------------------- 1 | package stack 2 | 3 | import "testing" 4 | 5 | func Test_find132pattern(t *testing.T) { 6 | type args struct { 7 | nums []int 8 | } 9 | tests := []struct { 10 | name string 11 | args args 12 | want bool 13 | }{ 14 | { 15 | args: args{nums: []int{3, 1, 4, 2}}, 16 | want: true, 17 | }, 18 | { 19 | args: args{nums: []int{1, 2, 3, 4}}, 20 | want: false, 21 | }, 22 | } 23 | for _, tt := range tests { 24 | t.Run(tt.name, func(t *testing.T) { 25 | if got := find132pattern(tt.args.nums); got != tt.want { 26 | t.Errorf("find132pattern() = %v, want %v", got, tt.want) 27 | } 28 | }) 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /03-leetcode/04_stack/71-simplify-path.go: -------------------------------------------------------------------------------- 1 | package stack 2 | 3 | import "strings" 4 | 5 | func simplifyPath(path string) string { 6 | paths := strings.Split(path, "/") 7 | var res []string 8 | for _, p := range paths { 9 | switch p { 10 | case "..": 11 | if len(res) > 0 { 12 | res = res[:len(res)-1] 13 | } 14 | case "", ".": 15 | default: 16 | res = append(res, p) 17 | } 18 | } 19 | return "/" + strings.Join(res, "/") 20 | } 21 | -------------------------------------------------------------------------------- /03-leetcode/04_stack/stack.go: -------------------------------------------------------------------------------- 1 | package stack 2 | 3 | type Stack struct { 4 | data []int 5 | } 6 | 7 | func (s *Stack) Push(v int) { 8 | s.data = append(s.data, v) 9 | } 10 | 11 | func (s *Stack) Pop() int { 12 | v := s.data[len(s.data)-1] 13 | s.data = s.data[:len(s.data)-1] 14 | return v 15 | } 16 | -------------------------------------------------------------------------------- /03-leetcode/06_hash/1-two-sum.go: -------------------------------------------------------------------------------- 1 | package hash 2 | 3 | func twoSum(nums []int, target int) []int { 4 | data := map[int]int{} 5 | for i, num := range nums { 6 | if index, ok := data[target-num]; ok { 7 | return []int{index, i} 8 | } 9 | data[num] = i 10 | } 11 | return nil 12 | } 13 | -------------------------------------------------------------------------------- /03-leetcode/06_hash/3-longest-substring-without-repeating-characters.go: -------------------------------------------------------------------------------- 1 | package hash 2 | 3 | func lengthOfLongestSubstring(s string) int { 4 | var ( 5 | start, end, max int 6 | data = map[byte]int{} 7 | ) 8 | for ; end < len(s); end++ { 9 | b := s[end] 10 | i, ok := data[b] 11 | if ok { 12 | for j := i; j >= start && j <= i; j-- { 13 | delete(data, s[j]) 14 | } 15 | start = i + 1 16 | } else if max < end-start+1 { 17 | max = end - start + 1 18 | } 19 | data[b] = end 20 | } 21 | return max 22 | } 23 | -------------------------------------------------------------------------------- /03-leetcode/06_hash/3-longest-substring-without-repeating-characters_test.go: -------------------------------------------------------------------------------- 1 | package hash 2 | 3 | import "testing" 4 | 5 | func Test_lengthOfLongestSubstring(t *testing.T) { 6 | type args struct { 7 | s string 8 | } 9 | tests := []struct { 10 | name string 11 | args args 12 | want int 13 | }{ 14 | { 15 | name: "", 16 | args: args{ 17 | s: "tmmzuxt", 18 | }, 19 | want: 5, 20 | }, 21 | { 22 | name: "", 23 | args: args{ 24 | s: "abcabcbb", 25 | }, 26 | want: 3, 27 | }, 28 | } 29 | for _, tt := range tests { 30 | t.Run(tt.name, func(t *testing.T) { 31 | if got := lengthOfLongestSubstring(tt.args.s); got != tt.want { 32 | t.Errorf("lengthOfLongestSubstring() = %v, want %v", got, tt.want) 33 | } 34 | }) 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /03-leetcode/07_dp/121-best-time-to-buy-and-sell-stock.go: -------------------------------------------------------------------------------- 1 | package dp 2 | 3 | func maxProfit(prices []int) int { 4 | var stack []int 5 | var res int 6 | for _, price := range prices { 7 | if len(stack) == 0 || stack[len(stack)-1] < price { 8 | stack = append(stack, price) 9 | continue 10 | } 11 | i := len(stack) - 1 12 | for ; i >= 0 && stack[i] >= price; i-- { 13 | if stack[i]-stack[0] > res { 14 | res = stack[i] - stack[0] 15 | } 16 | } 17 | i++ 18 | stack = stack[:i] 19 | stack = append(stack, price) 20 | } 21 | if stack[len(stack)-1]-stack[0] > res { 22 | res = stack[len(stack)-1] - stack[0] 23 | } 24 | return res 25 | } 26 | -------------------------------------------------------------------------------- /03-leetcode/07_dp/121-best-time-to-buy-and-sell-stock_test.go: -------------------------------------------------------------------------------- 1 | package dp 2 | 3 | import "testing" 4 | 5 | func Test_maxProfit(t *testing.T) { 6 | type args struct { 7 | prices []int 8 | } 9 | tests := []struct { 10 | name string 11 | args args 12 | want int 13 | }{ 14 | { 15 | name: "", 16 | args: args{ 17 | prices: []int{7, 1, 5, 3, 6, 4}, 18 | }, 19 | want: 5, 20 | }, 21 | } 22 | for _, tt := range tests { 23 | t.Run(tt.name, func(t *testing.T) { 24 | if got := maxProfit(tt.args.prices); got != tt.want { 25 | t.Errorf("maxProfit() = %v, want %v", got, tt.want) 26 | } 27 | }) 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /03-leetcode/07_dp/215-kth-largest-element-in-an-array_test.go: -------------------------------------------------------------------------------- 1 | package dp 2 | 3 | import "testing" 4 | 5 | func Test_findKthLargest(t *testing.T) { 6 | type args struct { 7 | nums []int 8 | k int 9 | } 10 | var tests = []struct { 11 | name string 12 | args args 13 | want int 14 | }{ 15 | { 16 | name: "", 17 | args: args{ 18 | nums: []int{3, 1, 2, 4}, 19 | k: 2, 20 | }, 21 | want: 3, 22 | }, 23 | { 24 | name: "", 25 | args: args{ 26 | nums: []int{3, 2, 1, 5, 6, 4}, 27 | k: 2, 28 | }, 29 | want: 5, 30 | }, 31 | } 32 | for _, tt := range tests { 33 | t.Run(tt.name, func(t *testing.T) { 34 | if got := findKthLargestHeapSort(tt.args.nums, tt.args.k); got != tt.want { 35 | t.Errorf("findKthLargest() = %v, want %v", got, tt.want) 36 | } 37 | }) 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /03-leetcode/07_dp/494-target-sum.go: -------------------------------------------------------------------------------- 1 | package dp 2 | 3 | func findTargetSumWays(nums []int, target int) int { 4 | data := map[int]int{0: 1} 5 | for _, num := range nums { 6 | nData := map[int]int{} 7 | for sum, count := range data { 8 | nData[sum+num] += count 9 | nData[sum-num] += count 10 | } 11 | data = nData 12 | } 13 | return data[target] 14 | } 15 | -------------------------------------------------------------------------------- /03-leetcode/07_dp/494-target-sum_test.go: -------------------------------------------------------------------------------- 1 | package dp 2 | 3 | import "testing" 4 | 5 | func Test_findTargetSumWays(t *testing.T) { 6 | type args struct { 7 | nums []int 8 | target int 9 | } 10 | tests := []struct { 11 | name string 12 | args args 13 | want int 14 | }{ 15 | { 16 | name: "", 17 | args: args{ 18 | nums: []int{1, 1, 1, 1, 1}, 19 | target: 3, 20 | }, 21 | want: 5, 22 | }, 23 | { 24 | name: "", 25 | args: args{ 26 | nums: []int{1, 1}, 27 | target: 0, 28 | }, 29 | want: 2, 30 | }, 31 | } 32 | for _, tt := range tests { 33 | t.Run(tt.name, func(t *testing.T) { 34 | if got := findTargetSumWays(tt.args.nums, tt.args.target); got != tt.want { 35 | t.Errorf("findTargetSumWays() = %v, want %v", got, tt.want) 36 | } 37 | }) 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /03-leetcode/07_dp/5-longest-palindromic-substring.go: -------------------------------------------------------------------------------- 1 | package dp 2 | 3 | func longestPalindrome(s string) string { 4 | var sub string 5 | for i := range s { 6 | // 先查找是否存在相同字符串,如果存在就作为一个整体 7 | k := i + 1 8 | for ; k < len(s) && s[k] == s[i]; k++ { 9 | } 10 | k = k - 1 11 | 12 | // 从中心向外扩散,查找是否相等 13 | j := 1 14 | for ; k+j < len(s) && i-j >= 0 && s[k+j] == s[i-j]; j++ { 15 | } 16 | j = j - 1 17 | if len(sub) < (k+j)-(i-j)+1 { 18 | sub = s[i-j : k+j+1] 19 | } 20 | } 21 | return sub 22 | } 23 | -------------------------------------------------------------------------------- /03-leetcode/go.mod: -------------------------------------------------------------------------------- 1 | module github.com/mohuishou/blog-code/leetcode 2 | 3 | go 1.16 4 | 5 | require ( 6 | github.com/davecgh/go-spew v1.1.1 // indirect 7 | github.com/stretchr/testify v1.7.0 8 | gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b // indirect 9 | ) 10 | -------------------------------------------------------------------------------- /99-other/01-localhost/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM golang:1.15 as builder 2 | 3 | WORKDIR /app 4 | 5 | COPY main.go main.go 6 | COPY run.sh run.sh 7 | 8 | ENV CGO_ENABLED=0 9 | ENV GOOS=linux 10 | 11 | RUN go build main.go 12 | 13 | FROM alpine:3 14 | 15 | WORKDIR /app 16 | 17 | COPY --from=builder /app /app 18 | 19 | #COPY main.go main.go 20 | COPY run.sh run.sh 21 | #COPY nsswitch.conf /etc/nsswitch.conf 22 | 23 | RUN chmod +x run.sh 24 | 25 | ENV GODEBUG="netdns=go+2" 26 | ENV CGO_ENABLED=0 27 | ENV GOOS=linux 28 | 29 | CMD /app/run.sh -------------------------------------------------------------------------------- /99-other/01-localhost/Makefile: -------------------------------------------------------------------------------- 1 | build: 2 | DOCKER_BUILDKIT=1 docker build -f Dockerfile -t locahost-test . 3 | 4 | run: build 5 | docker run locahost-test -------------------------------------------------------------------------------- /99-other/01-localhost/go.mod: -------------------------------------------------------------------------------- 1 | module github.com/mohuishou/blog-code/99-other/01-localhost 2 | 3 | go 1.14 4 | -------------------------------------------------------------------------------- /99-other/01-localhost/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | "net/http" 6 | ) 7 | 8 | func main() { 9 | client := &http.Client{} 10 | _, err := client.Get("http://localhost:8080") 11 | fmt.Println(err) 12 | } 13 | -------------------------------------------------------------------------------- /99-other/01-localhost/nsswitch.conf: -------------------------------------------------------------------------------- 1 | # /etc/nsswitch.conf 2 | # 3 | # Example configuration of GNU Name Service Switch functionality. 4 | # If you have the `glibc-doc-reference' and `info' packages installed, try: 5 | # `info libc "Name Service Switch"' for information about this file. 6 | 7 | passwd: files 8 | group: files 9 | shadow: files 10 | gshadow: files 11 | 12 | hosts: dns 13 | networks: files 14 | 15 | protocols: db files 16 | services: db files 17 | ethers: db files 18 | rpc: db files 19 | 20 | netgroup: nis 21 | -------------------------------------------------------------------------------- /99-other/01-localhost/run.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | cat /etc/nsswitch.conf 4 | #go run main.go 5 | chmod +x /app/main 6 | /app/main -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # blog-code 2 | 3 | https://lailin.xyz 博客代码 4 | 5 | > 之前的文章代码迁移中 6 | 7 | - [Kubernetes 扩展: Operator 系列文章代码](./02-k8s-operator) 8 | - [Go 进阶训练营系列文章代码](./01-go-training) 9 | - [LeetCode 系列](./03-leetcode) 10 | - [非系列文章](./99-other) 11 | 和文章路由保持一致 --------------------------------------------------------------------------------