/client/fli/searcher.go

https://github.com/ClusterHQ/fli · Go · 493 lines · 345 code · 58 blank · 90 comment · 142 complexity · 3565404c3b56a2bb4c573fe29aa4ea02 MD5 · raw file

  1. /*
  2. * Copyright 2016 ClusterHQ
  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. package fli
  17. import (
  18. "strings"
  19. "github.com/ClusterHQ/fli/dp/metastore"
  20. "github.com/ClusterHQ/fli/errors"
  21. "github.com/ClusterHQ/fli/meta/branch"
  22. "github.com/ClusterHQ/fli/meta/snapshot"
  23. "github.com/ClusterHQ/fli/meta/volume"
  24. "github.com/ClusterHQ/fli/meta/volumeset"
  25. "github.com/ClusterHQ/fli/miscutils/uuid"
  26. "github.com/gobwas/glob"
  27. )
  28. // FindVolumesets reports whether the search matches the VolumeSets in mds
  29. // search syntax is
  30. // search:
  31. // c8980031-b0ba
  32. // e6296a4a-b481-406c-9d33-ae074c6df78b
  33. // /chq/volset/name
  34. // /chq/volset*
  35. // /chq/volset?
  36. // (empty string)
  37. func FindVolumesets(mds metastore.Syncable, search string) ([]*volumeset.VolumeSet, error) {
  38. searchByUUID, err := uuid.IsUUID(search)
  39. if err != nil {
  40. return nil, err
  41. }
  42. var vsFound = []*volumeset.VolumeSet{}
  43. if searchByUUID {
  44. isShrunkID, err := uuid.IsShrunkUUID(search)
  45. if err != nil {
  46. return nil, err
  47. }
  48. if isShrunkID {
  49. vsFound, err = metastore.GetVolumeSets(
  50. mds,
  51. volumeset.Query{
  52. ShortUUID: search,
  53. },
  54. )
  55. if err != nil {
  56. return nil, errors.New(err)
  57. }
  58. } else {
  59. vs, err := metastore.GetVolumeSet(mds, volumeset.NewID(search))
  60. if err != nil {
  61. _, ok := err.(*metastore.ErrVolumeSetNotFound)
  62. if !ok {
  63. return nil, errors.New(err)
  64. }
  65. } else {
  66. vsFound = append(vsFound, vs)
  67. }
  68. }
  69. } else {
  70. vsFound, err = metastore.GetVolumeSets(
  71. mds,
  72. volumeset.Query{
  73. RegExName: search,
  74. },
  75. )
  76. if err != nil {
  77. return nil, errors.New(err)
  78. }
  79. }
  80. if len(vsFound) == 0 {
  81. return nil, &ErrVolSetNotFound{Name: search}
  82. }
  83. return vsFound, nil
  84. }
  85. // FindBranches reports whether the search matches the Branches in mds
  86. // search syntax is
  87. // search:
  88. // {volumeset}:{branch}
  89. // {branch}
  90. // volumeset:
  91. // c8980031-b0ba
  92. // e6296a4a-b481-406c-9d33-ae074c6df78b
  93. // /chq/volset/name
  94. // /chq/volset*
  95. // /chq/volset?
  96. // (empty string)
  97. // branch:
  98. // br*
  99. // *
  100. // (empty string)
  101. func FindBranches(mds metastore.Syncable, search string) ([]*branch.Branch, error) {
  102. var (
  103. brFound = []*branch.Branch{}
  104. )
  105. vsname := ""
  106. brname := ""
  107. if strings.Contains(search, ":") {
  108. splitSearch := strings.Split(search, ":")
  109. if len(splitSearch) != 2 {
  110. return brFound, &ErrInvalidSearch{search}
  111. }
  112. // The first part is VolSet and second part is branch
  113. vsname = splitSearch[0]
  114. brname = splitSearch[1]
  115. } else {
  116. vsname = "*"
  117. brname = search
  118. }
  119. // If branch name passed it empty then search for everything
  120. if brname == "" {
  121. brname = "*"
  122. }
  123. vs, err := FindVolumesets(mds, vsname)
  124. if err != nil {
  125. return brFound, err
  126. }
  127. var g glob.Glob
  128. g = glob.MustCompile(brname)
  129. for _, v := range vs {
  130. brs, err := metastore.GetBranches(mds, branch.Query{VolSetID: v.ID})
  131. if err != nil {
  132. return brFound, errors.New(err)
  133. }
  134. for _, br := range brs {
  135. if g.Match(br.Name) {
  136. brFound = append(brFound, br)
  137. }
  138. }
  139. }
  140. if len(brFound) == 0 {
  141. return brFound, &ErrBranchNotFound{Name: search}
  142. }
  143. return brFound, nil
  144. }
  145. // FindSnapshots reports whether the search matches the Snapshots in mds
  146. // search syntax is
  147. // search:
  148. // {volumeset}:{snapshot}
  149. // {snapshot}
  150. // volumeset:
  151. // c8980031-b0ba
  152. // e6296a4a-b481-406c-9d33-ae074c6df78b
  153. // /chq/volset/name
  154. // /chq/volset*
  155. // /chq/volset?
  156. // (empty string)
  157. // snapshot:
  158. // c8980031-b0ba
  159. // e6296a4a-b481-406c-9d33-ae074c6df78b
  160. // snap*
  161. // *
  162. // (empty string)
  163. func FindSnapshots(mds metastore.Syncable, search string) ([]*snapshot.Snapshot, error) {
  164. var (
  165. snapFound = []*snapshot.Snapshot{}
  166. )
  167. check, err := uuid.IsUUID(search)
  168. if err != nil {
  169. return snapFound, err
  170. }
  171. if !check {
  172. vsname := ""
  173. snapname := ""
  174. if strings.Contains(search, ":") {
  175. splitSearch := strings.Split(search, ":")
  176. if len(splitSearch) != 2 {
  177. return snapFound, &ErrInvalidSearch{search}
  178. }
  179. // The first part is VolSet and second part is branch
  180. vsname = splitSearch[0]
  181. snapname = splitSearch[1]
  182. } else {
  183. vsname = "*"
  184. snapname = search
  185. }
  186. if snapname == "" {
  187. snapname = "*"
  188. }
  189. check, err := uuid.IsUUID(snapname)
  190. if err != nil {
  191. return snapFound, err
  192. }
  193. vs, err := FindVolumesets(mds, vsname)
  194. if err != nil {
  195. return snapFound, err
  196. }
  197. if !check {
  198. var g glob.Glob
  199. g = glob.MustCompile(snapname)
  200. for _, v := range vs {
  201. // Find the snapshot name in every VolSet found
  202. snaps, err := metastore.GetSnapshots(mds, snapshot.Query{VolSetID: v.ID})
  203. if err != nil {
  204. return snapFound, errors.New(err)
  205. }
  206. for _, snap := range snaps {
  207. if g.Match(snap.Name) {
  208. snapFound = append(snapFound, snap)
  209. }
  210. }
  211. }
  212. } else {
  213. // Search is an id then simply search for that ID
  214. isShrunkID, err := uuid.IsShrunkUUID(snapname)
  215. if err != nil {
  216. return snapFound, err
  217. }
  218. if isShrunkID {
  219. for _, v := range vs {
  220. // Find the snapshot name in every VolSet found
  221. snaps, err := metastore.GetSnapshots(mds, snapshot.Query{VolSetID: v.ID})
  222. if err != nil {
  223. return snapFound, errors.New(err)
  224. }
  225. for _, snap := range snaps {
  226. if uuid.ShrinkUUID(snap.ID.String()) == snapname {
  227. snapFound = append(snapFound, snap)
  228. }
  229. }
  230. }
  231. } else {
  232. snap, err := metastore.GetSnapshot(mds, snapshot.NewID(snapname))
  233. if err != nil {
  234. _, ok := err.(*metastore.ErrSnapshotNotFound)
  235. if !ok {
  236. return snapFound, errors.New(err)
  237. }
  238. } else {
  239. snapFound = append(snapFound, snap)
  240. }
  241. }
  242. }
  243. } else {
  244. // Search is an id then simply search for that ID
  245. isShrunkID, err := uuid.IsShrunkUUID(search)
  246. if err != nil {
  247. return snapFound, err
  248. }
  249. if isShrunkID {
  250. snaps, err := metastore.GetSnapshots(mds, snapshot.Query{})
  251. if err != nil {
  252. return snapFound, errors.New(err)
  253. }
  254. for _, snap := range snaps {
  255. if uuid.ShrinkUUID(snap.ID.String()) == search {
  256. snapFound = append(snapFound, snap)
  257. }
  258. }
  259. } else {
  260. snap, err := metastore.GetSnapshot(mds, snapshot.NewID(search))
  261. if err != nil {
  262. _, ok := err.(*metastore.ErrSnapshotNotFound)
  263. if !ok {
  264. return snapFound, errors.New(err)
  265. }
  266. } else {
  267. snapFound = append(snapFound, snap)
  268. }
  269. }
  270. }
  271. if len(snapFound) == 0 {
  272. return snapFound, &ErrSnapshotNotFound{Name: search}
  273. }
  274. return snapFound, nil
  275. }
  276. // FindVolumes reports whether the search matches the Volume in mds
  277. // search syntax is
  278. // search:
  279. // {volumeset}:{volume}
  280. // {volume}
  281. // volumeset:
  282. // c8980031-b0ba
  283. // e6296a4a-b481-406c-9d33-ae074c6df78b
  284. // /chq/volset/name
  285. // /chq/volset*
  286. // /chq/volset?
  287. // (empty string)
  288. // volume:
  289. // c8980031-b0ba
  290. // e6296a4a-b481-406c-9d33-ae074c6df78b
  291. // vol*
  292. // *
  293. // (empty string)
  294. func FindVolumes(mds metastore.Client, search string) ([]*volume.Volume, error) {
  295. var (
  296. volFound = []*volume.Volume{}
  297. )
  298. check, err := uuid.IsUUID(search)
  299. if err != nil {
  300. return volFound, err
  301. }
  302. if !check {
  303. vsname := ""
  304. volname := ""
  305. if strings.Contains(search, ":") {
  306. splitSearch := strings.Split(search, ":")
  307. if len(splitSearch) != 2 {
  308. return volFound, &ErrInvalidSearch{search}
  309. }
  310. // The first part is VolSet and second part is branch
  311. vsname = splitSearch[0]
  312. volname = splitSearch[1]
  313. } else {
  314. vsname = "*"
  315. volname = search
  316. }
  317. if volname == "" {
  318. volname = "*"
  319. }
  320. check, err := uuid.IsUUID(volname)
  321. if err != nil {
  322. return volFound, err
  323. }
  324. vs, err := FindVolumesets(mds, vsname)
  325. if err != nil {
  326. return volFound, err
  327. }
  328. if !check {
  329. var g glob.Glob
  330. g = glob.MustCompile(volname)
  331. for _, v := range vs {
  332. // Find the volume name in every VolSet found
  333. vols, err := metastore.GetVolumes(mds, v.ID)
  334. if err != nil {
  335. return volFound, errors.New(err)
  336. }
  337. for _, vol := range vols {
  338. if g.Match(vol.Name) {
  339. volFound = append(volFound, vol)
  340. }
  341. }
  342. }
  343. } else {
  344. // Search is an id then simply search for that ID
  345. isShrunkID, err := uuid.IsShrunkUUID(volname)
  346. if err != nil {
  347. return volFound, err
  348. }
  349. if isShrunkID {
  350. for _, v := range vs {
  351. // Find the volume name in every VolSet found
  352. vols, err := metastore.GetVolumes(mds, v.ID)
  353. if err != nil {
  354. // TODO: Handle error here and return fli error here
  355. return volFound, errors.New(err)
  356. }
  357. for _, vol := range vols {
  358. if uuid.ShrinkUUID(vol.ID.String()) == volname {
  359. volFound = append(volFound, vol)
  360. }
  361. }
  362. }
  363. } else {
  364. vol, err := metastore.GetVolume(mds, volume.NewID(volname))
  365. if err != nil {
  366. _, ok := err.(*metastore.ErrVolumeNotFound)
  367. if !ok {
  368. return volFound, errors.New(err)
  369. }
  370. } else {
  371. volFound = append(volFound, vol)
  372. }
  373. }
  374. }
  375. } else {
  376. // Search is an id then simply search for that ID
  377. isShrunkID, err := uuid.IsShrunkUUID(search)
  378. if err != nil {
  379. return volFound, err
  380. }
  381. if isShrunkID {
  382. vols, err := metastore.GetAllVolumes(mds)
  383. if err != nil {
  384. return volFound, errors.New(err)
  385. }
  386. for _, vol := range vols {
  387. if uuid.ShrinkUUID(vol.ID.String()) == search {
  388. volFound = append(volFound, vol)
  389. }
  390. }
  391. } else {
  392. vol, err := metastore.GetVolume(mds, volume.NewID(search))
  393. if err != nil {
  394. _, ok := err.(*metastore.ErrVolumeNotFound)
  395. if !ok {
  396. return volFound, errors.New(err)
  397. }
  398. } else {
  399. volFound = append(volFound, vol)
  400. }
  401. }
  402. }
  403. if len(volFound) == 0 {
  404. return volFound, &ErrVolumeNotFound{Name: search}
  405. }
  406. return volFound, nil
  407. }
  408. // FindAll ...
  409. func FindAll(mds metastore.Client, search string) ([]*snapshot.Snapshot, []*branch.Branch, []*volume.Volume, error) {
  410. brFound := []*branch.Branch{}
  411. snapFound := []*snapshot.Snapshot{}
  412. volFound := []*volume.Volume{}
  413. brFound, err := FindBranches(mds, search)
  414. if err != nil {
  415. _, isNotFound := err.(*ErrBranchNotFound)
  416. if !isNotFound {
  417. return snapFound, brFound, volFound, err
  418. }
  419. }
  420. snapFound, err = FindSnapshots(mds, search)
  421. if err != nil {
  422. _, isNotFound := err.(*ErrSnapshotNotFound)
  423. if !isNotFound {
  424. return snapFound, brFound, volFound, err
  425. }
  426. }
  427. volFound, err = FindVolumes(mds, search)
  428. if err != nil {
  429. _, isNotFound := err.(*ErrVolumeNotFound)
  430. if !isNotFound {
  431. return snapFound, brFound, volFound, err
  432. }
  433. }
  434. return snapFound, brFound, volFound, nil
  435. }