registry_handler.go 8.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384
  1. package api
  2. import (
  3. "encoding/json"
  4. "net/http"
  5. "strconv"
  6. "time"
  7. "github.com/porter-dev/porter/internal/registry"
  8. "github.com/go-chi/chi"
  9. "github.com/porter-dev/porter/internal/forms"
  10. "github.com/porter-dev/porter/internal/models"
  11. "github.com/aws/aws-sdk-go/service/ecr"
  12. )
  13. // HandleCreateRegistry creates a new registry
  14. func (app *App) HandleCreateRegistry(w http.ResponseWriter, r *http.Request) {
  15. projID, err := strconv.ParseUint(chi.URLParam(r, "project_id"), 0, 64)
  16. if err != nil || projID == 0 {
  17. app.handleErrorFormDecoding(err, ErrProjectDecode, w)
  18. return
  19. }
  20. form := &forms.CreateRegistry{
  21. ProjectID: uint(projID),
  22. }
  23. // decode from JSON to form value
  24. if err := json.NewDecoder(r.Body).Decode(form); err != nil {
  25. app.handleErrorFormDecoding(err, ErrProjectDecode, w)
  26. return
  27. }
  28. // validate the form
  29. if err := app.validator.Struct(form); err != nil {
  30. app.handleErrorFormValidation(err, ErrProjectValidateFields, w)
  31. return
  32. }
  33. // convert the form to a registry
  34. registry, err := form.ToRegistry()
  35. if err != nil {
  36. app.handleErrorFormDecoding(err, ErrProjectDecode, w)
  37. return
  38. }
  39. // if the registry is ECR and URL is not set, get the registry url
  40. if registry.URL == "" && registry.AWSIntegrationID != 0 {
  41. awsInt, err := app.Repo.AWSIntegration.ReadAWSIntegration(registry.AWSIntegrationID)
  42. if err != nil {
  43. app.handleErrorDataRead(err, w)
  44. return
  45. }
  46. sess, err := awsInt.GetSession()
  47. if err != nil {
  48. app.handleErrorDataRead(err, w)
  49. return
  50. }
  51. ecrSvc := ecr.New(sess)
  52. output, err := ecrSvc.GetAuthorizationToken(&ecr.GetAuthorizationTokenInput{})
  53. if err != nil {
  54. app.handleErrorDataRead(err, w)
  55. return
  56. }
  57. registry.URL = *output.AuthorizationData[0].ProxyEndpoint
  58. }
  59. // handle write to the database
  60. registry, err = app.Repo.Registry.CreateRegistry(registry)
  61. if err != nil {
  62. app.handleErrorDataWrite(err, w)
  63. return
  64. }
  65. app.Logger.Info().Msgf("New registry created: %d", registry.ID)
  66. w.WriteHeader(http.StatusCreated)
  67. regExt := registry.Externalize()
  68. if err := json.NewEncoder(w).Encode(regExt); err != nil {
  69. app.handleErrorFormDecoding(err, ErrProjectDecode, w)
  70. return
  71. }
  72. }
  73. // HandleListProjectRegistries returns a list of registries for a project
  74. func (app *App) HandleListProjectRegistries(w http.ResponseWriter, r *http.Request) {
  75. projID, err := strconv.ParseUint(chi.URLParam(r, "project_id"), 0, 64)
  76. if err != nil || projID == 0 {
  77. app.handleErrorFormDecoding(err, ErrProjectDecode, w)
  78. return
  79. }
  80. regs, err := app.Repo.Registry.ListRegistriesByProjectID(uint(projID))
  81. if err != nil {
  82. app.handleErrorRead(err, ErrProjectDataRead, w)
  83. return
  84. }
  85. extRegs := make([]*models.RegistryExternal, 0)
  86. for _, reg := range regs {
  87. extRegs = append(extRegs, reg.Externalize())
  88. }
  89. w.WriteHeader(http.StatusOK)
  90. if err := json.NewEncoder(w).Encode(extRegs); err != nil {
  91. app.handleErrorFormDecoding(err, ErrProjectDecode, w)
  92. return
  93. }
  94. }
  95. // temp -- token response
  96. type ECRTokenResponse struct {
  97. Token string `json:"token"`
  98. ExpiresAt *time.Time `json:"expires_at"`
  99. }
  100. // HandleGetProjectRegistryECRToken gets an ECR token for a registry
  101. func (app *App) HandleGetProjectRegistryECRToken(w http.ResponseWriter, r *http.Request) {
  102. projID, err := strconv.ParseUint(chi.URLParam(r, "project_id"), 0, 64)
  103. if err != nil || projID == 0 {
  104. app.handleErrorFormDecoding(err, ErrProjectDecode, w)
  105. return
  106. }
  107. region := chi.URLParam(r, "region")
  108. if region == "" {
  109. app.handleErrorFormDecoding(err, ErrProjectDecode, w)
  110. return
  111. }
  112. // list registries and find one that matches the region
  113. regs, err := app.Repo.Registry.ListRegistriesByProjectID(uint(projID))
  114. var token string
  115. var expiresAt *time.Time
  116. for _, reg := range regs {
  117. if reg.AWSIntegrationID != 0 {
  118. awsInt, err := app.Repo.AWSIntegration.ReadAWSIntegration(reg.AWSIntegrationID)
  119. if err != nil {
  120. app.handleErrorDataRead(err, w)
  121. return
  122. }
  123. if awsInt.AWSRegion == region {
  124. // get the aws integration and session
  125. sess, err := awsInt.GetSession()
  126. if err != nil {
  127. app.handleErrorDataRead(err, w)
  128. return
  129. }
  130. ecrSvc := ecr.New(sess)
  131. output, err := ecrSvc.GetAuthorizationToken(&ecr.GetAuthorizationTokenInput{})
  132. if err != nil {
  133. app.handleErrorDataRead(err, w)
  134. return
  135. }
  136. token = *output.AuthorizationData[0].AuthorizationToken
  137. expiresAt = output.AuthorizationData[0].ExpiresAt
  138. }
  139. }
  140. }
  141. resp := &ECRTokenResponse{
  142. Token: token,
  143. ExpiresAt: expiresAt,
  144. }
  145. w.WriteHeader(http.StatusOK)
  146. if err := json.NewEncoder(w).Encode(resp); err != nil {
  147. app.handleErrorFormDecoding(err, ErrProjectDecode, w)
  148. return
  149. }
  150. }
  151. // HandleUpdateProjectRegistry updates a registry
  152. func (app *App) HandleUpdateProjectRegistry(w http.ResponseWriter, r *http.Request) {
  153. projID, err := strconv.ParseUint(chi.URLParam(r, "project_id"), 0, 64)
  154. if err != nil || projID == 0 {
  155. app.handleErrorFormDecoding(err, ErrProjectDecode, w)
  156. return
  157. }
  158. registryID, err := strconv.ParseUint(chi.URLParam(r, "registry_id"), 0, 64)
  159. if err != nil || registryID == 0 {
  160. app.handleErrorFormDecoding(err, ErrProjectDecode, w)
  161. return
  162. }
  163. form := &forms.UpdateRegistryForm{
  164. ID: uint(registryID),
  165. }
  166. // decode from JSON to form value
  167. if err := json.NewDecoder(r.Body).Decode(form); err != nil {
  168. app.handleErrorFormDecoding(err, ErrProjectDecode, w)
  169. return
  170. }
  171. // validate the form
  172. if err := app.validator.Struct(form); err != nil {
  173. app.handleErrorFormValidation(err, ErrProjectValidateFields, w)
  174. return
  175. }
  176. // convert the form to a registry
  177. registry, err := form.ToRegistry(app.Repo.Registry)
  178. if err != nil {
  179. app.handleErrorFormDecoding(err, ErrProjectDecode, w)
  180. return
  181. }
  182. // handle write to the database
  183. registry, err = app.Repo.Registry.UpdateRegistry(registry)
  184. if err != nil {
  185. app.handleErrorDataWrite(err, w)
  186. return
  187. }
  188. w.WriteHeader(http.StatusOK)
  189. regExt := registry.Externalize()
  190. if err := json.NewEncoder(w).Encode(regExt); err != nil {
  191. app.handleErrorFormDecoding(err, ErrProjectDecode, w)
  192. return
  193. }
  194. }
  195. // HandleDeleteProjectRegistry handles the deletion of a Registry via the registry ID
  196. func (app *App) HandleDeleteProjectRegistry(w http.ResponseWriter, r *http.Request) {
  197. id, err := strconv.ParseUint(chi.URLParam(r, "registry_id"), 0, 64)
  198. if err != nil || id == 0 {
  199. app.handleErrorFormDecoding(err, ErrProjectDecode, w)
  200. return
  201. }
  202. reg, err := app.Repo.Registry.ReadRegistry(uint(id))
  203. if err != nil {
  204. app.handleErrorRead(err, ErrProjectDataRead, w)
  205. return
  206. }
  207. err = app.Repo.Registry.DeleteRegistry(reg)
  208. if err != nil {
  209. app.handleErrorRead(err, ErrProjectDataRead, w)
  210. return
  211. }
  212. w.WriteHeader(http.StatusOK)
  213. }
  214. // HandleListRepositories returns a list of repositories for a given registry
  215. func (app *App) HandleListRepositories(w http.ResponseWriter, r *http.Request) {
  216. regID, err := strconv.ParseUint(chi.URLParam(r, "registry_id"), 0, 64)
  217. if err != nil || regID == 0 {
  218. app.handleErrorFormDecoding(err, ErrProjectDecode, w)
  219. return
  220. }
  221. reg, err := app.Repo.Registry.ReadRegistry(uint(regID))
  222. if err != nil {
  223. app.handleErrorRead(err, ErrProjectDataRead, w)
  224. return
  225. }
  226. // cast to a registry from registry package
  227. _reg := registry.Registry(*reg)
  228. regAPI := &_reg
  229. repos, err := regAPI.ListRepositories(*app.Repo)
  230. if err != nil {
  231. app.handleErrorRead(err, ErrProjectDataRead, w)
  232. return
  233. }
  234. w.WriteHeader(http.StatusOK)
  235. if err := json.NewEncoder(w).Encode(repos); err != nil {
  236. app.handleErrorFormDecoding(err, ErrProjectDecode, w)
  237. return
  238. }
  239. }
  240. // HandleListImages retrieves a list of repo names
  241. func (app *App) HandleListImages(w http.ResponseWriter, r *http.Request) {
  242. regID, err := strconv.ParseUint(chi.URLParam(r, "registry_id"), 0, 64)
  243. if err != nil || regID == 0 {
  244. app.handleErrorFormDecoding(err, ErrProjectDecode, w)
  245. return
  246. }
  247. repoName := chi.URLParam(r, "*")
  248. reg, err := app.Repo.Registry.ReadRegistry(uint(regID))
  249. if err != nil {
  250. app.handleErrorRead(err, ErrProjectDataRead, w)
  251. return
  252. }
  253. // cast to a registry from registry package
  254. _reg := registry.Registry(*reg)
  255. regAPI := &_reg
  256. imgs, err := regAPI.ListImages(repoName, *app.Repo)
  257. if err != nil {
  258. app.handleErrorRead(err, ErrProjectDataRead, w)
  259. return
  260. }
  261. w.WriteHeader(http.StatusOK)
  262. if err := json.NewEncoder(w).Encode(imgs); err != nil {
  263. app.handleErrorFormDecoding(err, ErrProjectDecode, w)
  264. return
  265. }
  266. // ref, err := name.ParseReference("gcr.io/google-containers/pause")
  267. // if err != nil {
  268. // fmt.Println(err)
  269. // return
  270. // }
  271. // img, err := remote.Image(ref)
  272. // if err != nil {
  273. // fmt.Println(err)
  274. // return
  275. // }
  276. // fmt.Println(img.Size())
  277. // ctx := r.Context()
  278. // reg, err := name.NewRegistry("index.docker.io")
  279. // if err != nil {
  280. // fmt.Println("fuk")
  281. // fmt.Println(err)
  282. // return
  283. // }
  284. // stuff, err := remote.Catalog(ctx, reg, remote.WithAuthFromKeychain(authn.DefaultKeychain))
  285. // if err != nil {
  286. // fmt.Println(err)
  287. // return
  288. // }
  289. // fmt.Println(stuff[0])
  290. }