basic.go 7.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196
  1. /*
  2. Copyright 2017 The Kubernetes Authors.
  3. Licensed under the Apache License, Version 2.0 (the "License");
  4. you may not use this file except in compliance with the License.
  5. You may obtain a copy of the License at
  6. http://www.apache.org/licenses/LICENSE-2.0
  7. Unless required by applicable law or agreed to in writing, software
  8. distributed under the License is distributed on an "AS IS" BASIS,
  9. WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  10. See the License for the specific language governing permissions and
  11. limitations under the License.
  12. */
  13. package stackdriver
  14. import (
  15. "fmt"
  16. "time"
  17. "k8s.io/apimachinery/pkg/util/json"
  18. "k8s.io/apimachinery/pkg/util/uuid"
  19. "k8s.io/apimachinery/pkg/util/wait"
  20. "k8s.io/kubernetes/test/e2e/framework"
  21. e2eskipper "k8s.io/kubernetes/test/e2e/framework/skipper"
  22. instrumentation "k8s.io/kubernetes/test/e2e/instrumentation/common"
  23. "k8s.io/kubernetes/test/e2e/instrumentation/logging/utils"
  24. "github.com/onsi/ginkgo"
  25. )
  26. const (
  27. ingestionInterval = 10 * time.Second
  28. ingestionTimeout = 10 * time.Minute
  29. )
  30. var _ = instrumentation.SIGDescribe("Cluster level logging implemented by Stackdriver", func() {
  31. f := framework.NewDefaultFramework("sd-logging")
  32. ginkgo.BeforeEach(func() {
  33. e2eskipper.SkipUnlessProviderIs("gce", "gke")
  34. })
  35. ginkgo.It("should ingest logs [Feature:StackdriverLogging]", func() {
  36. withLogProviderForScope(f, podsScope, func(p *sdLogProvider) {
  37. ginkgo.By("Checking ingesting text logs", func() {
  38. pod, err := utils.StartAndReturnSelf(utils.NewRepeatingLoggingPod("synthlogger-1", "hey"), f)
  39. framework.ExpectNoError(err, "Failed to start a pod")
  40. ginkgo.By("Waiting for logs to ingest")
  41. c := utils.NewLogChecker(p, utils.UntilFirstEntry, utils.JustTimeout, pod.Name())
  42. err = utils.WaitForLogs(c, ingestionInterval, ingestionTimeout)
  43. framework.ExpectNoError(err)
  44. })
  45. ginkgo.By("Checking ingesting json logs", func() {
  46. logRaw := "{\"a\":\"b\"}"
  47. pod, err := utils.StartAndReturnSelf(utils.NewRepeatingLoggingPod("synthlogger-2", logRaw), f)
  48. framework.ExpectNoError(err, "Failed to start a pod")
  49. ginkgo.By("Waiting for logs to ingest")
  50. c := utils.NewLogChecker(p, func(_ string, logEntries []utils.LogEntry) (bool, error) {
  51. if len(logEntries) == 0 {
  52. return false, nil
  53. }
  54. log := logEntries[0]
  55. if log.JSONPayload == nil {
  56. return false, fmt.Errorf("log entry unexpectedly is not json: %s", log.TextPayload)
  57. }
  58. if log.JSONPayload["a"] != "b" {
  59. bytes, err := json.Marshal(log.JSONPayload)
  60. if err != nil {
  61. return false, fmt.Errorf("log entry ingested incorrectly, failed to marshal: %v", err)
  62. }
  63. return false, fmt.Errorf("log entry ingested incorrectly, got %v, want %s",
  64. string(bytes), logRaw)
  65. }
  66. return true, nil
  67. }, utils.JustTimeout, pod.Name())
  68. err = utils.WaitForLogs(c, ingestionInterval, ingestionTimeout)
  69. framework.ExpectNoError(err)
  70. })
  71. ginkgo.By("Checking ingesting logs in glog format", func() {
  72. logUnformatted := "Text"
  73. logRaw := fmt.Sprintf("I0101 00:00:00.000000 1 main.go:1] %s", logUnformatted)
  74. pod, err := utils.StartAndReturnSelf(utils.NewRepeatingLoggingPod("synthlogger-3", logRaw), f)
  75. framework.ExpectNoError(err, "Failed to start a pod")
  76. ginkgo.By("Waiting for logs to ingest")
  77. c := utils.NewLogChecker(p, func(_ string, logEntries []utils.LogEntry) (bool, error) {
  78. if len(logEntries) == 0 {
  79. return false, nil
  80. }
  81. log := logEntries[0]
  82. if log.TextPayload == "" {
  83. return false, fmt.Errorf("log entry is unexpectedly json: %v", log.JSONPayload)
  84. }
  85. if log.TextPayload != logUnformatted {
  86. return false, fmt.Errorf("log entry ingested incorrectly, got %s, want %s",
  87. log.TextPayload, logUnformatted)
  88. }
  89. return true, nil
  90. }, utils.JustTimeout, pod.Name())
  91. err = utils.WaitForLogs(c, ingestionInterval, ingestionTimeout)
  92. framework.ExpectNoError(err)
  93. })
  94. ginkgo.By("Checking that too long lines are trimmed", func() {
  95. maxLength := 100 * 1024
  96. cmd := []string{
  97. "/bin/sh",
  98. "-c",
  99. fmt.Sprintf("while :; do printf '%%*s' %d | tr ' ' 'A'; echo; sleep 60; done", maxLength+1),
  100. }
  101. pod, err := utils.StartAndReturnSelf(utils.NewExecLoggingPod("synthlogger-4", cmd), f)
  102. framework.ExpectNoError(err, "Failed to start a pod")
  103. ginkgo.By("Waiting for logs to ingest")
  104. c := utils.NewLogChecker(p, func(_ string, logEntries []utils.LogEntry) (bool, error) {
  105. if len(logEntries) == 0 {
  106. return false, nil
  107. }
  108. log := logEntries[0]
  109. if log.JSONPayload != nil {
  110. return false, fmt.Errorf("got json log entry %v, wanted plain text", log.JSONPayload)
  111. }
  112. if len(log.TextPayload) > maxLength {
  113. return false, fmt.Errorf("got too long entry of length %d", len(log.TextPayload))
  114. }
  115. return true, nil
  116. }, utils.JustTimeout, pod.Name())
  117. err = utils.WaitForLogs(c, ingestionInterval, ingestionTimeout)
  118. framework.ExpectNoError(err)
  119. })
  120. })
  121. })
  122. ginkgo.It("should ingest events [Feature:StackdriverLogging]", func() {
  123. eventCreationInterval := 10 * time.Second
  124. withLogProviderForScope(f, eventsScope, func(p *sdLogProvider) {
  125. ginkgo.By("Running pods to generate events while waiting for some of them to be ingested")
  126. stopCh := make(chan struct{})
  127. cleanupCh := make(chan struct{})
  128. defer func() { <-cleanupCh }()
  129. defer close(stopCh)
  130. go func() {
  131. defer ginkgo.GinkgoRecover()
  132. defer close(cleanupCh)
  133. wait.PollUntil(eventCreationInterval, func() (bool, error) {
  134. podName := fmt.Sprintf("synthlogger-%s", string(uuid.NewUUID()))
  135. err := utils.NewLoadLoggingPod(podName, "", 1, 1*time.Second).Start(f)
  136. if err != nil {
  137. framework.Logf("Failed to create a logging pod: %v", err)
  138. }
  139. return false, nil
  140. }, stopCh)
  141. }()
  142. ginkgo.By("Waiting for events to ingest")
  143. location := framework.TestContext.CloudConfig.Zone
  144. if framework.TestContext.CloudConfig.MultiMaster {
  145. location = framework.TestContext.CloudConfig.Region
  146. }
  147. c := utils.NewLogChecker(p, utils.UntilFirstEntryFromLocation(location), utils.JustTimeout, "")
  148. err := utils.WaitForLogs(c, ingestionInterval, ingestionTimeout)
  149. framework.ExpectNoError(err)
  150. })
  151. })
  152. ginkgo.It("should ingest system logs from all nodes [Feature:StackdriverLogging]", func() {
  153. withLogProviderForScope(f, systemScope, func(p *sdLogProvider) {
  154. ginkgo.By("Waiting for some kubelet logs to be ingested from each node", func() {
  155. nodeIds := utils.GetNodeIds(f.ClientSet)
  156. log := fmt.Sprintf("projects/%s/logs/kubelet", framework.TestContext.CloudConfig.ProjectID)
  157. c := utils.NewLogChecker(p, utils.UntilFirstEntryFromLog(log), utils.JustTimeout, nodeIds...)
  158. err := utils.WaitForLogs(c, ingestionInterval, ingestionTimeout)
  159. framework.ExpectNoError(err)
  160. })
  161. ginkgo.By("Waiting for some container runtime logs to be ingested from each node", func() {
  162. nodeIds := utils.GetNodeIds(f.ClientSet)
  163. log := fmt.Sprintf("projects/%s/logs/container-runtime", framework.TestContext.CloudConfig.ProjectID)
  164. c := utils.NewLogChecker(p, utils.UntilFirstEntryFromLog(log), utils.JustTimeout, nodeIds...)
  165. err := utils.WaitForLogs(c, ingestionInterval, ingestionTimeout)
  166. framework.ExpectNoError(err)
  167. })
  168. })
  169. })
  170. })