github_test.go 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199
  1. /*
  2. Licensed under the Apache License, Version 2.0 (the "License");
  3. you may not use this file except in compliance with the License.
  4. You may obtain a copy of the License at
  5. http://www.apache.org/licenses/LICENSE-2.0
  6. Unless required by applicable law or agreed to in writing, software
  7. distributed under the License is distributed on an "AS IS" BASIS,
  8. WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  9. See the License for the specific language governing permissions and
  10. limitations under the License.
  11. */
  12. package github
  13. import (
  14. "context"
  15. "fmt"
  16. "net/http"
  17. "net/http/httptest"
  18. "os"
  19. "reflect"
  20. "testing"
  21. "github.com/stretchr/testify/assert"
  22. "github.com/stretchr/testify/require"
  23. v1 "k8s.io/api/core/v1"
  24. apiextensions "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1"
  25. metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
  26. "sigs.k8s.io/controller-runtime/pkg/client"
  27. clientfake "sigs.k8s.io/controller-runtime/pkg/client/fake"
  28. )
  29. const (
  30. tstCrtName = "github_test.pem"
  31. )
  32. func testHTTPSrv(t *testing.T, r []byte, s int) *httptest.Server {
  33. return httptest.NewServer(http.HandlerFunc(func(rw http.ResponseWriter, req *http.Request) {
  34. assert.Equal(t, "POST", req.Method, "Expected POST request")
  35. assert.NotEmpty(t, req.Body)
  36. assert.NotEmpty(t, req.Header.Get("Authorization"))
  37. assert.Equal(t, "application/vnd.github.v3+json", req.Header.Get("Accept"))
  38. // Send response to be tested
  39. rw.WriteHeader(s)
  40. rw.Write(r)
  41. }))
  42. }
  43. func TestGenerate(t *testing.T) {
  44. type args struct {
  45. ctx context.Context
  46. jsonSpec *apiextensions.JSON
  47. kube client.Client
  48. namespace string
  49. }
  50. pem, err := os.ReadFile(tstCrtName)
  51. assert.NoError(t, err, "Should not error when reading privateKey")
  52. validResponce := []byte(`{
  53. "token": "ghs_16C7e42F292c6912E7710c838347Ae178B4a",
  54. "expires_at": "2016-07-11T22:14:10Z",
  55. "permissions": {
  56. "contents": "read"
  57. },
  58. "repositories": [
  59. {
  60. "id": 10000
  61. }
  62. ],
  63. "repository_selection": "selected"
  64. }`)
  65. invalidResponce := []byte(`{
  66. "documentation_url": "https://docs.github.com/rest/reference/apps#create-an-installation-access-token-for-an-app",
  67. "message": "There is at least one repository that does not exist or is not accessible to the parent installation.",
  68. "status": 422
  69. }`)
  70. server := testHTTPSrv(t, validResponce, http.StatusCreated)
  71. badServer := testHTTPSrv(t, invalidResponce, 422)
  72. tests := []struct {
  73. name string
  74. g *Generator
  75. args args
  76. want map[string][]byte
  77. assertErr func(t *testing.T, err error)
  78. server *httptest.Server
  79. }{
  80. {
  81. name: "nil spec",
  82. args: args{
  83. jsonSpec: nil,
  84. },
  85. assertErr: func(t *testing.T, err error) {
  86. require.Error(t, err)
  87. },
  88. server: server,
  89. },
  90. {
  91. name: "full spec",
  92. args: args{
  93. ctx: context.TODO(),
  94. namespace: "foo",
  95. kube: clientfake.NewClientBuilder().WithObjects(&v1.Secret{
  96. ObjectMeta: metav1.ObjectMeta{
  97. Name: "testName",
  98. Namespace: "foo",
  99. },
  100. Data: map[string][]byte{
  101. "privateKey": pem,
  102. },
  103. }).Build(),
  104. jsonSpec: &apiextensions.JSON{
  105. Raw: []byte(fmt.Sprintf(`apiVersion: generators.external-secrets.io/v1alpha1
  106. kind: GithubToken
  107. spec:
  108. appID: "0000000"
  109. installID: "00000000"
  110. URL: %q
  111. repositories:
  112. - "Hello-World"
  113. permissions:
  114. contents: "read"
  115. auth:
  116. privateKey:
  117. secretRef:
  118. name: "testName"
  119. namespace: "foo"
  120. key: "privateKey"`, server.URL)),
  121. },
  122. },
  123. want: map[string][]byte{
  124. "token": []byte("ghs_16C7e42F292c6912E7710c838347Ae178B4a"),
  125. },
  126. assertErr: func(t *testing.T, err error) {
  127. require.NoError(t, err)
  128. },
  129. server: server,
  130. },
  131. {
  132. name: "fail on bad request",
  133. args: args{
  134. ctx: context.TODO(),
  135. namespace: "foo",
  136. kube: clientfake.NewClientBuilder().WithObjects(&v1.Secret{
  137. ObjectMeta: metav1.ObjectMeta{
  138. Name: "testName",
  139. Namespace: "foo",
  140. },
  141. Data: map[string][]byte{
  142. "privateKey": pem,
  143. },
  144. }).Build(),
  145. jsonSpec: &apiextensions.JSON{
  146. Raw: []byte(fmt.Sprintf(`apiVersion: generators.external-secrets.io/v1alpha1
  147. kind: GithubToken
  148. spec:
  149. appID: "0000000"
  150. installID: "00000000"
  151. URL: %q
  152. repositories:
  153. - "octocat/Hello-World"
  154. permissions:
  155. contents: "read"
  156. auth:
  157. privateKey:
  158. secretRef:
  159. name: "testName"
  160. namespace: "foo"
  161. key: "privateKey"`, badServer.URL)),
  162. },
  163. },
  164. assertErr: func(t *testing.T, err error) {
  165. assert.ErrorContains(t, err, "error generating token")
  166. },
  167. server: badServer,
  168. },
  169. }
  170. for _, tt := range tests {
  171. t.Run(tt.name, func(t *testing.T) {
  172. g := &Generator{httpClient: tt.server.Client()}
  173. got, _, err := g.generate(
  174. tt.args.ctx,
  175. tt.args.jsonSpec,
  176. tt.args.kube,
  177. tt.args.namespace,
  178. )
  179. tt.assertErr(t, err)
  180. if !reflect.DeepEqual(got, tt.want) {
  181. t.Errorf("Generator.Generate() = %s, want %s", got, tt.want)
  182. }
  183. })
  184. }
  185. }