github.com/cloudfoundry/libcfbuildpack@v1.91.23/services/services.go (about) 1 /* 2 * Copyright 2018-2020 the original author or 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 * https://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 package services 18 19 import ( 20 "strings" 21 22 "github.com/buildpack/libbuildpack/services" 23 ) 24 25 // Services is a collection of services bound to the application. 26 type Services struct { 27 services.Services 28 } 29 30 // FindServiceCredentials returns the credentials payload for given service. The selected service is one who's 31 // BindingName, InstanceName, Label, or Tags contain the filter and has the required credentials. Returns the 32 // credentials and true if exactly one service is matched, otherwise false. 33 // 34 // NOTE: This function should ONLY be used to extract values that are CONSTANT throughout the lifecycle of a staged 35 // application. Typically this means you should only use this function to get agent download information from Service 36 // Brokers and SHOULD NOT EVER retrieve and use connection credentials. 37 func (s Services) FindServiceCredentials(filter string, credentials ...string) (Credentials, bool) { 38 match := make([]Service, 0) 39 40 for _, c := range s.Services { 41 if s.matchesService(c, filter) && s.matchesCredentials(c, credentials) { 42 match = append(match, c) 43 } 44 } 45 46 if len(match) != 1 { 47 return nil, false 48 } 49 50 return match[0].Credentials, true 51 } 52 53 // HasService determines whether a single service, who's BindingName, InstanceName, Label, or Tags contain the filter 54 // and has the required credentials, exists. Returns true if exactly one service is matched, false otherwise. 55 func (s Services) HasService(filter string, credentials ...string) bool { 56 var match []Service 57 58 for _, c := range s.Services { 59 if s.matchesService(c, filter) && s.matchesCredentials(c, credentials) { 60 match = append(match, c) 61 } 62 } 63 64 return len(match) == 1 65 } 66 67 type biPredicate func(x string, y string) bool 68 69 func (Services) any(test biPredicate, s string, candidates []string) bool { 70 for _, c := range candidates { 71 if test(c, s) { 72 return true 73 } 74 } 75 76 return false 77 } 78 79 func (Services) equality(x string, y string) bool { 80 return x == y 81 } 82 83 func (Services) matchesBindingName(service Service, filter string) bool { 84 return strings.Contains(service.BindingName, filter) 85 } 86 87 func (s Services) matchesCredentials(service Service, credentials []string) bool { 88 cr := service.Credentials 89 90 candidates := make([]string, 0, len(cr)) 91 for k := range cr { 92 candidates = append(candidates, k) 93 } 94 95 for _, c := range credentials { 96 if !s.any(s.equality, c, candidates) { 97 return false 98 } 99 } 100 101 return true 102 } 103 104 func (Services) matchesInstanceName(service Service, filter string) bool { 105 return strings.Contains(service.InstanceName, filter) 106 } 107 108 func (Services) matchesLabel(service Service, filter string) bool { 109 return strings.Contains(service.Label, filter) 110 } 111 112 func (s Services) matchesService(service Service, filter string) bool { 113 return s.matchesBindingName(service, filter) || 114 s.matchesInstanceName(service, filter) || 115 s.matchesLabel(service, filter) || 116 s.matchesTag(service, filter) 117 } 118 119 func (s Services) matchesTag(service Service, filter string) bool { 120 return s.any(strings.Contains, filter, service.Tags) 121 }